feat: PresetDiff – Unterschied zweier Preset-Bestände für den Probelauf
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
578ccba118
commit
388b52ea76
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Design;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* What a preset change does (spec §4 step 4, "diff"): per preset added, changed (with the changed top-level keys),
|
||||
* removed, and per module/group a default that is set or cleared. Keys the plugin derives or Divi maintains
|
||||
* (updated, styleAttrs, renderAttrs, version) are no change of their own. Sorted by kind, scope, id, action.
|
||||
* Pure PHP.
|
||||
*/
|
||||
final class PresetDiff
|
||||
{
|
||||
private const DERIVED = ['updated', 'styleAttrs', 'renderAttrs', 'version'];
|
||||
|
||||
/**
|
||||
* @return list<array{kind: string, scope: string, id: string, name: string, action: string,
|
||||
* fields?: list<string>}>
|
||||
*/
|
||||
public static function between(PresetBook $before, PresetBook $after): array
|
||||
{
|
||||
$old = $before->data();
|
||||
$new = $after->data();
|
||||
$rows = [];
|
||||
foreach ([PresetScope::MODULE, PresetScope::GROUP] as $kind) {
|
||||
$names = array_unique(array_merge(array_keys($old[$kind] ?? []), array_keys($new[$kind] ?? [])));
|
||||
sort($names);
|
||||
foreach ($names as $name) {
|
||||
$was = $old[$kind][$name] ?? ['default' => '', 'items' => []];
|
||||
$is = $new[$kind][$name] ?? ['default' => '', 'items' => []];
|
||||
array_push($rows, ...self::items($kind, (string) $name, $was['items'], $is['items']));
|
||||
array_push($rows, ...self::defaults($kind, (string) $name, $was, $is));
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>> $was
|
||||
* @param array<string, array<string, mixed>> $is
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private static function items(string $kind, string $scope, array $was, array $is): array
|
||||
{
|
||||
$ids = array_unique(array_merge(array_keys($was), array_keys($is)));
|
||||
sort($ids);
|
||||
$rows = [];
|
||||
foreach ($ids as $id) {
|
||||
$key = (string) $id;
|
||||
$before = $was[$key] ?? null;
|
||||
$after = $is[$key] ?? null;
|
||||
if ($before === null || $after === null) {
|
||||
$rows[] = self::row($kind, $scope, $key, $after ?? $before, $before === null ? 'added' : 'removed');
|
||||
continue;
|
||||
}
|
||||
$fields = self::changedFields($before, $after);
|
||||
if ($fields !== []) {
|
||||
$rows[] = self::row($kind, $scope, $key, $after, 'changed') + ['fields' => $fields];
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{default: string, items: array<string, array<string, mixed>>} $was
|
||||
* @param array{default: string, items: array<string, array<string, mixed>>} $is
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private static function defaults(string $kind, string $scope, array $was, array $is): array
|
||||
{
|
||||
if ($was['default'] === $is['default']) {
|
||||
return [];
|
||||
}
|
||||
if ($is['default'] === '') {
|
||||
$gone = $was['items'][$was['default']] ?? null;
|
||||
|
||||
return [self::row($kind, $scope, $was['default'], $gone, 'default_cleared')];
|
||||
}
|
||||
|
||||
$item = $is['items'][$is['default']] ?? null;
|
||||
|
||||
return [self::row($kind, $scope, $is['default'], $item, 'default_set')];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $before
|
||||
* @param array<string, mixed> $after
|
||||
* @return list<string>
|
||||
*/
|
||||
private static function changedFields(array $before, array $after): array
|
||||
{
|
||||
$keys = array_diff(array_unique(array_merge(array_keys($before), array_keys($after))), self::DERIVED);
|
||||
$fields = [];
|
||||
foreach ($keys as $key) {
|
||||
$was = $before[$key] ?? null;
|
||||
$is = $after[$key] ?? null;
|
||||
if ($was != $is) { // phpcs:ignore Universal.Operators.StrictComparisons
|
||||
$fields[] = (string) $key;
|
||||
}
|
||||
}
|
||||
sort($fields);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed>|null $item
|
||||
* @return array{kind: string, scope: string, id: string, name: string, action: string}
|
||||
*/
|
||||
private static function row(string $kind, string $scope, string $id, ?array $item, string $action): array
|
||||
{
|
||||
return [
|
||||
'kind' => $kind,
|
||||
'scope' => $scope,
|
||||
'id' => $id,
|
||||
'name' => is_string($item['name'] ?? null) ? $item['name'] : $id,
|
||||
'action' => $action,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user