self::SLUG, 'tab' => $tab ), $args ), admin_url( 'admin.php' ) );
}
/** Хук страницы плагина (страница внутри пункта WP-ADDON). */
public static function hook() {
return YSNO_Wpaddon_Menu::hook( self::SLUG );
}
public static function menu() {
YSNO_Wpaddon_Menu::add_page( __( 'Русский язык 168-ФЗ', 'yasno' ), __( 'Русский язык 168-ФЗ', 'yasno' ), self::SLUG, array( __CLASS__, 'render' ) );
}
public static function action_links( $links ) {
array_unshift( $links, '' . esc_html__( 'Проверить сайт', 'yasno' ) . '' );
if ( ! YSNO_Plugin::has_pro_addon() ) {
$links[] = 'Pro';
}
return $links;
}
public static function assets( $hook ) {
if ( self::hook() !== $hook && 'edit.php' !== $hook ) {
return;
}
wp_enqueue_style( 'ysno-admin', YSNO_URL . 'assets/css/admin.css', array(), YSNO_VERSION );
if ( 'edit.php' === $hook ) {
return;
}
wp_enqueue_script( 'ysno-admin', YSNO_URL . 'assets/js/admin.js', array(), YSNO_VERSION, true );
wp_localize_script(
'ysno-admin',
'ysnoAdmin',
array(
'ajax' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'ysno_ajax' ),
'back' => self::url( 'check' ),
'i18n' => array(
/* translators: 1: проверено, 2: всего */
'progress' => __( 'Проверено %1$s из %2$s', 'yasno' ),
'starting' => __( 'Собираю список страниц…', 'yasno' ),
'done' => __( 'Готово. Обновляю результаты…', 'yasno' ),
'error' => __( 'Ошибка запроса. Попробуйте ещё раз.', 'yasno' ),
'added' => __( 'В исключениях', 'yasno' ),
/* translators: %s: слово */
'confirm' => __( 'Считать «%s» товарным знаком или фирменным наименованием и не проверять?', 'yasno' ),
),
)
);
}
public static function notices() {
$screen = get_current_screen();
if ( ! $screen || self::hook() !== $screen->id ) {
return;
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['ysno_saved'] ) ) {
echo '
' . esc_html__( 'Настройки сохранены. Запустите проверку заново, чтобы обновить результаты.', 'yasno' ) . '
';
}
if ( isset( $_GET['ysno_msg'] ) ) {
echo '' . esc_html( sanitize_text_field( wp_unslash( $_GET['ysno_msg'] ) ) ) . '
';
}
// phpcs:enable
}
/* =====================================================================
* Сохранение настроек
* =================================================================== */
public static function save() {
if ( empty( $_POST['ysno_tab'] ) || ! current_user_can( self::CAP ) ) {
return;
}
$tab = sanitize_key( wp_unslash( $_POST['ysno_tab'] ) );
check_admin_referer( 'ysno_save_' . $tab );
$post = map_deep( wp_unslash( $_POST ), 'sanitize_textarea_field' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- очищается map_deep().
$s = YSNO_Settings::all();
if ( 'settings' === $tab ) {
$types = array_keys( YSNO_Settings::available_post_types() );
$s['post_types'] = array_values( array_intersect( array_keys( (array) ( $post['post_types'] ?? array() ) ), $types ) );
foreach ( array( 'check_latin', 'check_words', 'check_abbr', 'common_terms', 'menus', 'site_title' ) as $k ) {
$s[ $k ] = empty( $post[ $k ] ) ? 0 : 1;
}
$lines = array();
foreach ( preg_split( '/\R/', (string) ( $post['exceptions'] ?? '' ) ) as $line ) {
$line = trim( sanitize_text_field( $line ) );
if ( '' !== $line ) {
$lines[ YSNO_Checker::lower( $line ) ] = $line;
}
}
$s['exceptions'] = implode( "\n", array_slice( $lines, 0, 2000 ) );
}
/**
* Сохранение настроек дополнений.
*
* @param array $s Настройки.
* @param string $tab Вкладка.
* @param array $post Очищенные данные формы.
*/
$s = apply_filters( 'ysno/save_settings', $s, $tab, $post );
YSNO_Settings::update( $s );
YSNO_Checker::reset();
wp_safe_redirect( self::url( $tab, array( 'ysno_saved' => 1 ) ) );
exit;
}
/* =====================================================================
* Колонка «Русский язык» в списке записей
* =================================================================== */
public static function columns() {
foreach ( YSNO_Sources::post_types() as $type ) {
add_filter( "manage_{$type}_posts_columns", array( __CLASS__, 'column_head' ) );
add_action( "manage_{$type}_posts_custom_column", array( __CLASS__, 'column_cell' ), 10, 2 );
}
}
public static function column_head( $cols ) {
$cols['ysno'] = '' . esc_html__( 'Русский язык', 'yasno' ) . '';
return $cols;
}
public static function column_cell( $col, $post_id ) {
if ( 'ysno' !== $col ) {
return;
}
$n = get_post_meta( $post_id, YSNO_Scan::META, true );
if ( '' === $n ) {
echo '—';
} elseif ( 0 === (int) $n ) {
echo '✓';
} else {
printf(
'%d',
esc_url( self::url( 'check', array( 'view' => 'pages', 'item' => 'post:' . (int) $post_id ) ) . '#ysno-results' ),
esc_attr__( 'Слов, которые стоит проверить', 'yasno' ),
(int) $n
);
}
}
/* =====================================================================
* Отрисовка
* =================================================================== */
public static function tabs() {
$tabs = array(
'overview' => __( 'Обзор', 'yasno' ),
'check' => __( 'Проверка сайта', 'yasno' ),
'settings' => __( 'Настройки и исключения', 'yasno' ),
);
if ( ! YSNO_Plugin::has_pro_addon() ) {
$tabs['pro'] = '★ Pro-версия';
}
/**
* Вкладки страницы плагина.
*
* @param array $tabs Вкладки.
*/
return (array) apply_filters( 'ysno/admin_tabs', $tabs );
}
private static function tab_icon( $tab ) {
$icons = array(
'overview' => 'dashicons-yes-alt',
'check' => 'dashicons-search',
'settings' => 'dashicons-admin-settings',
'pro' => 'dashicons-star-filled',
);
/**
* Иконка вкладки.
*
* @param string $icon Класс dashicons.
* @param string $tab Вкладка.
*/
return (string) apply_filters( 'ysno/admin_tab_icon', $icons[ $tab ] ?? 'dashicons-admin-generic', $tab );
}
public static function header() {
$is_pro = YSNO_Plugin::has_pro_addon();
echo '';
echo 'Аа';
echo '' . esc_html__( 'Русский язык 168-ФЗ', 'yasno' );
echo $is_pro ? ' Pro' : ' ' . esc_html__( 'Бесплатная версия', 'yasno' ) . '';
echo '
' . esc_html__( 'Проверка текстов сайта на слова латиницей и англицизмы по закону о защите русского языка', 'yasno' ) . '
';
echo '';
if ( ! $is_pro ) {
printf( '
%s', esc_url( self::url( 'pro' ) ), esc_html__( '★ Получить Pro', 'yasno' ) );
}
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 ) {
YSNO_Admin_Pro_Page::render();
} elseif ( method_exists( 'YSNO_Admin_Views', $tab ) ) {
YSNO_Admin_Views::$tab();
} else {
/**
* Вкладка дополнения.
*
* @param string $tab Вкладка.
*/
do_action( 'ysno/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 '
';
}
}