На протяжении всей этой серии мы создавали плагин, предназначенный для того, чтобы предоставить авторам возможность собирать, управлять и сохранять идеи и ссылки на контент, который они создают в WordPress.
При этом мы также ищем способы организации нашего плагина таким образом, чтобы код и организация файлов были понятными и поддерживаемыми, чтобы по мере продолжения разработки плагина мы могли легко добавлять, удалять и поддерживать его функции.
До этого момента мы собрали базовую файловую организацию плагина, а также интерфейс, но на самом деле мы не реализовали функциональность для сохранения информации в базу данных. И если вы не можете сохранить информацию, то плагин мало кому пригодится.
В этом посте мы вернемся к серверному коду и начнем реализовывать функциональность, которая будет:
- Убедитесь, что у пользователя есть возможность сохранять метаданные сообщения
- Очистить метаданные поста
- Сохранить метаданные поста
- Проверить и получить метаданные сообщения
Мы получили нашу работу для нас. В этой статье мы рассмотрим первые два шага, а затем в следующем посте мы рассмотрим последние два шага.
Проверка разрешений
Чтобы убедиться, что у пользователя есть возможность публикации для сохранения метаданных публикации, нам необходимо реализовать проверку безопасности в процессе сериализации. Чтобы сделать это, нам нужно воспользоваться значением nonce .
Одноразовый номер — это «число, используемое один раз» для защиты URL-адресов и форм от неправильного использования.
1. Добавьте одноразовый номер
Чтобы добавить его в наш мета-блок, мы можем реализовать функциональность в разметке, которая отвечает за отображение шаблона публикации. Для этого загрузите admin/views/authors-commentary-navigation.php
и обновите шаблон так, чтобы он включал вызов wp_nonce_field
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<div id=»authors-commentary-navigation»>
<h2 class=»nav-tab-wrapper current»>
<a class=»nav-tab nav-tab-active» href=»javascript:;»>Draft</a>
<a class=»nav-tab» href=»javascript:;»>Resources</a>
<a class=»nav-tab» href=»javascript:;»>Published</a>
</h2>
<?php
// Include the partials for rendering the tabbed content
include_once( ‘partials/drafts.php’ );
include_once( ‘partials/resources.php’ );
include_once( ‘partials/published.php’ );
// Add a nonce field for security
wp_nonce_field( ‘authors_commentary_save’, ‘authors_commentary_nonce’ );
?>
</div>
|
В приведенном выше коде мы ввели одноразовый номер, который соответствует действию сохранения комментария автора (который мы authors_commentary_nonce
), и связали его со значением, которое идентифицировано authors_commentary
.
Посмотрим, где это вступит в игру на мгновение. На данный момент, если вы загрузите свой браузер, вы не увидите ничего нового. Это потому, что одноразовые значения отображаются в скрытом поле.
Для тех, кто интересуется, вы можете запустить инструменты разработки вашего любимого браузера, осмотреть метаблок, и вы должны найти что-то вроде следующего в разметке:
1
|
<input type=»hidden» id=»authors_commentary_nonce» name=»authors_commentary_nonce» value=»f3cd131d28″>
|
Конечно, value
вашего nonce будет отличаться.
2. Проверьте одноразовый номер
Чтобы убедиться, что у пользователя есть разрешение на сохранение сообщения, мы хотим проверить три вещи:
- что пользователь сохраняет информацию для типа сообщения
- что пост не сохраняется автоматически в WordPress
- что пользователь на самом деле имеет разрешение на сохранение
Мы напишем две вспомогательные функции для достижения первой и третьей, и мы будем использовать некоторые встроенные функции для проверки номер два (которые фактически будут использоваться во второй вспомогательной функции).
Сначала давайте настроим хук и функцию, которые будут использоваться для использования вспомогательных функций и сохранения метаданных. В конструкторе для Authors_Commentary_Meta_Box
добавьте следующую строку кода:
1
|
<?php add_action( ‘save_post’, array( $this, ‘save_post’ ) );
|
Далее давайте определим функцию. Обратите внимание, что я выполняю вызовы двух функций в следующем блоке кода. Мы определим их на мгновение:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<?php
/**
* Sanitizes and serializes the information associated with this post.
*
* @since 0.5.0
*
* @param int $post_id The ID of the post that’s currently being edited.
*/
public function save_post( $post_id ) {
/* If we’re not working with a ‘post’ post type or the user doesn’t have permission to save,
* then we exit the function.
*/
if ( ! $this->is_valid_post_type() || ! $this->user_can_save( $post_id, ‘authors_commentary_nonce’, ‘authors_commentary_save’ ) ) {
return;
}
}
|
Учитывая приведенный выше код, мы говорим WordPress save_post
нашу функцию save_post
всякий раз, когда save_post
ее действие save_post
. Внутри функции мы говорим: «Если сохраняемый пост не относится к типу поста или если у пользователя нет прав на сохранение, выйдите из функции».
Конечно, нам нужно определить функции так, чтобы логика работала. Сначала мы напишем функцию is_valid_post_type
как private
функцию текущего класса. Он проверит массив $_POST
чтобы убедиться, что тип сохраняемой записи — это фактически запись.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<?php
/**
* Verifies that the post type that’s being saved is actually a post (versus a page or another
* custom post type.
*
*
* @since 0.5.0
* @access private
* @return bool Return if the current post type is a post;
*/
private function is_valid_post_type() {
return !
}
|
Далее мы добавим функцию user_can_save
. Это функция, которая гарантирует, что сообщение не сохраняется в WordPress, и что если пользователь сохраняет функцию, то значение nonce, связанное с действием публикации, будет правильно установлено.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?php
/**
* Determines whether or not the current user has the ability to save meta data associated with this post.
*
* @since 0.5.0
* @access private
* @param int $post_id The ID of the post being save
* @param string $nonce_action The name of the action associated with the nonce.
* @param string $nonce_id The ID of the nonce field.
* @return bool Whether or not the user has the ability to save this post.
*/
private function user_can_save( $post_id, $nonce_action, $nonce_id ) {
$is_autosave = wp_is_post_autosave( $post_id );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = ( isset( $_POST[ $nonce_action ] ) && wp_verify_nonce( $_POST[ $nonce_action ], $nonce_id ) );
// Return true if the user is able to save;
return !
}
|
Обратите внимание, что здесь мы nonce_action
и nonce_id
которые мы определили в шаблоне на первом шаге. Мы также используем wp_verify_nonce
в сочетании с указанной информацией.
Таким образом мы можем убедиться, что сохраняемая запись сделана пользователем, имеющим надлежащие права доступа и разрешения.
Санитарная обработка данных
Предполагая, что пользователь работает со стандартным типом записей и что он / она имеет разрешение на сохранение информации, нам необходимо очистить данные.
Для этого нам нужно сделать следующее:
- Убедитесь, что никакая информация в метаданных публикации не пуста
- Уберите все, что может быть опасно, для записи в базу данных.
После того, как мы это сделаем, мы рассмотрим сохранение информации для каждого из мета-блоков. Но сначала давайте поработаем над санацией. Есть несколько способов реализовать это. Для целей этого поста мы сделаем это самым простым способом: мы проверим наличие информации на основе ее ключа, а затем, если она существует, мы очистим ее.
Для опытных программистов вы, вероятно, заметите некоторые запахи кода с кодом, который мы собираемся написать. Позже в этой серии мы проведем некоторый рефакторинг, чтобы увидеть, как мы можем сделать плагин более обслуживаемым, так что это все часть замысла этого конкретного поста.
После этого вернитесь в функцию save_post
.
1. Черновики
Поскольку первая вкладка, которая существует внутри мета-блока, — это вкладка « Черновики », мы начнем с нее. Обратите внимание, что это textarea
, поэтому логика, которая существует для очистки этой информации, должна быть следующей:
- удалить любые теги HTML
- экранировать содержимое текстовой области
Напомним, что textarea
называется « authors-commentary-drafts
поэтому мы можем получить к ней доступ в массиве $_POST
. Для этого мы будем использовать следующий код:
01
02
03
04
05
06
07
08
09
10
11
12
|
<?php
// If the ‘Drafts’ textarea has been populated, then we sanitize the information.
if ( ! empty( $_POST[‘authors-commentary-drafts’] ) ) {
// We’ll remove all white space, HTML tags, and encode the information to be saved
$drafts = trim( $_POST[‘authors-commentary-drafts’] );
$drafts = esc_textarea( strip_tags( $drafts ) );
// More to come…
}
|
Проще говоря, мы проверяем, является ли информация в массиве $_POST
пустой. Если нет, то мы очистим данные.
2. Ресурсы
Это конкретное поле немного больше формы, потому что оно динамично. То есть у пользователя может быть что угодно, от нуля до множества полей ввода, которыми мы должны управлять. Помните, что эта конкретная вкладка предназначена в первую очередь для URL-адресов, поэтому мы должны убедиться, что мы безопасно очищаем информацию таким образом.
Во-первых, нам нужно внести одно небольшое изменение в функцию createInputElement
которая существует в файле admin/assets/js/resources.js
. В частности, нам нужно убедиться, что атрибут name использует массив, чтобы мы могли правильно обращаться к нему и проходить по нему, просматривая данные $_POST
.
Убедитесь, что строки кода, отвечающие за создание фактического элемента, выглядят так:
1
2
3
4
5
6
7
|
// Next, create the actual input element and then return it to the caller
$inputElement =
$( ‘<input />’ )
.attr( ‘type’, ‘text’ )
.attr( ‘name’, ‘authors-commentary-resources[‘ + iInputCount + ‘]’ )
.attr( ‘id’, ‘authors-commentary-resource-‘ + iInputCount )
.attr( ‘value’, » );
|
Обратите внимание, что ключ к тому, что мы сделали, лежит в строке, которая обновляет name
. В частности, мы помещаем количество входов в индексы массива.
Затем вернитесь в функцию save_post
и добавьте следующий код (который мы обсудим после блока):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<?php
// If the ‘Resources’ inputs exist, iterate through them and sanitize them
if ( ! empty( $_POST[‘authors-commentary-resources’] ) ) {
$resources = $_POST[‘authors-commentary-resources’];
foreach ( $resources as $resource ) {
$resource = esc_url( strip_tags( $resource ) );
// More to come…
}
}
|
Поскольку мы работаем с массивом входных данных, нам нужно сначала проверить, что массив не пустой. Если это не так, то нам нужно пройти через это, потому что мы не уверены, сколько входов нам нужно будет обработать.
Как и в предыдущем блоке, мы выполняем базовый уровень очистки и экранирования. Это то, что вы можете сделать настолько агрессивным или расслабленным, насколько захотите. Мы вернемся к этому условию в следующем посте, когда пришло время сохранить данные.
3. Опубликовано
Эта вкладка похожа на предыдущие вкладки в том, что мы имеем дело с неопределенным количеством элементов, которые нам необходимо очистить. Это означает, что нам нужно сделать небольшое обновление для части, ответственной за рендеринг этого ввода.
С другой стороны, мы имеем дело только с флажком, который имеет логическое значение: проверяется или нет (или, в частности, «включено» или пусто), поэтому дезинфекция информации действительно проста.
Сначала давайте обновим частичное. Найдите admin/views/partials/published.php
. Затем найдите строку, которая определяет флажок input
и измените ее так, чтобы она выглядела следующим образом:
1
2
3
4
|
<label for=»authors-commentary-comment-<?php echo $comment->comment_ID ?>»>
<input type=»checkbox» name=»authors-commentary-comments[<?php echo $comment->comment_ID ?>]» id=»authors-commentary-comment-<?php echo $comment->comment_ID ?>» />
This comment has received a reply.
</label>
|
Обратите внимание, что мы изменили атрибут name
чтобы он использовал массив с индексом в качестве значения. Далее мы вернемся к функции save_post
еще раз, чтобы ввести проверку этого конкретного элемента:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<?php
// If there are any values saved in the ‘Resources’ input, save them
if ( ! empty( $_POST[‘authors-commentary-comments’] ) ) {
$comments = $_POST[‘authors-commentary-comments’];
foreach ( $comments as $comment ) {
$comment = strip_tags( stripslashes( $comment ) );
// More to come…
}
}
|
Как и в случае с предыдущими фрагментами данных, мы сначала проверяем, существует ли контент. Если так, то мы продезинфицируем его, чтобы подготовить к сохранению. Если этого не произойдет, то мы ничего не делаем.
На сохранение
На данный момент мы готовы взять два последних пункта серии:
- Сохранение и получение
- Рефакторинг
Начиная со следующего поста, мы еще раз вернемся к коду, который мы написали в этом посте, чтобы увидеть, как мы можем сохранить его в базе данных и извлечь его из базы данных, чтобы отобразить его на внешнем интерфейсе.
Далее мы перейдем к рефакторингу. В конце концов, часть написания поддерживаемого кода гарантирует, что он хорошо организован и легко изменяем. Поскольку код, с которым мы работаем на ежедневной основе, уже написан и может быть подвергнут рефакторингу, мы увидим, как это сделать к концу серии.
А пока просмотрите приведенный выше код, ознакомьтесь с источником из GitHub и оставьте все вопросы и комментарии в поле ниже.