}> */ public static function serviceInterfaces(): iterable { yield 'auth service vocabulary' => [ AuthServiceInterface::class, ['checkRateLimit', 'recordFailure', 'resetRateLimit', 'checkPasswordResetRateLimit', 'recordPasswordResetAttempt', 'authenticate', 'changePassword', 'isLoggedIn', 'login', 'logout'], ]; yield 'password reset service vocabulary' => [ PasswordResetServiceInterface::class, ['requestReset', 'validateToken', 'resetPassword'], ]; yield 'authorization service vocabulary' => [ AuthorizationServiceInterface::class, ['canRole', 'canUser', 'permissionsForRole'], ]; yield 'settings service vocabulary' => [ SettingsServiceInterface::class, ['all', 'delete', 'get', 'getBool', 'getInt', 'getString', 'has', 'set'], ]; yield 'audit log service vocabulary' => [ AuditLogServiceInterface::class, ['listRecent', 'record'], ]; yield 'notification service vocabulary' => [ NotificationServiceInterface::class, ['recent', 'send', 'sendTemplate'], ]; yield 'taxonomy service vocabulary' => [ TaxonomyServiceInterface::class, ['findAll', 'findPaginated', 'findById', 'findBySlug', 'create', 'delete'], ]; yield 'media service vocabulary' => [ MediaServiceInterface::class, ['findAll', 'findPaginated', 'findByUserId', 'findByUserIdPaginated', 'findById', 'store', 'getUsageSummary', 'getUsageSummaries', 'delete'], ]; yield 'user service vocabulary' => [ UserServiceInterface::class, ['findAll', 'findPaginated', 'findById', 'delete', 'deleteFromAdministration', 'updateRole', 'updateRoleFromAdministration', 'create'], ]; } #[\PHPUnit\Framework\Attributes\DataProvider('serviceInterfaces')] public function testApplicationServiceInterfacesExposeAnExplicitVocabulary(string $interface, array $expectedMethods): void { $reflection = new \ReflectionClass($interface); $methods = array_values(array_map( static fn (\ReflectionMethod $method): string => $method->getName(), $reflection->getMethods(\ReflectionMethod::IS_PUBLIC), )); sort($methods); $expected = $expectedMethods; sort($expected); self::assertSame( $expected, $methods, sprintf('%s must keep its agreed application vocabulary to stay aligned with the other modules.', $interface), ); } }