feat: lit/divi-design-restore stellt Farben und Variablen wieder her; nur theme_options folgt mit 4d (V10)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
bd2043564b
commit
88a939787d
@@ -17,7 +17,7 @@ defined('ABSPATH') || exit;
|
|||||||
* lit/divi-design-restore (spec §5, G6, ruling V10): writes a snapshot back through the change pipeline – dry run with
|
* lit/divi-design-restore (spec §5, G6, ruling V10): writes a snapshot back through the change pipeline – dry run with
|
||||||
* the diff to the current state, confirm with design_rev, and first a snapshot of the current state, so a restore can
|
* the diff to the current state, confirm with design_rev, and first a snapshot of the current state, so a restore can
|
||||||
* be undone as well. The area comes from the snapshot ID; its RestorePlanner brings the rights, the Divi features and
|
* be undone as well. The area comes from the snapshot ID; its RestorePlanner brings the rights, the Divi features and
|
||||||
* the plan. Areas without a planner are not restorable yet.
|
* the plan. Areas without a planner (theme_options until Etappe 4d) are not restorable yet.
|
||||||
*/
|
*/
|
||||||
final class DiviDesignRestoreAbility implements Ability, RequiresDiviFeatures
|
final class DiviDesignRestoreAbility implements Ability, RequiresDiviFeatures
|
||||||
{
|
{
|
||||||
@@ -50,7 +50,9 @@ final class DiviDesignRestoreAbility implements Ability, RequiresDiviFeatures
|
|||||||
{
|
{
|
||||||
return 'Stellt einen Snapshot des Designsystems wieder her (snapshot_id aus lit/divi-design-snapshots oder '
|
return 'Stellt einen Snapshot des Designsystems wieder her (snapshot_id aus lit/divi-design-snapshots oder '
|
||||||
. 'einer Änderungsantwort). Zuerst Probelauf (Unterschied zum aktuellen Stand, design_rev), nach Rückfrage '
|
. 'einer Änderungsantwort). Zuerst Probelauf (Unterschied zum aktuellen Stand, design_rev), nach Rückfrage '
|
||||||
. 'beim Nutzer confirm: true; vorher wird der aktuelle Stand selbst gesichert.';
|
. 'beim Nutzer confirm: true; vorher wird der aktuelle Stand selbst gesichert. Bereiche: presets, colors '
|
||||||
|
. '(Farben, die es im Snapshot nicht gibt, entfallen) und variables (Variablen, die erst nach dem Snapshot '
|
||||||
|
. 'entstanden, bleiben archiviert erhalten).';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function inputSchema(): array
|
public function inputSchema(): array
|
||||||
@@ -110,7 +112,7 @@ final class DiviDesignRestoreAbility implements Ability, RequiresDiviFeatures
|
|||||||
if ($planner === null) {
|
if ($planner === null) {
|
||||||
return Errors::unsupported(
|
return Errors::unsupported(
|
||||||
'Snapshots dieses Bereichs lassen sich noch nicht wiederherstellen.',
|
'Snapshots dieses Bereichs lassen sich noch nicht wiederherstellen.',
|
||||||
'Farben und Variablen folgen mit Etappe 4c, Theme-Optionen mit 4d.'
|
'Theme-Optionen folgen mit Etappe 4d.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$snapshot = $this->snapshots->get($area, $id);
|
$snapshot = $this->snapshots->get($area, $id);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use LIT\MCP\Integrations\Bootable;
|
|||||||
use LIT\MCP\Integrations\Divi\Admin\DiviTab;
|
use LIT\MCP\Integrations\Divi\Admin\DiviTab;
|
||||||
use LIT\MCP\Integrations\Divi\Cli\DiviCheckCommand;
|
use LIT\MCP\Integrations\Divi\Cli\DiviCheckCommand;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\ColorRestorePlanner;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignSystemAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviDesignSystemAbility;
|
||||||
@@ -22,6 +23,7 @@ use LIT\MCP\Integrations\Divi\Design\DiviPresetGetAbility;
|
|||||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignRestoreAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviDesignRestoreAbility;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignSnapshotsAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviDesignSnapshotsAbility;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignDetachAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviDesignDetachAbility;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviPresetsAssignAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviPresetsAssignAbility;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviPresetsDeleteAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviPresetsDeleteAbility;
|
||||||
@@ -31,6 +33,7 @@ use LIT\MCP\Integrations\Divi\Design\PresetAssignment;
|
|||||||
use LIT\MCP\Integrations\Divi\Design\PresetComposer;
|
use LIT\MCP\Integrations\Divi\Design\PresetComposer;
|
||||||
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
||||||
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
|
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\VariableRestorePlanner;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviRoles;
|
use LIT\MCP\Integrations\Divi\Library\DiviRoles;
|
||||||
use LIT\MCP\Integrations\Divi\Library\GlobalEdits;
|
use LIT\MCP\Integrations\Divi\Library\GlobalEdits;
|
||||||
@@ -266,7 +269,9 @@ final class DiviIntegration implements Integration, Bootable
|
|||||||
new DiviDesignRestoreAbility(
|
new DiviDesignRestoreAbility(
|
||||||
$this->designChange(),
|
$this->designChange(),
|
||||||
new SnapshotStore(),
|
new SnapshotStore(),
|
||||||
new PresetRestorePlanner($this->designWriter, DesignRights::unfilteredHtml())
|
new PresetRestorePlanner($this->designWriter, DesignRights::unfilteredHtml()),
|
||||||
|
new ColorRestorePlanner($this->designWriter, new GlobalColorsAdapter()),
|
||||||
|
new VariableRestorePlanner($this->designWriter, new GlobalVariablesAdapter())
|
||||||
),
|
),
|
||||||
new DiviPresetsAssignAbility(
|
new DiviPresetsAssignAbility(
|
||||||
$this->designWriter,
|
$this->designWriter,
|
||||||
|
|||||||
@@ -5,14 +5,21 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\ColorBook;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\ColorRestorePlanner;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignRestoreAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviDesignRestoreAbility;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
||||||
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
|
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\VariableRestorePlanner;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
|
use Mockery\MockInterface;
|
||||||
|
|
||||||
final class DiviDesignRestoreAbilityTest extends TestCase
|
final class DiviDesignRestoreAbilityTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -111,21 +118,174 @@ final class DiviDesignRestoreAbilityTest extends TestCase
|
|||||||
self::assertToolError($ability->execute($input), 'forbidden');
|
self::assertToolError($ability->execute($input), 'forbidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUnknownSnapshotAndOtherAreas(): void
|
public function testUnknownSnapshotAndThemeOptions(): void
|
||||||
{
|
{
|
||||||
|
$snapshots = Mockery::mock(SnapshotStore::class);
|
||||||
|
$snapshots->allows('get')->andReturn(null);
|
||||||
|
$ability = self::allAreas($snapshots, self::colorStore([]), self::variableStore([]));
|
||||||
|
|
||||||
|
self::assertToolError($ability->execute(['snapshot_id' => 'presets-20261016T100000Z-abcdef']), 'not_found');
|
||||||
|
self::assertToolError($ability->execute(['snapshot_id' => 'colors-20261016T100000Z-abcdef']), 'not_found');
|
||||||
|
self::assertToolError($ability->execute(['snapshot_id' => 'variables-20261016T100000Z-abcdef']), 'not_found');
|
||||||
|
$themeOptions = self::assertToolError(
|
||||||
|
$ability->execute(['snapshot_id' => 'theme_options-20261016T100000Z-abcdef']),
|
||||||
|
'unsupported'
|
||||||
|
);
|
||||||
|
self::assertSame('Theme-Optionen folgen mit Etappe 4d.', $themeOptions['hint']);
|
||||||
|
self::assertToolError($ability->execute(['snapshot_id' => 'kaputt']), 'validation_failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The ability with the planners of all three areas; the user has every right unless $manage is false. */
|
||||||
|
private static function allAreas(
|
||||||
|
SnapshotStore $snapshots,
|
||||||
|
GlobalColorsAdapter $colors,
|
||||||
|
GlobalVariablesAdapter $variables,
|
||||||
|
?FakeChangeLog $log = null
|
||||||
|
): DiviDesignRestoreAbility {
|
||||||
Functions\when('current_user_can')->justReturn(true);
|
Functions\when('current_user_can')->justReturn(true);
|
||||||
$writer = Mockery::mock(DesignSystemWriter::class);
|
$writer = Mockery::mock(DesignSystemWriter::class);
|
||||||
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
||||||
$snapshots = Mockery::mock(SnapshotStore::class);
|
$writer->allows('presets')->andReturn(PresetBookTest::stored());
|
||||||
$snapshots->allows('get')->andReturn(null);
|
$writer->shouldNotReceive('savePresets');
|
||||||
$ability = new DiviDesignRestoreAbility(
|
|
||||||
new DesignChange($snapshots, FakeChangeLog::forbidden()),
|
|
||||||
$snapshots,
|
|
||||||
new PresetRestorePlanner($writer)
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertToolError($ability->execute(['snapshot_id' => 'presets-20261016T100000Z-abcdef']), 'not_found');
|
return new DiviDesignRestoreAbility(
|
||||||
self::assertToolError($ability->execute(['snapshot_id' => 'colors-20261016T100000Z-abcdef']), 'unsupported');
|
new DesignChange($snapshots, $log ?? FakeChangeLog::forbidden()),
|
||||||
self::assertToolError($ability->execute(['snapshot_id' => 'kaputt']), 'validation_failed');
|
$snapshots,
|
||||||
|
new PresetRestorePlanner($writer),
|
||||||
|
new ColorRestorePlanner($writer, $colors),
|
||||||
|
new VariableRestorePlanner($writer, $variables)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A colors adapter that reads what it last saved, starting with $stored.
|
||||||
|
*
|
||||||
|
* @param array<string, array<string, mixed>> $stored
|
||||||
|
*/
|
||||||
|
private static function colorStore(array $stored): GlobalColorsAdapter&MockInterface
|
||||||
|
{
|
||||||
|
$colors = Mockery::mock(GlobalColorsAdapter::class);
|
||||||
|
$colors->allows('read')->andReturnUsing(static function () use (&$stored): array {
|
||||||
|
return $stored;
|
||||||
|
});
|
||||||
|
$colors->allows('save')->andReturnUsing(static function (array $entries, bool $replace) use (&$stored): void {
|
||||||
|
self::assertTrue($replace, 'a restore replaces every color (V4)');
|
||||||
|
$stored = $entries;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variables adapter that reads what it last saved, starting with $stored.
|
||||||
|
*
|
||||||
|
* @param array<string, array<string, array<string, mixed>>> $stored
|
||||||
|
*/
|
||||||
|
private static function variableStore(array $stored, bool $manage = true): GlobalVariablesAdapter&MockInterface
|
||||||
|
{
|
||||||
|
$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) use (&$stored): void {
|
||||||
|
$stored = $data;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<array-key, mixed> $data */
|
||||||
|
private static function snapshotIn(string $area, string $id, array $data): array
|
||||||
|
{
|
||||||
|
return ['id' => $id, 'data' => $data, 'created' => 'x', 'user_id' => 1, 'ability' => 'lit/divi-' . $area . '-set',
|
||||||
|
'log_id' => 2, 'size' => 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRestoresColorsWithDryRunAndASnapshotOfTheCurrentColors(): void
|
||||||
|
{
|
||||||
|
$id = ColorRestorePlannerTest::SNAPSHOT_ID;
|
||||||
|
$colors = self::colorStore(ColorRestorePlannerTest::current());
|
||||||
|
$snapshots = Mockery::mock(SnapshotStore::class);
|
||||||
|
$snapshots->allows('get')->with('colors', $id)
|
||||||
|
->andReturn(self::snapshotIn('colors', $id, ColorRestorePlannerTest::snapshot()));
|
||||||
|
$snapshots->expects('save')
|
||||||
|
->with('colors', ColorBook::fromDivi(ColorRestorePlannerTest::current())->data(), 'lit/divi-design-restore')
|
||||||
|
->andReturn('colors-5');
|
||||||
|
$snapshots->expects('attachLog');
|
||||||
|
$ability = self::allAreas($snapshots, $colors, self::variableStore([]), new FakeChangeLog(8));
|
||||||
|
|
||||||
|
$dry = self::assertToolError($ability->execute(['snapshot_id' => $id]), 'confirm_required');
|
||||||
|
self::assertSame(['changed', 'removed'], array_column($dry['diff'], 'action'));
|
||||||
|
self::assertStringContainsString('„Akzent“', $dry['warnings'][0]);
|
||||||
|
|
||||||
|
$result = $ability->execute(['snapshot_id' => $id, 'confirm' => true, 'design_rev' => $dry['design_rev']]);
|
||||||
|
self::assertSame('colors-5', $result['snapshot_id']);
|
||||||
|
self::assertSame(ColorBook::fromDivi(ColorRestorePlannerTest::snapshot())->data(), $colors->read());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRestoresVariablesAndKeepsNewerOnesArchived(): void
|
||||||
|
{
|
||||||
|
$id = VariableRestorePlannerTest::SNAPSHOT_ID;
|
||||||
|
$variables = self::variableStore(VariableRestorePlannerTest::current());
|
||||||
|
$snapshots = Mockery::mock(SnapshotStore::class);
|
||||||
|
$snapshots->allows('get')->with('variables', $id)
|
||||||
|
->andReturn(self::snapshotIn('variables', $id, VariableRestorePlannerTest::snapshot()));
|
||||||
|
$snapshots->expects('save')
|
||||||
|
->with('variables', Mockery::type('array'), 'lit/divi-design-restore')
|
||||||
|
->andReturn('variables-5');
|
||||||
|
$snapshots->expects('attachLog');
|
||||||
|
$ability = self::allAreas($snapshots, self::colorStore([]), $variables, new FakeChangeLog(8));
|
||||||
|
|
||||||
|
$dry = self::assertToolError($ability->execute(['snapshot_id' => $id]), 'confirm_required');
|
||||||
|
self::assertStringContainsString('„Neu“', $dry['warnings'][0]);
|
||||||
|
|
||||||
|
$result = $ability->execute(['snapshot_id' => $id, 'confirm' => true, 'design_rev' => $dry['design_rev']]);
|
||||||
|
self::assertSame('variables-5', $result['snapshot_id']);
|
||||||
|
$stored = $variables->read();
|
||||||
|
self::assertSame('4px', $stored['numbers']['gvid-radius0001']['value']);
|
||||||
|
self::assertSame('archived', $stored['numbers']['gvid-neu0000001']['status']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Spec §10, V10: the rights are those of the snapshot's area. */
|
||||||
|
public function testRightsFollowTheSnapshotArea(): void
|
||||||
|
{
|
||||||
|
$snapshots = Mockery::mock(SnapshotStore::class);
|
||||||
|
$snapshots->shouldNotReceive('get');
|
||||||
|
$ability = self::allAreas($snapshots, self::colorStore([]), self::variableStore([], false));
|
||||||
|
|
||||||
|
self::assertToolError(
|
||||||
|
$ability->permission(['snapshot_id' => VariableRestorePlannerTest::SNAPSHOT_ID]),
|
||||||
|
'forbidden'
|
||||||
|
);
|
||||||
|
self::assertToolError(
|
||||||
|
$ability->execute(['snapshot_id' => VariableRestorePlannerTest::SNAPSHOT_ID]),
|
||||||
|
'forbidden'
|
||||||
|
);
|
||||||
|
self::assertTrue($ability->permission(['snapshot_id' => ColorRestorePlannerTest::SNAPSHOT_ID]));
|
||||||
|
self::assertTrue($ability->permission(['snapshot_id' => 'presets-20261016T100000Z-aaaaaa']));
|
||||||
|
self::assertToolError($ability->permission(['snapshot_id' => 'kaputt']), 'forbidden', 'fail closed');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFeaturesFollowTheSnapshotArea(): void
|
||||||
|
{
|
||||||
|
$ability = self::allAreas(Mockery::mock(SnapshotStore::class), self::colorStore([]), self::variableStore([]));
|
||||||
|
|
||||||
|
self::assertSame(
|
||||||
|
[DiviFeature::DesignRead, DiviFeature::ColorWrite],
|
||||||
|
$ability->diviFeatures(['snapshot_id' => ColorRestorePlannerTest::SNAPSHOT_ID])
|
||||||
|
);
|
||||||
|
self::assertSame(
|
||||||
|
[DiviFeature::DesignRead, DiviFeature::VariableWrite],
|
||||||
|
$ability->diviFeatures(['snapshot_id' => VariableRestorePlannerTest::SNAPSHOT_ID])
|
||||||
|
);
|
||||||
|
self::assertSame(
|
||||||
|
[DiviFeature::DesignRead, DiviFeature::PresetWrite],
|
||||||
|
$ability->diviFeatures(['snapshot_id' => 'presets-20261016T100000Z-aaaaaa'])
|
||||||
|
);
|
||||||
|
self::assertSame(
|
||||||
|
[DiviFeature::DesignRead, DiviFeature::PresetWrite, DiviFeature::ColorWrite, DiviFeature::VariableWrite],
|
||||||
|
$ability->diviFeatures([])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ final class DiviToolFeaturesTest extends TestCase
|
|||||||
'lit/divi-presets-set' => ['design-read', 'preset-write', 'catalog'],
|
'lit/divi-presets-set' => ['design-read', 'preset-write', 'catalog'],
|
||||||
'lit/divi-presets-delete' => ['design-read', 'preset-write'],
|
'lit/divi-presets-delete' => ['design-read', 'preset-write'],
|
||||||
'lit/divi-design-snapshots' => [],
|
'lit/divi-design-snapshots' => [],
|
||||||
'lit/divi-design-restore' => ['design-read', 'preset-write'],
|
'lit/divi-design-restore' => ['design-read', 'preset-write', 'color-write', 'variable-write'],
|
||||||
'lit/divi-presets-assign' => [
|
'lit/divi-presets-assign' => [
|
||||||
'page-read', 'page-write', 'catalog', 'design-read', 'preset-write', 'library-read', 'library-write',
|
'page-read', 'page-write', 'catalog', 'design-read', 'preset-write', 'library-read', 'library-write',
|
||||||
'tb-write', 'roles',
|
'tb-write', 'roles',
|
||||||
@@ -180,6 +180,18 @@ final class DiviToolFeaturesTest extends TestCase
|
|||||||
'library-write', 'tb-write', 'roles', 'variable-write',
|
'library-write', 'tb-write', 'roles', 'variable-write',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'design-restore of presets' => [
|
||||||
|
'lit/divi-design-restore', ['snapshot_id' => 'presets-20261016T100000Z-aaaaaa'],
|
||||||
|
['design-read', 'preset-write'],
|
||||||
|
],
|
||||||
|
'design-restore of colors' => [
|
||||||
|
'lit/divi-design-restore', ['snapshot_id' => 'colors-20261016T100000Z-aaaaaa'],
|
||||||
|
['design-read', 'color-write'],
|
||||||
|
],
|
||||||
|
'design-restore of variables' => [
|
||||||
|
'lit/divi-design-restore', ['snapshot_id' => 'variables-20261016T100000Z-aaaaaa'],
|
||||||
|
['design-read', 'variable-write'],
|
||||||
|
],
|
||||||
'library-list' => ['lit/library-list', [], ['library-read', 'roles']],
|
'library-list' => ['lit/library-list', [], ['library-read', 'roles']],
|
||||||
'library-list of one entry' => [
|
'library-list of one entry' => [
|
||||||
'lit/library-list', ['id' => $library], ['library-read', 'roles', 'page-read', 'design-read'],
|
'lit/library-list', ['id' => $library], ['library-read', 'roles', 'page-read', 'design-read'],
|
||||||
|
|||||||
Reference in New Issue
Block a user