Files
WP-LIT-MCP/src/Integrations/Divi/Compose/StoredForms.php
T
janniclas.loosenandClaude Opus 5.5 b24eb6c3e9 fix(security): no direct HTTP access to plugin PHP files (audit L2, cheap part)
Every file under src/ exits outside WordPress (defined('ABSPATH') ||
exit; after the use block, so a direct request no longer prints a fatal
error with the server path); divi-convert-fixture.php gets the WP_CLI
guard the other integration scripts have. A unit test keeps both true;
PSR1 side-effects warning excluded for the guard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 19:32:12 +02:00

61 lines
2.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
use LIT\MCP\Integrations\Divi\BlockTree\Serializer;
defined('ABSPATH') || exit;
/**
* The forms a search text can take in stored block markup – the database prefilter of
* lit/divi-replace-text and the check for global modules it does not edit. Only a prefilter:
* the exact, safe match happens in the tree (TextReplacer). Pure PHP.
*/
final class StoredForms
{
/**
* The search text as it can be stored in block markup: raw, as serialize_block_attributes()
* escapes it (<, >, &, " and --; the JS builder keeps non-ASCII raw) and with \uXXXX for
* non-ASCII (WordPress' PHP serializer). Case-insensitive adds the lower and upper case
* forms, since the hex digits of \u escapes do not fold.
*
* @return list<string>
*/
public static function of(string $search, bool $caseSensitive): array
{
$variants = $caseSensitive ? [$search] : [$search, mb_strtolower($search), mb_strtoupper($search)];
$forms = [];
foreach ($variants as $variant) {
$escaped = substr(Serializer::attributes(['s' => $variant]), 6, -2);
array_push($forms, $variant, $escaped, self::unicodeEscaped($escaped));
}
return array_values(array_unique($forms));
}
/** Whether block markup contains $search in one of its stored forms. */
public static function mentions(string $markup, string $search, bool $caseSensitive): bool
{
foreach (self::of($search, $caseSensitive) as $form) {
$found = $caseSensitive ? str_contains($markup, $form) : mb_stripos($markup, $form) !== false;
if ($found) {
return true;
}
}
return false;
}
/** Non-ASCII characters as JSON \uXXXX escapes (UTF-16, lower-case hex like json_encode()). */
private static function unicodeEscaped(string $value): string
{
return (string) preg_replace_callback('/[^\x00-\x7F]/u', static function (array $match): string {
$units = unpack('n*', (string) mb_convert_encoding($match[0], 'UTF-16BE', 'UTF-8'));
return implode('', array_map(static fn (int $unit): string => sprintf('\\u%04x', $unit), (array) $units));
}, $value);
}
}