self::SLUG, 'tab' => $tab ), $args ), admin_url( 'admin.php' ) ); } /** Хук страницы плагина (страница внутри пункта WP-ADDON). */ public static function hook() { return PRPS_Wpaddon_Menu::hook( self::SLUG ); } public static function menu() { PRPS_Wpaddon_Menu::add_page( __( 'Вход 406-ФЗ', 'propusk' ), __( 'Вход 406-ФЗ', 'propusk' ), self::SLUG, array( __CLASS__, 'render' ) ); } public static function action_links( $links ) { array_unshift( $links, '' . esc_html__( 'Настройки', 'propusk' ) . '' ); if ( ! PRPS_Plugin::has_pro_addon() ) { $links[] = 'Pro'; } return $links; } public static function assets( $hook ) { if ( self::hook() !== $hook && 'users.php' !== $hook ) { return; } wp_enqueue_style( 'prps-admin', PRPS_URL . 'assets/css/admin.css', array(), PRPS_VERSION ); if ( 'users.php' === $hook ) { return; } wp_enqueue_script( 'prps-admin', PRPS_URL . 'assets/js/admin.js', array(), PRPS_VERSION, true ); wp_localize_script( 'prps-admin', 'prpsAdmin', array( 'ajax' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'prps_admin' ), 'i18n' => array( 'checking' => __( 'Проверяю…', 'propusk' ), 'copied' => __( 'Скопировано', 'propusk' ), 'error' => __( 'Ошибка запроса. Попробуйте ещё раз.', 'propusk' ), ), ) ); } public static function notices() { $screen = get_current_screen(); if ( ! $screen || self::hook() !== $screen->id ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['prps_saved'] ) ) { echo '

' . esc_html__( 'Настройки сохранены.', 'propusk' ) . '

'; } } /* ===================================================================== * Сохранение настроек * =================================================================== */ public static function save() { if ( empty( $_POST['prps_tab'] ) || ! current_user_can( self::CAP ) ) { return; } $tab = sanitize_key( wp_unslash( $_POST['prps_tab'] ) ); check_admin_referer( 'prps_save_' . $tab ); $post = map_deep( wp_unslash( $_POST ), 'sanitize_text_field' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- очищается map_deep(). $s = PRPS_Settings::all(); if ( 'phone' === $tab ) { $s['phone'] = empty( $post['phone'] ) ? 0 : 1; $providers = PRPS_Phone::providers(); $s['provider'] = isset( $providers[ $post['provider'] ?? '' ] ) ? $post['provider'] : 'smsru'; $s['phone_mode'] = 'call' === ( $post['phone_mode'] ?? '' ) ? 'call' : 'sms'; $s['smsru_key'] = preg_replace( '/[^A-Za-z0-9-]/', '', (string) ( $post['smsru_key'] ?? '' ) ); $s['smsru_from'] = substr( preg_replace( '/[^A-Za-z0-9 ._-]/', '', (string) ( $post['smsru_from'] ?? '' ) ), 0, 11 ); $text = trim( (string) ( $post['sms_text'] ?? '' ) ); $s['sms_text'] = false !== strpos( $text, '{code}' ) ? mb_substr( $text, 0, 140 ) : PRPS_Settings::defaults()['sms_text']; $s['code_length'] = min( 6, max( 4, (int) ( $post['code_length'] ?? 4 ) ) ); $s['limit_phone'] = min( 20, max( 1, (int) ( $post['limit_phone'] ?? 3 ) ) ); $s['limit_ip'] = min( 100, max( 1, (int) ( $post['limit_ip'] ?? 10 ) ) ); } if ( 'social' === $tab ) { $s['vk'] = empty( $post['vk'] ) ? 0 : 1; $s['vk_client_id'] = preg_replace( '/\D/', '', (string) ( $post['vk_client_id'] ?? '' ) ); $s['yandex'] = empty( $post['yandex'] ) ? 0 : 1; $s['ya_client_id'] = preg_replace( '/[^a-f0-9]/i', '', (string) ( $post['ya_client_id'] ?? '' ) ); $secret = preg_replace( '/[^a-f0-9]/i', '', (string) ( $post['ya_secret'] ?? '' ) ); if ( '' !== $secret || ! empty( $post['ya_secret_clear'] ) ) { $s['ya_secret'] = $secret; // Пустое поле не стирает сохранённый секрет. } } if ( 'login' === $tab ) { $s['register'] = empty( $post['register'] ) ? 0 : 1; $s['email_register'] = 'keep' === ( $post['email_register'] ?? '' ) ? 'keep' : 'off'; $s['password_login'] = 'admins' === ( $post['password_login'] ?? '' ) ? 'admins' : 'all'; $s['link_email'] = empty( $post['link_email'] ) ? 0 : 1; $s['wp_login'] = empty( $post['wp_login'] ) ? 0 : 1; $role = sanitize_key( (string) ( $post['role'] ?? '' ) ); $s['role'] = ( '' === $role || PRPS_Users::is_safe_role( $role ) ) ? $role : ''; $redirect = esc_url_raw( (string) ( $post['redirect'] ?? '' ) ); $s['redirect'] = $redirect && wp_validate_redirect( $redirect, '' ) ? $redirect : ''; } /** * Сохранение настроек дополнений. * * @param array $s Настройки. * @param string $tab Вкладка. * @param array $post Очищенные данные формы. */ $s = apply_filters( 'prps/save_settings', $s, $tab, $post ); PRPS_Settings::update( $s ); wp_safe_redirect( self::url( $tab, array( 'prps_saved' => 1 ) ) ); exit; } /** Проверка ключа SMS.ru: баланс. */ public static function ajax_balance() { check_ajax_referer( 'prps_admin', 'nonce' ); if ( ! current_user_can( self::CAP ) ) { wp_send_json_error( array( 'message' => __( 'Недостаточно прав', 'propusk' ) ) ); } if ( ! PRPS_Smsru::ready() ) { wp_send_json_error( array( 'message' => __( 'Сначала сохраните ключ API.', 'propusk' ) ) ); } $balance = PRPS_Smsru::balance(); if ( is_wp_error( $balance ) ) { wp_send_json_error( array( 'message' => $balance->get_error_message() ) ); } /* translators: %s: сумма в рублях */ wp_send_json_success( array( 'message' => sprintf( __( 'Ключ работает. Баланс: %s ₽', 'propusk' ), number_format_i18n( $balance, 2 ) ) ) ); } /* ===================================================================== * Колонка в списке пользователей * =================================================================== */ public static function users_column( $cols ) { $cols['prps'] = esc_html__( 'Вход', 'propusk' ); return $cols; } public static function users_cell( $out, $col, $user_id ) { if ( 'prps' !== $col ) { return $out; } $list = array(); foreach ( array( 'phone', 'vk', 'yandex', 'max' ) as $p ) { if ( '' !== (string) get_user_meta( $user_id, PRPS_Users::meta_key( $p ), true ) ) { $list[] = '' . esc_html( PRPS_Users::label( $p ) ) . ''; } } return $list ? '' . implode( ' ', $list ) . '' : '' . esc_html__( 'пароль', 'propusk' ) . ''; } /* ===================================================================== * Отрисовка * =================================================================== */ public static function tabs() { $tabs = array( 'overview' => __( 'Обзор', 'propusk' ), 'phone' => __( 'Телефон', 'propusk' ), 'social' => __( 'VK ID и Яндекс ID', 'propusk' ), 'login' => __( 'Регистрация и вход', 'propusk' ), ); if ( ! PRPS_Plugin::has_pro_addon() ) { $tabs['pro'] = '★ Pro-версия'; } /** * Вкладки страницы плагина. * * @param array $tabs Вкладки. */ return (array) apply_filters( 'prps/admin_tabs', $tabs ); } private static function tab_icon( $tab ) { $icons = array( 'overview' => 'dashicons-yes-alt', 'phone' => 'dashicons-smartphone', 'social' => 'dashicons-id', 'login' => 'dashicons-admin-users', 'pro' => 'dashicons-star-filled', ); /** * Иконка вкладки. * * @param string $icon Класс dashicons. * @param string $tab Вкладка. */ return (string) apply_filters( 'prps/admin_tab_icon', $icons[ $tab ] ?? 'dashicons-admin-generic', $tab ); } public static function header() { $is_pro = PRPS_Plugin::has_pro_addon(); echo '
'; echo ''; echo '

' . esc_html__( 'Вход 406-ФЗ', 'propusk' ); echo $is_pro ? ' Pro' : ' ' . esc_html__( 'Бесплатная версия', 'propusk' ) . ''; echo '

' . esc_html__( 'Вход и регистрация по номеру телефона, через VK ID и Яндекс ID — как требует закон 406-ФЗ', 'propusk' ) . '

'; echo '
'; if ( ! $is_pro ) { printf( '%s', esc_url( self::url( 'pro' ) ), esc_html__( '★ Получить Pro', 'propusk' ) ); } echo '
'; } public static function render() { if ( ! current_user_can( self::CAP ) ) { return; } $tabs = self::tabs(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'overview'; $tab = isset( $tabs[ $tab ] ) ? $tab : 'overview'; echo '
'; self::header(); echo '
'; echo '
'; if ( 'pro' === $tab ) { PRPS_Admin_Pro_Page::render(); } elseif ( method_exists( 'PRPS_Admin_Views', $tab ) ) { PRPS_Admin_Views::$tab(); } else { /** * Вкладка дополнения. * * @param string $tab Вкладка. */ do_action( 'prps/admin_tab', $tab ); } echo '
'; } /** Карточка-раздел (используется и Pro). */ public static function card_open( $title, $desc = '', array $args = array() ) { echo '
'; if ( '' !== $title ) { echo '
'; if ( ! empty( $args['icon'] ) ) { echo ''; } echo '

' . wp_kses_post( $title ) . '

'; if ( '' !== $desc ) { echo '

' . wp_kses_post( $desc ) . '

'; } echo '
'; } echo '
'; } public static function card_close() { echo '
'; } /** Начало формы вкладки. */ public static function form_open( $tab ) { echo '
'; wp_nonce_field( 'prps_save_' . $tab ); echo ''; } public static function form_close() { echo '

'; } }