From 6793fbfc6d9fcc3f3a1d25c26f088d798d8354ec Mon Sep 17 00:00:00 2001 From: Alex Cube Date: Sun, 25 Oct 2026 17:04:36 +0300 Subject: [PATCH] SEOJak 1.0.0: SEO plugin for WordPress Co-Authored-By: Claude Opus 5.5 --- README.md | 30 ++ assets/icon-128x128.png | Bin 0 -> 10127 bytes assets/icon-256x256.png | Bin 0 -> 30364 bytes assets/icon.svg | 17 ++ seojak.php | 630 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 677 insertions(+) create mode 100644 README.md create mode 100644 assets/icon-128x128.png create mode 100644 assets/icon-256x256.png create mode 100644 assets/icon.svg create mode 100644 seojak.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8f79d8 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# SEOJak + +Лёгкий SEO-плагин для WordPress. Написан для [lexium.ru](https://www.lexium.ru/) на замену +All in One SEO: те же возможности бесплатной версии, без рекламы и лишних таблиц. + +- Заголовок, описание и «не индексировать» для каждой записи и страницы — блок «SEO» в + редакторе со счётчиками символов и предпросмотром сниппета. +- ``, meta description, robots, canonical, prev/next. +- Open Graph и Twitter Card; картинка — превью записи, иначе картинка по умолчанию. +- Schema.org одним JSON-LD: WebSite, Person, WebPage, BlogPosting, BreadcrumbList. +- Карта сайта — встроенная в WordPress (`/wp-sitemap.xml`): только записи, страницы и + открытые для индексации рубрики, без noindex-записей. Старые `/sitemap.xml` и + `post-sitemap.xml` перенаправляются на неё. +- IndexNow: после публикации и обновления адрес сообщается Яндексу (не чаще раза в + 10 минут на запись, только на production). +- Перенос из All in One SEO: при активации забирает настройки главной, автора, соцсетей и + данные записей из таблицы `aioseo_posts`. Повторно: `wp seojak import-aioseo`. + +Пока All in One SEO активен, SEOJak на сайте ничего не выводит — можно ставить рядом и +переключаться без пустого окна. + +Настройки: «Настройки → SEOJak». Данные записей лежат в postmeta +`_seojak_title`, `_seojak_description`, `_seojak_noindex` и доступны через REST API. + +Требования: WordPress 6.4+, PHP 7.4+. + +## Деплой на lexium.ru + +Рабочая копия для сайта — `www/wp-content/plugins/seojak/` в репозитории lexium.ru. +Правка здесь → копия туда → коммит и сборка по правилам lexium.ru. diff --git a/assets/icon-128x128.png b/assets/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d7d493c62bd77e97a14ba25ed10e66d05bd56c GIT binary patch literal 10127 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 literal 0 HcmV?d00001 diff --git a/assets/icon-256x256.png b/assets/icon-256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..47337f136be3fb673f435bbfd658166a9e2b127a GIT binary patch literal 30364 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 UWkuiyenVz>*G%`Twqw-)0%&R2^#A|> literal 0 HcmV?d00001 diff --git a/assets/icon.svg b/assets/icon.svg new file mode 100644 index 0000000..74e80bb --- /dev/null +++ b/assets/icon.svg @@ -0,0 +1,17 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"> + <defs> + <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"> + <stop offset="0" stop-color="#1f3b73"/> + <stop offset="1" stop-color="#0f1e3d"/> + </linearGradient> + </defs> + <rect width="256" height="256" rx="48" fill="url(#bg)"/> + <!-- линза --> + <circle cx="112" cy="104" r="58" fill="#ffffff" fill-opacity=".08" stroke="#ffffff" stroke-width="18"/> + <!-- столбики «позиций» внутри линзы --> + <rect x="82" y="112" width="14" height="26" rx="4" fill="#7fd1ff"/> + <rect x="105" y="96" width="14" height="42" rx="4" fill="#7fd1ff"/> + <rect x="128" y="78" width="14" height="60" rx="4" fill="#ffc94d"/> + <!-- ручка лупы загибается в букву J --> + <path d="M154 146 L188 180 L188 206 A26 26 0 0 1 136 206" fill="none" stroke="#ffc94d" stroke-width="22" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/seojak.php b/seojak.php new file mode 100644 index 0000000..94b3597 --- /dev/null +++ b/seojak.php @@ -0,0 +1,630 @@ +<?php +/** + * Plugin Name: SEOJak + * Description: SEO без лишнего: заголовок и описание записи, robots, canonical, Open Graph, Schema.org, карта сайта и IndexNow для Яндекса. + * Version: 1.0.0 + * Author: Алексей Якубов + * Author URI: https://www.lexium.ru/about-me/ + * License: GPL-2.0-or-later + * Requires at least: 6.4 + * Requires PHP: 7.4 + * Text Domain: seojak + */ + +defined( 'ABSPATH' ) || exit; + +const SEOJAK_VERSION = '1.0.0'; +const SEOJAK_OPTION = 'seojak'; + +/* ===================== Настройки ===================== */ + +function seojak_defaults(): array { + return array( + 'home_title' => get_bloginfo( 'name' ), + 'home_description' => get_bloginfo( 'description' ), + 'separator' => '|', + 'person_name' => '', + 'person_image' => '', + 'default_image' => '', + 'twitter_site' => '', + 'same_as' => '', + 'noindex_category' => 1, + 'noindex_tag' => 1, + 'noindex_author' => 1, + 'noindex_date' => 1, + 'indexnow' => 1, + 'indexnow_key' => '', + ); +} + +function seojak_opt( string $key ) { + static $opts = null; + if ( null === $opts ) { + $opts = wp_parse_args( (array) get_option( SEOJAK_OPTION, array() ), seojak_defaults() ); + } + return $opts[ $key ] ?? null; +} + +/* ===================== Данные записи ===================== */ + +const SEOJAK_META = array( + '_seojak_title' => 'string', + '_seojak_description' => 'string', + '_seojak_noindex' => 'boolean', +); + +add_action( 'init', function () { + foreach ( array( 'post', 'page' ) as $type ) { + foreach ( SEOJAK_META as $key => $kind ) { + register_post_meta( $type, $key, array( + 'type' => $kind, + 'single' => true, + 'show_in_rest' => true, + 'auth_callback' => function ( $allowed, $meta_key, $post_id ) { + return current_user_can( 'edit_post', $post_id ); + }, + ) ); + } + } +} ); + +function seojak_post_description( WP_Post $post ): string { + $custom = trim( (string) get_post_meta( $post->ID, '_seojak_description', true ) ); + if ( '' !== $custom ) { + return $custom; + } + $text = '' !== trim( $post->post_excerpt ) ? $post->post_excerpt : strip_shortcodes( $post->post_content ); + if ( function_exists( 'trim_text' ) ) { + return trim_text( $text, 160 ); + } + return wp_trim_words( wp_strip_all_tags( $text ), 25, '…' ); +} + +/* ===================== Что за страница сейчас ===================== */ + +/** Всё, что нужно для <head> текущей страницы. */ +function seojak_context(): array { + static $ctx = null; + if ( null !== $ctx ) { + return $ctx; + } + $sep = seojak_opt( 'separator' ); + $site = get_bloginfo( 'name' ); + $ctx = array( + 'title' => '', + 'description' => '', + 'url' => '', + 'type' => 'website', + 'image' => seojak_opt( 'default_image' ), + 'noindex' => false, + 'post' => null, + ); + + if ( is_front_page() || is_home() ) { + $ctx['title'] = seojak_opt( 'home_title' ); + $ctx['description'] = seojak_opt( 'home_description' ); + $ctx['url'] = home_url( '/' ); + } elseif ( is_singular() ) { + $post = get_queried_object(); + $custom = trim( (string) get_post_meta( $post->ID, '_seojak_title', true ) ); + $ctx['post'] = $post; + $ctx['title'] = '' !== $custom ? $custom : single_post_title( '', false ); + $ctx['description'] = seojak_post_description( $post ); + $ctx['url'] = get_permalink( $post ); + $ctx['type'] = 'article'; + $ctx['noindex'] = (bool) get_post_meta( $post->ID, '_seojak_noindex', true ); + if ( has_post_thumbnail( $post ) ) { + $ctx['image'] = get_the_post_thumbnail_url( $post, 'large' ); + } + } elseif ( is_category() || is_tag() || is_tax() ) { + $term = get_queried_object(); + $ctx['name'] = $term->name; + $ctx['description'] = wp_strip_all_tags( term_description( $term ) ); + $ctx['url'] = get_term_link( $term ); + $ctx['noindex'] = ( is_category() && seojak_opt( 'noindex_category' ) ) || ( is_tag() && seojak_opt( 'noindex_tag' ) ); + } elseif ( is_author() ) { + $ctx['name'] = get_the_author_meta( 'display_name', get_queried_object_id() ); + $ctx['url'] = get_author_posts_url( get_queried_object_id() ); + $ctx['noindex'] = (bool) seojak_opt( 'noindex_author' ); + } elseif ( is_date() ) { + $ctx['name'] = wp_strip_all_tags( get_the_archive_title() ); + $ctx['noindex'] = (bool) seojak_opt( 'noindex_date' ); + $ctx['url'] = is_year() ? get_year_link( get_query_var( 'year' ) ) : ( is_month() ? get_month_link( get_query_var( 'year' ), get_query_var( 'monthnum' ) ) : get_day_link( get_query_var( 'year' ), get_query_var( 'monthnum' ), get_query_var( 'day' ) ) ); + } elseif ( is_search() ) { + $ctx['name'] = get_search_query(); + $ctx['noindex'] = true; + } + if ( isset( $ctx['name'] ) ) { + $ctx['title'] = $ctx['name'] . " $sep $site"; + } + + // Вторая и дальше страницы списков: свой адрес, без индексации, ссылки по ним — да. + $paged = (int) get_query_var( 'paged' ); + if ( $paged > 1 && '' !== $ctx['title'] ) { + $ctx['noindex'] = true; + if ( $ctx['url'] ) { + $ctx['url'] = get_pagenum_link( $paged ); + } + $ctx['title'] .= " $sep Страница $paged"; + } + + if ( ! $ctx['image'] && seojak_opt( 'person_image' ) ) { + $ctx['image'] = seojak_opt( 'person_image' ); + } + return $ctx; +} + +/* ===================== <head> ===================== */ + +// Пока активен All in One SEO, фронтенд не трогаем: два плагина — два набора тегов. +function seojak_front_enabled(): bool { + return ! defined( 'AIOSEO_VERSION' ) && ! is_admin() && ! is_feed(); +} + +add_filter( 'pre_get_document_title', function ( $title ) { + if ( ! seojak_front_enabled() ) { + return $title; + } + $t = seojak_context()['title']; + return '' !== $t ? $t : $title; +}, 20 ); + +add_filter( 'wp_robots', function ( array $robots ) { + if ( seojak_front_enabled() && seojak_context()['noindex'] ) { + $robots['noindex'] = true; + $robots['follow'] = true; + } + return $robots; +} ); + +add_action( 'wp', function () { + if ( seojak_front_enabled() ) { + remove_action( 'wp_head', 'rel_canonical' ); // свой canonical — для всех страниц, а не только записей + } +} ); + +add_action( 'wp_head', function () { + if ( ! seojak_front_enabled() || is_404() ) { + return; + } + $c = seojak_context(); + $tags = array(); + + if ( $c['description'] ) { + $tags[] = array( 'name', 'description', $c['description'] ); + } + if ( $c['url'] && ! $c['noindex'] ) { + echo '<link rel="canonical" href="' . esc_url( $c['url'] ) . "\" />\n"; + } + foreach ( array( 'prev' => get_previous_posts_page_link(), 'next' => get_next_posts_page_link() ) as $rel => $link ) { + if ( ! is_singular() && $link && ( 'prev' === $rel ? get_query_var( 'paged' ) > 1 : max( 1, get_query_var( 'paged' ) ) < $GLOBALS['wp_query']->max_num_pages ) ) { + echo '<link rel="' . $rel . '" href="' . esc_url( $link ) . "\" />\n"; + } + } + + $tags[] = array( 'property', 'og:locale', get_locale() ); + $tags[] = array( 'property', 'og:site_name', get_bloginfo( 'name' ) ); + $tags[] = array( 'property', 'og:type', $c['type'] ); + $tags[] = array( 'property', 'og:title', $c['title'] ); + if ( $c['description'] ) { + $tags[] = array( 'property', 'og:description', $c['description'] ); + } + if ( $c['url'] ) { + $tags[] = array( 'property', 'og:url', $c['url'] ); + } + if ( $c['image'] ) { + $tags[] = array( 'property', 'og:image', $c['image'] ); + } + if ( $c['post'] && 'article' === $c['type'] ) { + $tags[] = array( 'property', 'article:published_time', get_post_time( 'c', true, $c['post'] ) ); + $tags[] = array( 'property', 'article:modified_time', get_post_modified_time( 'c', true, $c['post'] ) ); + } + $tags[] = array( 'name', 'twitter:card', $c['image'] ? 'summary_large_image' : 'summary' ); + if ( seojak_opt( 'twitter_site' ) ) { + $tags[] = array( 'name', 'twitter:site', seojak_opt( 'twitter_site' ) ); + } + $tags[] = array( 'name', 'twitter:title', $c['title'] ); + if ( $c['description'] ) { + $tags[] = array( 'name', 'twitter:description', $c['description'] ); + } + if ( $c['image'] ) { + $tags[] = array( 'name', 'twitter:image', $c['image'] ); + } + + echo "<!-- SEOJak -->\n"; + foreach ( $tags as list( $attr, $name, $content ) ) { + printf( "<meta %s=\"%s\" content=\"%s\" />\n", $attr, esc_attr( $name ), esc_attr( $content ) ); + } + echo '<script type="application/ld+json">' . wp_json_encode( seojak_schema( $c ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) . "</script>\n"; + echo "<!-- /SEOJak -->\n"; +}, 1 ); + +/** Разметка Schema.org: сайт, автор, страница, статья, хлебные крошки. */ +function seojak_schema( array $c ): array { + $home = home_url( '/' ); + $person = array( + '@type' => 'Person', + '@id' => $home . '#person', + 'name' => seojak_opt( 'person_name' ) ?: get_bloginfo( 'name' ), + 'url' => $home, + ); + if ( seojak_opt( 'person_image' ) ) { + $person['image'] = seojak_opt( 'person_image' ); + } + $same = array_values( array_filter( array_map( 'trim', explode( "\n", (string) seojak_opt( 'same_as' ) ) ) ) ); + if ( $same ) { + $person['sameAs'] = $same; + } + $graph = array( + array( + '@type' => 'WebSite', + '@id' => $home . '#website', + 'url' => $home, + 'name' => get_bloginfo( 'name' ), + 'inLanguage' => get_bloginfo( 'language' ), + 'publisher' => array( '@id' => $home . '#person' ), + ), + $person, + ); + if ( ! $c['url'] ) { + return array( '@context' => 'https://schema.org', '@graph' => $graph ); + } + + $page = array( + '@type' => 'WebPage', + '@id' => $c['url'] . '#webpage', + 'url' => $c['url'], + 'name' => $c['title'], + 'isPartOf' => array( '@id' => $home . '#website' ), + 'inLanguage' => get_bloginfo( 'language' ), + ); + if ( $c['description'] ) { + $page['description'] = $c['description']; + } + + $crumbs = array( array( 'Главная', $home ) ); + if ( $c['post'] && 'post' === $c['post']->post_type ) { + $cat = get_the_category( $c['post']->ID ); + if ( $cat ) { + foreach ( array_reverse( get_ancestors( $cat[0]->term_id, 'category' ) ) as $parent ) { + $crumbs[] = array( get_cat_name( $parent ), get_category_link( $parent ) ); + } + $crumbs[] = array( $cat[0]->name, get_category_link( $cat[0] ) ); + } + } + if ( ! is_front_page() && ! is_home() ) { + $crumbs[] = array( $c['post'] ? get_the_title( $c['post'] ) : ( $c['name'] ?? $c['title'] ), $c['url'] ); + $items = array(); + foreach ( $crumbs as $i => list( $name, $url ) ) { + $items[] = array( '@type' => 'ListItem', 'position' => $i + 1, 'name' => wp_strip_all_tags( $name ), 'item' => $url ); + } + $graph[] = array( '@type' => 'BreadcrumbList', '@id' => $c['url'] . '#breadcrumbs', 'itemListElement' => $items ); + $page['breadcrumb'] = array( '@id' => $c['url'] . '#breadcrumbs' ); + } + $graph[] = $page; + + if ( $c['post'] && 'post' === $c['post']->post_type ) { + $article = array( + '@type' => 'BlogPosting', + '@id' => $c['url'] . '#article', + 'headline' => wp_strip_all_tags( get_the_title( $c['post'] ) ), + 'datePublished' => get_post_time( 'c', true, $c['post'] ), + 'dateModified' => get_post_modified_time( 'c', true, $c['post'] ), + 'author' => array( '@id' => $home . '#person' ), + 'publisher' => array( '@id' => $home . '#person' ), + 'mainEntityOfPage' => array( '@id' => $c['url'] . '#webpage' ), + 'inLanguage' => get_bloginfo( 'language' ), + ); + if ( $c['image'] ) { + $article['image'] = $c['image']; + } + if ( $c['description'] ) { + $article['description'] = $c['description']; + } + $graph[] = $article; + } + return array( '@context' => 'https://schema.org', '@graph' => $graph ); +} + +/* ===================== Карта сайта (встроенная в WordPress) ===================== */ + +add_filter( 'wp_sitemaps_post_types', function ( $types ) { + return array_intersect_key( $types, array_flip( array( 'post', 'page' ) ) ); +} ); +// Рубрики — в карту, только если открыты для индексации; метки не нужны. +add_filter( 'wp_sitemaps_taxonomies', function ( $taxonomies ) { + return seojak_opt( 'noindex_category' ) ? array() : array_intersect_key( $taxonomies, array( 'category' => 1 ) ); +} ); +add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) { + return 'users' === $name ? false : $provider; +}, 10, 2 ); +add_filter( 'wp_sitemaps_posts_query_args', function ( $args ) { + $args['meta_query'] = array( + 'relation' => 'OR', + array( 'key' => '_seojak_noindex', 'compare' => 'NOT EXISTS' ), + array( 'key' => '_seojak_noindex', 'value' => '1', 'compare' => '!=' ), + ); + return $args; +} ); + +// Старый адрес карты сайта и ключ IndexNow. +add_action( 'template_redirect', function () { + if ( defined( 'AIOSEO_VERSION' ) ) { + return; + } + $path = trim( (string) wp_parse_url( $_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH ), '/' ); + if ( in_array( $path, array( 'sitemap.xml', 'sitemap_index.xml', 'post-sitemap.xml', 'page-sitemap.xml' ), true ) ) { + wp_safe_redirect( home_url( '/wp-sitemap.xml' ), 301 ); + exit; + } + $key = seojak_indexnow_key(); + if ( $key && $path === $key . '.txt' ) { + status_header( 200 ); + header( 'Content-Type: text/plain; charset=utf-8' ); + echo $key; // phpcs:ignore WordPress.Security.EscapeOutput -- ключ из [a-f0-9] + exit; + } +}, 0 ); + +/* ===================== IndexNow ===================== */ + +function seojak_indexnow_key(): string { + if ( ! seojak_opt( 'indexnow' ) ) { + return ''; + } + $key = (string) seojak_opt( 'indexnow_key' ); + if ( ! preg_match( '/^[a-f0-9]{32}$/', $key ) ) { + $key = md5( wp_generate_password( 32, true, true ) ); + $opts = (array) get_option( SEOJAK_OPTION, array() ); + $opts['indexnow_key'] = $key; + update_option( SEOJAK_OPTION, $opts ); + } + return $key; +} + +/** Сообщить Яндексу (и всем участникам IndexNow), что адрес изменился. */ +function seojak_indexnow_ping( string $url ) { + $key = seojak_indexnow_key(); + if ( ! $key || 'production' !== wp_get_environment_type() && ! defined( 'SEOJAK_INDEXNOW_FORCE' ) ) { + return; + } + $response = wp_remote_post( 'https://yandex.com/indexnow', array( + 'timeout' => 5, + 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ), + 'body' => wp_json_encode( array( + 'host' => wp_parse_url( home_url(), PHP_URL_HOST ), + 'key' => $key, + 'keyLocation' => home_url( "/$key.txt" ), + 'urlList' => array( $url ), + ) ), + ) ); + $code = is_wp_error( $response ) ? $response->get_error_message() : wp_remote_retrieve_response_code( $response ); + update_option( 'seojak_indexnow_last', array( 'time' => time(), 'url' => $url, 'result' => $code ), false ); +} + +add_action( 'transition_post_status', function ( $new, $old, $post ) { + if ( 'publish' !== $new || ! in_array( $post->post_type, array( 'post', 'page' ), true ) || wp_is_post_revision( $post ) ) { + return; + } + // Не чаще раза в 10 минут на запись: «Обновить» жмут по нескольку раз подряд. + if ( get_transient( 'seojak_in_' . $post->ID ) ) { + return; + } + set_transient( 'seojak_in_' . $post->ID, 1, 10 * MINUTE_IN_SECONDS ); + // После сохранения, чтобы адрес был уже окончательным. + add_action( 'shutdown', function () use ( $post ) { + if ( ! get_post_meta( $post->ID, '_seojak_noindex', true ) ) { + seojak_indexnow_ping( get_permalink( $post->ID ) ); + } + } ); +}, 10, 3 ); + +/* ===================== Блок в редакторе записи ===================== */ + +add_action( 'add_meta_boxes', function () { + add_meta_box( 'seojak', 'SEO', 'seojak_meta_box', array( 'post', 'page' ), 'normal', 'high' ); +} ); + +function seojak_meta_box( WP_Post $post ) { + wp_nonce_field( 'seojak_save', 'seojak_nonce' ); + $title = get_post_meta( $post->ID, '_seojak_title', true ); + $desc = get_post_meta( $post->ID, '_seojak_description', true ); + $noindex = get_post_meta( $post->ID, '_seojak_noindex', true ); + $auto = seojak_post_description( get_post( $post->ID ) ); + ?> + <style> + #seojak label { display: block; font-weight: 600; margin: 10px 0 4px; } + #seojak input[type=text], #seojak textarea { width: 100%; } + #seojak .seojak-count { color: #646970; font-weight: 400; } + #seojak .seojak-count.is-long { color: #b32d2e; } + #seojak .seojak-snippet { margin-top: 12px; padding: 10px 12px; border: 1px solid #dcdcde; border-radius: 4px; max-width: 600px; font-family: arial, sans-serif; } + #seojak .seojak-snippet b { display: block; color: #1a0dab; font-size: 18px; font-weight: 400; } + #seojak .seojak-snippet i { display: block; color: #006621; font-style: normal; font-size: 13px; } + #seojak .seojak-snippet span { color: #4d5156; font-size: 13px; } + </style> + <label for="seojak-f-title">Заголовок для поисковиков <span class="seojak-count" data-for="seojak-f-title" data-max="60"></span></label> + <input type="text" id="seojak-f-title" name="seojak_title" value="<?php echo esc_attr( $title ); ?>" placeholder="<?php echo esc_attr( $post->post_title ); ?>"> + <label for="seojak-f-desc">Описание <span class="seojak-count" data-for="seojak-f-desc" data-max="160"></span></label> + <textarea id="seojak-f-desc" name="seojak_description" rows="3" placeholder="<?php echo esc_attr( $auto ); ?>"><?php echo esc_textarea( $desc ); ?></textarea> + <label><input type="checkbox" name="seojak_noindex" value="1" <?php checked( $noindex ); ?>> Не индексировать эту страницу</label> + <div class="seojak-snippet"><b></b><i><?php echo esc_html( get_permalink( $post ) ); ?></i><span></span></div> + <script> + ( function () { + var box = document.getElementById( 'seojak' ), t = box.querySelector( '#seojak-f-title' ), d = box.querySelector( '#seojak-f-desc' ), + post = document.getElementById( 'title' ); + function val( el ) { return el.value.trim() || el.placeholder; } + function update() { + box.querySelector( '.seojak-snippet b' ).textContent = t.value.trim() || ( post && post.value ) || t.placeholder; + box.querySelector( '.seojak-snippet span' ).textContent = val( d ); + box.querySelectorAll( '.seojak-count' ).forEach( function ( c ) { + var el = document.getElementById( c.dataset.for ), n = ( el.value.trim() || ( el === t && post ? post.value : el.placeholder ) ).length; + c.textContent = n + ' из ~' + c.dataset.max; + c.classList.toggle( 'is-long', n > +c.dataset.max ); + } ); + } + [ t, d, post ].forEach( function ( el ) { el && el.addEventListener( 'input', update ); } ); + update(); + }() ); + </script> + <?php +} + +add_action( 'save_post', function ( $post_id ) { + if ( ! isset( $_POST['seojak_nonce'] ) || ! wp_verify_nonce( $_POST['seojak_nonce'], 'seojak_save' ) + || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) ) { + return; + } + $fields = array( + '_seojak_title' => sanitize_text_field( wp_unslash( $_POST['seojak_title'] ?? '' ) ), + '_seojak_description' => sanitize_textarea_field( wp_unslash( $_POST['seojak_description'] ?? '' ) ), + '_seojak_noindex' => empty( $_POST['seojak_noindex'] ) ? '' : '1', + ); + foreach ( $fields as $key => $value ) { + if ( '' === $value ) { + delete_post_meta( $post_id, $key ); + } else { + update_post_meta( $post_id, $key, $value ); + } + } +} ); + +/* ===================== Страница настроек ===================== */ + +add_action( 'admin_menu', function () { + add_options_page( 'SEOJak', 'SEOJak', 'manage_options', 'seojak', 'seojak_settings_page' ); +} ); + +add_action( 'admin_init', function () { + register_setting( 'seojak', SEOJAK_OPTION, array( + 'sanitize_callback' => function ( $in ) { + $out = array(); + $prev = (array) get_option( SEOJAK_OPTION, array() ); + foreach ( seojak_defaults() as $key => $default ) { + if ( is_int( $default ) ) { + $out[ $key ] = empty( $in[ $key ] ) ? 0 : 1; + } elseif ( in_array( $key, array( 'person_image', 'default_image' ), true ) ) { + $out[ $key ] = esc_url_raw( $in[ $key ] ?? '' ); + } elseif ( in_array( $key, array( 'home_description', 'same_as' ), true ) ) { + $out[ $key ] = sanitize_textarea_field( $in[ $key ] ?? '' ); + } else { + $out[ $key ] = sanitize_text_field( $in[ $key ] ?? '' ); + } + } + $out['indexnow_key'] = $prev['indexnow_key'] ?? ''; + return $out; + }, + ) ); +} ); + +function seojak_settings_page() { + $o = wp_parse_args( (array) get_option( SEOJAK_OPTION, array() ), seojak_defaults() ); + $name = SEOJAK_OPTION; + $text = array( + 'home_title' => 'Заголовок главной', + 'separator' => 'Разделитель в заголовках', + 'person_name' => 'Автор (Schema.org)', + 'person_image' => 'Фото или логотип автора, URL', + 'default_image' => 'Картинка для соцсетей по умолчанию, URL', + 'twitter_site' => 'Twitter/X, @имя', + ); + $checks = array( + 'noindex_category' => 'Не индексировать рубрики', + 'noindex_tag' => 'Не индексировать метки', + 'noindex_author' => 'Не индексировать страницы авторов', + 'noindex_date' => 'Не индексировать архивы по датам', + 'indexnow' => 'Сообщать Яндексу о новых и обновлённых записях (IndexNow)', + ); + $last = get_option( 'seojak_indexnow_last' ); + ?> + <div class="wrap"> + <h1><img src="<?php echo esc_url( plugins_url( 'assets/icon.svg', __FILE__ ) ); ?>" alt="" width="32" height="32" style="vertical-align: middle; margin-right: 8px;">SEOJak</h1> + <form method="post" action="options.php"> + <?php settings_fields( 'seojak' ); ?> + <table class="form-table" role="presentation"> + <?php foreach ( $text as $key => $label ) : ?> + <tr><th><label for="sj-<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label></th> + <td><input type="text" class="regular-text" id="sj-<?php echo esc_attr( $key ); ?>" name="<?php echo esc_attr( "{$name}[{$key}]" ); ?>" value="<?php echo esc_attr( $o[ $key ] ); ?>"></td></tr> + <?php if ( 'home_title' === $key ) : ?> + <tr><th><label for="sj-home_description">Описание главной</label></th> + <td><textarea class="large-text" rows="3" id="sj-home_description" name="<?php echo esc_attr( "{$name}[home_description]" ); ?>"><?php echo esc_textarea( $o['home_description'] ); ?></textarea></td></tr> + <?php endif; ?> + <?php endforeach; ?> + <tr><th><label for="sj-same_as">Профили автора в соцсетях</label></th> + <td><textarea class="large-text" rows="3" id="sj-same_as" name="<?php echo esc_attr( "{$name}[same_as]" ); ?>" placeholder="По одному адресу в строке"><?php echo esc_textarea( $o['same_as'] ); ?></textarea></td></tr> + <tr><th>Индексация</th><td> + <?php foreach ( $checks as $key => $label ) : ?> + <label><input type="checkbox" name="<?php echo esc_attr( "{$name}[{$key}]" ); ?>" value="1" <?php checked( $o[ $key ] ); ?>> <?php echo esc_html( $label ); ?></label><br> + <?php endforeach; ?> + <?php if ( $last ) : ?> + <p class="description">Последний IndexNow: <?php echo esc_html( wp_date( 'd.m.Y H:i', $last['time'] ) . ' — ' . $last['url'] . ' — ответ ' . $last['result'] ); ?></p> + <?php endif; ?> + </td></tr> + </table> + <?php submit_button(); ?> + </form> + <p>Карта сайта: <a href="<?php echo esc_url( home_url( '/wp-sitemap.xml' ) ); ?>"><?php echo esc_html( home_url( '/wp-sitemap.xml' ) ); ?></a></p> + </div> + <?php +} + +/* ===================== Перенос из All in One SEO ===================== */ + +/** + * Копирует заголовки, описания и noindex из таблицы aioseo_posts в поля SEOJak. + * Заполненные поля SEOJak не перезаписывает. Возвращает число перенесённых записей. + */ +function seojak_import_aioseo(): int { + global $wpdb; + $table = $wpdb->prefix . 'aioseo_posts'; + if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) !== $table ) { + return 0; + } + $rows = $wpdb->get_results( "SELECT post_id, title, description, robots_noindex, robots_default FROM `$table` WHERE (title <> '' AND title IS NOT NULL) OR (description <> '' AND description IS NOT NULL) OR (robots_noindex = 1 AND robots_default = 0)" ); // phpcs:ignore WordPress.DB.PreparedSQL -- имя таблицы с префиксом + $count = 0; + foreach ( $rows as $r ) { + if ( ! get_post( $r->post_id ) ) { + continue; + } + $done = false; + foreach ( array( '_seojak_title' => trim( (string) $r->title ), '_seojak_description' => trim( (string) $r->description ) ) as $key => $value ) { + if ( '' !== $value && '' === (string) get_post_meta( $r->post_id, $key, true ) ) { + update_post_meta( $r->post_id, $key, $value ); + $done = true; + } + } + if ( 1 === (int) $r->robots_noindex && 0 === (int) $r->robots_default ) { + update_post_meta( $r->post_id, '_seojak_noindex', '1' ); + $done = true; + } + $count += (int) $done; + } + return $count; +} + +register_activation_hook( __FILE__, function () { + if ( ! get_option( SEOJAK_OPTION ) ) { + $opts = seojak_defaults(); + // Настройки главной и соцсетей — из All in One SEO, если он стоял. + $aio = json_decode( (string) get_option( 'aioseo_options' ), true ); + if ( is_array( $aio ) ) { + $g = $aio['searchAppearance']['global'] ?? array(); + $s = $aio['searchAppearance']['global']['schema'] ?? array(); + $opts['home_title'] = $g['siteTitle'] ?? $opts['home_title']; + $opts['home_description'] = $g['metaDescription'] ?? $opts['home_description']; + $opts['person_name'] = $s['personName'] ?? ''; + $opts['person_image'] = $s['personLogo'] ?? ''; + $opts['default_image'] = $aio['social']['facebook']['general']['defaultImagePosts'] ?? ''; + $tw = $aio['social']['profiles']['urls']['twitterUrl'] ?? ''; + $opts['twitter_site'] = $tw ? '@' . basename( untrailingslashit( $tw ) ) : ''; + $opts['same_as'] = implode( "\n", array_filter( array_map( 'strval', $aio['social']['profiles']['urls'] ?? array() ) ) ); + } + add_option( SEOJAK_OPTION, $opts ); + } + seojak_import_aioseo(); +} ); + +if ( defined( 'WP_CLI' ) && WP_CLI ) { + WP_CLI::add_command( 'seojak import-aioseo', function () { + WP_CLI::success( 'Перенесено записей: ' . seojak_import_aioseo() ); + } ); +}