fix: UsageMatcher reads Divi 4 shortcodes like WordPress and Divi, everywhere (ruling P24)

- G1: every decoded string value of a Divi 5 opener is scanned for shortcodes;
  outside the openers only the remaining content is.
- G2: attributes are parsed like shortcode_parse_atts() and global_module is
  cast with (int), as Divi does.
- G3: a non-empty global_module other than "0" that casts to 0 makes Divi
  render the newest layout, so it counts for every entry (fail closed).
- The prefilter LIKEs use LOWER(post_content), so they are case-insensitive
  under any collation.
- The guide describes the fail-closed rule without an absolute claim.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-27 04:53:54 +02:00
co-authored by Claude Opus 5.5
parent 8f87ec6163
commit b6d791d46a
5 changed files with 172 additions and 33 deletions
@@ -50,8 +50,9 @@ final class GlobalUsagesTest extends TestCase
self::assertSame([1053, 1054, 1055, 1056, 1061], array_column($rows, 'id'), '1061: undecodable, fail closed');
self::assertStringStartsWith('SELECT ID, post_status, post_type FROM', $queries[0]);
self::assertStringNotContainsString('post_content,', $queries[0]);
self::assertStringContainsString("post_content LIKE '%globalModule%'", $queries[0]);
self::assertStringContainsString("post_content LIKE '%global" . $bs . "_module%'", $queries[0]);
// Ruling P24: case-insensitive whatever the column collation.
self::assertStringContainsString("LOWER(post_content) LIKE '%globalmodule%'", $queries[0]);
self::assertStringContainsString("LOWER(post_content) LIKE '%global" . $bs . "_module%'", $queries[0]);
self::assertStringContainsString("post_content REGEXP '" . $bs . $bs . 'u00[4-7][0-9a-fA-F]' . "'", $queries[0]);
self::assertStringContainsString("post_status NOT IN ('trash', 'auto-draft', 'inherit')", $queries[0]);
self::assertStringContainsString("post_type <> 'revision'", $queries[0]);