fix: lit/divi-fonts-upload reicht DiviLocked aus dem Installer durch statt write_failed

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-19 18:09:26 +02:00
co-authored by Claude Sonnet 5.5
parent 7e7568ea62
commit 0a76f3c196
2 changed files with 25 additions and 0 deletions
@@ -12,6 +12,7 @@ use LIT\MCP\Abilities\ToolResult;
use LIT\MCP\Abilities\WriteFailed; use LIT\MCP\Abilities\WriteFailed;
use LIT\MCP\ChangeLog\ChangeLog; use LIT\MCP\ChangeLog\ChangeLog;
use LIT\MCP\Integrations\Divi\Release\DiviFeature; use LIT\MCP\Integrations\Divi\Release\DiviFeature;
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures; use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
use LIT\MCP\Integrations\Media\AdminIncludes; use LIT\MCP\Integrations\Media\AdminIncludes;
use LIT\MCP\Integrations\Media\RemoteFileFetcher; use LIT\MCP\Integrations\Media\RemoteFileFetcher;
@@ -409,6 +410,8 @@ final class DiviFontsUploadAbility implements Ability, RequiresDiviFeatures
{ {
try { try {
$installed = $this->installer->install($name, $paths, $weights, $family); $installed = $this->installer->install($name, $paths, $weights, $family);
} catch (DiviLocked $e) {
throw $e; // a refusal, not a write failure; assertFeature runs before anything is stored
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
// FontInstaller stores nothing when it throws. // FontInstaller stores nothing when it throws.
throw WriteFailed::rolledBack(self::REASON, $e, 'font upload: ' . $e->getMessage()); throw WriteFailed::rolledBack(self::REASON, $e, 'font upload: ' . $e->getMessage());
@@ -11,9 +11,12 @@ use LIT\MCP\Integrations\Divi\Design\DiviFontsUploadAbility;
use LIT\MCP\Integrations\Divi\Design\FontCatalog; use LIT\MCP\Integrations\Divi\Design\FontCatalog;
use LIT\MCP\Integrations\Divi\Design\FontInstaller; use LIT\MCP\Integrations\Divi\Design\FontInstaller;
use LIT\MCP\Integrations\Divi\Release\DiviFeature; use LIT\MCP\Integrations\Divi\Release\DiviFeature;
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
use LIT\MCP\Integrations\Media\RemoteFileFetcher; use LIT\MCP\Integrations\Media\RemoteFileFetcher;
use LIT\MCP\Limits; use LIT\MCP\Limits;
use LIT\MCP\Tests\Support\FakeChangeLog; use LIT\MCP\Tests\Support\FakeChangeLog;
use LIT\MCP\Tests\Support\ReleaseMatrices;
use LIT\MCP\Tests\Unit\TestCase; use LIT\MCP\Tests\Unit\TestCase;
use Mockery; use Mockery;
use Mockery\MockInterface; use Mockery\MockInterface;
@@ -492,4 +495,23 @@ final class DiviFontsUploadAbilityTest extends TestCase
} }
$this->assertTempFilesRemoved(); $this->assertTempFilesRemoved();
} }
public function testALockFromTheInstallerPropagatesInsteadOfBecomingAWriteFailure(): void
{
$locked = new DiviLocked(
ReleaseMatrices::uniform(ReleaseState::Incompatible, '5.3.0', ['x']),
[DiviFeature::FontUpload]
);
$installer = self::installer();
$installer->allows('install')->andThrow($locked);
$installer->expects('remove')->never();
try {
$this->ability($installer)->execute(self::input(['confirm' => true]));
self::fail('DiviLocked expected');
} catch (DiviLocked $e) {
self::assertSame($locked, $e);
}
$this->assertTempFilesRemoved();
}
} }