containerRegistrars as $registrar) { self::assertTrue( class_exists($registrar), "Module '{$module['id']}' declares container_registrar '{$registrar}' but class does not exist" ); } } } public function testSearchProviderClassesImplementContract(): void { foreach (self::$modules as $module) { foreach ($module['manifest']->searchResources as $providerClass) { self::assertTrue( class_exists($providerClass), "Module '{$module['id']}' search provider '{$providerClass}' class not found" ); $provider = new $providerClass(); self::assertInstanceOf( SearchResourceProvider::class, $provider, "Module '{$module['id']}' search provider must implement SearchResourceProvider" ); } } } public function testLayoutContextProviderClassesImplementContract(): void { foreach (self::$modules as $module) { foreach ($module['manifest']->layoutContextProviders as $providerClass) { self::assertTrue( class_exists($providerClass), "Module '{$module['id']}' layout context provider '{$providerClass}' class not found" ); $provider = new $providerClass(); self::assertInstanceOf( LayoutContextProvider::class, $provider, "Module '{$module['id']}' layout context provider must implement LayoutContextProvider" ); } } } public function testSessionProviderClassesImplementContract(): void { foreach (self::$modules as $module) { foreach ($module['manifest']->sessionProviders as $providerClass) { self::assertTrue( class_exists($providerClass), "Module '{$module['id']}' session provider '{$providerClass}' class not found" ); $provider = new $providerClass(); self::assertInstanceOf( SessionProvider::class, $provider, "Module '{$module['id']}' session provider must implement SessionProvider" ); } } } public function testAuthorizationPolicyClassesImplementContract(): void { foreach (self::$modules as $module) { foreach ($module['manifest']->authorizationPolicies as $policyClass) { self::assertTrue( class_exists($policyClass), "Module '{$module['id']}' authorization policy '{$policyClass}' class not found" ); self::assertTrue( is_subclass_of($policyClass, AuthorizationPolicyInterface::class) || in_array(AuthorizationPolicyInterface::class, class_implements($policyClass) ?: [], true), "Module '{$module['id']}' authorization policy must implement AuthorizationPolicyInterface" ); } } } public function testEventListenerClassesImplementContract(): void { foreach (self::$modules as $module) { foreach ($module['manifest']->eventListeners as $eventName => $handlers) { foreach ($handlers as $index => $handler) { $class = $handler['class']; self::assertTrue( class_exists($class), "Module '{$module['id']}' event_listeners['{$eventName}'][{$index}] class '{$class}' not found" ); self::assertTrue( is_subclass_of($class, EventListener::class) || in_array(EventListener::class, class_implements($class) ?: [], true), "Module '{$module['id']}' event_listeners['{$eventName}'][{$index}] class '{$class}' " . "must implement EventListener interface" ); } } } self::addToAssertionCount(1); } public function testDeactivationHandlerClassImplementsContract(): void { foreach (self::$modules as $module) { $handler = $module['manifest']->deactivationHandler; if ($handler === null) { continue; } self::assertTrue( class_exists($handler), "Module '{$module['id']}' deactivation_handler class '{$handler}' not found" ); self::assertTrue( is_subclass_of($handler, ModuleDeactivationHandler::class) || in_array(ModuleDeactivationHandler::class, class_implements($handler) ?: [], true), "Module '{$module['id']}' deactivation_handler class '{$handler}' " . "must implement ModuleDeactivationHandler interface" ); } self::addToAssertionCount(1); } }