steppedAside(); } $skin = SkinRegistry::get( '' !== $skinId ? $skinId : SkinRegistry::current() ); if ( null === $skin ) { return ''; } ob_start(); $this->output( $purpose, $skinId, $returnTo ); return (string) ob_get_clean(); } /** * Print the widget where the page is being built. * * The skin's template escapes every value it prints, so printing it directly * keeps the escaping at the point of output; {@see self::render()} is the * same thing captured into a string, for shortcodes and blocks that return it. * * @param string $purpose One of the PURPOSE_* constants. * @param string $skinId Skin to render with; empty uses the chosen one. * @param string $returnTo Where to go after signing in; empty lets the server decide. */ public function output( string $purpose, string $skinId = '', string $returnTo = '' ): void { if ( Failsafe::isActive() ) { echo wp_kses_post( $this->steppedAside() ); return; } $skin = SkinRegistry::get( '' !== $skinId ? $skinId : SkinRegistry::current() ); if ( null === $skin ) { return; } $rk = $this->config( $purpose, $skin['id'], $returnTo ); // The skin's template sees `$rk` (this configuration) and `$uid`, a // per-widget id prefix for label/field pairs. $uid = 'rahkar-login-' . wp_unique_id(); include $skin['path'] . 'widget.php'; } /** * Enqueue the stylesheets and script, for places that render with the page. * * The embedded panel does not use this: themes like Woodmart put a login form * on every page, and {@see LoginPanel} loads these on first use instead. * * @param string $skinId Skin in use; empty uses the chosen one. */ public function enqueue( string $skinId = '' ): void { foreach ( self::styleUrls( $skinId ) as $handle => $url ) { wp_enqueue_style( $handle, $url, [], RAHKAR_WP_VERSION ); // The shop's design tokens ride along with the first of our stylesheets // to load; see Tokens::attach(). Tokens::attach( $handle ); } wp_enqueue_script( 'rahkar-login', self::scriptUrl(), [], RAHKAR_WP_VERSION, true ); } /** * The shared stylesheet and the skin's, keyed by handle. * * @param string $skinId Skin in use; empty uses the chosen one. * * @return array */ public static function styleUrls( string $skinId = '' ): array { $skin = SkinRegistry::get( '' !== $skinId ? $skinId : SkinRegistry::current() ); $styles = [ 'rahkar-login' => RAHKAR_WP_URL . 'assets/dist/rahkar-login.css' ]; if ( null !== $skin ) { $styles[ 'rahkar-login-skin-' . $skin['id'] ] = $skin['url'] . 'skin.css'; } return $styles; } /** * The widget script. */ public static function scriptUrl(): string { return RAHKAR_WP_URL . 'assets/dist/rahkar-login.js'; } /** * The configuration a widget carries. * * @param string $purpose One of the PURPOSE_* constants. * @param string $skinId Skin id. * @param string $returnTo Where to go after signing in. * * @return array */ public function config( string $purpose, string $skinId, string $returnTo = '' ): array { $allowEmail = OtpAuthModule::IDENTIFIER_MOBILE_EMAIL === OtpAuthModule::identifier(); return [ 'purpose' => $purpose, 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => AuthController::nonce(), 'returnTo' => $returnTo, 'skin' => [ 'id' => $skinId, 'accent' => SkinRegistry::accent(), ], 'options' => [ // One field for both: an address goes to the password step, a // number to the code step. 'allowEmail' => $allowEmail, 'voice' => (bool) Settings::get( OtpAuthModule::SLUG . '.voice_enabled', false ) && OtpDispatcher::canCall(), // Where "Back" leads from the first step, for a skin that offers it // there. Empty everywhere the plugin renders the form itself: the // login page already has "back to the shop" under the card (or the // theme's header around it), and a theme form or the checkout must // not be left from its first field. 'homeUrl' => '', 'forgotUrl' => wp_lostpassword_url(), 'codeLength' => (int) Settings::get( OtpAuthModule::SLUG . '.code_length', 6 ), 'cooldown' => (int) Settings::get( OtpAuthModule::SLUG . '.resend_after', 60 ), 'askName' => (bool) Settings::get( OtpAuthModule::SLUG . '.ask_name', true ), ], 'i18n' => $this->strings( $allowEmail ), ]; } /** * Every string the widget shows. * * @param bool $allowEmail Whether the form takes an email address too. * * @return array */ private function strings( bool $allowEmail ): array { $shop = (string) get_bloginfo( 'name' ); return [ 'titlePhone' => '' !== $shop /* translators: %s: store name */ ? sprintf( __( 'ورود یا ثبت‌نام در %s', 'rahkar-toolkit' ), $shop ) : __( 'ورود یا ثبت‌نام', 'rahkar-toolkit' ), 'titlePassword' => __( 'رمز عبور را وارد کنید', 'rahkar-toolkit' ), /* translators: %phone%: the masked mobile number */ 'titleCode' => __( 'کد ارسال‌شده به %phone% را وارد کنید', 'rahkar-toolkit' ), /* translators: %phone%: the masked mobile number */ 'titleCodeVoice' => __( 'کدی را که در تماس با %phone% خوانده شد وارد کنید', 'rahkar-toolkit' ), 'titleName' => __( 'شما را چه صدا کنیم؟', 'rahkar-toolkit' ), 'intro' => $allowEmail ? __( 'شماره موبایل یا ایمیل خود را وارد کنید.', 'rahkar-toolkit' ) : __( 'شماره موبایل خود را وارد کنید. اگر حساب نداشته باشید، برایتان ساخته می‌شود.', 'rahkar-toolkit' ), 'back' => __( 'بازگشت', 'rahkar-toolkit' ), 'phoneLabel' => __( 'شماره موبایل', 'rahkar-toolkit' ), 'phonePlaceholder' => '09123456789', 'phoneInvalid' => __( 'یک شماره موبایل معتبر وارد کنید، مثلاً ۰۹۱۲۳۴۵۶۷۸۹.', 'rahkar-toolkit' ), 'identifierLabel' => __( 'شماره موبایل یا ایمیل', 'rahkar-toolkit' ), 'identifierInvalid' => __( 'یک شماره موبایل یا نشانی ایمیل معتبر وارد کنید.', 'rahkar-toolkit' ), 'continue' => __( 'ادامه', 'rahkar-toolkit' ), 'phoneSending' => __( 'در حال ارسال کد…', 'rahkar-toolkit' ), 'passwordLabel' => __( 'رمز عبور', 'rahkar-toolkit' ), 'passwordRequired' => __( 'رمز عبور را وارد کنید.', 'rahkar-toolkit' ), 'passwordSubmit' => __( 'ورود', 'rahkar-toolkit' ), /* translators: %email%: the email address */ 'passwordFor' => __( 'ورود با %email%', 'rahkar-toolkit' ), 'forgotPassword' => __( 'رمز عبور را فراموش کرده‌اید؟', 'rahkar-toolkit' ), 'noAccountHint' => __( 'حساب ندارید؟ برگردید و شماره موبایل خود را وارد کنید.', 'rahkar-toolkit' ), 'changeIdentifier' => __( 'شماره یا ایمیل دیگر', 'rahkar-toolkit' ), 'codeLabel' => __( 'کد تأیید', 'rahkar-toolkit' ), /* translators: %phone%: the masked mobile number */ 'codeHint' => __( 'کد به %phone% پیامک شد.', 'rahkar-toolkit' ), /* translators: %phone%: the masked mobile number */ 'codeHintVoice' => __( 'در حال تماس با %phone% برای خواندن کد هستیم.', 'rahkar-toolkit' ), 'codeSubmit' => __( 'ورود', 'rahkar-toolkit' ), 'codeRequired' => __( 'کدی را که دریافت کرده‌اید وارد کنید.', 'rahkar-toolkit' ), 'codeChecking' => __( 'در حال بررسی…', 'rahkar-toolkit' ), 'codeVerified' => __( 'وارد شدید. در حال انتقال…', 'rahkar-toolkit' ), 'resend' => __( 'ارسال دوباره کد', 'rahkar-toolkit' ), /* translators: %seconds%: seconds left */ 'resendIn' => __( 'ارسال دوباره تا %seconds% ثانیه دیگر', 'rahkar-toolkit' ), /* translators: %time%: a m:ss countdown */ 'resendInClock' => __( '%time% تا امکان درخواست کد جدید', 'rahkar-toolkit' ), 'voice' => __( 'دریافت کد با تماس تلفنی', 'rahkar-toolkit' ), 'voiceCalling' => __( 'در حال برقراری تماس…', 'rahkar-toolkit' ), 'changeNumber' => __( 'تغییر شماره', 'rahkar-toolkit' ), 'firstName' => __( 'نام', 'rahkar-toolkit' ), 'lastName' => __( 'نام خانوادگی', 'rahkar-toolkit' ), 'nameRequired' => __( 'نام و نام خانوادگی را وارد کنید.', 'rahkar-toolkit' ), 'nameSaving' => __( 'در حال ذخیره…', 'rahkar-toolkit' ), 'nameSubmit' => __( 'ادامه', 'rahkar-toolkit' ), 'genericError' => __( 'مشکلی پیش آمد. لطفاً دوباره تلاش کنید.', 'rahkar-toolkit' ), /* translators: %code%: the code */ 'testModeNotice' => __( 'حالت آزمایشی: پیامی ارسال نشد. کد شما %code% است.', 'rahkar-toolkit' ), ]; } /** * What stands in for the form while the failsafe holds. * * Points at the account page, where the theme's email-and-password form is * shown in the meantime — the "my account" redirect to the login page is * suspended for as long as this lasts. */ private function steppedAside(): string { $account = function_exists( 'wc_get_page_permalink' ) ? (string) wc_get_page_permalink( 'myaccount' ) : wp_login_url(); return sprintf( '', esc_html__( 'ورود با کد پیامکی موقتاً در دسترس نیست. لطفاً با ایمیل و رمز عبور وارد شوید.', 'rahkar-toolkit' ), esc_url( $account ), esc_html__( 'ورود با رمز عبور', 'rahkar-toolkit' ) ); } }