fix: lit-content-create mit divi auf einer Website ohne Divi verlangt keine Fähigkeiten – execute() antwortet mit unsupported (Divi 5 ist nicht aktiv) statt divi_incompatible samt refused-Eintrag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-18 22:48:23 +02:00
co-authored by Claude Opus 5.5
parent 39143c01d0
commit 56947e54cf
4 changed files with 36 additions and 2 deletions
@@ -112,11 +112,17 @@ final class ContentCreateAbility implements Ability, DeclaresRequirements
/** /**
* Without divi the call stays in WordPress and needs nothing; with divi it needs what the ContentComposer says it * Without divi the call stays in WordPress and needs nothing; with divi it needs what the ContentComposer says it
* needs (the Divi integration names its capabilities), so the guard refuses before a draft is inserted. * needs (the Divi integration names its capabilities), so the guard refuses before a draft is inserted. Without an
* available composer (Divi 5 not active) nothing is required either: execute() then answers with the precise
* unsupported error instead of the guard reporting locked capabilities.
*/ */
public function requirements(array $input): array public function requirements(array $input): array
{ {
return array_key_exists('divi', $input) && $this->divi !== null ? $this->divi->requirements() : []; if (! array_key_exists('divi', $input) || $this->divi === null || ! $this->divi->available()) {
return [];
}
return $this->divi->requirements();
} }
public function execute(array $input): mixed public function execute(array $input): mixed
@@ -208,6 +208,7 @@ final class DiviFeatureGateTest extends TestCase
private function composerNeeding(string ...$ids): ContentComposer private function composerNeeding(string ...$ids): ContentComposer
{ {
$composer = Mockery::mock(ContentComposer::class); $composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(true);
$composer->allows('requirements')->andReturn(array_values($ids)); $composer->allows('requirements')->andReturn(array_values($ids));
return $composer; return $composer;
@@ -237,6 +238,20 @@ final class DiviFeatureGateTest extends TestCase
self::assertSame('lit/content-create', $log->records[0]['ability']); self::assertSame('lit/content-create', $log->records[0]['ability']);
} }
public function testContentCreateWithDiviOnASiteWithoutDiviIsLeftToTheToolItself(): void
{
DiviFeatureFixtures::lock(DiviFeature::PageWrite, ReleaseState::Incompatible);
$composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(false);
$composer->shouldNotReceive('requirements');
$tool = $this->contentCreate($composer);
self::assertNull(
$this->gate(FakeChangeLog::forbidden())->refusal($tool, ['post_type' => 'page', 'divi' => [[]]]),
'no divi_incompatible and no refused entry: execute() answers "Divi 5 ist nicht aktiv"'
);
}
public function testContentCreateWithDiviRunsWhenOnlyOtherFeaturesAreLocked(): void public function testContentCreateWithDiviRunsWhenOnlyOtherFeaturesAreLocked(): void
{ {
DiviFeatureFixtures::useStates([ DiviFeatureFixtures::useStates([
@@ -216,6 +216,7 @@ final class DiviToolFeaturesTest extends TestCase
{ {
$divi = new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden()); $divi = new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden());
$composer = Mockery::mock(ContentComposer::class); $composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(true);
$composer->allows('requirements')->andReturn(self::COMPOSE); $composer->allows('requirements')->andReturn(self::COMPOSE);
$wordPress = new WordPressIntegration( $wordPress = new WordPressIntegration(
Mockery::mock(ContentSchema::class), Mockery::mock(ContentSchema::class),
@@ -103,6 +103,18 @@ final class ContentCreateDiviTest extends TestCase
self::assertSame([], $this->ability(null)->requirements(self::INPUT), 'no composer: the call is refused anyway'); self::assertSame([], $this->ability(null)->requirements(self::INPUT), 'no composer: the call is refused anyway');
} }
public function testRequirementsAreEmptyWhenTheComposerIsUnavailable(): void
{
$composer = $this->composer(available: false);
$composer->shouldNotReceive('requirements');
self::assertSame(
[],
$this->ability($composer)->requirements(self::INPUT),
'Divi inactive: execute() answers unsupported ("Divi 5 ist nicht aktiv"), the gate must not refuse first'
);
}
public function testRequirementsWithDiviAreThoseOfTheComposer(): void public function testRequirementsWithDiviAreThoseOfTheComposer(): void
{ {
$composer = $this->composer(); $composer = $this->composer();