Как включить предлагаемые правки?
Мне нравится идея включения возможности для любого пользователя моего сайта предлагать правки страниц. Похоже на систему правок в Stack Exchange, но с отличием - правки могут предлагать все, а не только зарегистрированные пользователи. Все правки будут проходить процесс утверждения.
Как я могу это реализовать?

Сравнение содержимого, заголовка и автора записи
Поскольку мне уже приходилось решать подобную задачу несколько месяцев назад, представляю самый простой и надежный способ (из тех, что я нашел) для проверки изменений в содержимом, заголовке или авторе записи:
// Обновление заголовка
'' !== wp_text_diff(
$el['post_title'],
$GLOBALS['post']->post_title
)
AND $GLOBALS['post']->post_title = $el['post_title'];
// Обновление содержимого
'' !== wp_text_diff(
$el['post_content'],
$GLOBALS['post']->post_content
)
AND $GLOBALS['post']->post_content = $el['post_content'];
// Обновление автора
$GLOBALS['post']->post_author !== $el['post_author']
AND $GLOBALS['post']->post_author = $el['post_author'];
Кратко объясню мой сценарий: я получал записи с удаленного источника через API, затем возвращал global $post
внутри цикла single post, содержащий либо оригинальные данные, либо новые. Таким образом, мне не приходилось вручную устанавливать все остальные значения записи, которые не требовали проверки на изменения.
Предложение правок
Основное, что нужно учитывать при поиске места для временного сохранения предлагаемых правок - это то, что содержимое записи хранится в базе данных как longtext
. Поэтому место для сохранения предложенных изменений должно соответствовать этому требованию. Комментарии подходят идеально.
Дополнительный плюс в том, что система комментариев предоставляет API для их удобного отображения в цикле, что обеспечивает плавную интеграцию, высокую степень кастомизации и быструю настройку. Кроме того, большинство тем уже имеют встроенную поддержку комментариев, что позволяет легко подключиться к существующей системе и работать практически с любой темой.
Я предлагаю просто расширить или изменить форму комментария. Можно использовать следующий код или добавить дополнительные поля через хук comment_form_default_fields
:
<?php
// Добавляем для авторизованных пользователей и гостей:
add_action( 'comment_form_logged_in_after', 'wpse_proposed_edit_textarea' );
add_action( 'comment_form_after_fields', 'wpse_proposed_edit_textarea' );
function wpse_proposed_edit_textarea()
{
?>
<p class="comment-form-title">
<label for="wpse_propsed_edit">
<?php _e( 'Предложить правку', 'your_textdomain' ); ?>
</label>
<textarea name="wpse_propsed_edit" id="wpse_propsed_edit">
<?php the_content(); ?>
</textarea>
</p>
<input type="hidden" name="comment_approved" id="comment_approved" value="0" />
<?php
}
Я добавил скрытое поле comment_approved
со значением 0
, чтобы отправлять предложения на модерацию. Не уверен, будет ли это работать напрямую или это значение является метаданными комментария и требует использования add_comment_meta()
при сохранении. Если нет, можно использовать что-то вроде следующего кода:
add_filter( 'pre_comment_approved' , 'wpse_pre_suggest_edit', 100, 2 );
function wpse_pre_suggest_edit( $approved , $commentdata )
{
// Возможно, потребуется проверить $commentdata
// для определения статуса одобрения, отклонения или спама
if ( ! empty( $commentdata['wpse_propsed_edit'] ) )
{
# Добавляем фильтр к действию сохранения комментария для сохранения метаданных
add_action( 'comment_post', 'wpse_set_proposed_edit' );
return 0;
}
return 1;
}
// Эта функция упрощает идентификацию комментариев по их мета-значению
function wpse_set_proposed_edit( $comment_id );
{
// Выполняется только один раз
remove_filter( current_filter(), __FUNCTION__ );
add_comment_meta( $comment_id, 'proposed_edit', true, true );
}
Отображение комментариев в админке
Здесь я бы использовал простое расширение класса и пользовательскую страницу в админке:
function wpse_add_proposed_edits_admin_page()
{
add_menu_page(
'Предложенные правки',
'Предложенные правки',
'activate_plugins',
'proposed_edits',
'wpse_proposed_edits_page_cb'
);
}
add_action( 'admin_menu', 'wpse_add_proposed_edits_admin_page' );
function wpse_proposed_edits_page_cb()
{
$proposed_edits_table = new WP_Proposed_Edits_Table();
$proposed_edits_table->prepare_items();
$proposed_edits_table->display();
}
class WP_Proposed_Edits_Table extends WP_List_Table
{
// Переопределяем стандартную логику таблицы здесь
}
Больше информации можно найти на WPEngineer.
Утверждение правок
Вы можете добавить пользовательские действия и обрабатывать предложенные правки, используя первый показанный код, чтобы проверить наличие изменений и затем просто обновить запись. Сам комментарий содержит значение с ключом comment_post_ID
, что упрощает идентификацию ID редактируемой записи.
Заключительное замечание
Буду рад увидеть готовый плагин. Пожалуйста, оставьте ссылку здесь :)

Моя идея довольно проста.
Вы можете добавить ссылку
Предложить правку
внизу записей, которая использует пользовательский шаблон. В этом шаблоне разместите текстовое поле (возможно, с редактором), связанное с пользовательской таксономией, где значением по умолчанию будетсодержание записи
.Любые изменения в
содержании
будут сравниваться соригинальным содержимым записи
после отправки (как черновик) и вводакода CAPTCHA
с использованием алгоритмов сравнения, таких как пакет PHP inline-diff или Text-Diff из PEAR или альтернативно с помощью PHP-функции согласно этому для не слишком длинных текстов в сочетании с CSS.Затем сохраните значения в 3 пользовательских метабоксах (на странице редактирования/добавления этой таксономии в админке), которые будут отображать:
- Оригинальное содержимое
- Отредактированную версию
- Никнейм пользователя и его Email
и сохраните
ID записи
, возможно, с помощью функцииupdate_option()
для дальнейшего использования.После проверки отредактированной версии и подтверждения администратором, оригинальная запись будет заменена, как вы прописали в functions.php.

Несколько замечаний: (A) "как вы закодировали в functions.php" - не согласен с этим. Это материал для плагина. (B) "связано с пользовательской таксономией со значением по умолчанию в виде содержимого записи" - У термина таксономии есть только одно возможное место, куда могло бы подойти содержимое: описание. И тогда вам понадобится место для хранения ID записи. Где это могло бы быть? Из-за ограничений системы таксономий WordPress для этого нет места, поэтому можно сохранить только ID термина. В этом случае это (ограниченная) односторонняя система: Запись > Данные термина.

Это довольно сложная задача, и для полного ответа потребуется значительное время. Поэтому это не настоящий ответ, а лишь некоторые мысли..
Использование встроенной функции WordPress wp_update_post
через ajax даст вам историю изменений, но не предоставит возможности утверждать правки.
Создание черновиков из правок по умолчанию невозможно, но этот вопрос обсуждался здесь: Есть ли способ создать черновик из опубликованной страницы или записи? Какие обходные решения вы использовали?
Можно попробовать использовать Front-end Editor, но у вас не будет контроля над публикацией правок, поэтому попробуйте совместить его с другим плагином, например Revisionary, который позволяет управлять правками на основе разрешений. Правда, я не знаю, будут ли они работать вместе.
Если нет, вам придётся модифицировать плагин на основе двух вышеуказанных или написать что-то с нуля.
Мой подход "с нуля" заключался бы в кнопке, которая ведёт на другую страницу, выводящую содержимое/данные записи в формате JSON (с ним проще работать при использовании Ajax и WYSIWYG-редакторов). Кнопка сохранения отправляла бы данные как черновик, а не публикацию, что дало бы контроль над правками (см. обсуждение выше на WPSE о том, как этого добиться — задача нетривиальная).
Дополнительные сложности включают санитизацию, кодирование, защиту от спама, работу с медиафайлами, пользовательские поля, временные метки, память и т.д. Хорошая новость в том, что в WordPress уже есть система ревизий, к которой можно подключиться, и неплохая поддержка множества редакторов.
P.S. Это была бы отличная идея для плагина.
