Skip to content

Commit 42b0cca

Browse files
committed
update Blade.md and ites functions
1 parent a50547a commit 42b0cca

File tree

6 files changed

+144
-158
lines changed

6 files changed

+144
-158
lines changed

docs/frontend/Blade.md

Lines changed: 14 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ InspireCMS leverages Laravel's powerful Blade templating engine to create dynami
44

55
## Introduction to Blade
66

7-
Blade is Laravel's templating engine that combines the simplicity of plain PHP with powerful features like template inheritance, components, and directives. In InspireCMS, Blade is used to build flexible and maintainable templates for your website.
7+
[Blade](https://laravel.com/docs/11.x/blade) is Laravel's templating engine that combines the simplicity of plain PHP with powerful features like template inheritance, components, and directives. In InspireCMS, Blade is used to build flexible and maintainable templates for your website.
88

99
### Basic Blade Syntax
1010

@@ -60,7 +60,7 @@ Access array properties:
6060
```php
6161
@propertyArray('gallery', 'images')
6262
@foreach($gallery_images ?? [] as $image)
63-
<img src="{{ $image->getUrl() }}" alt="{{ $image->alt_text }}">
63+
<img src="{{ $image->getUrl() }}" alt="{{ $image->caption }}">
6464
@endforeach
6565
```
6666

@@ -76,36 +76,6 @@ Conditionally display content when a property has a value:
7676
@endif
7777
```
7878

79-
### Navigation Directives
80-
81-
Render navigation menus:
82-
83-
```php
84-
@navigationMenu('main', ['class' => 'main-nav', 'id' => 'primary-menu'])
85-
```
86-
87-
Customize with a callback:
88-
89-
```php
90-
@navigationMenu('main', function($items) {
91-
echo '<ul class="main-nav">';
92-
foreach ($items as $item) {
93-
echo '<li><a href="' . $item->getUrl() . '">' . $item->getTitle() . '</a>';
94-
95-
if ($item->hasChildren()) {
96-
echo '<ul class="sub-menu">';
97-
foreach ($item->children as $child) {
98-
echo '<li><a href="' . $child->getUrl() . '">' . $child->getTitle() . '</a></li>';
99-
}
100-
echo '</ul>';
101-
}
102-
103-
echo '</li>';
104-
}
105-
echo '</ul>';
106-
})
107-
```
108-
10979
### Language and Localization Directives
11080

11181
Display content in multiple languages:
@@ -175,13 +145,13 @@ Create custom theme components:
175145
Use your component:
176146

177147
```php
178-
<x-inspirecms-my-theme::alert type="warning" title="Important Notice">
148+
<x-dynamic-component :component="inspirecms_templates()->getComponentWithTheme('alert')" type="warning" title="Important Notice">
179149
This is an important message for all users.
180150

181151
<x-slot:footer>
182152
<button>Dismiss</button>
183153
</x-slot>
184-
</x-inspirecms-my-theme::alert>
154+
</x-dynamic-component>
185155
```
186156

187157
## Blade Layouts and Template Inheritance
@@ -370,7 +340,7 @@ Work with collections and arrays:
370340

371341
```php
372342
@propertyArray('blog', 'related_posts')
373-
@forelse($blog_related_posts as $post)
343+
@forelse($blog_related_posts ?? [] as $post)
374344
<div class="related-post">
375345
<h3><a href="{{ $post->getUrl() }}">{{ $post->getTitle() }}</a></h3>
376346
<p>{{ Str::limit($post->getPropertyValue('blog', 'excerpt'), 100) }}</p>
@@ -385,7 +355,7 @@ Use the `@foreach` directive with loop variable:
385355
```php
386356
@foreach($gallery_images as $image)
387357
<div class="gallery-item {{ $loop->first ? 'first' : '' }} {{ $loop->last ? 'last' : '' }}">
388-
<img src="{{ $image->getUrl() }}" alt="{{ $image->alt_text }}">
358+
<img src="{{ $image->getUrl() }}" alt="{{ $image->caption }}">
389359
<span class="number">{{ $loop->iteration }}/{{ $loop->count }}</span>
390360
</div>
391361
@endforeach
@@ -418,9 +388,9 @@ class BladeServiceProvider extends ServiceProvider
418388
Blade::directive('contentLink', function ($expression) {
419389
$params = explode(',', $expression);
420390
$id = trim($params[0]);
421-
$text = isset($params[1]) ? trim($params[1]) : 'null';
422-
423-
return "<?php echo inspirecms_content_link($id, $text); ?>";
391+
$locale = isset($params[1]) ? trim($params[1]) : 'null';
392+
393+
return "<?php echo inspirecms_content()->findByIds(ids: $id, limit: 1)?->getUrl($locale); ?>";
424394
});
425395
}
426396
}
@@ -431,7 +401,7 @@ Use custom directives:
431401
```php
432402
<p>Posted on @formatDate($content->published_at)</p>
433403

434-
<a href="@contentLink('550e8400-e29b-41d4-a716-446655440000', 'Read our about page')">
404+
<a href="@contentLink('550e8400-e29b-41d4-a716-446655440000', 'en')">
435405
<!-- Link content -->
436406
</a>
437407
```
@@ -474,42 +444,6 @@ $cacheTtl = 60 * 24; // 24 hours in minutes
474444
@endcache
475445
```
476446

477-
## Testing Templates
478-
479-
Test your Blade templates to ensure they render correctly:
480-
481-
```php
482-
namespace Tests\Feature;
483-
484-
use Tests\TestCase;
485-
use SolutionForest\InspireCms\Models\Content;
486-
487-
class PageTemplateTest extends TestCase
488-
{
489-
/** @test */
490-
public function it_renders_page_template_correctly()
491-
{
492-
// Create a test content record
493-
$content = Content::factory()->create([
494-
'title' => json_encode(['en' => 'Test Page']),
495-
'slug' => 'test-page',
496-
'status' => 1, // Published
497-
]);
498-
499-
// Add content properties
500-
$content->setPropertyValue('hero', 'title', 'Test Hero Title');
501-
502-
// Visit the page
503-
$response = $this->get($content->getUrl());
504-
505-
// Assert response and content
506-
$response->assertStatus(200);
507-
$response->assertSee('Test Hero Title');
508-
$response->assertSee('Test Page');
509-
}
510-
}
511-
```
512-
513447
## Common Blade Patterns in InspireCMS
514448

515449
### SEO Meta Tags
@@ -592,13 +526,8 @@ Implement breadcrumb navigation:
592526

593527
```php
594528
@php
595-
$breadcrumbs = [];
596-
$current = $content;
597-
598-
while ($current) {
599-
array_unshift($breadcrumbs, $current);
600-
$current = $current->parent;
601-
}
529+
$breadcrumbs = $content->getAncestors()->toArray();
530+
$breadcrumbs[] = $content;
602531
@endphp
603532

604533
<nav aria-label="Breadcrumb">
@@ -698,8 +627,7 @@ $locale = app()->getLocale();
698627
$fallbackLocale = config('app.fallback_locale');
699628

700629
// Get title in current language or fallback to default language
701-
$title = $content->getPropertyValue('hero', 'title', null, $locale)
702-
?? $content->getPropertyValue('hero', 'title', null, $fallbackLocale)
630+
$title = $content->getPropertyValue('hero', 'title', $locale, $fallbackLocale)
703631
?? 'Default Title';
704632
@endphp
705633

@@ -850,7 +778,7 @@ Use helpers in templates:
850778
```php
851779
<p class="post-meta">
852780
Published on
853-
<time datetime="{{ $content->published_at->format('Y-m-d') }}">
781+
<time datetime="{{ $content->published_at?->format('Y-m-d') }}">
854782
{{ format_content_date($content->published_at) }}
855783
</time>
856784
&bull; {{ get_reading_time($content->getPropertyValue('blog', 'body')) }} min read
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace SolutionForest\InspireCms\Base\Dtos\Concerns;
4+
5+
use SolutionForest\InspireCms\Dtos\Collection\PropertyGroupCollection;
6+
use SolutionForest\InspireCms\Dtos\PropertyDataGroupDto;
7+
8+
trait HasPropertyGroup
9+
{
10+
/**
11+
* @var PropertyGroupCollection
12+
*/
13+
public $propertyData;
14+
15+
/**
16+
* Retrieves a property group by its key.
17+
*
18+
* @param string $key The unique identifier for the property group
19+
* @return ?PropertyDataGroupDto
20+
*/
21+
public function getPropertyGroup(string $key)
22+
{
23+
if (! $this->propertyData instanceof PropertyGroupCollection) {
24+
$this->propertyData = PropertyGroupCollection::make($this->propertyData);
25+
}
26+
27+
$result = $this->propertyData->get($key, null);
28+
if ($result && $result instanceof PropertyGroupCollection) {
29+
$result->setFallbackLocale($this->getFallbackLocale());
30+
}
31+
return $result;
32+
}
33+
34+
public function hasPropertyGroup(string $key): bool
35+
{
36+
return $this->propertyData->has($key);
37+
}
38+
}

src/Dtos/ContentDto.php

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Illuminate\Database\Eloquent\Model;
66
use Illuminate\Support\Collection as SupportCollection;
7+
use SolutionForest\InspireCms\Base\Dtos\Concerns\HasPropertyGroup;
8+
use SolutionForest\InspireCms\Collection\ContentCollection;
79
use SolutionForest\InspireCms\Dtos\Collection\PropertyGroupCollection;
810
use SolutionForest\InspireCms\Helpers\ContentHelper;
911
use SolutionForest\InspireCms\Helpers\SeoHelper;
@@ -15,6 +17,8 @@
1517
*/
1618
class ContentDto extends BaseTranslatableModelDto
1719
{
20+
use HasPropertyGroup;
21+
1822
/**
1923
* @var array<string,string>
2024
*/
@@ -45,11 +49,6 @@ class ContentDto extends BaseTranslatableModelDto
4549
*/
4650
public $propertyTypes;
4751

48-
/**
49-
* @var PropertyGroupCollection
50-
*/
51-
public $propertyData;
52-
5352
/**
5453
* @var SupportCollection<string,SeoDto>
5554
*/
@@ -70,6 +69,11 @@ class ContentDto extends BaseTranslatableModelDto
7069
*/
7170
protected $children = null;
7271

72+
/**
73+
* @var null|SupportCollection<ContentDto>
74+
*/
75+
protected $ancestors = null;
76+
7377
protected array $translatableAttributes = ['title'];
7478

7579
/**
@@ -144,18 +148,13 @@ public function getChildren()
144148

145149
$model = $this->getModel();
146150

147-
if (is_null($model)) {
148-
$children = collect();
149-
} elseif (! $model->relationLoaded('children')) {
150-
$children = $model->children()->with(static::getNecessaryRelationships())->get() ?? collect();
151-
} else {
152-
$children = $model->children ?? collect();
153-
}
151+
$children = $model?->children ?? collect();
152+
$children->map->loadMissing(static::getNecessaryRelationships());
154153

155154
$currLocale = $this->getLocale();
156-
$result = $children instanceof \SolutionForest\InspireCms\Collection\ContentCollection
155+
$result = $children instanceof ContentCollection
157156
? $children->toDto($currLocale)
158-
: (new \SolutionForest\InspireCms\Collection\ContentCollection($children))->toDto($currLocale);
157+
: ContentCollection::make($children)->toDto($currLocale);
159158

160159
return $this->children = $result;
161160
}
@@ -166,6 +165,30 @@ public function getPaginatedChildren($perPage = 10, $pageName = 'page', $page =
166165
return $this->getChildren()->paginate($perPage, $pageName, $page);
167166
}
168167

168+
public function getParent()
169+
{
170+
return $this->getAncestors()->first();
171+
}
172+
173+
public function getAncestors()
174+
{
175+
if ($this->ancestors != null) {
176+
return $this->ancestors;
177+
}
178+
179+
$model = $this->getModel();
180+
181+
$ancestors = $model->ancestors->reverse() ?? collect();
182+
$ancestors->map->loadMissing(static::getNecessaryRelationships());
183+
184+
$currLocale = $this->getLocale();
185+
$result = $ancestors instanceof ContentCollection
186+
? $ancestors->toDto($currLocale)
187+
: ContentCollection::make($ancestors)->toDto($currLocale);
188+
189+
return $this->ancestors = $result;
190+
}
191+
169192
public function getTemplate($slug)
170193
{
171194
// todo: improve this
@@ -176,43 +199,31 @@ public function getTemplate($slug)
176199
}
177200

178201
/**
179-
* Retrieves the property group associated with the given key.
202+
* Checks if a specific property exists for the given group and field.
180203
*
181-
* @param string $key The key identifying the property group.
182-
* @return ?PropertyDataGroupDto
204+
* @param string $group The property group to check
205+
* @param string $field The specific field name to check within the group
206+
* @return bool Returns true if the property exists, false otherwise
183207
*/
184-
public function getPropertyGroup(string $key)
208+
public function hasProperty(string $group, string $field): bool
185209
{
186-
if (! $this->propertyData instanceof PropertyGroupCollection) {
187-
$this->propertyData = new PropertyGroupCollection($this->propertyData);
188-
}
189-
190-
$target = $this->propertyData->get($key);
191-
if ($target && ($locale = $this->getLocale() ?? $this->getFallbackLocale()) != null) {
192-
$target->setFallbackLocale($locale);
193-
}
194-
195-
return $target;
210+
return $this->getPropertyGroup($group)?->hasProperty($field) ?? false;
196211
}
197212

198213
/**
199-
* Retrieve the property data associated with a specific property key.
214+
* Gets the value of a specific property within a group.
200215
*
201-
* @param string $key The key of the property to retrieve data for.
202-
* @return SupportCollection<string,PropertyDataDto>
216+
* @param string $group The property group identifier
217+
* @param string $field The field identifier within the group
218+
* @param string|null $locale Optional locale code to get localized value, defaults to current locale if null
219+
* @return mixed
203220
*/
204-
public function getPropertyData(string $key)
221+
public function getPropertyValue(string $group, string $field, ?string $locale = null, ?string $fallbackLocale = null)
205222
{
206-
if (! $this->propertyData instanceof PropertyGroupCollection) {
207-
$this->propertyData = new PropertyGroupCollection($this->propertyData);
208-
}
209-
210-
$groups = clone $this->propertyData;
211-
if (($locale = $this->getLocale() ?? $this->getFallbackLocale()) != null) {
212-
$groups->setFallbackLocale($locale);
213-
}
223+
$locale ??= $this->getLocale() ?? $this->getFallbackLocale();
224+
$fallbackLocale ??= $this->getFallbackLocale();
214225

215-
return $groups->getPropertyData($key);
226+
return $this->getPropertyGroup($group)?->getPropertyData($field, $fallbackLocale)?->getValue($locale) ?? null;
216227
}
217228

218229
/**

src/Dtos/PropertyDataDto.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ public static function fakeValueForPropertyType($propertyType, $availableLocales
8585

8686
/**
8787
* @param \SolutionForest\FilamentFieldGroup\FieldTypes\Configs\Contracts\FieldTypeConfig $fieldType
88-
* @param string[] $availableLocales
8988
*/
9089
protected static function getFakeValueForBasicFieldType($fieldType)
9190
{

0 commit comments

Comments
 (0)