Плагин WordPress. Исключаем ненужные категории.

Владимир | | HTML, PHP, Web разработка, WordPress.

wordpress plugin exclude categories

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

Я не буду утверждать, что создание плагинов для WP простой и интуитивно понятный процесс, но и назвать его сверхсложным я тоже не могу. Есть свои нюансы, к которым нужно привыкнуть.

В этот раз я хочу рассказать о разработке несложного плагина, позволяющего исключать записи из определённых категорий с главной страницы и из RSS ленты.

Для чего это может понадобиться.

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

2) Вы занимаетесь размещением платных статей. Тут вообще всё просто. Постоянные читатели вряд ли оценят seo'шную статью о преимуществах очередного интернет магазина 🙂 В тоже время, монетизировать блог как-то нужно.

Возвращаемся к реализации.

Сразу даю ссылку на архив

Source

UPD. Плагин обновлен для использования с WP 3.1.

Вообще-то, я нашел несколько готовых плагинов с похожим функционалом. Но по разным причинам они меня не устроили. Возможности некоторых были явно избыточны (для меня), другие работали не совсем так, как мне хотелось. Поэтом я решил сделать свой вариант.

Установка и подключение точно такие же, как и у большинства плагинов. Архив нужно распаковать в папку wp-content\plugins и активировать в панели у правления. После этого в разделе Settings появится страница с настройками плагина.

wp plugin exclude categories admin

Отмечаете нужные категории, и решаете где их не нужно показывать.

Теперь разберем реализацию плагина.

Начало стандартное.

/*
Plugin Name: Exclude Category Plugin
Plugin URI: https://www.simplecoding.org/plagin-wordpress-isklyuchaem-nenuzhnye-kategorii.html
Description: Позволяет убрать посты указанных категорий с главной страницы и из RSS ленты.
Version: 1.0
Author: Statsenko Vladimir
Author URI: https://www.simplecoding.org
*/

Этот комментарий содержит данные, которые отображаются на панели управления плагинами.

Создание страницы в панели управления.

Нам нужно выполнить два действия: создать новый пункт в меню Settings и создать форму с настройками плагина.

Начнём с создания формы.

  1. <?php
  2. function ec_settings_page() {
  3.   //получаем список категорий
  4.   $categories = get_categories(array('hide_empty' => false));
  5. ?>
  6. <div class="wrap">
  7.   <h2>Exclude Category Plugin Settings</h2>
  8.   <form method="post" action="options.php">
  9.     <?php
  10.       //Необходимо для автоматической обработки формы
  11.       settings_fields( 'ec-settings-group' );
  12.     ?>
  13.     <table class="form-table">
  14.       <tbody>
  15.         <tr valign="top">
  16.           <th scope="row">Выберите категории, которые нужно исключить</th>
  17.           <td>
  18.             <fieldset>
  19.               <legend class="screen-reader-text"><span>Выберите категории, которые нужно исключить</span></legend>
  20.             <?php
  21.               //читаем значение текущее опции
  22.               $curCL = get_option('cats_list');
  23.               foreach ($categories as $category) {
  24.                 $checked = '';
  25.                 if (is_array($curCL) && in_array($category->cat_ID, $curCL)) {
  26.                   $checked = 'checked="checked"';
  27.                 }
  28.                 echo '<label><input '.$checked.' type="checkbox" name="cats_list[]" value="'.$category->cat_ID.'" /> '.$category->name.'</label><br />';
  29.               }
  30.             ?>
  31.             </fieldset>
  32.           </td>
  33.         </tr>
  34.         <tr valign="top">
  35.           <th scope="row">Не выводить выбранные категории</th>
  36.           <td>
  37.             <fieldset>
  38.               <legend class="screen-reader-text"><span>Не выводить выбранные категории</span></legend>
  39.               <?php
  40.                 $curCH = get_option('cats_home');
  41.                 $cH = $cF = '';
  42.                 if (is_array($curCH)) {
  43.                   $cH = in_array('home', $curCH) ? 'checked="checked"' : '';
  44.                   $cF = in_array('feed', $curCH) ? 'checked="checked"' : '';
  45.                 }
  46.               ?>
  47.               <label><input type="checkbox" <?php echo $cH; ?> name="cats_home[]" value="home" /> на главной</label><br />
  48.               <label><input type="checkbox" <?php echo $cF; ?> name="cats_home[]" value="feed" /> в RSS ленте</label>
  49.             </fieldset>
  50.           </td>
  51.         </tr>
  52.       </tbody>
  53.     </table>
  54.     <p class="submit"><input type="submit" class="button-primary" value="Сохранить" /></p>
  55.   </form>
  56. </div>
  57.  
  58. <?php
  59. }
  60. ?>

* This source code was highlighted with Source Code Highlighter.

Получилась она довольно объёмной, но в основном из-за разметки. Кода совсем немного.

С разметкой формы ситуация следующая. По большому счёту, она может быть любой. Но, если вы хотите, чтобы ваша страница с настройками выглядела так же, как и остальная часть админки, то, нужно просто копировать их разметку со страниц с похожими формами. Что я и сделал.

Перед отображением формы мы получаем список всех постов с помощью функции get_categories. Внутри формы создаём группу чекбоксов для них. Атрибут name у этой группы имеет значение cats_list[].

Вторая группа чекбоксов позволяет указать, откуда нужно исключить записи. У неё атрибут name равен cats_home[].

Теперь обратите внимание на функцию settings_fields('ec-settings-group'), которую мы вызываем сразу после открытия формы. Она создаёт несколько скрытых полей, с помощью которых автоматически выполняется сохранение данных, введённых в форму.

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

function register_ec_settings() {
	register_setting( 'ec-settings-group', 'cats_list' );
	register_setting( 'ec-settings-group', 'cats_home' );
}

В первом параметре функции register_setting передаём имя группы (оно должно совпадать с параметром, переданным settings_fields). Во втором параметре указываем атрибут name группы чекбоксов.

Теперь, при сохранении формы данные автоматически будут записаны в таблицу wp_options (при этом выполняется их сериализация).

Получить сохранённые данные можно с помощью функции settings_fields. Что мы и делаем перед формированием списка чекбоксов в форме. Проверку, есть ли текущая категория среди выбранных ранее, выполняем с помощью функции is_array.

Добавляем новый пункт в меню Settings

  1. //создаём подменю Settings->Exclude Category Plugin и соответствующую форму
  2.  
  3. //регистрируем функцию создания меню
  4. add_action('admin_menu', 'ec_create_menu');
  5.  
  6. //функция создания меню
  7. function ec_create_menu() {
  8.   add_submenu_page('options-general.php'
  9.            ,'Exclude Category Plugin Settings'
  10.            , 'Exclude Category'
  11.            , 'edit_plugins'
  12.            , __FILE__
  13.            , 'ec_settings_page');
  14.   
  15.   //Регистрируем функцию register_ec_settings. Она нужна для автоматической
  16.   //обработки формы с настройками
  17.   add_action( 'admin_init', 'register_ec_settings' );
  18. }

* This source code was highlighted with Source Code Highlighter.

Сам пункт создаётся с помощью функции add_submenu_page, в параметрах которой необходимо указать различные настройки. Перечислять их все я не буду, лучше дам ссылку на статью с подробным описанием. Но, обратите внимание, что в последнем параметре указано имя функции, создающей форму.

Для того, чтобы WP создал меню, нужно добавить действие (add_action). В её первом параметре мы указываем название действия в котором мы хотим выполнить наш код (в данном случае это admin_menu), во втором параметре – имя функции, которую нужно выполнить, именно в ней должен быть вызов add_submenu_page. Кроме того, в этой функции мы добавляем еще одно действие — admin_init, и в нём регистрируем обработчик register_ec_settings.

На данном этапе у нас есть рабочая форма в админке с двумя наборами чекбоксов. Все отмеченные чекбоксы сохраняются в базе данных (таблица wp_options) и доступ к ним можно получить с помощью get_option('cats_home') и get_option('cats_list').

Рассмотрим принцип удаления постов.

Список постов движок WP получает из базы данных с помощью обычного запроса. Т.е. нам нужно добавить к этому запросу условия, которые исключат ненужные нам категории.

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

add_filter('pre_get_posts','ec_exclude');

Событие pre_get_posts возникает как раз перед отправкой запроса, а ec_exclude – название нашей функции, причем в первом её параметре WP передаст объект с запросом. Рассмотрим её подробнее.

  1. function ec_exclude($query) {
  2.   //читаем массивы с опциями
  3.   if (is_array($target = get_option('cats_home'))) {
  4.     if (is_array($categories = get_option('cats_list'))) {
  5.       //добавляем к id категорий знак "-"
  6.       foreach ($categories as $i => $category) {
  7.         $categories[$i] = '-'.$categories[$i];
  8.       }
  9.       //формируем строку с перечнем категорий
  10.       $cat_string = implode(',', $categories);
  11.       //удаляем посты указанных категорий из RSS ленты
  12.       if (in_array('feed', $target) && $query->is_feed) {
  13.         $query->set('cat',$cat_string);
  14.       }
  15.       //удаляем посты указанных категорий с главной страницы
  16.       if (in_array('home', $target) && $query->is_home) {
  17.         $query->set('cat',$cat_string);
  18.       }
  19.     }
  20.   }
  21.   return $query;
  22. }

* This source code was highlighted with Source Code Highlighter.

Исключить ненужные категории можно с помощью метода set.
Например:

$query->set('cat', '-1,-2,-5');

Здесь 1, 2, 5 – id категорий в БД, знак минус означает, что категории нужно исключить.

Обратите внимание. UPD. Плагин обновлен для использования с WP 3.1.
Теперь используется параметр. В качестве значения передается исходный архив с категориями, которые нужно исключить

$query->set('category__not_in',$categories);

В самой функции ec_exclude мы проверяем, указаны ли страницы, с которых нужно убрать посты и список ненужных категорий (с помощью get_option('cats_home') и get_option('cats_list')).

Если эти опции установлены, то формируем строку с id категорий $cat_string и передаём её методу set. При этом с $query->is_home и помощью $query->is_feed проверяем, какая страница в данный момент формируется.

Не зависимо от того, вносили мы изменения в запрос или нет, функция ec_exclude обязательно должна вернуть объект $query, иначе сформировать страницу не получится.

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

Все замечания, вопросы и предложения пишите в комментариях. Постараюсь ответить 😉