feat: Divi BlockTree – byte-exact parser/serializer with round-trip fixtures
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\BlockTree;
|
||||
|
||||
use JsonException;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* JSON of block attributes. PHP arrays cannot tell an empty JSON object from an empty list,
|
||||
* nor an object with the keys "0", "1", … from a list. decodeObject() therefore keeps such
|
||||
* objects as stdClass, so a regenerated opener encodes them as {} again (Divi breaks on
|
||||
* "[]" where it expects "{}" – see its EmptyArrayCorruptionMigration).
|
||||
*/
|
||||
final class Json
|
||||
{
|
||||
/** @return array<string, mixed>|null Null when $json is not a JSON object. */
|
||||
public static function decodeObject(string $json): ?array
|
||||
{
|
||||
try {
|
||||
$value = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $value instanceof stdClass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$converted = self::fromJson($value);
|
||||
|
||||
return is_array($converted) ? $converted : [];
|
||||
}
|
||||
|
||||
/** Converts json_decode(…, false) output: objects become arrays unless that would lose their object-ness. */
|
||||
public static function fromJson(mixed $value): mixed
|
||||
{
|
||||
if ($value instanceof stdClass) {
|
||||
$array = [];
|
||||
foreach (get_object_vars($value) as $key => $item) {
|
||||
$array[$key] = self::fromJson($item);
|
||||
}
|
||||
|
||||
return $array === [] || array_is_list($array) ? (object) $array : $array;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return array_map([self::class, 'fromJson'], $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/** @throws JsonException */
|
||||
public static function encode(mixed $value): string
|
||||
{
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode -- pure PHP (spec §4.4).
|
||||
return json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user