routes(); }, 9 ); if ( is_admin() ) { $settings = new Settings(); $providers = new ProviderRegistry( $settings ); ( new SettingsPage( $settings, $providers ) )->register(); ( new \Anar\Login\Admin\FeaturesPage() )->register(); ( new \Anar\Login\Commerce\Admin( new \Anar\Login\Commerce\Settings(), new \Anar\Login\Commerce\Repository(), $providers ) )->register(); ( new \Anar\Login\Commerce\Privacy( new \Anar\Login\Commerce\Repository(), new \Anar\Login\Commerce\Settings() ) )->register(); ( new \Anar\Login\Marketing\Privacy() )->register(); if ( class_exists( 'WooCommerce' ) ) { ( new \Anar\Login\Marketing\Admin() )->register(); } } } public function runtime() { $flags = \Anar\Login\Infrastructure\Features::all(); foreach ( array( 'login' => array( 'anar_login', 'anar_account', 'anar_login_button' ), 'reset' => array( 'anar_reset_password' ), 'recovery' => array( 'anar_cart_reminders', 'anar_recover_cart' ), 'games' => array( 'anar_game', 'anar_games' ), 'birthday' => array( 'anar_customer_preferences' ), 'referral' => array( 'anar_referrals' ) ) as $key => $shortcodes ) { if ( ! $flags[ $key ] ) { foreach ( $shortcodes as $shortcode ) { add_shortcode( $shortcode, '__return_empty_string' ); } } } // Historic opt-out links remain usable independently of a feature's runtime switch. // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Query presence only; each handler verifies its HMAC and POST nonce. if ( isset( $_GET['ar'] ) ) { add_action( 'template_redirect', static function () { ( new \Anar\Login\Commerce\Module( new \Anar\Login\Commerce\Settings(), new \Anar\Login\Commerce\Repository() ) )->link_page(); }, 0 ); } if ( isset( $_GET['am'] ) ) { add_action( 'template_redirect', static function () { ( new \Anar\Login\Marketing\Frontend( new \Anar\Login\Marketing\Settings(), new \Anar\Login\Marketing\Repository() ) )->route(); }, 0 ); } // phpcs:enable WordPress.Security.NonceVerification.Recommended $settings = $flags['login'] || $flags['reset'] || $flags['two_factor'] || \Anar\Login\Infrastructure\Features::queue_needed() ? new Settings() : null; if ( $flags['login'] || $flags['reset'] || $flags['two_factor'] ) { $codes = new OtpRepository(); $limiter = new RateLimiter( $settings ); $providers = new ProviderRegistry( $settings ); if ( $flags['reset'] ) { ( new \Anar\Login\Auth\PasswordRecovery( $settings, $codes, $limiter, $providers ) )->register(); } if ( $flags['login'] || $flags['two_factor'] ) { $users = new UserService( $settings ); $otp = new OtpService( $settings, $codes, $limiter, $providers, $users ); if ( $flags['two_factor'] ) { ( new TwoFactor( $settings, $otp, $users ) )->register(); } } if ( $flags['login'] ) { $google = $settings->get( 'google_enabled', 0 ) ? new GoogleAuth( $settings, $users, $limiter ) : null; $shortcodes = new Shortcodes( $settings ); $shortcodes->register(); ( new AuthController( $otp, $google, $settings ) )->register(); ( new ProfileController( $users ) )->register(); ( new Popup( $settings, $shortcodes ) )->register(); ( new WpLogin( $settings, $shortcodes ) )->register(); if ( $settings->get( 'replace_theme_login', 1 ) && WoodMart::active() ) { ( new WoodMart() )->register(); } if ( class_exists( 'WooCommerce' ) ) { ( new WooCommerce( $settings ) )->register(); } } } if ( $flags['login_log'] ) { add_action( 'anar_toolkit_sms_result', static function ( $recipient, $context, $provider, $result ) { ( new \Anar\Login\Commerce\Repository() )->sms_result( $recipient, $context, $provider, $result ); }, 10, 4 ); } if ( ! class_exists( 'WooCommerce' ) ) { return; } if ( $flags['recovery'] || $flags['orders'] || \Anar\Login\Infrastructure\Features::queue_needed() ) { $commerce = new \Anar\Login\Commerce\Settings(); $repo = new \Anar\Login\Commerce\Repository(); $module = new \Anar\Login\Commerce\Module( $commerce, $repo ); if ( $flags['recovery'] || $flags['orders'] ) { $module->register(); } if ( $flags['recovery'] && 'automatic' === $commerce->get( 'capture_mode' ) ) { ( new \Anar\Login\Commerce\AutomaticCapture( $commerce, $module ) )->register(); } if ( $flags['orders'] ) { ( new \Anar\Login\Commerce\OrderEvents( $commerce, $repo ) )->register(); } if ( \Anar\Login\Infrastructure\Features::queue_needed() ) { ( new \Anar\Login\Commerce\Worker( $commerce, $repo, $module, new \Anar\Login\Messaging\NotificationSender( $settings, new \Anar\Login\Messaging\HttpClient() ) ) )->register(); } } // Existing personal coupons keep their restrictions even if their creating module is stopped. add_filter( 'woocommerce_coupon_is_valid', static function ( $valid, $coupon ) { if ( ! $coupon->get_meta( '_anar_phone_hash' ) ) { return $valid; } return ( new \Anar\Login\Commerce\Coupons( new \Anar\Login\Commerce\Settings(), new \Anar\Login\Commerce\Repository() ) )->valid( $valid, $coupon ); }, 10, 2 ); $validate = static function ( $order ) { if ( $order->get_coupon_codes() ) { ( new \Anar\Login\Commerce\Coupons( new \Anar\Login\Commerce\Settings(), new \Anar\Login\Commerce\Repository() ) )->validate_order( $order ); } }; add_action( 'woocommerce_checkout_create_order', $validate, 20 ); add_action( 'woocommerce_store_api_checkout_update_order_from_request', $validate, 20 ); if ( ! \Anar\Login\Infrastructure\Features::marketing() ) { return; } $marketing = new \Anar\Login\Marketing\Settings(); $repository = new \Anar\Login\Marketing\Repository(); if ( \Anar\Login\Infrastructure\Features::facts_needed() || \Anar\Login\Infrastructure\Features::queue_needed() ) { ( new \Anar\Login\Marketing\Engine( $marketing, $repository ) )->register(); } if ( $flags['stock'] || $flags['birthday'] || $flags['survey'] || \Anar\Login\Infrastructure\Features::queue_needed() ) { ( new \Anar\Login\Marketing\Frontend( $marketing, $repository ) )->register(); } if ( $flags['invoice'] ) { ( new \Anar\Login\Marketing\Invoices() )->register(); } if ( $flags['games'] ) { ( new \Anar\Login\Marketing\Games() )->register(); } if ( $flags['referral'] ) { ( new \Anar\Login\Marketing\Referrals() )->register(); } if ( $flags['traffic'] ) { ( new \Anar\Login\Marketing\Insights() )->register(); } } public function cleanup() { ( new OtpRepository() )->cleanup(); RateLimiter::cleanup(); ( new \Anar\Login\Commerce\Repository() )->cleanup( (int) ( new \Anar\Login\Commerce\Settings() )->get( 'retention' ) ); ( new \Anar\Login\Marketing\Engine( new \Anar\Login\Marketing\Settings(), new \Anar\Login\Marketing\Repository() ) )->cleanup(); } /** * Load translations and run pending upgrades. * * @return void */ public function init() { // Register the bundled fallback; WordPress keeps global language packs first. load_plugin_textdomain( 'anar-toolkit', false, dirname( plugin_basename( ANAR_LOGIN_FILE ) ) . '/languages' ); if ( ANAR_LOGIN_VERSION !== get_option( 'anar_login_db_version' ) ) { Activator::activate(); } $features = (array) get_option( \Anar\Login\Infrastructure\Features::OPTION, array() ); if ( empty( $features['_snapshot'] ) ) { \Anar\Login\Infrastructure\Features::refresh(); } } /** * Prevent direct construction. */ private function __construct() {} }