feat: VariableArea schreibt globale Variablen mit Divis Stale-Prüfung und behält beim Wiederherstellen spätere Variablen archiviert
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
2fd03f3900
commit
f1f70114f4
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Design;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* The area "variables" (spec §7.2, rulings V1, V7): the global variables in their stored form (VariableBook), saved
|
||||
* as a whole through GlobalVariablesAdapter::save() together with the inventory read right before, which Divi checks
|
||||
* for changes in between (global_variables_stale). Divi refuses an inventory that lacks a stored ID, so a restore keeps
|
||||
* the variables created after the snapshot, archived (VariableBook::restoredFrom()) – also when the pipeline rolls back
|
||||
* a write that went through. Without the variables_manager right Divi silently saves nothing: verify() compares the
|
||||
* read-back (same variables, status and non-empty values), differences() names the values Divi sanitized.
|
||||
*/
|
||||
final class VariableArea implements DesignArea
|
||||
{
|
||||
public function __construct(private GlobalVariablesAdapter $variables)
|
||||
{
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return 'variables';
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'Variablen';
|
||||
}
|
||||
|
||||
public function feature(): DiviFeature
|
||||
{
|
||||
return DiviFeature::VariableWrite;
|
||||
}
|
||||
|
||||
public function raw(): array
|
||||
{
|
||||
return VariableBook::fromDivi($this->variables->read())->data();
|
||||
}
|
||||
|
||||
public function rev(array $raw): string
|
||||
{
|
||||
return VariableBook::fromDivi($raw)->rev();
|
||||
}
|
||||
|
||||
/** $mayRemove has no effect: variables are never removed (ruling V1). */
|
||||
public function write(array $raw, bool $mayRemove): array
|
||||
{
|
||||
$this->variables->save(VariableBook::fromDivi($raw)->data(), $this->variables->read());
|
||||
|
||||
return $this->raw();
|
||||
}
|
||||
|
||||
public function restore(array $raw): array
|
||||
{
|
||||
$live = $this->variables->read();
|
||||
$this->variables->save(
|
||||
VariableBook::fromDivi($live)->restoredFrom(VariableBook::fromDivi($raw))->data(),
|
||||
$live
|
||||
);
|
||||
|
||||
return $this->raw();
|
||||
}
|
||||
|
||||
public function verify(array $expected, array $actual): bool
|
||||
{
|
||||
return self::shape($expected) === self::shape($actual);
|
||||
}
|
||||
|
||||
public function differences(array $expected, array $actual): array
|
||||
{
|
||||
$warnings = [];
|
||||
foreach (VariableDiff::between(VariableBook::fromDivi($expected), VariableBook::fromDivi($actual)) as $row) {
|
||||
if ($row['action'] === 'changed') {
|
||||
$warnings[] = sprintf('Divi hat den Wert der Variablen „%s“ beim Speichern bereinigt.', $row['name']);
|
||||
}
|
||||
}
|
||||
|
||||
return $warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array-key, mixed> $raw
|
||||
* @return array<string, array{0: string, 1: bool}> "type/id" => [status, has a value], sorted
|
||||
*/
|
||||
private static function shape(array $raw): array
|
||||
{
|
||||
$shape = [];
|
||||
foreach (VariableBook::fromDivi($raw)->data() as $type => $entries) {
|
||||
foreach ($entries as $id => $entry) {
|
||||
$value = $entry['value'] ?? '';
|
||||
$shape[$type . '/' . $id] = [
|
||||
(string) ($entry['status'] ?? ''),
|
||||
is_scalar($value) && (string) $value !== '',
|
||||
];
|
||||
}
|
||||
}
|
||||
ksort($shape);
|
||||
|
||||
return $shape;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user