fix(4e-review clean-code): eine sanitize_key-Nachbildung (LoopScope::sanitizeKey) statt dreier; Docblock zur strengeren LoopContext::enabled()
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
71ffbdbf59
commit
410e773d28
@@ -26,7 +26,13 @@ final class LoopContext
|
|||||||
{
|
{
|
||||||
private const PATH = 'module.advanced.loop';
|
private const PATH = 'module.advanced.loop';
|
||||||
|
|
||||||
/** @param array<string, mixed> $attrs Attributes of a block */
|
/**
|
||||||
|
* Whether the block runs a loop for the tools: exactly the raw string "on", Divi's render gate. Deliberately
|
||||||
|
* stricter than the write guard (ValueCleaner::guardLoop reads enable like sanitize_key): a loop the render
|
||||||
|
* gate does not run gives its content no loop context, which fails closed.
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $attrs Attributes of a block
|
||||||
|
*/
|
||||||
public static function enabled(array $attrs): bool
|
public static function enabled(array $attrs): bool
|
||||||
{
|
{
|
||||||
return (self::settings($attrs)['enable'] ?? null) === 'on';
|
return (self::settings($attrs)['enable'] ?? null) === 'on';
|
||||||
@@ -45,10 +51,7 @@ final class LoopContext
|
|||||||
|
|
||||||
$queryType = self::settings($attrs)['queryType'] ?? 'post_types';
|
$queryType = self::settings($attrs)['queryType'] ?? 'post_types';
|
||||||
|
|
||||||
// Divi's sanitize_key() (LoopUtils.php:729-731) makes a non-string "" and lowercases and strips the rest.
|
return LoopScope::ofQueryType(LoopScope::sanitizeKey($queryType));
|
||||||
return LoopScope::ofQueryType(
|
|
||||||
is_string($queryType) ? preg_replace('/[^a-z0-9_\-]/', '', strtolower($queryType)) ?? '' : ''
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -158,6 +158,12 @@ final class LoopScope
|
|||||||
return ! str_contains($option, '_meta_key_') || array_unique($this->kinds()) === [$kind];
|
return ! str_contains($option, '_meta_key_') || array_unique($this->kinds()) === [$kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Divi's sanitize_key(): lowercase, only a-z, 0-9, "_" and "-"; "" for anything that is no scalar. */
|
||||||
|
public static function sanitizeKey(mixed $value): string
|
||||||
|
{
|
||||||
|
return is_scalar($value) ? (string) preg_replace('/[^a-z0-9_\-]/', '', strtolower((string) $value)) : '';
|
||||||
|
}
|
||||||
|
|
||||||
/** Kind of a loop_* option by its name; null for other names and ACF repeater options. */
|
/** Kind of a loop_* option by its name; null for other names and ACF repeater options. */
|
||||||
public static function kindOfOption(string $option): ?string
|
public static function kindOfOption(string $option): ?string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -181,15 +181,14 @@ final class ValueCleaner
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Divi reads enable and queryType through sanitize_key() (LoopUtils.php:725-731): stored values count so.
|
// Divi reads enable and queryType through sanitize_key() (LoopUtils.php:725-731): stored values count so.
|
||||||
$key = static fn (mixed $value): string => is_scalar($value)
|
if (LoopScope::sanitizeKey($desktopValue['enable'] ?? null) !== 'on') {
|
||||||
? (string) preg_replace('/[^a-z0-9_\-]/', '', strtolower((string) $value))
|
|
||||||
: '';
|
|
||||||
if ($key($desktopValue['enable'] ?? null) !== 'on') {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isset() like Divi: null falls back to post_types.
|
// isset() like Divi: null falls back to post_types.
|
||||||
$queryType = isset($desktopValue['queryType']) ? $key($desktopValue['queryType']) : 'post_types';
|
$queryType = isset($desktopValue['queryType'])
|
||||||
|
? LoopScope::sanitizeKey($desktopValue['queryType'])
|
||||||
|
: 'post_types';
|
||||||
if (($queryType === 'user_roles' || $queryType === 'users') && ! $this->sanitizer->canListUsers()) {
|
if (($queryType === 'user_roles' || $queryType === 'users') && ! $this->sanitizer->canListUsers()) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
'Eine Benutzer-Schleife listet Konten und E-Mail-Adressen und braucht das Recht list_users; '
|
'Eine Benutzer-Schleife listet Konten und E-Mail-Adressen und braucht das Recht list_users; '
|
||||||
@@ -214,7 +213,7 @@ final class ValueCleaner
|
|||||||
foreach ($raw as $entry) {
|
foreach ($raw as $entry) {
|
||||||
$value = is_string($subTypes) ? $entry : (is_array($entry) ? ($entry['value'] ?? null) : null);
|
$value = is_string($subTypes) ? $entry : (is_array($entry) ? ($entry['value'] ?? null) : null);
|
||||||
if (is_string($value) && trim($value) !== '') {
|
if (is_string($value) && trim($value) !== '') {
|
||||||
$types[] = preg_replace('/[^a-z0-9_\-]/', '', strtolower($value));
|
$types[] = LoopScope::sanitizeKey($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,4 +105,14 @@ final class LoopScopeTest extends TestCase
|
|||||||
self::assertFalse(LoopScope::ofQueryType('repeater_team')->fits('loop_post_title'));
|
self::assertFalse(LoopScope::ofQueryType('repeater_team')->fits('loop_post_title'));
|
||||||
self::assertTrue(LoopScope::ofQueryType('current_page')->fits('loop_post_title'));
|
self::assertTrue(LoopScope::ofQueryType('current_page')->fits('loop_post_title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The one reading of Divi's sanitize_key() (LoopUtils.php:725-731) the loop checks share. */
|
||||||
|
public function testSanitizeKeyReadsLikeDivi(): void
|
||||||
|
{
|
||||||
|
self::assertSame('userbb_roles', LoopScope::sanitizeKey(' User<b></b>_Roles '));
|
||||||
|
self::assertSame('on', LoopScope::sanitizeKey('o n'));
|
||||||
|
self::assertSame('1', LoopScope::sanitizeKey(true));
|
||||||
|
self::assertSame('', LoopScope::sanitizeKey(null));
|
||||||
|
self::assertSame('', LoopScope::sanitizeKey(['on']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user