Статьи

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

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

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

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


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

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

  1. Скачать копию WordPress Plugin Boilerplate
  2. Заполните TODO с конкретной информацией для вашего собственного проекта
  3. Реализуйте код, необходимый для отображения и сохранения информации в мета-поле поста
  4. Проверьте наличие мета поста и затем отобразите его в контенте.
  5. Завершить README и локализацию

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


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

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

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

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

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

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?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 protected])
 
  This program is free software;
  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;
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this program;
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
*/
 
// TODO: rename this class to a proper name for your plugin
class PluginName {
 
    /*———————————————*
     * Constructor
     *———————————————*/
 
    /**
     * Initializes the plugin by setting localization, filters, and administration functions.
     */
    function __construct() {
 
        // Load plugin text domain
        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.
         * 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.
         * 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 translation
     */
    public function plugin_textdomain() {
 
        // TODO: replace «plugin-name-locale» with a unique value for your plugin
        load_plugin_textdomain( ‘plugin-name-locale’, false, dirname( plugin_basename( __FILE__ ) ) . ‘/lang’ );
 
    } // end plugin_textdomain
 
    /**
     * Registers and enqueues admin-specific styles.
     */
    public function register_admin_styles() {
 
        // TODO: Change ‘plugin-name’ to the name of your plugin
        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 plugin
        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 plugin
        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 plugin
        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 definition
$plugin_name = new PluginName();

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

Например:

  • Замените название плагина на сообщение
  • Замените URL плагина вашим URL по вашему выбору
  • Заполните имя, адрес электронной почты и всю личную информацию с тем, что работает
  • Назовите класс Post_Message
  • Назовите любые связанные с языком строки, имена классов и post-message идентификатора

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

  • просмотров / display.php
  • CSS / plugin.css
  • JS / admin.js
  • JS / plugin.js

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

WordPress Плагин Boilerplate Структура каталогов

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php
/*
Plugin Name: Tom McFarlin
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 McFarlin
Author URI: http://tommcfarlin.com/
Author Email: [email protected]
License:
 
  Copyright 2013 Tom McFarlin ([email protected])
 
  This program is free software;
  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;
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this program;
  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 domain
        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 translation
     */
    public function plugin_textdomain() {
        load_plugin_textdomain( ‘post-message’, false, dirname( plugin_basename( __FILE__ ) ) . ‘/lang’ );
    } // end plugin_textdomain
 
    /**
     * 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
 
new Post_Message();

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

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

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

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

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

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

01
02
03
04
05
06
07
08
09
10
11
12
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

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

1
2
3
4
5
6
7
8
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’ ) . ‘»>’ .
 
} // end post_message_display

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

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

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

1
#post-message { width: 100%;

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

Пример сообщения плагина

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

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

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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’] ) ?
 
        // If the value for the post message exists, delete it first.
        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

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

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

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

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

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

  • Зарегистрировать функцию с фильтром the_content
  • Проверьте наличие метаданных поста
  • Визуализируйте его выше содержимого, если оно присутствует

Итак, давайте сделаем это. Во-первых, давайте зарегистрируем функцию с фильтром the_content :

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
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 .
 
    } // end if
 
    return $content;
 
} // end prepend_post_message

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

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

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

Достаточно просто, не правда ли?

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
=== Post Message ===
Contributors: tommcfarlin
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 announcements above posts.
 
== Description ==
 
Post Message is a plugin that allows you to add custom messages, announcements, and notices to individual posts.
 
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 translation
 
== 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

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

Локализация плагина

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


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

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

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