Skip to content

Commit fc536d6

Browse files
committed
Adds support for grid repeaters / post-video and get_post - get_term support
1 parent 8efd732 commit fc536d6

4 files changed

Lines changed: 194 additions & 78 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"name": "totalonion"
77
}
88
],
9-
"version": "1.1.4",
9+
"version": "1.1.5",
1010
"require": {},
1111
"minimum-stability": "dev"
1212
}

inc/Renderer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ public static function return_pattern_block(int $pid): array
3232
$html = Clean::replaceBlockId($html);
3333
$html = Clean::addBlockClass($html);
3434

35-
$html = Fields::transform($html, 'fields', $name);
3635
$html = Links::transform($html);
3736
$html = Images::transform($html);
3837
$html = Videos::transform($html);
3938

39+
$html = Fields::transform($html, 'fields', $name);
40+
4041
$html = Clean::fixHtml($html);
4142
$html = Clean::fixCloseTags($html);
4243

inc/transforms/Fields.php

Lines changed: 53 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -9,71 +9,18 @@ class Fields
99
{
1010
public static function transform(string $html, string $type = 'fields', string $name = ''): string
1111
{
12-
$html = self::repeaters($html);
12+
$html = Repeater::wrapDynamicContainers($html, $name);
13+
$html = Repeater::explicitRepeaters($html, $name);
14+
1315
$html = self::replacePostMeta($html, $type);
1416
$html = self::replaceGenerics($html, $type);
1517
$html = self::replaceNodeValues($html, $type, $name);
1618
$html = self::wrapGradientOverlay($html);
1719
$html = self::formReplace($html);
1820
return $html;
1921
}
20-
// Repeaters
21-
private static function repeaters(string $html): string
22-
{
23-
$dom = Utils::loadDom($html);
24-
$xpath = new \DOMXPath($dom);
25-
// $nodes = $xpath->query('//*[@data-pattern-repeater-child]');
26-
$nodes = $xpath->query('//*[@data-pattern-repeater-child and not(@data-processed)]');
27-
28-
if ($nodes->length === 0) {
29-
return $html;
30-
}
31-
32-
$chunk_html = '';
33-
foreach ($nodes as $node) {
34-
$node->setAttribute('data-processed', '1');
35-
36-
$tmp_dom = Utils::newDom();
37-
$tmp_dom->appendChild($tmp_dom->importNode($node, true));
38-
39-
$repeated = trim($tmp_dom->saveHTML());
40-
41-
$repeated = Links::transform($repeated, 'item');
42-
$repeated = Images::transform($repeated, 'item');
43-
$repeated = Videos::transform($repeated, 'item');
44-
45-
$repeated = self::replacePostMeta($repeated, 'item');
46-
$repeated = self::replaceGenerics($repeated, 'item');
47-
$repeated = self::replaceNodeValues($repeated, 'item', $name ?? '');
48-
49-
$repeated = Clean::fixCloseTags($repeated);
50-
$repeated = Clean::fixHtml($repeated);
51-
52-
$chunk_html .= $repeated;
53-
}
54-
55-
56-
$parent = $xpath->query('//*[@data-pattern-repeater-parent]')[0];
57-
$parent->nodeValue = ''; // clear
58-
59-
$loop_start = $dom->createDocumentFragment();
60-
$loop_start->appendXML("{% if fields.items %}\n{% for item in fields.items %}");
61-
$parent->appendChild($loop_start);
62-
63-
$chunk = $dom->createDocumentFragment();
64-
$chunk->appendXML('<![CDATA[' . $chunk_html . ']]>');
65-
$parent->appendChild($chunk);
66-
67-
$loop_end = $dom->createDocumentFragment();
68-
$loop_end->appendXML("{% endfor %}\n{% endif %}");
69-
$parent->appendChild($loop_end);
70-
71-
$html = $dom->saveHTML();
72-
73-
return $html;
74-
}
7522
// Generic fields
76-
private static function replaceGenerics(string $html, string $type): string
23+
public static function replaceGenerics(string $html, string $type): string
7724
{
7825
preg_match_all('/%%(.*?)%%/', $html, $matches);
7926

@@ -90,7 +37,7 @@ private static function replaceGenerics(string $html, string $type): string
9037
return $html;
9138
}
9239
// Post meta
93-
private static function replacePostMeta(string $html, string $type): string
40+
public static function replacePostMeta(string $html, string $type): string
9441
{
9542
preg_match_all('/%%(.*?)%%/', $html, $matches);
9643

@@ -108,37 +55,36 @@ private static function replacePostMeta(string $html, string $type): string
10855
return $html;
10956
}
11057
// Post info
111-
private static function replaceNodeValues(string $html, string $type, string $name): string
58+
public static function replaceNodeValues(string $html, string $type, string $name): string
11259
{
11360
$dom = Utils::loadDom($html);
11461
$xpath = new \DOMXPath($dom);
11562
$nodes = $xpath->query('//*[@data-pattern-post-info]');
63+
if ($nodes->length === 0) return $html;
11664

117-
if ($nodes->length === 0) {
118-
return $html;
119-
}
65+
$sectionTypeNode = $xpath->query('//section[@data-post-info-type][1]')->item(0);
66+
$postInfoKind = $sectionTypeNode ? $sectionTypeNode->getAttribute('data-post-info-type') : 'post-info';
67+
$isTaxonomy = ($postInfoKind === 'post-taxonomy');
68+
$getter = $isTaxonomy ? 'get_term' : 'get_post';
12069

12170
$postInfo = 'postInfoItem';
122-
$postInfoType = 'item.post';
71+
$postInfoType = ($type === 'fields')
72+
? ($name === 'current-post-info' ? 'current_post' : 'fields.post')
73+
: 'item.post';
12374

124-
if ($type === 'fields') {
125-
if ($name === 'current-post-info') {
126-
$postInfoType = 'current_post';
127-
} else {
128-
$postInfoType = 'fields.post';
129-
}
130-
}
13175
$imageSelectNode = $xpath->query('//*[@data-image-select]')->item(0);
13276
$imageSelect = $imageSelectNode ? $imageSelectNode->getAttribute('data-image-select') : 'image';
13377
$imageKey = "post_" . $imageSelect;
13478

135-
foreach ($nodes as $key => $node) {
79+
foreach ($nodes as $i => $node) {
80+
if ($node->getAttribute('data-post-info-processed') === '1') continue;
81+
$node->setAttribute('data-post-info-processed', '1');
82+
13683
$elem = $node->getAttribute('data-pattern-post-info');
13784

138-
if ($key === 0) {
85+
if ($i === 0) {
13986
$frag = $dom->createDocumentFragment();
140-
$frag->appendXML("<inserttwig>{% set {$postInfo} = get_post({$postInfoType}) %}</inserttwig>");
141-
87+
$frag->appendXML("<inserttwig>{% set {$postInfo} = {$getter}({$postInfoType}) %}</inserttwig>");
14288
$section = $xpath->query('//section[1]')->item(0);
14389
if ($section && $section->parentNode) {
14490
$section->parentNode->insertBefore($frag, $section);
@@ -157,7 +103,6 @@ private static function replaceNodeValues(string $html, string $type, string $na
157103
{% set isSVG = check_file_type(image.id) == 'image/svg+xml' %}
158104
{% set mainImageSrc = gt_image_mainsrc(image) %}
159105
{% set srcset = isSVG ? '' : gt_image_srcset(image) %}</inserttwig>");
160-
161106
if ($node->nodeName === 'img' && $node->hasAttribute('srcset')) {
162107
$img = $node;
163108
$img->parentNode->insertBefore($frag, $img);
@@ -166,8 +111,40 @@ private static function replaceNodeValues(string $html, string $type, string $na
166111
$img->setAttribute('title', '{{ image.title }}');
167112
$img->setAttribute('alt', '{{ image.alt }}');
168113
}
114+
} elseif ($elem === 'post_video') {
115+
$videoSelect = $node->getAttribute('data-video-select');
116+
$frag = $dom->createDocumentFragment();
117+
$frag->appendXML("<inserttwig>{% set videoSelect = '$videoSelect' %}
118+
{% set videoDesktop = attribute({$postInfo}, videoSelect) %}
119+
{% set mainVideoSrc = gt_video_mainsrc(videoDesktop['url']) %}</inserttwig>");
120+
$videos = $node->getElementsByTagName('video');
121+
if ($videos->length > 0) {
122+
$video = $videos->item(0);
123+
$video->parentNode->insertBefore($frag, $video);
124+
$sources = $video->getElementsByTagName('source');
125+
foreach ($sources as $source) {
126+
$source->setAttribute('src', '{{ mainVideoSrc }}');
127+
}
128+
}
169129
} else {
170130
$node->nodeValue = "{{ {$postInfo}.{$elem} }}";
131+
$parent = $node->parentNode;
132+
if ($parent && $parent->nodeType === XML_ELEMENT_NODE) {
133+
$parentClass = ' ' . ($parent->getAttribute('class') ?? '') . ' ';
134+
if (strpos($parentClass, ' post-info-v3__content-container ') !== false) {
135+
$toRemove = [];
136+
for ($child = $parent->firstChild; $child !== null; $child = $child->nextSibling) {
137+
if ($child !== $node) {
138+
$toRemove[] = $child;
139+
}
140+
}
141+
foreach ($toRemove as $rm) {
142+
if ($rm->parentNode) {
143+
$rm->parentNode->removeChild($rm);
144+
}
145+
}
146+
}
147+
}
171148
}
172149
}
173150
return Utils::saveDom($dom);
@@ -231,7 +208,7 @@ private static function formReplace(string $html): string
231208
}
232209

233210
if ($endNode->parentNode) {
234-
if ( $renderDynamic === '1') {
211+
if ($renderDynamic === '1') {
235212
$shortcode = $dom->createTextNode("{{ function('do_shortcode', '[cdbform id=' ~ fields.form ~ ']') }}");
236213
} else {
237214
$shortcode = $dom->createTextNode("{{ function('do_shortcode', '[cdbform id=" . $formId . "]') }}");

inc/transforms/Repeater.php

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php
2+
3+
namespace GetPattern\Transforms;
4+
5+
use GetPattern\DOM\Utils;
6+
use GetPattern\DOM\Clean;
7+
use GetPattern\Transforms\Links;
8+
use GetPattern\Transforms\Images;
9+
use GetPattern\Transforms\Videos;
10+
use GetPattern\Transforms\Fields;
11+
12+
class Repeater
13+
{
14+
public static function wrapDynamicContainers(string $html, string $name = ''): string
15+
{
16+
$dom = Utils::loadDom($html);
17+
$xpath = new \DOMXPath($dom);
18+
19+
$containers = $xpath->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' group-container-v3 ') or contains(concat(' ', normalize-space(@class), ' '), ' sub-group-container-v3 ')][@data-render-dynamic='1' and not(@data-processed)]");
20+
21+
if ($containers->length === 0) {
22+
return $html;
23+
}
24+
25+
foreach ($containers as $container) {
26+
$container->setAttribute('data-processed', '1');
27+
28+
$suffix = self::extractSuffix($container);
29+
30+
$grid = $xpath->query(".//*[contains(@class, '__grid-container')][1]", $container)->item(0);
31+
if (!$grid) {
32+
// Fallback: wrap entire inner
33+
$inner = '';
34+
for ($n = $container->firstChild; $n !== null; $n = $n->nextSibling) {
35+
$inner .= $dom->saveHTML($n);
36+
}
37+
$processed = self::processAsItem($inner, $name);
38+
while ($container->firstChild) $container->removeChild($container->firstChild);
39+
self::appendLoopWithChunk($dom, $container, $processed, $suffix);
40+
continue;
41+
}
42+
43+
$firstBlock = $xpath->query(".//*[contains(@class, '__block-container')][1]", $grid)->item(0);
44+
if (!$firstBlock) {
45+
continue; // nothing to repeat
46+
}
47+
48+
$repeatParent = $firstBlock->parentNode;
49+
$chunkHtml = '';
50+
for ($n = $firstBlock; $n !== null; $n = $n->nextSibling) {
51+
$chunkHtml .= $dom->saveHTML($n);
52+
}
53+
54+
$processed = self::processAsItem($chunkHtml, $name);
55+
56+
$toRemove = [];
57+
for ($n = $firstBlock; $n !== null; $n = $n->nextSibling) $toRemove[] = $n;
58+
foreach ($toRemove as $node) {
59+
if ($node->parentNode) $node->parentNode->removeChild($node);
60+
}
61+
62+
self::appendLoopWithChunk($dom, $repeatParent, $processed, $suffix);
63+
}
64+
65+
return Utils::saveDom($dom);
66+
}
67+
68+
public static function explicitRepeaters(string $html, string $name = ''): string
69+
{
70+
$dom = Utils::loadDom($html);
71+
$xpath = new \DOMXPath($dom);
72+
73+
$children = $xpath->query('//*[@data-pattern-repeater-child and not(@data-processed)]');
74+
if ($children->length === 0) {
75+
return $html;
76+
}
77+
78+
$chunkHtml = '';
79+
foreach ($children as $child) {
80+
$child->setAttribute('data-processed', '1');
81+
82+
$tmp = Utils::newDom();
83+
$tmp->appendChild($tmp->importNode($child, true));
84+
$repeated = trim($tmp->saveHTML());
85+
86+
$repeated = self::processAsItem($repeated, $name);
87+
$chunkHtml .= $repeated;
88+
}
89+
90+
$parent = $xpath->query('//*[@data-pattern-repeater-parent]')[0] ?? null;
91+
if ($parent) {
92+
$suffix = self::extractSuffix($parent);
93+
$parent->nodeValue = '';
94+
self::appendLoopWithChunk($dom, $parent, $chunkHtml, $suffix);
95+
}
96+
97+
return $dom->saveHTML();
98+
}
99+
100+
public static function processAsItem(string $html, string $name = ''): string
101+
{
102+
$out = $html;
103+
$out = Links::transform($out, 'item');
104+
$out = Images::transform($out, 'item');
105+
$out = Videos::transform($out, 'item');
106+
$out = Fields::replacePostMeta($out, 'item');
107+
$out = Fields::replaceGenerics($out, 'item');
108+
$out = Fields::replaceNodeValues($out, 'item', $name ?: '');
109+
$out = Clean::fixCloseTags($out);
110+
$out = Clean::fixHtml($out);
111+
return $out;
112+
}
113+
114+
public static function appendLoopWithChunk(\DOMDocument $dom, \DOMNode $parent, string $chunkHtml, string $suffix = ''): void
115+
{
116+
$loopStart = $dom->createDocumentFragment();
117+
$loopStart->appendXML("{% if fields.items{$suffix} %}{% for item in fields.items{$suffix} %}");
118+
$parent->appendChild($loopStart);
119+
120+
$chunk = $dom->createDocumentFragment();
121+
$chunk->appendXML('<![CDATA[' . $chunkHtml . ']]>');
122+
$parent->appendChild($chunk);
123+
124+
$loopEnd = $dom->createDocumentFragment();
125+
$loopEnd->appendXML("{% endfor %}{% endif %}");
126+
$parent->appendChild($loopEnd);
127+
}
128+
private static function extractSuffix(\DOMElement $el): string
129+
{
130+
if ($el->hasAttribute('data-render-dynamic-suffix')) {
131+
$raw = trim((string)$el->getAttribute('data-render-dynamic-suffix'));
132+
if ($raw !== '') {
133+
return '_' . $raw;
134+
}
135+
}
136+
return '';
137+
}
138+
}

0 commit comments

Comments
 (0)