/Provider.php mit Klasse * Payments\Providers\\Provider * Beispiel: module 'paypal_v2' -> Payments\Providers\PaypalV2\Provider * * Neuer Anbieter = neues Verzeichnis, sonst nichts. */ final class Registry { /** @var array */ private static array $cache = []; public static function has(string $module): bool { $module = self::clean($module); return $module !== '' && \is_file(self::dir($module) . '/Provider.php'); } public static function get(string $module, object $base): ?ProviderInterface { $module = self::clean($module); if ($module === '') { return null; } if (\array_key_exists($module, self::$cache)) { return self::$cache[$module]; } $file = self::dir($module) . '/Provider.php'; if (!\is_file($file)) { return self::$cache[$module] = null; } self::requireCore(); require_once $file; $class = 'Payments\\Providers\\' . self::studly($module) . '\\Provider'; if (!\class_exists($class)) { \error_log('Payments: Provider-Klasse fehlt: ' . $class); return self::$cache[$module] = null; } $p = new $class($base); return self::$cache[$module] = ($p instanceof ProviderInterface ? $p : null); } /** Alle installierten Anbieter (fuer Backend-Liste und Abgleicher). @return list */ public static function all(): array { $out = []; foreach (\glob(__DIR__ . '/providers/*/Provider.php') ?: [] as $f) { $out[] = \basename(\dirname($f)); } \sort($out); return $out; } public static function requireCore(): void { foreach (['ProviderInterface', 'Result', 'Secrets', 'Log', 'Overview', 'AbstractProvider'] as $c) { require_once __DIR__ . '/' . $c . '.php'; } } private static function dir(string $module): string { return __DIR__ . '/providers/' . $module; } private static function clean(string $module): string { return \preg_match('/^[a-z0-9_]+$/', $module) ? $module : ''; } private static function studly(string $module): string { return \str_replace('_', '', \ucwords($module, '_')); } } // Wer die Registry laedt, bekommt die Kernklassen gleich mit (Secrets, Log, Result ...), // nicht erst beim ersten Provider. Sonst faellt z.B. der Zahlart-Editor um, der nur // Secrets braucht. Registry::requireCore();