feat: ThemeOptionBook – unveränderlicher Bestand der Theme-Optionen mit rev() (W6)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
a9edd850c1
commit
d9c4bc3751
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Design;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* The managed theme options as stored in get_option('et_divi') (ruling W6): only the whitelist keys that are
|
||||
* set, in the fixed order of ThemeOptionSpec::KEYS, with the raw value and type (int, float, string or false –
|
||||
* Divi stores its default font as false). A key that is not set is missing. Takes a snapshot or the whole et_divi
|
||||
* array alike. Immutable – with() and without() return a new book, and a key is either set or missing, never both.
|
||||
* rev() is the design_rev of the area "theme_options". Pure PHP.
|
||||
*/
|
||||
final class ThemeOptionBook
|
||||
{
|
||||
/** 1.0 and 1 are different stored values, so the hash must tell them apart (zero fraction kept). */
|
||||
private const JSON_FLAGS = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION;
|
||||
|
||||
/** @param array<string, int|float|string|false> $data */
|
||||
private function __construct(private array $data)
|
||||
{
|
||||
}
|
||||
|
||||
/** @param array<array-key, mixed> $raw Other keys, null and values of other types are dropped. */
|
||||
public static function fromDivi(array $raw): self
|
||||
{
|
||||
$data = [];
|
||||
foreach (ThemeOptionSpec::KEYS as $key) {
|
||||
$value = $raw[$key] ?? null;
|
||||
if ($value === false || is_int($value) || is_float($value) || is_string($value)) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
/** @return array<string, int|float|string|false> */
|
||||
public function data(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/** Hash of the canonical JSON; the key order is fixed, and 1, 1.0 and "1" differ. */
|
||||
public function rev(): string
|
||||
{
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode -- pure PHP (spec §4.4).
|
||||
$json = (string) json_encode($this->data, self::JSON_FLAGS);
|
||||
|
||||
return Rev::of('theme_options' . "\0" . $json);
|
||||
}
|
||||
|
||||
public function has(string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
public function get(string $key): int|float|string|false|null
|
||||
{
|
||||
return $this->data[$key] ?? null;
|
||||
}
|
||||
|
||||
/** @throws InvalidArgumentException For a key outside the whitelist. */
|
||||
public function with(string $key, int|float|string|false $value): self
|
||||
{
|
||||
ThemeOptionSpec::definition($key);
|
||||
|
||||
return self::fromDivi([...$this->data, $key => $value]);
|
||||
}
|
||||
|
||||
public function without(string $key): self
|
||||
{
|
||||
return self::fromDivi(array_diff_key($this->data, [$key => true]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user