fix(audit L4): Restore prüft die Fundstellen aller Diff-Zeilen (auch aktivierte und wieder angelegte IDs, Standard-Preset-Wechsel)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
c4ee195392
commit
bb5487082e
@@ -70,7 +70,7 @@ final class PresetRestorePlanner implements RestorePlanner
|
|||||||
$after->data(),
|
$after->data(),
|
||||||
$diff,
|
$diff,
|
||||||
sprintf('Snapshot %s wiederherstellen – %s', $snapshotId, PresetDiff::summary($diff)),
|
sprintf('Snapshot %s wiederherstellen – %s', $snapshotId, PresetDiff::summary($diff)),
|
||||||
$this->usagesOf($before, $diff),
|
$this->usagesOf($before, $after, $diff),
|
||||||
['Seiten, die Presets verwenden, die es im Snapshot nicht gibt, behalten den Verweis; das Modul fällt '
|
['Seiten, die Presets verwenden, die es im Snapshot nicht gibt, behalten den Verweis; das Modul fällt '
|
||||||
. 'dann auf das Standard-Preset zurück.'],
|
. 'dann auf das Standard-Preset zurück.'],
|
||||||
true
|
true
|
||||||
@@ -78,20 +78,18 @@ final class PresetRestorePlanner implements RestorePlanner
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Audit L4: the pages using a preset the restore changes or removes (spec §4 step 4, ruling P8a); a default
|
* Audit L4: the pages using a preset the restore touches in any way, also re-created ones (spec §4 step 4, ruling P8a); a default
|
||||||
* preset also counts its implicit users (like lit/divi-presets-delete). The orphan warning stays (spec §5).
|
* preset also counts its implicit users (like lit/divi-presets-delete). The orphan warning stays (spec §5).
|
||||||
*
|
*
|
||||||
* @param list<array<string, mixed>> $diff
|
* @param list<array<string, mixed>> $diff
|
||||||
*/
|
*/
|
||||||
private function usagesOf(PresetBook $before, array $diff): ?UsageReport
|
private function usagesOf(PresetBook $before, PresetBook $after, array $diff): ?UsageReport
|
||||||
{
|
{
|
||||||
$targets = [];
|
$targets = [];
|
||||||
foreach ($diff as $row) {
|
foreach ($diff as $row) {
|
||||||
if (in_array($row['action'], RestoreUsages::TOUCHING, true)) {
|
$scope = new PresetScope((string) $row['kind'], (string) $row['scope']);
|
||||||
$scope = new PresetScope((string) $row['kind'], (string) $row['scope']);
|
$targets[] = ['scope' => $scope, 'id' => (string) $row['id'],
|
||||||
$targets[] = ['scope' => $scope, 'id' => (string) $row['id'],
|
'default' => $before->defaultId($scope) === $row['id'] || $after->defaultId($scope) === $row['id']];
|
||||||
'default' => $before->defaultId($scope) === $row['id']];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $targets === []
|
return $targets === []
|
||||||
|
|||||||
@@ -11,14 +11,11 @@ defined('ABSPATH') || exit;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The usages a snapshot restore has to report (audit L4, spec §4 step 4): the pages that use an entry the restore
|
* The usages a snapshot restore has to report (audit L4, spec §4 step 4): the pages that use an entry the restore
|
||||||
* changes, removes or deactivates – DesignChange then blocks the confirmed restore for pages the caller may not edit
|
* changes, removes, (de)activates or re-creates (an old ID that pages still reference) – DesignChange then blocks the confirmed restore for pages the caller may not edit
|
||||||
* (ruling P8a) and the dry run lists them as "affected".
|
* (ruling P8a) and the dry run lists them as "affected".
|
||||||
*/
|
*/
|
||||||
final class RestoreUsages
|
final class RestoreUsages
|
||||||
{
|
{
|
||||||
/** Diff actions that change what a page shows (colors: deactivated, variables: archived). */
|
|
||||||
public const TOUCHING = ['changed', 'removed', 'deactivated', 'archived'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param list<array<string, mixed>> $diff Rows with "id" (gcid-/gvid-) and "action"
|
* @param list<array<string, mixed>> $diff Rows with "id" (gcid-/gvid-) and "action"
|
||||||
*/
|
*/
|
||||||
@@ -26,9 +23,7 @@ final class RestoreUsages
|
|||||||
{
|
{
|
||||||
$ids = [];
|
$ids = [];
|
||||||
foreach ($diff as $row) {
|
foreach ($diff as $row) {
|
||||||
if (in_array($row['action'], self::TOUCHING, true)) {
|
$ids[] = (string) $row['id'];
|
||||||
$ids[] = (string) $row['id'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ids === [] ? null : $usages->reportFor(new ReferenceUsageQuery(array_values(array_unique($ids))));
|
return $ids === [] ? null : $usages->reportFor(new ReferenceUsageQuery(array_values(array_unique($ids))));
|
||||||
|
|||||||
@@ -139,4 +139,23 @@ final class ColorRestorePlannerTest extends TestCase
|
|||||||
self::assertInstanceOf(DesignPlan::class, $plan);
|
self::assertInstanceOf(DesignPlan::class, $plan);
|
||||||
self::assertNull($plan->usages);
|
self::assertNull($plan->usages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Audit L4 (re-review): a color the snapshot brings back (old ID, pages may still reference it) is looked up too. */
|
||||||
|
public function testReportsThePagesUsingAColorTheSnapshotRecreates(): void
|
||||||
|
{
|
||||||
|
$usages = Mockery::mock(GlobalUsages::class);
|
||||||
|
$usages->expects('reportFor')->once()->with(Mockery::on(
|
||||||
|
static fn (mixed $query): bool => $query instanceof ReferenceUsageQuery && $query->matches('gcid-alt000001')
|
||||||
|
))->andReturn(UsageFixture::blockedReport());
|
||||||
|
|
||||||
|
$plan = self::planner(true, $usages)->plan(
|
||||||
|
self::snapshot(),
|
||||||
|
self::snapshot() + ['gcid-alt000001' => self::color('Alt', '#123456')],
|
||||||
|
self::SNAPSHOT_ID
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertInstanceOf(DesignPlan::class, $plan);
|
||||||
|
self::assertSame(['added'], array_column($plan->diff, 'action'));
|
||||||
|
self::assertTrue($plan->usages?->blocks());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,4 +89,21 @@ final class PresetRestorePlannerTest extends TestCase
|
|||||||
self::assertInstanceOf(DesignPlan::class, $plan);
|
self::assertInstanceOf(DesignPlan::class, $plan);
|
||||||
self::assertNull($plan->usages);
|
self::assertNull($plan->usages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Audit L4 (re-review): a preset becoming the default reaches modules without an own preset – looked up as default. */
|
||||||
|
public function testALookupCoversPresetsTheSnapshotMakesDefault(): void
|
||||||
|
{
|
||||||
|
$older = PresetBookTest::stored();
|
||||||
|
$older['module']['divi/button']['default'] = 'aaaaaaaaaa';
|
||||||
|
$usages = Mockery::mock(GlobalUsages::class);
|
||||||
|
$usages->expects('reportFor')->once()->with(Mockery::on(
|
||||||
|
static fn (mixed $query): bool => $query instanceof PresetUsageQuery
|
||||||
|
&& $query->matches('<!-- wp:divi/button {} /-->')
|
||||||
|
))->andReturn(UsageFixture::blockedReport());
|
||||||
|
|
||||||
|
$plan = self::planner(true, $usages)->plan(PresetBookTest::stored(), $older, 'presets-1');
|
||||||
|
|
||||||
|
self::assertInstanceOf(DesignPlan::class, $plan);
|
||||||
|
self::assertTrue($plan->usages?->blocks());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user