fix: Task 1 review round 4 - meta keys checked after Divi's prefix derivation (S30)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 13:52:00 +02:00
co-authored by Claude Opus 5.5
parent 665e603abe
commit 4832ec1e10
2 changed files with 109 additions and 7 deletions
+34 -7
View File
@@ -35,9 +35,10 @@ use stdClass;
* DynamicContentOptions::get_options($post_id, 'edit') – option name => its "fields" (key =>
* field "type"). Always, whatever the map says: "enable_html" is rejected, loop_* names only
* when the map names them, custom_meta_<key> names and the values of settings whose key ends in
* "meta_key" (meta_key, select_meta_key, loop_meta_key …) obey META_KEY (ruling S29), and no
* string – before or after cleaning (ruling S28) – may contain a reference or ")$". A map
* of another shape fails in the constructor with InvalidArgumentException.
* "meta_key" (meta_key, select_meta_key, loop_meta_key …) obey META_KEY after Divi's own prefix
* stripping (rulings S29, S30), and no string – before or after cleaning (ruling S28) – may
* contain a reference or ")$". A map of another shape fails in the constructor with
* InvalidArgumentException.
*/
final class VariableRef
{
@@ -80,12 +81,23 @@ final class VariableRef
private const META_PREFIX = 'custom_meta_';
/**
* Prefixes Divi strips from a meta key option with str_replace – every occurrence, not just
* the leading one (DynamicContentOptionPostMetaKey.php:232,249,275,286;
* DynamicContentOptionLoopPostMetaKey.php:366-373). Ruling S30.
*/
private const META_KEY_PREFIXES = [
self::META_PREFIX,
'loop_post_meta_key_',
'loop_user_meta_key_',
'loop_term_meta_key_',
];
private const NUMBER = '/^-?\d+(\.\d+)?$/';
/** @var array<string, array<string, string>> */
private array $dynamicContent;
/** @param array<string, array<string, string>>|null $dynamicContent See the class docblock. */
/**
* @param array<array-key, mixed>|null $dynamicContent See the class docblock.
* @throws InvalidArgumentException When the map does not have that shape.
@@ -342,11 +354,26 @@ final class VariableRef
return $clean;
}
/** "telefon", "custom_meta_telefon" yes; "_edit_lock", "custom_meta__edit_lock", "a b" no. */
/**
* Checks the meta key Divi derives from $key (ruling S30): a leading known prefix is removed the
* way Divi does it – str_replace of every occurrence – and a prefix still present afterwards is
* rejected (defensive). "telefon", "custom_meta_telefon", "loop_post_meta_key_telefon" yes;
* "_edit_lock", "custom_meta__edit_lock", "custom_meta_custom_meta__edit_lock",
* "loop_post_meta_key__edit_lock", "a b" no.
*/
private static function isMetaKey(string $key): bool
{
if (str_starts_with($key, self::META_PREFIX)) {
$key = substr($key, strlen(self::META_PREFIX));
foreach (self::META_KEY_PREFIXES as $prefix) {
if (str_starts_with($key, $prefix)) {
$key = str_replace($prefix, '', $key);
break;
}
}
foreach (self::META_KEY_PREFIXES as $prefix) {
if (str_contains($key, $prefix)) {
return false;
}
}
return preg_match(self::META_KEY, $key) === 1;