From 432c8a010a7b055b2cab93c4a2aeae6a40fb8228 Mon Sep 17 00:00:00 2001 From: Divarion-D Date: Wed, 24 Jun 2026 22:18:52 +0300 Subject: [PATCH] =?UTF-8?q?chore(psr4):=20phase=203=20(Core)=20=E2=80=94?= =?UTF-8?q?=20namespace=20Core/Events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move Core/Events into XcVm\Core\Events and its sub-trees: \Contract (StoppableEventInterface), \Auth, \Module, \Settings, \Stream (the event classes), plus root EventDispatcher, ListenerProvider, ListensTo, AbstractEvent. - Namespace 14 files across 6 namespaces; cross-namespace refs imported via use (AbstractEvent/EventDispatcher → Contract\StoppableEventInterface; Stream events → root AbstractEvent). Built-in \Attribute (ListensTo) and ioncube \XC_VM (PackageInstalledEvent) qualified. - Rewrite 'use ListensTo;' → FQCN; add use to referrers across src/ and tests/; fix leading-backslash refs (\EventDispatcher, \ListensTo, \PackageInstalledEvent from the Module commit) to their FQCNs. - Tests: add real top-level use imports to ModuleLoaderBootTest (EventDispatcher) and ListensToAttributeTest (ListensTo) — the use-inserter skipped/mis-placed them due to a namespace() method and a heredoc fixture already containing the FQCN. - phpstan-baseline.neon regenerated (292→292). Completes Core/Container + Core/Events. Verified: php -l clean; PHPStan no errors; PHPUnit 295/295; EventDispatcher resolves and AbstractEvent implements XcVm\Core\Events\Contract\StoppableEventInterface. --- src/Core/Events/AbstractEvent.php | 3 +++ .../Events/Auth/UserAuthenticatedEvent.php | 2 ++ src/Core/Events/Auth/UserLoggedOutEvent.php | 2 ++ .../Contract/StoppableEventInterface.php | 2 ++ src/Core/Events/EventDispatcher.php | 3 +++ src/Core/Events/ListenerProvider.php | 2 ++ src/Core/Events/ListensTo.php | 2 ++ src/Core/Events/Module/ModuleBootedEvent.php | 2 ++ src/Core/Events/Module/ModuleLoadedEvent.php | 2 ++ .../Events/Module/PackageInstalledEvent.php | 2 ++ .../Events/Settings/SettingsChangedEvent.php | 2 ++ src/Core/Events/Stream/StreamStartedEvent.php | 2 ++ .../Events/Stream/StreamStartingEvent.php | 3 +++ src/Core/Events/Stream/StreamStoppedEvent.php | 2 ++ src/Core/Module/ModuleLoader.php | 26 ++++++++++--------- src/Core/Module/ModuleManager.php | 8 +++--- src/bootstrap.php | 1 + tests/Unit/ComposerDiscoveryTest.php | 1 + tests/Unit/EventDispatcherTest.php | 3 +++ tests/Unit/InterfaceContractTest.php | 2 ++ tests/Unit/ListensToAttributeTest.php | 10 ++++--- tests/Unit/ModuleLoaderBootTest.php | 1 + tests/Unit/ModuleLoaderPsr4ResolverTest.php | 1 + 23 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/Core/Events/AbstractEvent.php b/src/Core/Events/AbstractEvent.php index 6fce3665..aca1539e 100644 --- a/src/Core/Events/AbstractEvent.php +++ b/src/Core/Events/AbstractEvent.php @@ -1,5 +1,8 @@ callable] or ['EventClass' => [callable, $priority]] * - * 2. #[\ListensTo] attribute — declarative PHP 8.1 attribute on public methods: - * #[\ListensTo(SomeEvent::class, priority: 10)] + * 2. #[\XcVm\Core\Events\ListensTo] attribute — declarative PHP 8.1 attribute on public methods: + * #[\XcVm\Core\Events\ListensTo(SomeEvent::class, priority: 10)] * public function onSome(SomeEvent $e): void { ... } * * Both paths are additive — using one does not disable the other. * - * If the event class named in a #[\ListensTo] attribute does not exist at + * If the event class named in a #[\XcVm\Core\Events\ListensTo] attribute does not exist at * registration time the listener is silently skipped (graceful degradation). * * @param ServiceProviderInterface $module @@ -625,9 +627,9 @@ class ModuleLoader { * @return void */ private function registerEventSubscribers(ServiceProviderInterface $module, \XcVm\Core\Container\ServiceContainer $container): void { - // Verify the container holds an actual \EventDispatcher instance (not just the class name). - // Static calls below route to the same instance via \EventDispatcher::getInstance(). - if (!$container->has('events') || !$container->get('events') instanceof \EventDispatcher) { + // Verify the container holds an actual \XcVm\Core\Events\EventDispatcher instance (not just the class name). + // Static calls below route to the same instance via \XcVm\Core\Events\EventDispatcher::getInstance(). + if (!$container->has('events') || !$container->get('events') instanceof \XcVm\Core\Events\EventDispatcher) { return; } @@ -636,22 +638,22 @@ class ModuleLoader { foreach ($subscribers as $event => $handler) { if (is_array($handler) && isset($handler[0]) && is_callable($handler[0])) { // [callable, int $priority] tuple — new PSR-14 style - \EventDispatcher::listen($event, $handler[0], $handler[1] ?? 0); + \XcVm\Core\Events\EventDispatcher::listen($event, $handler[0], $handler[1] ?? 0); } else { // Legacy: string event name or class-string, plain callable - \EventDispatcher::listen($event, $handler); + \XcVm\Core\Events\EventDispatcher::listen($event, $handler); } } - // ── 2. #[\ListensTo] attribute scan via Reflection ───────────────── + // ── 2. #[\XcVm\Core\Events\ListensTo] attribute scan via Reflection ───────────────── $reflection = new \ReflectionClass($module); foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { - $attributes = $method->getAttributes(\ListensTo::class); + $attributes = $method->getAttributes(\XcVm\Core\Events\ListensTo::class); if (empty($attributes)) { continue; } foreach ($attributes as $attribute) { - /** @var \ListensTo $listensTo */ + /** @var \XcVm\Core\Events\ListensTo $listensTo */ $listensTo = $attribute->newInstance(); // Graceful degradation: skip if the event class is not (yet) loadable. @@ -659,7 +661,7 @@ class ModuleLoader { continue; } - \EventDispatcher::listen( + \XcVm\Core\Events\EventDispatcher::listen( $listensTo->eventClass, [$module, $method->getName()], $listensTo->priority, diff --git a/src/Core/Module/ModuleManager.php b/src/Core/Module/ModuleManager.php index ee7a90b0..21fc00a8 100644 --- a/src/Core/Module/ModuleManager.php +++ b/src/Core/Module/ModuleManager.php @@ -1,6 +1,8 @@ installModule($slug, $resolvedVersion); - \EventDispatcher::dispatch(new \PackageInstalledEvent( + \XcVm\Core\Events\EventDispatcher::dispatch(new \XcVm\Core\Events\Module\PackageInstalledEvent( slug: $result['module'], version: $resolvedVersion, path: $modulePath, @@ -760,7 +762,7 @@ class ModuleManager { public function deployFromPlatformFilesOnly(string $slug, string $version, ?string $apiKey = null): void { $result = $this->pullFilesFromPlatform($slug, $version, $apiKey); - \EventDispatcher::dispatch(new \PackageInstalledEvent( + \XcVm\Core\Events\EventDispatcher::dispatch(new \XcVm\Core\Events\Module\PackageInstalledEvent( slug: $result['module'], version: $result['version'], path: $result['path'], diff --git a/src/bootstrap.php b/src/bootstrap.php index 9c5ec7cd..c74066f1 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -54,6 +54,7 @@ */ declare(strict_types=0); +use XcVm\Core\Events\EventDispatcher; use XcVm\Core\Container\ServiceContainer; use XcVm\Core\Database\Database; use XcVm\Core\Database\DatabaseHandler; diff --git a/tests/Unit/ComposerDiscoveryTest.php b/tests/Unit/ComposerDiscoveryTest.php index a3fc3cc3..859fd9ab 100644 --- a/tests/Unit/ComposerDiscoveryTest.php +++ b/tests/Unit/ComposerDiscoveryTest.php @@ -1,5 +1,6 @@