diff --git a/composer.json b/composer.json index 941bf8a..d90f262 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,8 @@ "require": { "php": "^8.3", "symfony/console": "^7.4", - "dbschemix/core": "^1.0", - "dbschemix/pdo": "^1.0", + "dbschemix/core": "^1.1", + "dbschemix/pdo": "^1.1", "league/climate": "^3.10" }, "require-dev": { diff --git a/src/tools/PrettyConsoleOutput.php b/src/tools/PrettyConsoleOutput.php index affb4b6..d39f72d 100644 --- a/src/tools/PrettyConsoleOutput.php +++ b/src/tools/PrettyConsoleOutput.php @@ -11,6 +11,7 @@ use dbschemix\core\event\EventSubscriberInterface; use dbschemix\core\event\MigrateErrorEvent; use dbschemix\core\event\MigrateSuccessEvent; +use dbschemix\core\event\Subscription; /** * @api @@ -28,26 +29,24 @@ public function subscriptions(): array { $subscriptions = []; foreach (Event::cases() as $event) { - $subscriptions[$event->value] = match ($event) { - Event::MigrateSuccess => $this->success(...), - Event::MigrateError => $this->error(...), - Event::FilesystemNotice => $this->notice(...), - default => $this->failure(...), + $subscriptions[] = match ($event) { + Event::MigrateSuccess => new Subscription($event, $this->success(...)), + Event::MigrateError => new Subscription($event, $this->error(...)), + Event::FilesystemNotice => new Subscription($event, $this->notice(...)), + default => new Subscription($event, $this->failure(...)), }; } - /** - * @var non-empty-array $subscriptions - * @phpstan-ignore varTag.nativeType - */ return $subscriptions; } /** * @noinspection PhpUnusedParameterInspection */ - public function success(Event $name, MigrateSuccessEvent $event): void + public function success(Event $name, EventInterface $event): void { + assert($event instanceof MigrateSuccessEvent); + $this->output->out( match ($event->action) { "up", @@ -74,8 +73,10 @@ public function success(Event $name, MigrateSuccessEvent $event): void /** * @noinspection PhpUnusedParameterInspection */ - public function error(Event $name, MigrateErrorEvent $event): void + public function error(Event $name, EventInterface $event): void { + assert($event instanceof MigrateErrorEvent); + $this->output->out( sprintf( '[%s] %s: %s error', diff --git a/src/tools/TraceConsoleOutput.php b/src/tools/TraceConsoleOutput.php index ad34d7a..d835f21 100644 --- a/src/tools/TraceConsoleOutput.php +++ b/src/tools/TraceConsoleOutput.php @@ -10,6 +10,7 @@ use dbschemix\core\event\EventInterface; use dbschemix\core\event\EventSubscriberInterface; use dbschemix\core\event\MigrateSuccessEvent; +use dbschemix\core\event\Subscription; /** * @api @@ -25,24 +26,21 @@ public function subscriptions(): array { $subscriptions = []; foreach (Event::cases() as $event) { - $subscriptions[$event->value] = match ($event) { - Event::MigrateSuccess => $this->success(...), - default => $this->error(...), + $subscriptions[] = match ($event) { + Event::MigrateSuccess => new Subscription($event, $this->success(...)), + default => new Subscription($event, $this->error(...)), }; } - /** - * @var non-empty-array $subscriptions - * @phpstan-ignore varTag.nativeType - */ return $subscriptions; } /** * @noinspection PhpUnusedParameterInspection */ - public function success(Event $name, MigrateSuccessEvent $event): void + public function success(Event $name, EventInterface $event): void { + assert($event instanceof MigrateSuccessEvent); $this->stdout($event->getMessage()); } diff --git a/tests/tools/PrettyConsoleOutputTest.php b/tests/tools/PrettyConsoleOutputTest.php index 1ac46fa..232697b 100644 --- a/tests/tools/PrettyConsoleOutputTest.php +++ b/tests/tools/PrettyConsoleOutputTest.php @@ -4,6 +4,7 @@ namespace dbschemix\migrator\tests\tools; +use Closure; use League\CLImate\CLImate; use League\CLImate\Util\Writer\Buffer; use PHPUnit\Framework\Attributes\CoversClass; @@ -15,6 +16,7 @@ use dbschemix\core\event\MigrateErrorEvent; use dbschemix\core\event\MigrateSuccessEvent; use dbschemix\core\event\ExceptionEvent; +use dbschemix\core\event\Subscription; use dbschemix\migrator\tools\PrettyConsoleOutput; use RuntimeException; @@ -42,6 +44,21 @@ private function makeBufferedClimate(): array return [$climate, $buffer->get(...)]; } + /** + * @param list $subscriptions + * @return Closure(Event, \dbschemix\core\event\EventInterface): void + */ + private static function callbackFor(array $subscriptions, Event $event): Closure + { + foreach ($subscriptions as $subscription) { + if ($subscription->event === $event) { + return $subscription->callback; + } + } + + self::fail("No subscription registered for event {$event->value}"); + } + // ----------------------------------------------------------------------- // subscriptions() // ----------------------------------------------------------------------- @@ -56,13 +73,13 @@ public function subscriptions_covers_every_event_case(): void $subscriptions = $pretty->subscriptions(); // Then - $expectedKeys = array_map(static fn(Event $e): string => $e->value, Event::cases()); - sort($expectedKeys); + $expected = Event::cases(); + sort($expected); - $actualKeys = array_keys($subscriptions); - sort($actualKeys); + $actual = array_map(static fn(Subscription $s): Event => $s->event, $subscriptions); + sort($actual); - self::assertSame($expectedKeys, $actualKeys); + self::assertSame($expected, $actual); } #[Test] @@ -76,7 +93,7 @@ public function subscriptions_maps_migrate_success_to_success_handler(): void // When $subscriptions = $pretty->subscriptions(); - ($subscriptions[Event::MigrateSuccess->value])(Event::MigrateSuccess, $event); + (self::callbackFor($subscriptions, Event::MigrateSuccess))(Event::MigrateSuccess, $event); // Then self::assertStringContainsString('db', $readBuffer()); @@ -97,7 +114,7 @@ public function subscriptions_maps_migrate_error_to_error_handler(): void // When $subscriptions = $pretty->subscriptions(); - ($subscriptions[Event::MigrateError->value])(Event::MigrateError, $event); + (self::callbackFor($subscriptions, Event::MigrateError))(Event::MigrateError, $event); // Then self::assertStringContainsString('error', $readBuffer()); @@ -113,7 +130,7 @@ public function subscriptions_maps_filesystem_notice_to_notice_handler(): void // When $subscriptions = $pretty->subscriptions(); - ($subscriptions[Event::FilesystemNotice->value])(Event::FilesystemNotice, $event); + (self::callbackFor($subscriptions, Event::FilesystemNotice))(Event::FilesystemNotice, $event); // Then self::assertStringContainsString('notice', $readBuffer()); @@ -144,7 +161,7 @@ public function subscriptions_maps_remaining_events_to_failure_handler(): void $subscriptions2 = $pretty2->subscriptions(); // When - ($subscriptions2[$case->value])($case, $event); + (self::callbackFor($subscriptions2, $case))($case, $event); // Then — failure() format contains "error:" $msg = "Event {$case->value} should use failure handler"; diff --git a/tests/tools/TraceConsoleOutputTest.php b/tests/tools/TraceConsoleOutputTest.php index 17d4231..e874c33 100644 --- a/tests/tools/TraceConsoleOutputTest.php +++ b/tests/tools/TraceConsoleOutputTest.php @@ -4,6 +4,7 @@ namespace dbschemix\migrator\tests\tools; +use Closure; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; @@ -11,6 +12,7 @@ use dbschemix\core\event\Event; use dbschemix\core\event\MigrateSuccessEvent; use dbschemix\core\event\MigrateErrorEvent; +use dbschemix\core\event\Subscription; use dbschemix\migrator\tests\Fakes\FakeConsoleOutput; use dbschemix\migrator\tools\TraceConsoleOutput; use RuntimeException; @@ -18,6 +20,21 @@ #[CoversClass(TraceConsoleOutput::class)] final class TraceConsoleOutputTest extends TestCase { + /** + * @param list $subscriptions + * @return Closure(Event, \dbschemix\core\event\EventInterface): void + */ + private static function callbackFor(array $subscriptions, Event $event): Closure + { + foreach ($subscriptions as $subscription) { + if ($subscription->event === $event) { + return $subscription->callback; + } + } + + self::fail("No subscription registered for event {$event->value}"); + } + // ----------------------------------------------------------------------- // subscriptions() // ----------------------------------------------------------------------- @@ -33,13 +50,13 @@ public function subscriptions_covers_every_event_case(): void $subscriptions = $trace->subscriptions(); // Then — every Event case must have a subscription - $expectedKeys = array_map(static fn(Event $e): string => $e->value, Event::cases()); - sort($expectedKeys); + $expected = Event::cases(); + sort($expected); - $actualKeys = array_keys($subscriptions); - sort($actualKeys); + $actual = array_map(static fn(Subscription $s): Event => $s->event, $subscriptions); + sort($actual); - self::assertSame($expectedKeys, $actualKeys); + self::assertSame($expected, $actual); } #[Test] @@ -56,7 +73,7 @@ public function subscriptions_maps_migrate_success_to_success_handler(): void $context = new Context(dbName: 'testdb', filename: 'V1__init.sql', query: 'SELECT 1'); $event = new MigrateSuccessEvent(action: 'up', context: $context); - ($subscriptions[Event::MigrateSuccess->value])(Event::MigrateSuccess, $event); + (self::callbackFor($subscriptions, Event::MigrateSuccess))(Event::MigrateSuccess, $event); self::assertCount(1, $output->lines); // success() writes event->getMessage() which is "[testdb] up: V1__init.sql, vers: 0" @@ -84,7 +101,7 @@ public function subscriptions_maps_non_success_events_to_error_handler(): void $output = new FakeConsoleOutput(); $subscriptions = (new TraceConsoleOutput($output))->subscriptions(); - ($subscriptions[$case->value])($case, $error); + (self::callbackFor($subscriptions, $case))($case, $error); self::assertCount(1, $output->lines, "Expected one writeln for event {$case->value}"); self::assertStringContainsString($error->getName(), $output->lines[0]); self::assertStringContainsString($error->getMessage(), $output->lines[0]);