fix(audit M1, L2): Meta-Schlüssel-Optionen gegen alle Schleifen der Vorfahrenkette prüfen; queryType wie sanitize_key normalisieren, terms/users als Term-/Benutzer-Schleife

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-19 23:47:58 +02:00
co-authored by Claude Sonnet 5.5
parent 52208764f0
commit 522fc8ff4d
9 changed files with 246 additions and 35 deletions
@@ -119,6 +119,37 @@ final class LoopContextTest extends TestCase
self::assertSame('repeater_team', $inner->queryType());
}
/** Audit M1: a meta key option must fit EVERY enabled loop of the chain (an empty inner loop hands over to the outer). */
public function testMetaKeyOptionsMustFitEveryLoopOfTheChain(): void
{
$posts = self::loop(['enable' => 'on', 'queryType' => 'post_types']);
$terms = self::loop(['enable' => 'on', 'queryType' => 'post_taxonomies']);
$repeater = self::loop(['enable' => 'on', 'queryType' => 'repeater_team']);
$meta = 'loop_post_meta_key_manual_custom_field';
$postInTerm = LoopContext::fromChain([$terms, $posts]);
self::assertSame([LoopScope::POST, LoopScope::TERM], $postInTerm->kinds());
self::assertFalse($postInTerm->fits($meta));
self::assertTrue($postInTerm->fits('loop_post_title'), 'other options keep the innermost rule');
self::assertTrue(LoopContext::fromChain([$posts, $posts])->fits($meta));
self::assertFalse(LoopContext::fromChain([$repeater, $posts])->fits($meta), 'unsupported outer loop');
self::assertTrue(LoopContext::fromChain([self::loop([]), $posts])->fits($meta), 'a disabled loop is no loop');
}
/** Audit L2: Divi sanitize_key()s queryType and knows the aliases terms/users. */
public function testQueryTypeIsNormalisedLikeSanitizeKey(): void
{
$kind = static fn (string $q): ?string => LoopContext::ownScope(self::loop(['enable' => 'on', 'queryType' => $q]))
?->kind();
self::assertSame(LoopScope::TERM, $kind('Post_Taxonomies'));
self::assertSame(LoopScope::TERM, $kind(' post_taxonomies '));
self::assertSame(LoopScope::TERM, $kind('terms'));
self::assertSame(LoopScope::USER, $kind('users'));
self::assertSame(LoopScope::POST, $kind("POST_TYPES\n"));
self::assertNull($kind('repeater_team'));
}
private static function page(): NodeIndex
{
$loop = static fn (string $queryType): string => '{"module":{"advanced":{"loop":{"desktop":{"value":'
@@ -19,6 +19,8 @@ final class LoopScopeTest extends TestCase
'taxonomies' => ['post_taxonomies', LoopScope::TERM, 'Terme'],
'user roles' => ['user_roles', LoopScope::USER, 'Benutzer'],
'menus' => ['menus', LoopScope::MENU, 'Menü'],
'terms alias (audit L2)' => ['terms', LoopScope::TERM, 'Terme'],
'users alias (audit L2)' => ['users', LoopScope::USER, 'Benutzer'],
];
}
@@ -50,7 +52,7 @@ final class LoopScopeTest extends TestCase
*/
public function testOtherQueryTypesAreALoopWithoutKind(): void
{
foreach (['repeater_team', 'terms', 'users', '', 'Post_Types', 'post_types '] as $queryType) {
foreach (['repeater_team', '', 'Post_Types', 'post_types '] as $queryType) {
$scope = LoopScope::ofQueryType($queryType);
self::assertFalse($scope->active(), $queryType);