Разработка плагинов с помощью Boiler-плагинов WordPress: создание плагина

17 января 2018

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

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

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


Плагин сообщений для сообщений

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

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

    Загрузить копию плагина WordPress BoilerplatenЗагрузить TODO с конкретной информацией для вашего собственного проекта. Дополните код, необходимый для отображения и сохранения информации в метатете сообщений. Проверяйте наличие метаданных и затем визуализируйте их в contentnFinish до README и Localizatio

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


Построение виджета

1. Загрузите плагин для плагинов WordPress

. Чтобы начать работу, вам нужно загрузить копию плагина WordPress Plugin. Вы можете сделать это, перейдя на страницу GitHub, а затем нажав кнопку «zip», которую вы видите в верхней части страницы, или нажав здесь.

Затем извлеките содержимое загрузки в свой каталог плагинов. Сначала он должен выписать каталог под названием плагин-шаблон.

2. Заполните TODO в Boilerplate

Затем откройте каталог сообщений в вашей любимой среде IDE. Первое, что мы хотим сделать, это открыть plugin.php, а затем найти все TODO, которые существуют в коде.

Из коробки код будет выглядеть примерно так:

<?php
/*
Plugin Name: TODO
Plugin URI: TODO
Description: TODO
Version: 1.0
Author: TODO
Author URI: TODO
Author Email: TODO
License:
  Copyright 2013 TODO (email@domain.com)
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
// TODO: rename this class to a proper name for your plugi
class Plugiame {
    /*--------------------------------------------*
     * Constructor
     *--------------------------------------------*/
    /**
     * Initializes the plugin by setting localization, filters, and administration functions.
     */
    function __construct() {
        // Load plugin text domai
        add_action( 'init', array( $this, 'plugin_textdomain' ) );
        // Register admin styles and scripts
        add_action( 'admin_print_styles', array( $this, 'register_admin_styles' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'register_admin_scripts' ) );
        // Register site styles and scripts
        add_action( 'wp_enqueue_scripts', array( $this, 'register_plugin_styles' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'register_plugin_scripts' ) );
        // Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively.
        register_activation_hook( __FILE__, array( $this, 'activate' ) );
        register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
        register_uninstall_hook( __FILE__, array( $this, 'uninstall' ) );
        /*
         * TODO:
         * Define the custom functionality for your plugin. The first parameter of the
         * add_action/add_filter calls are the hooks into which your code should fire.
         *
         * The second parameter is the function name located within this class. See the stubs
         * later in the file.
         *
         * For more information:
         * http://codex.wordpress.org/Plugin_API#Hooks.2C_Actions_and_Filters
         */
        add_action( 'TODO', array( $this, 'action_method_name' ) );
        add_filter( 'TODO', array( $this, 'filter_method_name' ) );
    } // end constructor
    /**
     * Fired when the plugin is activated.
     *
     * @param   boolean $network_wide   True if WPMU superadmin uses "Network Activate" action, false if WPMU is disabled or plugin is activated on an individual blog
     */
    public function activate( $network_wide ) {
        // TODO:    Define activation functionality here
    } // end activate
    /**
     * Fired when the plugin is deactivated.
     *
     * @param   boolean $network_wide   True if WPMU superadmin uses "Network Activate" action, false if WPMU is disabled or plugin is activated on an individual blog
     */
    public function deactivate( $network_wide ) {
        // TODO:    Define deactivation functionality here
    } // end deactivate
    /**
     * Fired when the plugin is uninstalled.
     *
     * @param   boolean $network_wide   True if WPMU superadmin uses "Network Activate" action, false if WPMU is disabled or plugin is activated on an individual blog
     */
    public function uninstall( $network_wide ) {
        // TODO:    Define uninstall functionality here
    } // end uninstall
    /**
     * Loads the plugin text domain for translatio
     */
    public function plugin_textdomain() {
        // TODO: replace "plugin-name-locale" with a unique value for your plugi
        load_plugin_textdomain( 'plugin-name-locale', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
    } // end plugin_textdomai
    /**
     * Registers and enqueues admin-specific styles.
     */
    public function register_admin_styles() {
        // TODO:    Change 'plugin-name' to the name of your plugi
        wp_enqueue_style( 'plugin-name-admin-styles', plugins_url( 'plugin-name/css/admin.css' ) );
    } // end register_admin_styles
    /**
     * Registers and enqueues admin-specific JavaScript.
     */
    public function register_admin_scripts() {
        // TODO:    Change 'plugin-name' to the name of your plugi
        wp_enqueue_script( 'plugin-name-admin-script', plugins_url( 'plugin-name/js/admin.js' ) );
    } // end register_admin_scripts
    /**
     * Registers and enqueues plugin-specific styles.
     */
    public function register_plugin_styles() {
        // TODO:    Change 'plugin-name' to the name of your plugi
        wp_enqueue_style( 'plugin-name-plugin-styles', plugins_url( 'plugin-name/css/display.css' ) );
    } // end register_plugin_styles
    /**
     * Registers and enqueues plugin-specific scripts.
     */
    public function register_plugin_scripts() {
        // TODO:    Change 'plugin-name' to the name of your plugi
        wp_enqueue_script( 'plugin-name-plugin-script', plugins_url( 'plugin-name/js/display.js' ) );
    } // end register_plugin_scripts
    /*--------------------------------------------*
     * Core Functions
     *---------------------------------------------*/
    /**
     * NOTE:  Actions are points in the execution of a page or process
     *        lifecycle that WordPress fires.
     *
     *        WordPress Actions: http://codex.wordpress.org/Plugin_API#Actions
     *        Action Reference:  http://codex.wordpress.org/Plugin_API/Action_Reference
     *
     */
    function action_method_name() {
        // TODO:    Define your action method here
    } // end action_method_name
    /**
     * NOTE:  Filters are points of execution in which WordPress modifies data
     *        before saving it or sending it to the browser.
     *
     *        WordPress Filters: http://codex.wordpress.org/Plugin_API#Filters
     *        Filter Reference:  http://codex.wordpress.org/Plugin_API/Filter_Reference
     *
     */
    function filter_method_name() {
        // TODO:    Define your filter method here
    } // end filter_method_name
} // end class
// TODO:    Update the instantiation call of your plugin to the name given at the class definitio
$plugin_name = new Plugiame();

Далее, мы должны сделать каждый TODO-плагин конкретным, поэтому мы поместим все экземпляры там, где это необходимо, с изменением имени плагина.

Например:

Заменить имя плагина с помощью Post MessageReplace URL-адрес плагина с URL-адресом choicenПоказать имя, адрес электронной почты и всю личную информацию с помощью того, что работаетNName класса Post_MessageName любых связанных с locale строк, классных имен, и ID post-message

Далее мы также удалим все вызовы JavaScript и таблиц стилей, кроме стилей admin.css. Мы будем использовать этот файл позже. Также не забудьте удалить из Boilerplate следующие файлы:

views display.phpncss plugin.cssnjs admin.jsnjs plugin.js

Это должно оставить вас со следующей структурой каталогов:

Обратите внимание, что это одно дело о Boilerplate: если что-нибудь, вы должны удалить что-то из него. Если вам нужно добавить что-то к этому, что поможет вам сбиться с земли - или это более основательно - тогда это может быть возможность улучшить его.

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

<?php
/*
Plugin Name: Tom McFarli
Plugin URI: http://tommcfarlin.com/single-post-message/
Description: A simple way to add a message at the top of each of your posts.
Version: 1.0
Author: Tom McFarli
Author URI: http://tommcfarlin.com/
Author Email: tom@tommcfarlin.com
License:
  Copyright 2013 Tom McFarlin (om@tommcfarlin.com)
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
class Post_Message {
    /*--------------------------------------------*
     * Constructor
     *--------------------------------------------*/
    /**
     * Initializes the plugin by setting localization, filters, and administration functions.
     */
    function __construct() {
        // Load plugin text domai
        add_action( 'init', array( $this, 'plugin_textdomain' ) );
        // Register admin styles and scripts
        add_action( 'admin_print_styles', array( $this, 'register_admin_styles' ) );
    } // end constructor
    /**
     * Loads the plugin text domain for translatio
     */
    public function plugin_textdomain() {
        load_plugin_textdomain( 'post-message', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
    } // end plugin_textdomai
    /**
     * Registers and enqueues admin-specific styles.
     */
    public function register_admin_styles() {
        wp_enqueue_style( 'post-message-admin', plugins_url( 'post-message/css/admin.css' ) );
    } // end register_admin_styles
} // end class
ew Post_Message();

Затем нам нужно начать работу над нашей основной бизнес-логикой.

3. Внедрить код, необходимый для отображения и сохранения информации в метатеге сообщений

Во-первых, нам нужно точно определить, как это будет работать:

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

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

add_action ('add_meta_boxes', array ($ this, 'add_notice_metabox'));

Затем нам нужно определить функцию add_notice_metabox, чтобы мы могли реально отобразить мета-поле, поэтому давайте теперь эту функцию:

function add_notice_metabox() {
    add_meta_box(
        'post_message',
        __( 'Post Message', 'post-message' ),
        array( $this, 'post_message_display' ),
        'post',
        'normal',
        'high'
    );
} // end add_notice_metabox

После этого нам нужно написать функцию, которая отвечает за фактическое отображение содержимого сообщения:

function post_message_display( $post ) {
    wp_nonce_field( plugin_basename( __FILE__ ), 'post_message_nonce' );
    // The textfield and preview area
    echo '<textarea id="post-message" name="post_message" placeholder="' . __( 'Enter your post message here. HTML accepted.', 'post-message' ) . '">' . esc_textarea( get_post_meta( $post->ID, 'post_message', true ) ) . '</textarea>';
} // end post_message_display

Выше, обратите внимание, что мы внедрили поле nonce для целей безопасности. Обратите также внимание на то, что мы дали этому textarea идентификатор пост-сообщения, чтобы мы могли легко стилизовать его с помощью CSS, и мы дали ему имя post_message, которое пригодится, поскольку мы сохраняем содержимое текстового поля до определенного метаданные.

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

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

#post-message { width: 100%; }

Это должно привести к следующему:

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

Итак, последнее, что нам нужно сделать, это ввести функцию save_notice. Сначала мы зарегистрируем это в конструкторе со следующим кодом:

add_action ('save_post', array ($ this, 'save_notice'));

Затем мы определим следующую функцию:

function save_notice( $post_id ) {
    if ( isset( $_POST['post_message_nonce'] ) &&isset( $_POST['post_type'] ) ) {
        // Don't save if the user hasn't submitted the changes
        if ( defined( 'DOING_AUTOSAVE' ) &&DOING_AUTOSAVE ) {
            return;
        } // end if
        // Verify that the input is coming from the proper form
        if ( ! wp_verify_nonce( $_POST['post_message_nonce'], plugin_basename( __FILE__ ) ) ) {
            return;
        } // end if
        // Make sure the user has permissions to post
        if ( 'post' == $_POST['post_type'] ) {
            if ( ! current_user_can( 'edit_post', $post_id ) ) {
                return;
            } // end if
        } // end if/else
        // Read the post message
        $post_message = isset( $_POST['post_message'] ) ? $_POST['post_message'] : '';
        // If the value for the post message exists, delete it first. Don't want to write extra rows into the table.
        if ( 0 == count( get_post_meta( $post_id, 'post_message' ) ) ) {
            delete_post_meta( $post_id, 'post_message' );
        } // end if
        // Update it for this post.
        update_post_meta( $post_id, 'post_message', $post_message );
    } // end if
} // end save_notice

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

Verifies, что пользователь имеет разрешение на сохранить эту информацию. Определяет любые существующие метаданные. Сохраняет данные в связанную запись meta data

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

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

4. Оформить уведомление по почте

Затем мы готовы отобразить сообщение в контенте. Процесс для этого будет выглядеть следующим образом:

Проверьте функцию с файлом fil_file_content Проверьте наличие метаданных в почтовом ящике над содержимым, если оно присутствует

Итак, давайте сделаем именно это. Сначала зарегистрируем функцию с фильтром the_content:

add_filter ('the_content', array ($ this, 'prepend_post_message'));

После этого давайте настроим фактическую функцию:

function prepend_post_message( $content ) {
    // If there is a notice, prepend it to the content
    if ( '' != get_post_meta( get_the_ID(), 'post_message', true ) ) {
        $post_message = '<p class="post-message">';
        $post_message .= get_post_meta( get_the_ID(), 'post_message', true );
        $post_message .= '</p><!-- /.post-message -->';
        $content = $post_message . $content;
    } // end if
    return $content;
} // end prepend_post_message

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

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

Затем удалите содержимое сообщения, а затем убедитесь, что ничего не отображается.

Достаточно легко, не так ли?

5. Завершите README и локализацию

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

Во-первых, README должен содержать обычную информацию. Это в значительной степени субъективно; однако я привел пример README ниже:

=== Post Message ===
Contributors: tommcfarli
Donate link: http://tommcfarlin.com/single-post-message/
Tags: post
Requires at least: 3.4.1
Tested up to: 3.5
Stable tag: 1.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Easily add short messages and aouncements above posts. Displays in the RSS feed and on the blog.
== Description ==
Post Message is a plugin that allows you to add custom messages, aouncements, and notices to individual posts. It's styled to grab the reader's attention and will render in both the browser *and* in RSS readers.
Post Message...
* Supports the use of HTML tags in the message content
* Is available directly under the post content editor
* Is fully localized and ready for translatio
== Installation ==
= Using The WordPress Dashboard =
1. Navigate to the 'Add New' Plugin Dashboard
1. Select `post-message.zip` from your computer
1. Upload
1. Activate the plugin on the WordPress Plugin Dashboard
= Using FTP =
1. Extract `post-message.zip` to your computer
1. Upload the `post-messsage` directory to your `wp-content/plugins` directory
1. Activate the plugin on the WordPress Plugins dashboard
== Changelog ==
= 1.0 =
* Initial release

И, наконец, локализация должна быть cinch: просто откройте файл `plugin.po` в каталоге` lang` в вашей среде IDE, убедитесь, что вы изменили имя плагина и информацию об авторе, затем откройте его в POEdit, чтобы зарегистрируйте файлы локализации.

Сохраните свою работу, и вы готовы к работе!


Заключение

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

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

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