Статьи

Создание пользовательских страниц администрирования WordPress, часть 3

В этой серии мы рассмотрели, как создавать собственные страницы администрирования в WordPress без использования API настроек . Это не означает, что API настроек бесполезен ( потому что это так !), Но могут быть случаи, когда нам необходимо реализовать некоторые пользовательские функции или более специализированные реализации функций, которые недоступны в доступных API.

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

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

Хотя я не могу суммировать все, что мы рассмотрели в этой серии, я могу убедиться, что выделил важные моменты.

  • Мы представили основной плагин и добавили элемент подменю и страницу параметров для плагина в панели управления WordPress.
  • Мы обсудили принцип единой ответственности и роль, которую он играет в нашем развитии.
  • Был добавлен единственный элемент input , который будет принимать пользовательский ввод.
  • Мы добавили значение nonce на страницу, но на самом деле ничего с этим не сделали.

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

Как и в других статьях, я предполагаю, что на вашем компьютере настроена локальная среда разработки WordPress.

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

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

Однако, если вы что-то запутали в коде и учебник не объясняет, что происходит, оставьте комментарий, и я обязательно с вами свяжусь.

Давайте начнем.

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

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

В частности, мы будем заниматься следующими темами:

  • Мы собираемся проверить значение nonce, которое мы создали и определили в предыдущем уроке, чтобы понять, как работает один компонент безопасности WordPress.
  • Мы проверим, что у существующего пользователя есть разрешение на фактическую отправку информации (и запретим ему делать это, если они этого не делают).
  • Если отправка защищена, и у пользователя есть разрешение, мы затем очистим информацию, чтобы убедиться, что вредоносный контент не попадет в базу данных.

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

Напомним из предыдущего поста, мы воспользовались функцией WordPress API wp_nonce_field . Эта конкретная функция делает следующее:

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

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

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

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

Запускает аутентифицированный запрос администратора, когда не было предоставлено никаких действий.

Вспомните из наших предыдущих обсуждений, однако, что мы не хотим перегружать наши классы с большей ответственностью, чем необходимо. Помните, вопрос, который мы должны постоянно задавать себе: «Какую причину должен изменить этот класс?»

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

Класс Serializer в нашем каталоге плагинов

Как видите, я назвал свой файл class-serializer.php . Мы знаем из опыта и из приведенного выше кода, что потребуется подключиться к admin_post упомянутому выше, и мы знаем, что нам понадобится функция, отвечающая за сохранение информации.

Давайте определим это сейчас.

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
<?php
/**
 * Performs all sanitization functions required to save the option values to
 * the database.
 *
 * @package Custom_Admin_Settings
 */
 
/**
 * Performs all sanitization functions required to save the option values to
 * the database.
 *
 * This will also check the specified nonce and verify that the current user has
 * permission to save the data.
 *
 * @package Custom_Admin_Settings
 */
class Serializer {
 
    public function init() {
        add_action( ‘admin_post’, array( $this, ‘save’ ) );
    }
 
    public function save() {
 
        // First, validate the nonce.
        // Secondly, verify the user has permission to save.
        // If the above are valid, save the option.
 
    }
}

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

Прежде чем мы добавим какую-либо функциональность, давайте продолжим и настроим это при первой загрузке нашего плагина. Сначала верните custom-admin-settings.php . Теперь, на этом этапе, мы должны спросить себя, должен ли какой-либо из наших существующих классов иметь Serializer в качестве зависимости.

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

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?php
 
add_action( ‘plugins_loaded’, ‘tutsplus_custom_admin_settings’ );
/**
 * Starts the plugin.
 *
 * @since 1.0.0
 */
function tutsplus_custom_admin_settings() {
 
    $serializer = new Serializer();
    $serializer->init();
 
    $plugin = new Submenu( new Submenu_Page( $serializer ) );
    $plugin->init();
 
}

После этого мы готовы продолжить сохранение наших опций.

Вернемся к Serializer . Теперь, когда мы подключили его к остальной части плагина, пришло время написать некоторый код, поэтому, как следует из комментария, давайте проверим значение nonce, которое мы создали во внешнем интерфейсе.

К счастью, WordPress делает это легко благодаря встроенной функции API: wp_verify_nonce . Эта функция принимает два аргумента:

  1. Действие
  2. Название

Если вы помните предыдущую статью, мы использовали acme-settings-save качестве нашего действия и acme-custom-message качестве значения nonce. Чтобы проверить это, нам нужно проверить, существует ли он в коллекции $_POST и проходит ли он собственные проверки WordPress.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
 
/**
 * Determines if the nonce variable associated with the options page is set
 * and is valid.
 *
 * @access private
 *
 * @return boolean False if the field isn’t set or the nonce value is invalid;
 * otherwise, true.
 */
private function has_valid_nonce() {
 
    // If the field isn’t even in the $_POST, then it’s invalid.
    if ( ! isset( $_POST[‘acme-custom-message’] ) ) { // Input var okay.
        return false;
    }
 
    $field = wp_unslash( $_POST[‘acme-custom-message’] );
    $action = ‘acme-settings-save’;
 
    return wp_verify_nonce( $field, $action );
 
}

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

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

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

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

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

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

Но сначала возникает вопрос: если пользователь не может сохранить параметры, почему ему следует разрешить фактически видеть страницу в первую очередь?

Если вы помните, что ранее в этой серии мы написали следующий фрагмент кода:

01
02
03
04
05
06
07
08
09
10
11
12
<?php
 
public function add_options_page() {
 
    add_options_page(
        ‘Tuts+ Custom Administration Page’,
        ‘Custom Administration Page’,
        ‘manage_options’,
        ‘custom-admin-page’,
        array( $this->submenu_page, ‘render’ )
    );
}

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

Теперь мы можем обновить условное выражение, где мы также проверяем значение nonce также для проверки разрешения текущего пользователя:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?php
 
/**
 * Validates the incoming nonce value, verifies the current user has
 * permission to save the value from the options page and saves the
 * option to the database.
 */
public function save() {
 
    // First, validate the nonce and verify the user as permission to save.
    if ( ! ( $this->has_valid_nonce() && current_user_can( ‘manage_options’ ) ) ) {
        // TODO: Display an error message.
    }
 
    // If the above are valid, save the option.
 
}

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

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

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

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

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

В нашем коде мы будем использовать sanitize_text_field (как указано выше). Эта функция будет делать следующее:

  • Проверяет на недействительность UTF-8
  • Преобразует отдельные символы `<` в сущности
  • Удаляет все метки
  • Удаляет разрывы строк, вкладки и лишние пробелы
  • Полоски октетов

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?php
/**
 * Validates the incoming nonce value, verifies the current user has
 * permission to save the value from the options page and saves the
 * option to the database.
 */
public function save() {
 
    // First, validate the nonce and verify the user as permission to save.
    if ( ! ( $this->has_valid_nonce() && current_user_can( ‘manage_options’ ) ) ) {
        // TODO: Display an error message.
    }
 
    // If the above are valid, sanitize and save the option.
    if ( null !== wp_unslash( $_POST[‘acme-message’] ) ) {
 
        $value = sanitize_text_field( $_POST[‘acme-message’] );
        update_option( ‘tutsplus-custom-data’, $value );
 
    }
}

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

В этой статье я предпочитаю использовать ключ tutsplus-custom-data . Что бы вы ни использовали, важно, чтобы к нему добавлялось что-то уникальное, чтобы другой плагин или тема не перезаписывали опцию и вы не перезаписывали существующую опцию.

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

Сначала создайте функцию с именем redirect и убедитесь, что она выглядит следующим образом:

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
<?php
/**
 * Redirect to the page from which we came (which should always be the
 * admin page.
 * the login page.
 *
 * @access private
 */
private function redirect() {
 
    // To make the Coding Standards happy, we have to initialize this.
    if ( ! isset( $_POST[‘_wp_http_referer’] ) ) { // Input var okay.
        $_POST[‘_wp_http_referer’] = wp_login_url();
    }
 
    // Sanitize the value of the $_POST collection for the Coding Standards.
    $url = sanitize_text_field(
        wp_unslash( $_POST[‘_wp_http_referer’] ) // Input var okay.
    );
 
    // Finally, redirect back to the admin page.
    wp_safe_redirect( urldecode( $url ) );
    exit;
 
}

Приведенный выше код должен быть понятен, но чтобы убедиться, что он понятен, он делает следующее:

  1. Он проверяет наличие частного значения WordPress в коллекции $_POST . Если он не установлен, он будет установлен равным URL входа в WordPress. Это заставит людей заходить на страницу входа, если реферальный URL не задан; Однако нет причин, почему это не должно быть.
  2. Далее мы берем реферер и очищаем данные. Это то, чего требуют стандарты кодирования, и это гарантирует, что данные чисты.
  3. Наконец, мы инициализируем wp_safe_redirect для URL, чтобы мы вернулись на страницу параметров.

Как только все это будет сделано, добавьте это как последнюю строку в функции save выше. Окончательная версия кода должна выглядеть так:

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php
/**
 * Performs all sanitization functions required to save the option values to
 * the database.
 *
 * @package Custom_Admin_Settings
 */
 
/**
 * Performs all sanitization functions required to save the option values to
 * the database.
 *
 * This will also check the specified nonce and verify that the current user has
 * permission to save the data.
 *
 * @package Custom_Admin_Settings
 */
class Serializer {
 
    /**
     * Initializes the function by registering the save function with the
     * admin_post hook so that we can save our options to the database.
     */
    public function init() {
        add_action( ‘admin_post’, array( $this, ‘save’ ) );
    }
 
    /**
     * Validates the incoming nonce value, verifies the current user has
     * permission to save the value from the options page and saves the
     * option to the database.
     */
    public function save() {
 
        // First, validate the nonce and verify the user as permission to save.
        if ( ! ( $this->has_valid_nonce() && current_user_can( ‘manage_options’ ) ) ) {
            // TODO: Display an error message.
        }
 
        // If the above are valid, sanitize and save the option.
        if ( null !== wp_unslash( $_POST[‘acme-message’] ) ) {
 
            $value = sanitize_text_field( $_POST[‘acme-message’] );
            update_option( ‘tutsplus-custom-data’, $value );
 
        }
 
        $this->redirect();
 
    }
 
    /**
     * Determines if the nonce variable associated with the options page is set
     * and is valid.
     *
     * @access private
     *
     * @return boolean False if the field isn’t set or the nonce value is invalid;
     * otherwise, true.
     */
    private function has_valid_nonce() {
 
        // If the field isn’t even in the $_POST, then it’s invalid.
        if ( ! isset( $_POST[‘acme-custom-message’] ) ) { // Input var okay.
            return false;
        }
 
        $field = wp_unslash( $_POST[‘acme-custom-message’] );
        $action = ‘acme-settings-save’;
 
        return wp_verify_nonce( $field, $action );
 
    }
 
    /**
     * Redirect to the page from which we came (which should always be the
     * admin page.
     * the login page.
     *
     * @access private
     */
    private function redirect() {
 
        // To make the Coding Standards happy, we have to initialize this.
        if ( ! isset( $_POST[‘_wp_http_referer’] ) ) { // Input var okay.
            $_POST[‘_wp_http_referer’] = wp_login_url();
        }
 
        // Sanitize the value of the $_POST collection for the Coding Standards.
        $url = sanitize_text_field(
                wp_unslash( $_POST[‘_wp_http_referer’] ) // Input var okay.
        );
 
        // Finally, redirect back to the admin page.
        wp_safe_redirect( urldecode( $url ) );
        exit;
 
    }
}

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

Вот где мы подберём следующий урок.

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

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

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

Помните, что вы можете просмотреть все мои курсы и учебные пособия на странице моего профиля , и вы можете следить за мной в моем блоге и / или Twitter по адресу @tommcfarlin, где я рассказываю о различных методах разработки программного обеспечения и о том, как мы можем использовать их в WordPress.

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