> */ private $available_definitions = [ // Add new payment method definitions here. CardDefinition::class, AffirmDefinition::class, AfterpayDefinition::class, AlipayDefinition::class, BancontactDefinition::class, BecsDefinition::class, EpsDefinition::class, GiropayDefinition::class, GrabPayDefinition::class, IdealDefinition::class, LinkDefinition::class, MultibancoDefinition::class, KlarnaDefinition::class, P24Definition::class, SepaDefinition::class, SofortDefinition::class, WechatPayDefinition::class, ApplePayDefinition::class, GooglePayDefinition::class, ]; /** * Payment method definitions that have been registered for use. * * @var array> */ private $payment_methods = []; /** * Constructor is private to enforce singleton pattern. */ private function __construct() {} /** * Get the singleton instance. * * @return PaymentMethodDefinitionRegistry */ public static function instance(): self { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Initialize the registry by registering all available payment method definitions. * * @return void */ public function init(): void { foreach ( $this->available_definitions as $definition ) { $this->register_payment_method( $definition ); } // When Amazon Pay is promoted from feature flag, we can register it directly in the `available_definitions` array. if ( \WC_Payments_Features::is_amazon_pay_enabled() ) { $this->register_payment_method( AmazonPayDefinition::class ); } } /** * Get all available payment method definitions. * * @return array> Array of payment method definition class names. */ public function get_available_definitions(): array { return $this->available_definitions; } /** * Register a payment method definition. * * @param class-string $definition_class The payment method definition class to register. * @throws \InvalidArgumentException If the class does not exist or does not implement PaymentMethodDefinitionInterface. */ public function register_payment_method( $definition_class ): void { if ( ! class_exists( $definition_class ) ) { throw new \InvalidArgumentException( sprintf( 'Payment method definition class "%s" does not exist.', $definition_class ) ); } $interfaces = class_implements( $definition_class ); if ( ! isset( $interfaces[ PaymentMethodDefinitionInterface::class ] ) ) { throw new \InvalidArgumentException( sprintf( 'Payment method definition class "%s" must implement %s.', $definition_class, PaymentMethodDefinitionInterface::class ) ); } /** * Ensure type safety for the payment method definition class. * * @var class-string $definition_class */ $this->payment_methods[ $definition_class::get_id() ] = $definition_class; } /** * Get all registered payment method definitions. * * @return class-string[] All registered payment method definition classes. */ public function get_all_payment_method_definitions(): array { return $this->payment_methods; } /** * Get all available payment method definitions for a given account and currency. * * @param string $account_country The account country. * @param string $currency The currency. * @return string[] All available payment method definition classes. */ public function get_available_payment_method_definitions( string $account_country, string $currency ): array { return array_filter( $this->payment_methods, function ( $definition_class ) use ( $account_country, $currency ) { return $definition_class::is_available_for( $currency, $account_country ); } ); } }