From 88d6e77425b281ba7e952a724ed11b4499cd67f5 Mon Sep 17 00:00:00 2001 From: Olivier Gorzalka Date: Wed, 4 Nov 2026 15:44:17 +0100 Subject: [PATCH] refactor: respect the architecture rules (CONV-03, ARCH-03) Rename WpCliUnavailable to WpCliUnavailableException and make WpCliService depend on the new WpCliAdapterInterface contract. Run tests/Arch.php in an Architecture test suite. --- CHANGELOG.md | 3 +- phpunit.xml.dist | 3 ++ src/Application/Services/WpCliService.php | 4 +-- .../Contracts/WpCliAdapterInterface.php | 28 +++++++++++++++++++ ...able.php => WpCliUnavailableException.php} | 2 +- src/Infrastructure/Adapters/WpCliAdapter.php | 7 +++-- ....php => WpCliUnavailableExceptionTest.php} | 4 +-- 7 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/Domain/Contracts/WpCliAdapterInterface.php rename src/Domain/Exceptions/{WpCliUnavailable.php => WpCliUnavailableException.php} (86%) rename tests/Unit/Domain/Exceptions/{WpCliUnavailableTest.php => WpCliUnavailableExceptionTest.php} (70%) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd198b1..5d009ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Registering a command outside WP-CLI throws the named `WpCliUnavailable` exception instead of a bare `\RuntimeException`. It extends `\RuntimeException`, and the message keeps its `WP-CLI is not available` prefix, followed by how to avoid it +- `WpCliService` now depends on the new `WpCliAdapterInterface` contract (implemented by `WpCliAdapter`) instead of the concrete adapter, so that the application layer no longer depends on the infrastructure layer. Passing a `WpCliAdapter` keeps working +- Registering a command outside WP-CLI throws the named `WpCliUnavailableException` exception instead of a bare `\RuntimeException`. It extends `\RuntimeException`, and the message keeps its `WP-CLI is not available` prefix, followed by how to avoid it ## [0.1.1] - 2026-10-13 diff --git a/phpunit.xml.dist b/phpunit.xml.dist index bf62396..1c4e8b0 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,6 +8,9 @@ tests/Unit + + tests/Arch.php + diff --git a/src/Application/Services/WpCliService.php b/src/Application/Services/WpCliService.php index 21a9bb0..dac2785 100644 --- a/src/Application/Services/WpCliService.php +++ b/src/Application/Services/WpCliService.php @@ -4,7 +4,7 @@ namespace Pollora\WpCli\Application\Services; -use Pollora\WpCli\Infrastructure\Adapters\WpCliAdapter; +use Pollora\WpCli\Domain\Contracts\WpCliAdapterInterface; use Psr\Log\LoggerInterface; use WP_CLI; @@ -23,7 +23,7 @@ class WpCliService private array $registeredCommands = []; public function __construct( - private readonly WpCliAdapter $wpCliAdapter, + private readonly WpCliAdapterInterface $wpCliAdapter, private readonly ?LoggerInterface $logger = null ) {} diff --git a/src/Domain/Contracts/WpCliAdapterInterface.php b/src/Domain/Contracts/WpCliAdapterInterface.php new file mode 100644 index 0000000..ece8325 --- /dev/null +++ b/src/Domain/Contracts/WpCliAdapterInterface.php @@ -0,0 +1,28 @@ + $args Additional arguments for WP-CLI + * + * @throws \RuntimeException If WP-CLI is not available + * @throws \InvalidArgumentException If the handler is invalid + */ + public function addCommand(string $name, string|array|object $handler, array $args = []): void; +} diff --git a/src/Domain/Exceptions/WpCliUnavailable.php b/src/Domain/Exceptions/WpCliUnavailableException.php similarity index 86% rename from src/Domain/Exceptions/WpCliUnavailable.php rename to src/Domain/Exceptions/WpCliUnavailableException.php index 58c9273..2acab84 100644 --- a/src/Domain/Exceptions/WpCliUnavailable.php +++ b/src/Domain/Exceptions/WpCliUnavailableException.php @@ -9,7 +9,7 @@ /** * Thrown when a command is registered outside a WP-CLI process. */ -final class WpCliUnavailable extends RuntimeException +final class WpCliUnavailableException extends RuntimeException { public static function whenRegisteringACommand(): self { diff --git a/src/Infrastructure/Adapters/WpCliAdapter.php b/src/Infrastructure/Adapters/WpCliAdapter.php index a8e1d37..d2472c0 100644 --- a/src/Infrastructure/Adapters/WpCliAdapter.php +++ b/src/Infrastructure/Adapters/WpCliAdapter.php @@ -4,7 +4,8 @@ namespace Pollora\WpCli\Infrastructure\Adapters; -use Pollora\WpCli\Domain\Exceptions\WpCliUnavailable; +use Pollora\WpCli\Domain\Contracts\WpCliAdapterInterface; +use Pollora\WpCli\Domain\Exceptions\WpCliUnavailableException; use WP_CLI; /** @@ -14,7 +15,7 @@ * providing a clean interface that respects hexagonal architecture * by isolating external dependencies in the infrastructure layer. */ -final class WpCliAdapter +final class WpCliAdapter implements WpCliAdapterInterface { /** * Check if WP-CLI is available. @@ -37,7 +38,7 @@ public function isAvailable(): bool public function addCommand(string $name, string|array|object $handler, array $args = []): void { if (! $this->isAvailable()) { - throw WpCliUnavailable::whenRegisteringACommand(); + throw WpCliUnavailableException::whenRegisteringACommand(); } $this->validateHandler($handler); diff --git a/tests/Unit/Domain/Exceptions/WpCliUnavailableTest.php b/tests/Unit/Domain/Exceptions/WpCliUnavailableExceptionTest.php similarity index 70% rename from tests/Unit/Domain/Exceptions/WpCliUnavailableTest.php rename to tests/Unit/Domain/Exceptions/WpCliUnavailableExceptionTest.php index eb5d259..b361330 100644 --- a/tests/Unit/Domain/Exceptions/WpCliUnavailableTest.php +++ b/tests/Unit/Domain/Exceptions/WpCliUnavailableExceptionTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -use Pollora\WpCli\Domain\Exceptions\WpCliUnavailable; +use Pollora\WpCli\Domain\Exceptions\WpCliUnavailableException; it('says WP-CLI is missing and what to do about it', function (): void { - $exception = WpCliUnavailable::whenRegisteringACommand(); + $exception = WpCliUnavailableException::whenRegisteringACommand(); expect($exception)->toBeInstanceOf(RuntimeException::class) ->and($exception->getMessage())->toStartWith('WP-CLI is not available')