>> */ public static function stored(): array { $entry = static fn (string $type, string $id, string $label, string $value, string $order, string $status) : array => ['id' => $id, 'label' => $label, 'value' => $value, 'order' => $order, 'status' => $status, 'lastUpdated' => '2026-10-01T10:00:00.000Z', 'variableType' => $type]; return [ 'numbers' => [ 'gvid-radius0001' => $entry('numbers', 'gvid-radius0001', 'Eckenradius', '8px', '1', 'active'), ], 'strings' => [ 'gvid-slogan0001' => $entry('strings', 'gvid-slogan0001', 'Slogan', 'Holz mit Herz', '1', 'active'), 'gvid-alt0000001' => $entry('strings', 'gvid-alt0000001', 'Alter Slogan', 'Früher', '', 'archived'), 'gvid-leer000001' => $entry('strings', 'gvid-leer000001', 'Leer', '', '', 'archived'), ], 'gradients' => [ 'gvid-verlauf001' => $entry( 'gradients', 'gvid-verlauf001', 'Verlauf', 'linear-gradient(#fff, #000)', '1', 'active' ), ], ]; } /** * A GlobalVariablesAdapter over $stored: save() replaces the inventory like set_global_variables() and notes each * call (data, expected) in $saves. * * @param array>> $stored * @param list, 1: array}> $saves */ public static function adapter(array &$stored, array &$saves, bool $manage = true): GlobalVariablesAdapter { $variables = Mockery::mock(GlobalVariablesAdapter::class); $variables->allows('canManage')->andReturn($manage); $variables->allows('read')->andReturnUsing(static function () use (&$stored): array { return $stored; }); $variables->allows('save')->andReturnUsing( static function (array $data, array $expected) use (&$stored, &$saves): void { $saves[] = [$data, $expected]; $stored = $data; } ); return $variables; } public function testAreaReadsThroughTheAdapter(): void { $stored = self::stored(); $saves = []; $area = new VariableArea(self::adapter($stored, $saves)); self::assertSame(['variables', 'Variablen'], [$area->name(), $area->label()]); self::assertSame(DiviFeature::VariableWrite, $area->feature()); self::assertSame(VariableBook::fromDivi($stored)->data(), $area->raw()); self::assertSame(VariableBook::fromDivi($stored)->rev(), $area->rev($stored)); } /** Ruling V7: the whole planned inventory, with the inventory read before for Divi's stale check. */ public function testWriteSavesThePlannedInventoryAgainstTheLiveOne(): void { $stored = self::stored(); $saves = []; $area = new VariableArea(self::adapter($stored, $saves)); $planned = self::stored(); $planned['numbers']['gvid-radius0001']['value'] = '12px'; $saved = $area->write($planned, false); self::assertSame([[VariableBook::fromDivi($planned)->data(), self::stored()]], $saves); self::assertSame('12px', $saved['numbers']['gvid-radius0001']['value']); } /** Ruling V1b: Divi refuses an inventory without a stored ID – later variables stay, archived. */ public function testRestoreKeepsVariablesCreatedAfterTheSnapshotArchived(): void { $stored = self::stored(); $stored['numbers']['gvid-neu0000001'] = ['id' => 'gvid-neu0000001', 'label' => 'Neu', 'value' => '4px', 'order' => '2', 'status' => 'active', 'lastUpdated' => '2026-10-19T09:00:00.000Z', 'variableType' => 'numbers']; $live = $stored; $saves = []; $area = new VariableArea(self::adapter($stored, $saves)); $area->restore(VariableBook::fromDivi(self::stored())->data()); self::assertCount(1, $saves); self::assertSame( VariableBook::fromDivi($live)->restoredFrom(VariableBook::fromDivi(self::stored()))->data(), $saves[0][0] ); self::assertSame($live, $saves[0][1]); self::assertSame('archived', $saves[0][0]['numbers']['gvid-neu0000001']['status']); } public function testVerifyInsistsOnTheSameVariablesStatusAndValues(): void { $stored = self::stored(); $saves = []; $area = new VariableArea(self::adapter($stored, $saves)); $expected = self::stored(); $sanitized = $expected; $sanitized['strings']['gvid-slogan0001']['value'] = 'Holz mit Herz '; $missing = $expected; unset($missing['numbers']['gvid-radius0001']); $archived = $expected; $archived['numbers']['gvid-radius0001']['status'] = 'archived'; $emptied = $expected; $emptied['numbers']['gvid-radius0001']['value'] = ''; self::assertTrue($area->verify($expected, $sanitized)); self::assertFalse($area->verify($expected, $missing)); self::assertFalse($area->verify($expected, $archived)); self::assertFalse($area->verify($expected, $emptied)); } public function testDifferencesNameTheVariablesDiviChanged(): void { $stored = self::stored(); $saves = []; $area = new VariableArea(self::adapter($stored, $saves)); $expected = self::stored(); $sanitized = $expected; $sanitized['strings']['gvid-slogan0001']['value'] = 'Holz mit Herz '; self::assertSame([], $area->differences($expected, $expected)); self::assertSame( ['Divi hat den Wert der Variablen „Slogan“ beim Speichern bereinigt.'], $area->differences($expected, $sanitized) ); } }