Skip to content

Commit 3b541a0

Browse files
committed
Follow up on modxcms#16322
Fixes issue with default value not working when prop set is specified in an Element call
1 parent ae3560e commit 3b541a0

File tree

3 files changed

+220
-43
lines changed

3 files changed

+220
-43
lines changed

Diff for: _build/test/Tests/Model/modParserTest.php

+184-17
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
*/
1212
namespace MODX\Revolution\Tests\Model;
1313

14-
14+
use MODX\Revolution\modElementPropertySet;
15+
use MODX\Revolution\modPropertySet;
16+
use MODX\Revolution\modSnippet;
1517
use MODX\Revolution\modX;
1618
use MODX\Revolution\MODxTestCase;
1719
use MODX\Revolution\MODxTestHarness;
@@ -764,23 +766,188 @@ public function providerProcessElementTags() {
764766
],
765767
// tags directly within brackets
766768
// @todo this test fails
767-
// [
768-
// [
769-
// 'processed' => 1,
770-
// 'content' => '<input type="text" name="item[Tag2][name]" />'
771-
// ],
772-
// '[[+tag1:notempty=`<input type="text" name="item[[[+tag2]]][name]" />`]]',
773-
// [
774-
// 'parentTag' => '',
775-
// 'processUncacheable' => true,
776-
// 'removeUnprocessed' => false,
777-
// 'prefix' => '[[',
778-
// 'suffix' => ']]',
779-
// 'tokens' => [],
780-
// 'depth' => 1
781-
// ]
782-
// ],
769+
// [
770+
// [
771+
// 'processed' => 1,
772+
// 'content' => '<input type="text" name="item[Tag2][name]" />'
773+
// ],
774+
// '[[+tag1:notempty=`<input type="text" name="item[[[+tag2]]][name]" />`]]',
775+
// [
776+
// 'parentTag' => '',
777+
// 'processUncacheable' => true,
778+
// 'removeUnprocessed' => false,
779+
// 'prefix' => '[[',
780+
// 'suffix' => ']]',
781+
// 'tokens' => [],
782+
// 'depth' => 1
783+
// ]
784+
// ],
785+
786+
// #16318 parsing tags with @ in the value causes it to break the tag
787+
[
788+
[
789+
'processed' => 1,
790+
'content' => "aaa
791+
[[nonExistentSnippet? &x=`bbb@ccc`]]
792+
ddd
793+
eee"
794+
],
795+
"[[+empty_content:empty=`aaa
796+
[[nonExistentSnippet? &x=`bbb@ccc`]]
797+
ddd
798+
`]]eee",
799+
[
800+
'parentTag' => '',
801+
'processUncacheable' => true,
802+
'removeUnprocessed' => false,
803+
'prefix' => '[[',
804+
'suffix' => ']]',
805+
'tokens' => [],
806+
'depth' => 0
807+
]
808+
]
809+
];
810+
}
811+
812+
/**
813+
* @dataProvider providerPropertySetCall
814+
* @param $content
815+
* @param $expected
816+
* @param $propertySet
817+
* @param $params
818+
* @return void
819+
*/
820+
public function testPropertySetCall($content, $expected, $propertySet, $params)
821+
{
822+
/** @var modPropertySet $set */
823+
$set = $this->modx->newObject(modPropertySet::class);
824+
$set->set('name', 'propset_' . bin2hex(random_bytes(4)));
825+
$set->setProperties($propertySet);
826+
self::assertTrue($set->save());
827+
828+
/** @var modSnippet $set */
829+
$snippet = $this->modx->newObject(modSnippet::class);
830+
$snippet->set('name', 'snippet_' . bin2hex(random_bytes(4)));
831+
$snippet->set('content', '<?php
832+
return $scriptProperties["prop"] ?? "";');
833+
self::assertTrue($snippet->save());
834+
835+
$join = $this->modx->newObject(modElementPropertySet::class);
836+
$join->fromArray([
837+
'element' => $snippet->get('id'),
838+
'element_class' => $snippet->_class,
839+
'property_set' => $set->get('id'),
840+
], '', true);
841+
$join->save();
842+
self::assertTrue($join->save());
843+
844+
$content = str_replace('propSetName', $set->get('name'), $content);
845+
$content = str_replace('snippetName', $snippet->get('name'), $content);
846+
847+
$c = $content;
848+
849+
$this->modx->parser->processElementTags(
850+
$params['parentTag'],
851+
$content,
852+
$params['processUncacheable'],
853+
$params['removeUnprocessed'],
854+
$params['prefix'],
855+
$params['suffix'],
856+
$params['tokens'],
857+
$params['depth']
858+
);
859+
860+
$set->remove();
861+
$snippet->remove();
862+
$join->remove();
863+
864+
$this->assertEquals($expected, $content, "Did not get expected results from parsing {$c}.");
865+
}
866+
public function providerPropertySetCall()
867+
{
868+
// In this test, snippetName and propSetName are replaced with a random string
869+
// for each run
870+
return [
871+
[
872+
'[[snippetName? &prop=`123`]]',
873+
'123',
874+
[],
875+
[
876+
'parentTag' => '',
877+
'processUncacheable' => true,
878+
'removeUnprocessed' => false,
879+
'prefix' => '[[',
880+
'suffix' => ']]',
881+
'tokens' => [],
882+
'depth' => 10
883+
]
884+
],
885+
[
886+
'[[snippetName@propSetName]]',
887+
'123',
888+
[
889+
'prop' => '123',
890+
],
891+
[
892+
'parentTag' => '',
893+
'processUncacheable' => true,
894+
'removeUnprocessed' => false,
895+
'prefix' => '[[',
896+
'suffix' => ']]',
897+
'tokens' => [],
898+
'depth' => 10
899+
]
900+
],
901+
[
902+
'[[snippetName@propSetName? &otherProp=`foo`]]',
903+
'789',
904+
[
905+
'prop' => '789',
906+
],
907+
[
908+
'parentTag' => '',
909+
'processUncacheable' => true,
910+
'removeUnprocessed' => false,
911+
'prefix' => '[[',
912+
'suffix' => ']]',
913+
'tokens' => [],
914+
'depth' => 10
915+
]
916+
],
917+
[
918+
'[[snippetName@propSetName? &prop=`123`]]',
919+
'123',
920+
[
921+
'prop' => '456', // needs to be ignored because &prop is specified as override
922+
],
923+
[
924+
'parentTag' => '',
925+
'processUncacheable' => true,
926+
'removeUnprocessed' => false,
927+
'prefix' => '[[',
928+
'suffix' => ']]',
929+
'tokens' => [],
930+
'depth' => 10
931+
]
932+
],
933+
[
934+
'This is a [[snippetName@propSetName:default=`default value`]]',
935+
'This is a default value',
936+
[
937+
'otherProp' => 'not this one', // props other than the test 'prop' should have no effect on output
938+
],
939+
[
940+
'parentTag' => '',
941+
'processUncacheable' => true,
942+
'removeUnprocessed' => false,
943+
'prefix' => '[[',
944+
'suffix' => ']]',
945+
'tokens' => [],
946+
'depth' => 10
947+
]
948+
],
783949
];
950+
784951
}
785952

786953
/**

Diff for: core/src/Revolution/modElement.php

+19-13
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ public function getTag()
316316
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Instance of ' . get_class($this) . ' produced an empty tag!');
317317
}
318318

319+
320+
319321
return $this->_tag;
320322
}
321323

@@ -726,19 +728,23 @@ public function getPropertySet($setName = null)
726728
{
727729
$propertySet = null;
728730
$name = $this->get('name');
729-
if (strpos($name, '@') !== false) {
730-
$psName = '';
731-
$split = xPDO:: escSplit('@', $name);
732-
if ($split && isset($split[1])) {
733-
$name = $split[0];
734-
$psName = $split[1];
735-
$filters = xPDO:: escSplit(':', $setName);
736-
if ($filters && isset($filters[1]) && !empty($filters[1])) {
737-
$psName = $filters[0];
738-
$name .= ':' . $filters[1];
739-
}
740-
$this->set('name', $name);
741-
}
731+
732+
$startFiltersIndex = strpos($name, ':');
733+
734+
if ($startFiltersIndex !== false) {
735+
$tagStart = mb_substr($name, 0, $startFiltersIndex);
736+
$tagEnd = mb_substr($name, $startFiltersIndex);
737+
} else {
738+
$tagStart = $name;
739+
$tagEnd = '';
740+
}
741+
742+
if (strpos($tagStart, '@') !== false) {
743+
$split = xPDO:: escSplit('@', $tagStart);
744+
$psName = $split[1];
745+
746+
$this->set('name', $split[0] . $tagEnd);
747+
742748
if (!empty($psName)) {
743749
$psObj = $this->xpdo->getObjectGraph(modPropertySet::class, '{"Elements":{}}', [
744750
'Elements.element' => $this->id,

Diff for: core/src/Revolution/modTag.php

+17-13
Original file line numberDiff line numberDiff line change
@@ -511,19 +511,23 @@ public function getPropertySet($setName = null)
511511
{
512512
$propertySet = null;
513513
$name = $this->get('name');
514-
if (strpos($name, '@') !== false) {
515-
$psName = '';
516-
$split = xPDO:: escSplit('@', $name);
517-
if ($split && isset($split[1])) {
518-
$name = $split[0];
519-
$psName = $split[1];
520-
$filters = xPDO:: escSplit(':', $setName);
521-
if ($filters && isset($filters[1]) && !empty($filters[1])) {
522-
$psName = $filters[0];
523-
$name .= ':' . $filters[1];
524-
}
525-
$this->set('name', $name);
526-
}
514+
515+
$startFiltersIndex = strpos($name, ':');
516+
517+
if ($startFiltersIndex !== false) {
518+
$tagStart = mb_substr($name, 0, $startFiltersIndex);
519+
$tagEnd = mb_substr($name, $startFiltersIndex);
520+
} else {
521+
$tagStart = $name;
522+
$tagEnd = '';
523+
}
524+
525+
if (strpos($tagStart, '@') !== false) {
526+
$split = xPDO:: escSplit('@', $tagStart);
527+
$psName = $split[1];
528+
529+
$this->set('name', $split[0] . $tagEnd);
530+
527531
if (!empty($psName)) {
528532
$psObj = $this->modx->getObject(modPropertySet::class, ['name' => $psName]);
529533
if ($psObj) {

0 commit comments

Comments
 (0)