Skip to content

Commit fde6da9

Browse files
committed
Second pass: library support for empty containers with less bloat
1 parent 409373e commit fde6da9

13 files changed

Lines changed: 479 additions & 72 deletions

File tree

examples/dotcms-laravel/app/Helpers/DotCmsHelpers.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Dotcms\PhpSdk\Utils\DotCmsHelper;
66
use Dotcms\PhpSdk\Model\Content\Contentlet;
7+
use Dotcms\PhpSdk\Model\Layout\ContainerRef;
78

89
class DotCmsHelpers
910
{
@@ -42,4 +43,54 @@ public function generateHtmlBasedOnProperty(Contentlet $content)
4243
// Fall back to the SDK simple HTML renderer
4344
return DotCmsHelper::simpleContentHtml($content->jsonSerialize());
4445
}
46+
47+
/**
48+
* Render a complete container with empty state support
49+
*
50+
* @param ContainerRef $containerRef Container reference
51+
* @param array $contentlets Array of contentlets
52+
* @param string|null $mode Current mode (EDIT_MODE for UVE)
53+
* @param callable|null $contentRenderer Custom content renderer
54+
* @return string Rendered container HTML
55+
*/
56+
public function renderContainer(
57+
ContainerRef $containerRef,
58+
array $contentlets,
59+
?string $mode = null,
60+
?callable $contentRenderer = null
61+
): string {
62+
// If no custom renderer provided, use the existing Laravel content rendering logic
63+
if ($contentRenderer === null) {
64+
$contentRenderer = function(Contentlet $content) {
65+
$contentType = $content->contentType;
66+
if ($contentType) {
67+
$viewPath = 'dotcms.content-types.' . strtolower($contentType);
68+
if (view()->exists($viewPath)) {
69+
return view($viewPath, ['content' => $content])->render();
70+
}
71+
}
72+
// Fall back to the SDK simple HTML renderer
73+
return DotCmsHelper::simpleContentHtml($content->jsonSerialize());
74+
};
75+
}
76+
77+
return DotCmsHelper::renderContainer($containerRef, $contentlets, $mode, $contentRenderer);
78+
}
79+
80+
81+
82+
/**
83+
* Rewrite container identifier for dynamic host support
84+
*
85+
* @param ContainerRef $containerRef Container reference to modify
86+
* @param string $newHost New host to use
87+
* @return ContainerRef Modified container reference
88+
*/
89+
public function rewriteContainerIdentifier(ContainerRef $containerRef, string $newHost): ContainerRef
90+
{
91+
if (isset($containerRef->identifier)) {
92+
$containerRef->identifier = str_replace('//demo.dotcms.com/', "//$newHost/", $containerRef->identifier);
93+
}
94+
return $containerRef;
95+
}
4596
}

examples/dotcms-laravel/app/Http/Controllers/AppController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public function index(Request $request)
8787
return view('page', [
8888
'pageAsset' => $page,
8989
'navigation' => $nav,
90-
'publishDate' => $publishDate
90+
'publishDate' => $publishDate,
91+
'mode' => $mode
9192
]);
9293
} catch (\Exception $e) {
9394
// Log the error

examples/dotcms-laravel/resources/css/app.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
display: grid;
2222
grid-template-columns: repeat(12, 1fr);
2323
gap: 1rem;
24+
margin-bottom: 1rem;
2425
}
2526

2627
.col-start-1 { grid-column-start: 1; }

examples/dotcms-laravel/resources/views/layouts/app.blade.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
@section('stylesheets')
1010
@vite(['resources/css/app.css', 'resources/js/app.js'])
1111
@show
12+
13+
{{-- Load UVE script from DotCMS --}}
14+
<script src="{{ env('DOTCMS_HOST') }}/ext/uve/dot-uve.js"></script>
1215
</head>
1316
<body>
1417
@include('layouts.header')
Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,2 @@
1-
@php
2-
$containerAttrs = [
3-
'data-dot-object' => 'container',
4-
'data-dot-identifier' => $containerRef->identifier ?? '',
5-
'data-dot-accept-types' => $containerRef->acceptTypes ?? '',
6-
'data-max-contentlets' => $containerRef->maxContentlets ?? '',
7-
'data-dot-uuid' => $containerRef->uuid ?? ''
8-
];
9-
@endphp
10-
11-
<div {!! $dotCmsHelpers->htmlAttr($containerAttrs) !!}>
12-
@foreach($containerRef->contentlets as $content)
13-
@php
14-
$contentAttrs = [
15-
'data-dot-object' => 'contentlet',
16-
'data-dot-identifier' => $content->identifier ?? '',
17-
'data-dot-basetype' => $content->baseType ?? '',
18-
'data-dot-title' => $content->widgetTitle ?? $content->title ?? '',
19-
'data-dot-inode' => $content->inode ?? '',
20-
'data-dot-type' => $content->contentType ?? '',
21-
'data-dot-container' => json_encode([
22-
'acceptTypes' => $containerRef->acceptTypes ?? '',
23-
'identifier' => $containerRef->identifier ?? '',
24-
'maxContentlets' => $containerRef->maxContentlets ?? '',
25-
'variantId' => $containerRef->variantId ?? '',
26-
'uuid' => $containerRef->uuid ?? ''
27-
])
28-
];
29-
@endphp
30-
31-
<div {!! $dotCmsHelpers->htmlAttr($contentAttrs) !!}>
32-
{!! $dotCmsHelpers->generateHtmlBasedOnProperty($content) !!}
33-
</div>
34-
@endforeach
35-
</div>
1+
{{-- Use the SDK's renderContainer method which includes empty container logic --}}
2+
{!! $dotCmsHelpers->renderContainer($containerRef, $containerRef->contentlets ?? [], $mode ?? null) !!}

examples/dotcms-laravel/resources/views/page.blade.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44

55
@section('content')
66

7-
{{-- Page Content --}}
7+
{{-- Page Content with UVE page-level attributes --}}
8+
<div data-dot-object="page"
9+
data-dot-identifier="{{ $pageAsset->page->identifier ?? '' }}"
10+
data-dot-inode="{{ $pageAsset->page->inode ?? '' }}"
11+
data-dot-title="{{ $pageAsset->page->title ?? '' }}"
12+
data-dot-url="{{ $pageAsset->page->uri ?? '' }}"
13+
data-dot-type="{{ $pageAsset->page->contentType ?? '' }}">
14+
815
@if(isset($pageAsset->layout) && isset($pageAsset->layout->body) && isset($pageAsset->layout->body->rows))
916
@foreach($pageAsset->layout->body->rows as $row)
1017
<div class="container">
@@ -21,7 +28,8 @@
2128
@foreach($column->containers as $containerRef)
2229
@include('layouts.container', [
2330
'containerRef' => $containerRef,
24-
'containers' => $pageAsset->containers ?? []
31+
'containers' => $pageAsset->containers ?? [],
32+
'mode' => $mode ?? null
2533
])
2634
@endforeach
2735
@endif
@@ -66,4 +74,5 @@
6674
</div>
6775
</div>
6876
@endif
77+
</div>
6978
@endsection

examples/dotcms-symfony/config/services.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,9 @@ services:
4747
console: true
4848

4949
App\Twig\DotCMSExtension:
50+
tags: ['twig.extension']
51+
52+
# Register the core SDK Twig extension for empty container support
53+
Dotcms\PhpSdk\Twig\DotCMSExtension:
54+
arguments: ['@twig']
5055
tags: ['twig.extension']

examples/dotcms-symfony/src/Controller/CatchAllController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public function show(string $path = ''): Response
5353
'layout' => $pageAsset->layout ?? null,
5454
'page' => $pageAsset->page ?? null,
5555
'containers' => $pageAsset->containers ?? [],
56-
'navigation' => $navigation
56+
'navigation' => $navigation,
57+
'mode' => $mode
5758
]);
5859
} catch (HttpException $e) {
5960
// Map HTTP errors to appropriate Symfony exceptions
Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,2 @@
1-
{% set containerAttrs = {
2-
'data-dot-object': 'container',
3-
'data-dot-identifier': container.identifier,
4-
'data-dot-accept-types': container.acceptTypes,
5-
'data-max-contentlets': container.maxContentlets,
6-
'data-dot-uuid': container.uuid
7-
} %}
8-
9-
<div {{ htmlAttr(containerAttrs) }}>
10-
{% for content in container.contentlets %}
11-
{% set contentAttrs = {
12-
'data-dot-object': 'contentlet',
13-
'data-dot-identifier': content.identifier,
14-
'data-dot-basetype': content.baseType,
15-
'data-dot-title': content.widgetTitle|default(content.title),
16-
'data-dot-inode': content.inode,
17-
'data-dot-type': content.contentType,
18-
'data-dot-container': {
19-
'acceptTypes': container.acceptTypes,
20-
'identifier': container.identifier,
21-
'maxContentlets': container.maxContentlets,
22-
'variantId': container.variantId,
23-
'uuid': container.uuid
24-
}|json_encode
25-
} %}
26-
27-
<div {{ htmlAttr(contentAttrs) }}>
28-
{{ generateHtmlBasedOnProperty(content)|raw }}
29-
</div>
30-
{% endfor %}
31-
</div>
1+
{# Use the SDK's renderContainer method which includes empty container logic #}
2+
{{ renderContainer(container, container.contentlets, mode|default(null))|raw }}

examples/dotcms-symfony/templates/page.html.twig

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@
55
{% block body %}
66
{% include 'dotcms/header.twig' %}
77

8-
{# Page Content #}
8+
{# Page Content with UVE page-level attributes #}
9+
<div data-dot-object="page"
10+
data-dot-identifier="{{ page.identifier|default(pageAsset.page.identifier|default('')) }}"
11+
data-dot-inode="{{ page.inode|default(pageAsset.page.inode|default('')) }}"
12+
data-dot-title="{{ page.title|default(pageAsset.page.title|default(page.friendlyName|default(''))) }}"
13+
data-dot-url="{{ page.uri|default(pageAsset.page.uri|default('')) }}"
14+
data-dot-type="{{ page.contentType|default(pageAsset.page.contentType|default('')) }}">
15+
916
{% if layout is not null and layout.body is defined %}
1017
{% for row in layout.body.rows %}
1118
<div class="container">
@@ -20,7 +27,8 @@
2027
{% for container in column.containers %}
2128
{% include 'dotcms/container.twig' with {
2229
'container': container,
23-
'containers': containers
30+
'containers': containers,
31+
'mode': mode|default(null)
2432
} %}
2533
{% endfor %}
2634
{% endif %}
@@ -41,4 +49,5 @@
4149
</div>
4250
</div>
4351
{% endif %}
52+
</div>
4453
{% endblock %}

0 commit comments

Comments
 (0)