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
@@ -144,6 +144,10 @@ final class VariableRefTest extends TestCase
'opacity',
],
'protected meta key' => [self::content('custom_meta__edit_lock', '{}'), 'custom_meta__edit_lock'],
'doubled meta prefix' => [
self::content('custom_meta_custom_meta__edit_lock', '{}'),
'custom_meta_custom_meta__edit_lock',
],
'loop content outside a loop' => [self::content('loop_post_title', '{}'), 'loop_post_title'],
'unknown dynamic content' => [self::content('post_meta_key', '{}'), 'post_meta_key'],
'extra top-level key' => ['$variable({"type":"color","value":{"name":"gcid-a1b2","settings":{}},"x":1})$', 'x'],
@@ -296,6 +300,77 @@ final class VariableRefTest extends TestCase
}
}
/** @return array<string, array{string}> */
public static function derivedMetaKeyBypasses(): array
{
return [
'doubled prefix in the name' => [self::content('custom_meta_custom_meta__edit_lock', '{}')],
'tripled prefix in the name' => [self::content('custom_meta_custom_meta_custom_meta__edit_lock', '{}')],
'prefix rebuilt by the strip' => [self::content('custom_meta_custom_mcustom_meta_eta_telefon', '{}')],
'loop prefix in the name' => [self::content('custom_meta_loop_post_meta_key__edit_lock', '{}')],
'doubled prefix in select_meta_key' => [
self::content('post_meta_key', '{"select_meta_key":"custom_meta_custom_meta__wp_page_template"}'),
],
'doubled prefix in meta_key' => [self::content('post_meta_key', '{"meta_key":"custom_meta_custom_meta__x"}')],
'loop post prefix' => [self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_post_meta_key__edit_lock"}')],
'loop user prefix' => [self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_user_meta_key__session_tokens"}')],
'loop term prefix' => [self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_term_meta_key__secret"}')],
'doubled loop prefix' => [
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_post_meta_key_loop_post_meta_key__edit_lock"}'),
],
'mixed loop and meta prefix' => [
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_post_meta_key_custom_meta__edit_lock"}'),
],
'mixed meta and loop prefix' => [
self::content('post_meta_key', '{"select_meta_key":"custom_meta_loop_term_meta_key__secret"}'),
],
'two loop prefixes' => [
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_user_meta_key_loop_post_meta_key_telefon"}'),
],
];
}
/**
* Ruling S30: Divi derives the meta key with str_replace of every prefix occurrence
* (DynamicContentOptionPostMetaKey.php:232,275; DynamicContentOptionLoopPostMetaKey.php:366-373).
*
* @dataProvider derivedMetaKeyBypasses
*/
public function testMetaKeysAreCheckedAfterDivisDerivation(string $value): void
{
$ref = self::ref([
'post_meta_key' => ['meta_key' => 'text', 'select_meta_key' => 'select'],
'loop_post_meta_key' => ['select_loop_meta_key' => 'select', 'loop_meta_key' => 'text'],
]);
$this->expectException(InvalidArgumentException::class);
$ref->canonical($value, ComposeFixture::sanitizer());
}
public function testDerivedMetaKeysThatAreFineStayAccepted(): void
{
$ref = self::ref([
'post_meta_key' => ['meta_key' => 'text', 'select_meta_key' => 'select'],
'loop_post_meta_key' => ['select_loop_meta_key' => 'select', 'loop_meta_key' => 'text'],
]);
$sanitizer = ComposeFixture::sanitizer();
foreach ([
self::content('custom_meta_telefon', '{}'),
self::content('post_meta_key', '{"select_meta_key":"custom_meta_fax"}'),
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_post_meta_key_telefon"}'),
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_user_meta_key_first_name"}'),
self::content('loop_post_meta_key', '{"select_loop_meta_key":"loop_term_meta_key_farbe"}'),
self::content(
'loop_post_meta_key',
'{"select_loop_meta_key":"loop_post_meta_key_manual_custom_field_value","loop_meta_key":"telefon"}'
),
] as $value) {
self::assertSame($value, $ref->canonical($value, $sanitizer));
}
}
/** @return array<string, array{array<array-key, mixed>}> */
public static function malformedMaps(): array
{