fix: Task 1 review round 1 - escaped )$ in reference settings, allow map, routing rulings

I-1: reject )$ in every decoded string setting and in the re-serialized
JSON. S21: string settings cleaned and re-serialized. S22: injectable
dynamic-content allow map (name => setting => field type), loop_* only via
the map. S23: unknown content.innerContent is rich text. S24: keys below
scalar kinds are unknown, ...Url path segments are URLs. S25: isVariable
removed. M-1: real \u escapes in tests, malicious suite as editor, fixture
html() raw for unfiltered_html. M-2: S7 gate at any depth plus
css.advanced.customCss.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 13:37:56 +02:00
co-authored by Claude Opus 5.5
parent 1ea2e16c49
commit 7180690611
7 changed files with 393 additions and 142 deletions
+4 -12
View File
@@ -38,21 +38,13 @@ final class Placeholders
private VariableRef $references;
public function __construct(private DesignSystem $design)
{
$this->references = new VariableRef($design);
}
/**
* Whether $value has the shape of one Divi variable reference ($variable({…})$), e.g. from an
* earlier read. A shape check only – never a reason to store a value unchecked: that is
* VariableRef::canonical() (ruling S1).
* @param array<string, array<string, string>>|null $dynamicContent Divi's dynamic content
* options for VariableRef (ruling S22); null = VariableRef::DEFAULT_DYNAMIC_CONTENT.
*/
public static function isVariable(string $value): bool
public function __construct(private DesignSystem $design, ?array $dynamicContent = null)
{
return preg_match('/^\$variable\((\{.*\})\)\$$/s', $value, $match) === 1
&& ! str_contains($match[1], ')$')
&& is_array(json_decode($match[1], true));
$this->references = new VariableRef($design, $dynamicContent);
}
/** The strict checker of $variable(…)$ values against this design system (ruling S1). */