XML карта сайта в WordPress

Решил поделится опытом как создать карту сайта в WordPress. В сети можно найти множество плагинов, которые создают файл sitemap.xml в корневой директории WordPress. Главный их недостаток заключается в том, что большинство из них слишком тяжелые, с чрезмерно раздутым функционалом и кривым интерфейсом. Мне не понятно почему разработчики до сих пор не реализовали эту функцию как штатный функционал WordPress.

После нескольких часов поиска, я так и не смог найти подходящий WordPress плагин для создания xml карты сайта. Среди моих требований были лаконичность, простота кода, продуманный интерфейс, без рекламы и выпрашивания денег.

Что касается интерфейса для управления плагином из админки WordPress. Я не вижу в нем никакой необходимости. Независимо от тех параметров, которые мы указали в xml карте сайта, поисковые роботы основе своих алгоритмов будут самостоятельно определять частоту индексации сайта. Логичнее один раз указать эти параметры внутри кода и больше никогда про них не вспоминать.

В итоге для реализации xml карты сайта в WordPress пришлось написать свой небольшой плагин. Признаюсь, в процессе решил не заморачиваться и просто позаимствовал часть кода у одного из плагинов. Чтобы лишний раз не нагружать сервер, можно кэшировать запросы к sitemap.xml в nginx. При желании плагин легко можно допилить под свои потребности.

<?php
/*
Plugin Name: Tiny XML Sitemap
Description: XML Sitemap for Google, Yandex and Yahoo
*/

add_action( 'template_redirect', 'google_sitemap' );

function google_sitemap() {
  if ( ! preg_match( '/sitemap\.xml$/', $_SERVER['REQUEST_URI'] ) ) {
    return;
  }
  global $wpdb;
  $posts = $wpdb->get_results( "SELECT ID, post_title, post_modified_gmt
    FROM $wpdb->posts
    WHERE post_status = 'publish'
    AND post_password = ''
    ORDER BY post_type DESC, post_modified DESC
    LIMIT 50000" );
  header( "HTTP/1.1 200 OK" );
  header( 'X-Robots-Tag: noindex, follow', true );
  header( 'Content-Type: text/xml' );
  echo '' . "\n";
  echo '' . "\n";
  $xml  = '' . "\n";
  $xml .= "\t" . "\n";
  $xml .= "\t\t" . home_url( '/' ) . "\n";
  $xml .= "\t\t" . mysql2date( 'Y-m-d\TH:i:s+00:00', get_lastpostmodified( 'GMT' ), false ) . "\n";
  $xml .= "\t\t" . 'hourly' . "\n";
  $xml .= "\t\t" . '1' . "\n";
  $xml .= "\t" . "\n";

foreach ( $posts as $post ) {
    if ( $post->ID == get_option( 'page_on_front' ) )
      continue;
    if ( ! empty( $post->post_title ) ) {
      $xml .= "\t\n";
      $xml .= "\t\t" . get_permalink( $post->ID ) . "\n";
      $xml .= "\t\t" . mysql2date( 'Y-m-d\TH:i:s+00:00', $post->post_modified_gmt, false ) . "\n";
      $xml .= "\t\t" . 'weekly' . "\n";
      $xml .= "\t\t" . '0.8' . "\n";
      $xml .= "\t\n";
    }
  }
  $xml .= '';
  echo ( "$xml" );
  exit();
}

WordPress и оригинальные тексты Яндекс

Воровство контента может стать настоящей головной болью для владельцев молодого сайта. Проблема в том, что защитить контент от воровства практически невозможно. Зато мы можем предупредить возможные последствия со стороны поисковой системы с помощью сервиса Оригинальные тексты Яндекс.

Обидно, когда украденный контент отображается в поисковой выдаче перед вашим сайтом. В силу возраста и раскрученности ресурса, страницы быстро индексируются и поисковой система считает сайт, который украл ваш материал в качестве первоисточника. Но это не самая большая проблема, с которой вы можете столкнуться.

Парадокс заключается в том, что бывают случаи, когда другие сайты делают copypast и добросовестно в качестве источника указывают активную ссылку на сайт, который украл ваш материал. В такой ситуации у нас нет ни одного шанса доказать свое авторство поисковой системе.

Чтобы защитить сайт от воровства контента можно попытаться заранее оповестить поисковую систему разместив анонс на материл в социальных сетях. Другим способом, который позволит поисковой системе определить первоисточник материала, является использование сервиса Оригинальные тексты Яндекс. Для этого перед публикацией материала необходимо добавить текст в форму Оригинальные тексты Яндекс.

Чтобы облегчить задачу по добавлению контента в сервис Оригинальные тексты Яндекс, в WordPress можно использовать специальный плагин Webmaster Yandex. Чтобы использовать плагин сайт должен быть добавлен в Яндекс.Вебмастер. После активации плагина в админке WordPresss необходимо настроить доступ к API сервиса.

Работа с опциями в WordPress

В этой заметке я кратко опишу процесс создания, редактирования и изменения и удаления опций в WordPress. Изначально потребность работы с опциями в WordPress у меня возникла в процессе написания функции для минификации содержимого файлов CSS. Чтобы не выполнять постоянно одну и туже операцию, нужно было хранить в базе WordPress хэш искомого файла стилей.

Создать новую опцию

Для создания опции в WordPress используется функция add_option(). После первого выполнения функция создает в базе WordPress новую запись, которую WordPress будет использовать для хранения настроек. Если опция с указанным именем уже существует, то в процессе вызова функции ничего не произойдет.

Синтаксис использования функции add_option():

add_option($name, $value = '', $deprecated = '', $autoload = 'yes');

Описание параметров:

  • $name — название опции, которая будет добавлена. Используйте слова в нижнем регистре, вместо пробела используйте нижнее подчеркивание.
  • $value — значение опции.  Может быть пустым.
  • $deprecated - текст описывающий опцию. Параметр больше не используется. Оставляем значение пустым.
  • $autoload — должна ли опция загружаться автоматически функцией wp_load_alloptions. Использует значения: yes или no.

Пример использования функции для добавления новой опции в WordPress:

add_option("my_option_name", '123', '', 'yes');

Необходимо отметить, что описание опций больше не используется в WordPress, поэтому, третий параметр всегда указывается пустым.

Получить значение опции

Когда новая опция создана в базе WordPress, ее значение можно получить с помощью функции get_option(). Если в MySQL опция с указанным именем не существует, функция вернет FALSE.

Синтаксис использования функции get_option():

get_option($name, $default);

Описание параметров:

  • $name — название опции, значение которой необходимо получить.
  • $value — значение по умолчанию, если никакого значения не вернулось.

Обновить значение опции

Как правило, функцию update_option() используют для изменения существующих опций в WordPress. Но эту функцию можно использовать и для создания новой опции. В этом случае update_option() проверяет наличие опции с указанным именем в базе данных. В случае ее отсутствия, будет автоматически вызвана функция add_option().

update_option($name, $newvalue);

Описание параметров:

  • $name — название опции, значение которой необходимо изменить.
  • $newvalue — новое значение для опции.

Пример использования функции для изменения значения опции в WordPress:

$option_name = 'my_option'; 
$newvalue = '123';
if ( get_option($option_name) ) {
    update_option($option_name, $newvalue);
}

Связи с тем, что при отсутствии опции с указным именем функция update_option() создает новую запись в базе, перед ее использованием рекомендуется выполнить проверку наличия опции.

Удалить опцию из базы WordPress

Чтобы удалить опцию из таблицы options в базе данных WordPress необходимо использовать функцию delete_option().

Синтаксис использования функции delete_option():

delete_option( $name );
  • $name — название опции, которая будет удалена.

Пример использования функции для удаления одной или нескольких опций в WordPress:

// Описание функции
function deleteOptions()
{
        // Массив с названиями опций
	$args = func_get_args();
	$num = count($args);
        
        // Удаление одной опции
	if ($num == 1) {
		return (delete_option($args[0]) ? TRUE : FALSE);
	}
        // Удаление группы опций
	elseif (count($args) > 1)
	{
		foreach ($args as $option) {
			if ( ! delete_option($option))
				return FALSE;
		}
		return TRUE;
	}
	return FALSE;
}

// Вызов функции deleteOptions
if (deleteOptions('is_installed', 'my_plugin_version', 'my_option'))
   echo 'Опции были удалены!';
else
   echo 'Ошибка в процессе удаления!';

Подсветка синтаксиса в WordPress

Достаточно длительное время я присматривался к различным решениям для подсветки синтаксиса в WordPress. Основными требованиями было легкость, простота установки и использования. Громоздкие плагины для WordPress были сразу мной откинуты. Среди всех решений, мне больше всего приглянулись Highlight.js, Prism.

Оба скрипта написаны на JavaScript, имеют примерно одинаковый размер благодаря наличию выбора языков программирования. Оба скрипта легко прикрутить к WordPress без использования дополнительных плагинов. Вы можете использовать любой из этих скриптов, я же остановил свой выбор на Prism.

Настройка Prism в WordPress

Начну с того, что Prism имеет неудобный формат выделения области кода. В прочем, Highlight.js имеет аналогичный недостаток. Для использования Prism необходимо выделить код следующим образом:

<pre class="lang-javascript"><code class="lang-javascript">
/* Использование Prism для подсветки синтаксиса JavaScript */
<code></pre>

Мне совершенно не нравится такой формат выделения кода, поэтому я решил его заменить на более лаконичный:

<pre class="lang-javascript">
/* Использование Prism для подсветки синтаксиса JavaScript */
</pre>

Для начала необходимо выбрать набор языков программирования для подсветки кода и скачать Prism по этой ссылке. После того как скачали Prism, в файле prism.js необходимо найти следующую строку:

for(var a,r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),l=0;a=r[l++];

Вручную измените code на pre или полностью замените строку на код из примера ниже:

for(var a,r=document.querySelectorAll('pre[class*="language-"], [class*="language-"] pre, pre[class*="lang-"], [class*="lang-"] pre'),l=0;a=r[l++];

После чего копируем файл prism.js в каталог с темой WordPress. Далее необходимо скопировать стили для подсветки синтаксиса в содержимое файла style.css вашей темы. В процессе может понадобится настроить стили под дизайн вашего сайта.

Подключаем загрузку скрипта в functions.php:

function add_prism() {
    wp_register_script('prismjs', get_stylesheet_directory_uri() . '/prism.js', false, '1.0', true);
    wp_enqueue_script('prismjs');
}
add_action('wp_enqueue_scripts', 'add_prism');

Для подсветки кода в WordPress выделяем область помощью тега pre, а для имени стиля указываем язык программирования:

<pre class="lang-php">
/* Использование Prism для подсветки синтаксиса PHP */
</pre>

Отключить комментарии в WordPress

Иногда возникают ситуации, когда необходимо сразу отключить коментарии для всех записей в WordPress. Панель управления WordPress позволяет отключить или включить комментарии только для одной записи. Таким образом, чтобы отключить комментарии на большом сайте может потребоваться достаточно много времиени.

Как вариант, можно быстро отключить комментарии в WordPress используя MySQL запрос:

use wordpressdb;
UPDATE wp_posts SET comment_status='closed' WHERE post_status = 'publish' AND post_type = 'post';

Чтобы включить комментарии для всех записей в WordPress, выполните запрос:

UPDATE wp_posts SET comment_status='open' WHERE post_status = 'publish' AND post_type = 'post';

Выпадающее меню в WordPress

В мобильной версии темы WordPress Twenty Fifteen сайдбар используется в виде выпадающего меню, которое отображается при нажатии на кнопку. Чтобы показать или скрыть меню используется JavaScript, который в свою очередь использует библиотеку jQuery.

Как я уже писал раньше, я поставил себе цель полностью выпилить jQuery из стандартной темы оформления Twenty Fifteen. Сначала перенес на CSS спойлер, который ранее работал на JavaScript и jQuery. И вот сейчас руки дошли до выпадающего меню в WordPress.

Для начала нужно полностью отключить загрузку jQuery, добавьте в файл в functions.php:

function wpdocs_dequeue_script() {
    wp_dequeue_style('jquery');
    wp_deregister_script('jquery');
}
add_action( 'wp_print_scripts', 'wpdocs_dequeue_script' );

Чтобы показать или скрыть выпадающее меню при нажатии на кнопку, добавьте JavaScript ниже в файл footer.php:

<script type="text/javascript">
    var dropdownButton = document.getElementById("dropdown"),
    dropdownDiv = document.getElementById("secondary");

    dropdownButton.addEventListener("click", function () {
        dropdownButton.classList.toggle("toggled-on");
        dropdownDiv.classList.toggle("toggled-on");

    if (dropdownButton.getAttribute("aria-expanded") == 'false') {
        dropdownButton.setAttribute("aria-expanded", "true");
        dropdownDiv.setAttribute("aria-expanded", "true");
    }
    else {
        dropdownButton.setAttribute("aria-expanded", "false");
        dropdownDiv.setAttribute("aria-expanded", "false");
    }
});
</script>

Преимущества данного скрипта — нет необходимости подгружать jQuery. К недостаткам можно отнести то, что данный скрипт не работает в Opera Mini по причине отсутствия поддержки classList. Возможно, в будущем перепишу выпадающее меню на CSS, но сейчас не хочу заморачиваться.

Cпойлер в WordPress на CSS

В этой записи я расскажу как сделать спойлер в WordPress на чистом HTML и CSS. Предпосылкой для написания этой статьи стало желание полностью отказаться от использования библиотеки jQuery, которая по умолчанию используется в стандартной теме WordPress Twenty Fifteen.

Стандартная тема WordPress Twenty Fifteen использует библиотеку jQuery для отображения блока сайдбара в мобильной версии сайта. Функционал не настолько сложный, чтобы ради него подключать jQuery. Поэтому, было принято решение полностью выпилить jQuery из содержимого шаблона.

Начать я решил с самого простого. Ранее спойлер на моем блоге работал на JavaScript, который требовал для своей работы наличие подключенной библиотеки jQuery. Представляю вашему вниманию небольшую функцию, которая добавляет возможность использовать спойлер в WordPress.

Текст спойлера

Для установки откройте файл functions.php вашей темы и добавьте в него следующий код:

function showhide_shortcode ($atts, $content = null) {
    $attributes = shortcode_atts (array('text' => 'Спойлер'), $atts );

    $output = '<span class="spoiler"> 
        <label for="spoiler">' . $attributes['text'] . '</label>
        <input type="checkbox" id="spoiler">';
    $output .= '<div class="spoiler_text">'. do_shortcode( $content ) .'</div>
        </span>';

return $output;
}
add_shortcode ('spoiler', 'showhide_shortcode');

Чтобы добавить спойлер в WordPress используйте шорткод [spоiler] для области, которую хотите скрыть. Через параметр text можно изменить текст, который будет отображаться в заголовке спойлера.

[spоiler text="Заголовок спойлера"]Текст[/spоiler]

За отображение данных под спойлером добавьте в файле style.css:

.spoiler label {
    color: #0060a0;
    border-bottom: 1px dashed rgba(0,96,160,.2);
    cursor:pointer;
}
.spoiler input {
    display: none;
}
.spoiler_text {
    display: none;
}
.spoiler input[type=checkbox]:checked + .spoiler_text {
    display: block;
}

Теперь, вам остается только подправить стили под дизайн вашего сайта.

WordPress версия стилей и скриптов

Достаточно часто приходится вносить изменения в дизайн сайта. Если не обновить файлы стилей в кэше браузера, можно столкнуться с проблемой некорректного отображения сайта. Если администратор сайта легко решит проблему нажатием славишь Alt+F5. То как быть с другими посетителями сайта, которые понятия не имеют, что сегодня администратор неожиданно решил обновить дизайн.

Причина данной проблемы связана с заголовком Cache-Control, который веб-сервер передает вашему браузеру во время загрузки файла:

Cache-Control: max-age=86400

Директива указывает браузеру хранить копию файлов в кэше в течение суток. Таким образом, до завтрашнего дня посетитель будет любоваться съехавшей версткой. Вы можете уменьшить значение директивы max-age, хотя сути проблемы это не решает.

Полный отказ от кэширования:

Cache-Control: no-cache

Может показаться, что это полностью решает проблему. Но этот вариант имеет существенный достаток: мы увеличим нагрузку на сервер и время загрузки сайта.

Во время передачи веб-сервер может автоматически посылать заголовок Last-Modified. Но это не дает гарантии, что браузер заинтересуется этим файлом.

Единственным правильным выходом из данной ситуации будет указывать версию для CSS и JS файлов:

<link rel="stylesheet" href="https://codebeer.ru/style.css?ver=4.4" type="text/css" />

Но согласитесь, менять версию файла при каждом изменении не совсем удобно. Для WordPress я предлагаю использовать специальную функцию, которая будет автоматически добавлять в параметр ver CRC32 хеш-код файла:

function wpdocs_dequeue_script() {
    wp_register_script('jquery', get_template_directory_uri() . '/jquery.min.js', false, hash_file('crc32', get_stylesheet_directory() . '/style.css'), true);
    wp_enqueue_script('jquery');
}

Функция, которая задает версию по умолчанию для всех подключаемых файлов:

function my_wp_default_styles($styles) {
    $styles->default_version = hash_file('crc32', get_stylesheet_directory() . '/style.css');
}
add_action("wp_default_styles", "my_wp_default_styles");

Как вариант, вместо хэша можно использовать дату изменения файла:

function my_wp_default_styles($styles) {
    $styles->default_version = filemtime(get_stylesheet_directory() . '/style.css' );
}
add_action("wp_default_styles", "my_wp_default_styles");

Настроить редирект в WordPress

Для перенаправления в WordPress можно использовать встроенный в ядро редирект. Настроить редирект в WordPress с помощью функций: wp_redirect() и wp_safe_redirect(). Разница между этими функциями состоит в том, что wp_safe_redirect() дополнительно проверяет адрес в списке разрешенных хостов.

Пример как настроить 301 редирект в WordPress:

function redirect_to_home($query) {
    if(is_author()) {
         wp_redirect(home_url(), 301);
         exit;
     }
}
add_action('parse_query', 'redirect_to_home');

При переходе по адресу https://codebeer.ru/author/admin, WordPress выполнит редирект на главную страницу сайта.

В качестве обязательного аргумента для функции необходимо указать адрес страницы, на которую будет вести редирект. Это могут быть как внутренние, так и внешние страницы. Второй аргумент указывает тип редиректа.

Отключить REST API в WordPress

Начиная с WordPress 4.4 в ядро CMS добавлена поддержка REST API. Поддержка REST API выводит функционал WordPress совершенно на новый уровень, но в данный момент в большинстве случаев нет никакой необходимости. Чтобы отключить REST API в WordPress, необходимо просто добавить в файл functions.php соответствующие фильтры.

Отключить сам REST API:

add_filter('rest_enabled', '__return_false');

Отключить фильтры REST API:

remove_action('xmlrpc_rsd_apis', 'rest_output_rsd');
remove_action('wp_head', 'rest_output_link_wp_head', 10, 0);
remove_action('template_redirect', 'rest_output_link_header', 11, 0);
remove_action('auth_cookie_malformed', 'rest_cookie_collect_status');
remove_action('auth_cookie_expired', 'rest_cookie_collect_status');
remove_action('auth_cookie_bad_username', 'rest_cookie_collect_status');
remove_action('auth_cookie_bad_hash', 'rest_cookie_collect_status');
remove_action('auth_cookie_valid', 'rest_cookie_collect_status');
remove_filter('rest_authentication_errors', 'rest_cookie_check_errors', 100);

Отключить события REST API:

remove_action('init', 'rest_api_init');
remove_action('rest_api_init', 'rest_api_default_filters', 10, 1);
remove_action('parse_request', 'rest_api_loaded');

Отключить Embeds связанные с REST API:

remove_action('rest_api_init', 'wp_oembed_register_route');
remove_filter('rest_pre_serve_request', '_oembed_rest_pre_serve_request', 10, 4);