Статьи

Часть 2. Плагин WordPress для плагинов: Разработка плагина

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

Эта статья будет посвящена созданию и активации плагина, а также развитию функциональности плагина для администратора. Чтобы следовать этому руководству, вам понадобится базовое понимание PHP и WordPress, а также практические знания API плагинов WordPress .

О плагине

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

Подготовка Boilerplate

Как упоминалось в первой статье, мы можем либо загрузить свежую копию Boilerplate и выполнить поиск и заменить себя, либо мы можем использовать неофициальный генератор WordPress Plugin Boilerplate Generator для ускорения процесса. Давайте использовать генератор для нашего плагина.

Зайдите на сайт WordPress Plugin Boilerplate Generator и заполните форму с соответствующими значениями. Давайте просто назовем наш плагин «Устаревшее уведомление». Вот пример формы с заполненными полями.

WordPress плагин Boilerplate

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

Нажмите кнопку «Создать», и вы получите красивую, настраиваемую копию шаблона WordPress Plugin Boilerplate.

Установка и активация плагина

Сгенерированный zip-архив будет содержать две ожидаемые директории, assets и trunk . Мы не собираемся использовать маршрут symlink при установке нашего плагина, поэтому извлеките папку trunk из архива и скопируйте ее в каталог wp-content/plugins .

Нам все еще нужно переименовать его соответствующим образом, чтобы избежать конфликта имен с другими плагинами, поэтому мы переименуем директорию trunk в outdated-notice .

Если вы сейчас перейдете в раздел «Установленные плагины» в wp-admin , то наверняка увидите, что ваш плагин находится в списке установленных, но еще не активированных плагинов. Генератор плагина Boilerplate ничего не меняет в отношении описания плагина, поэтому, если мы хотим его изменить, мы можем просто отредактировать описание в основном файле плагина, в нашем случае, outdated-notice.php .

Наш плагин Boilerplate

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

Добавление страницы параметров

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

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

Давайте начнем с добавления страницы параметров для нашего плагина.

Откройте class-oudated-notice-admin.php внутри вашей папки admin . Нам нужно изменить этот класс, чтобы позволить нам зарегистрировать страницу настроек для нашего плагина. Добавьте этот публичный метод в конец класса.

 /** * Add an options page under the Settings submenu * * @since 1.0.0 */ public function add_options_page() { $this->plugin_screen_hook_suffix = add_options_page( __( 'Outdated Notice Settings', 'outdated-notice' ), __( 'Outdated Notice', 'outdated-notice' ), 'manage_options', $this->plugin_name, array( $this, 'display_options_page' ) ); } 

Следует отметить одну вещь: поскольку мы используем классы для определения наших хуков, нам нужно передать массив в виде array( <class instance>, <class method ) вместо прямого указания, какая функция должна быть вызвана. Единственное правило, которое необходимо соблюдать, это то, что метод должен быть общедоступным.

Мы еще не совсем закончили! Как мы видим, add_options_page требует допустимой функции обратного вызова, которую мы еще не определили в нашем классе Outdated_Notice_Admin . Давайте добавим это. Это должно быть достаточно просто, так как мы собираемся использовать предоставленный outdated-notice-admin-display.php включенный в нашу папку admin/partials . Итак, все, что нам нужно сделать для нашей функции обратного вызова, это включить этот файл.

 /** * Render the options page for plugin * * @since 1.0.0 */ public function display_options_page() { include_once 'partials/outdated-notice-admin-display.php'; } 

Это должно сделать это. Последнее, что нам нужно сделать сейчас, это правильно загрузить его, используя предоставленный класс загрузчика в Boilerplate. Откройте ваш class-outdated-notice.php в папке class-outdated-notice.php и добавьте дополнительный хук, который мы определили ранее, в методе define_admin_hooks . Правильное действие, которое нужно включить в нашу страницу настроек, это admin_menu так что давайте добавим его.

 $this->loader->add_action( 'admin_menu', $plugin_admin, 'add_options_page' ); 

Теперь вы должны увидеть дополнительное подменю «Уведомление об устаревших» в разделе «Настройки». Вы можете получить доступ к пустой странице параметров, перейдя по URL-адресу http://<our-site-url>/wp-admin/options-general.php?page=outdated-notice .

Пока это пустая страница, поэтому давайте начнем заполнять частичный файл правильной разметкой.

Регистрация, сохранение и получение значений настроек

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

Вот разбивка того, что мы собираемся сделать в этом разделе:

  1. Зарегистрируйте крюк с помощью загрузчика Boilerplate
  2. Зарегистрировать раздел настроек
  3. Зарегистрируйте два поля настроек (пороговые дни и положение текста)
  4. Зарегистрируйте две настройки
  5. Заполните страницу параметров
  6. Сохранение и повторное заполнение полей для отображения.

Зарегистрируйте крюк на загрузчике

Давайте пройдемся по всем шагам один за другим.

Чтобы зарегистрировать раздел настроек, нам нужно использовать функцию register_setting . Правильный крюк для инициализации этой функции — admin_init . Итак, сначала мы собираемся добавить еще один хук в загрузчик define_admin_hooks чтобы зарегистрировать наши настройки в методе define_admin_hooks нашего основного класса Boilerplate, класса Outdated_Notice .

 $this->loader->add_action( 'admin_init', $plugin_admin, 'register_setting' ); 

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

 /** * The options name to be used in this plugin * * @since 1.0.0 * @access private * @var string $option_name Option name of this plugin */ private $option_name = 'outdated_notice'; 

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

Далее нужно реально зарегистрировать раздел настроек, поле настроек и отдельные настройки. Снова откройте класс Outdated_Notice_Admin и добавьте в него открытый метод register_setting .

Зарегистрировать раздел настроек

Внутри публичного метода register_setting мы собираемся зарегистрировать раздел настроек. Я не буду слишком углубляться в различные функции и API, чтобы сделать это, так как Кодекс уже предоставил достаточно информации для начала. Поскольку настройки нашего плагина относительно просты, мы собираемся зарегистрировать только один раздел.

Этот фрагмент позволит нам зарегистрировать раздел «Общие» для нашей страницы параметров, используя функцию add_settings_section .

 // Add a General section add_settings_section( $this->option_name . '_general', __( 'General', 'outdated-notice' ), array( $this, $this->option_name . '_general_cb' ), $this->plugin_name ); 

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

Мы собираемся добавить еще один публичный метод outdated_notice_general_cb который будет отображать основную информацию об этом разделе.

 /** * Render the text for the general section * * @since 1.0.0 */ public function outdated_notice_general_cb() { echo '<p>' . __( 'Please change the settings accordingly.', 'outdated-notice' ) . '</p>'; } 

Зарегистрируйте два поля настроек (пороговые дни и положение текста)

Следующая часть API настроек, которую нам нужно использовать, — это регистрация фактического поля, которое будет отображаться на странице параметров. Это может быть достигнуто с add_settings_field функции add_settings_field .

Мы будем использовать переключатели для настройки положения текста. Это делается путем добавления этого кода в register_setting у нас функцию register_setting .

 add_settings_field( $this->option_name . '_position', __( 'Text position', 'outdated-notice' ), array( $this, $this->option_name . '_position_cb' ), $this->plugin_name, $this->option_name . '_general', array( 'label_for' => $this->option_name . '_position' ) ); 

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

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

 ** * Render the radio input field for position option * * @since 1.0.0 */ public function outdated_notice_position_cb() { ?> <fieldset> <label> <input type="radio" name="<?php echo $this->option_name . '_position' ?>" id="<?php echo $this->option_name . '_position' ?>" value="before"> <?php _e( 'Before the content', 'outdated-notice' ); ?> </label> <br> <label> <input type="radio" name="<?php echo $this->option_name . '_position' ?>" value="after"> <?php _e( 'After the content', 'outdated-notice' ); ?> </label> </fieldset> <?php } 

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

 add_settings_field( $this->option_name . '_day', __( 'Post is outdated after', 'outdated-notice' ), array( $this, $this->option_name . '_day_cb' ), $this->plugin_name, $this->option_name . '_general', array( 'label_for' => $this->option_name . '_day' ) ); 

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

 /** * Render the treshold day input for this plugin * * @since 1.0.0 */ public function outdated_notice_day_cb() { echo '<input type="text" name="' . $this->option_name . '_day' . '" id="' . $this->option_name . '_day' . '"> '. __( 'days', 'outdated-notice' ); } 

Зарегистрируйте настройки

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

 register_setting( $this->plugin_name, $this->option_name . '_position', array( $this, $this->option_name . '_sanitize_position' ) ); register_setting( $this->plugin_name, $this->option_name . '_day', 'intval' ); 

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

Для ежедневной дезинфекции мы будем использовать встроенную функцию PHP, intval как этого достаточно в нашем случае. Что касается позиции текстового уведомления, мы собираемся определить нашу собственную функцию обратного вызова санации, которая позволит сохранять в базе данных только определенные значения. Это особенно полезно при работе с опциями, которые ограничены конкретными значениями, например, в этом случае, когда мы принимаем только два значения, которые находятся before и after , поэтому наш обратный вызов очистки должен быть уверен, что если значение не является одним из они не будут сохранены в базе данных.

Вот простая функция обратного вызова для очистки:

 /** * Sanitize the text position value before being saved to database * * @param string $position $_POST value * @since 1.0.0 * @return string Sanitized value */ public function outdated_notice_sanitize_position( $position ) { if ( in_array( $position, array( 'before', 'after' ), true ) ) { return $position; } } 

Заполните страницу параметров

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

Откройте outdated-notice-admin-display.php в папке admin/partials . Вот как мы можем отобразить страницу параметров на основе настроек, которые мы зарегистрировали ранее.

 <div class="wrap"> <h2><?php echo esc_html( get_admin_page_title() ); ?></h2> <form action="options.php" method="post"> <?php settings_fields( $this->plugin_name ); do_settings_sections( $this->plugin_name ); submit_button(); ?> </form> </div> 

С простой комбинацией функций do_settings_sections и settings_fields ваша страница параметров будет создана в do_settings_sections сроки.

Давайте сделаем перерыв и обновим страницу параметров.

Наш плагин

Сохранение и заполнение полей

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

 var_dump(get_option( $this->option_name . '_position' )); var_dump(get_option( $this->option_name . '_day' )); 

Мы должны получить некоторые значения из базы данных, как показано в примере ниже:

 string(5) "after" string(2) "90" 

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

Давайте сначала займемся переключателями. В качестве ярлыка, мы просто собираемся использовать checked функцию, предоставляемую WordPress, чтобы отметить выбранное ранее значение. Наш outdated_notice_position_cb нуждается в некоторой модификации.

Вот обновленный фрагмент для обратного вызова.

 /** * Render the radio input field for position option * * @since 1.0.0 */ public function outdated_notice_position_cb() { $position = get_option( $this->option_name . '_position' ); ?> <fieldset> <label> <input type="radio" name="<?php echo $this->option_name . '_position' ?>" id="<?php echo $this->option_name . '_position' ?>" value="before" <?php checked( $position, 'before' ); ?>> <?php _e( 'Before the content', 'outdated-notice' ); ?> </label> <br> <label> <input type="radio" name="<?php echo $this->option_name . '_position' ?>" value="after" <?php checked( $position, 'after' ); ?>> <?php _e( 'After the content', 'outdated-notice' ); ?> </label> </fieldset> <?php } [php] <p>Notice that we are retrieving the value back from the database and assigning it to the <code>$position</code> variable before using it in the <code>checked</code> function for the radio buttons.</p> <p>Next we are going to modify the <code>outdated_notice_day_cb</code> function.</p> [php] /** * Render the treshold day input for this plugin * * @since 1.0.0 */ public function outdated_notice_day_cb() { $day = get_option( $this->option_name . '_day' ); echo '<input type="text" name="' . $this->option_name . '_day' . '" id="' . $this->option_name . '_day' . '" value="' . $day . '"> ' . __( 'days', 'outdated-notice' ); } 

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

Дальнейшие улучшения

Это ни в коем случае не завершено. Мы всегда можем улучшить функциональность этого плагина для администратора. Вот некоторые вещи, о которых я могу думать:

  • Очистка кода — плагин WordPress Boilerplate поставляется с множеством полезных функций, но в нашем случае загрузка на стороне администратора, CSS и JS совершенно не нужна. Мы всегда можем удалить это из нашей кодовой базы, чтобы сделать ее меньше.
  • i18n (Интернационализация) готова — Хотя в нашем плагине мы широко используем __() и _e() , мы на самом деле не проходим сам процесс i18n. Я не буду описывать процесс здесь, так как эта тема довольно широко обсуждалась в SitePoint, например, в этой статье .
  • Более точный выбор — поскольку наша реализация будет применяться ко всем публикациям, мы можем дополнительно оптимизировать ее для применения к публикации в определенной категории или к сообщениям с определенными тегами в них.

Полный код можно посмотреть в этом репозитории GitHub , в ветке part-2 .

Вывод

Мы создали плагин с базовыми функциями для администратора, зарегистрировав соответствующие настройки и создав страницу параметров для пользователя, чтобы настроить наш плагин. За относительно короткое время, используя шаблон WordPress Plugin Boilerplate, мы достигли этого, не ставя под угрозу качество кода и все же придерживаясь лучших практик, рекомендованных WordPress.

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