Статьи

Разрешить пользователям отправлять на ваш сайт WordPress: плагин цитат

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


  • Как отобразить и обработать форму, используя шорткод
  • Используйте одноразовые номера для защиты представлений пользователей

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

Мы создадим плагин, который позволит вошедшим в систему пользователям:

  • отправить цитаты для модерации и публикации
  • просмотреть их неопубликованные цитаты
  • удалить их неопубликованные цитаты

Вот к чему мы стремимся:

Весь код доступен в исходном коде плагина в верхней части этого урока.


Папка плагинов WordPress находится в папке установки WordPress по адресу wp-content/plugins . Создайте папку внутри папки плагинов. Давайте назовем это submit-user-quotes . Теперь создайте сам файл плагина. Давайте назовем это submit_user_quotes.php . Путь к файлу вашего плагина должен быть следующим: wp-content/plugins/submit-user-quotes/submit_user_quotes.php

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

01
02
03
04
05
06
07
08
09
10
<?php
/*
Plugin Name: Submit User Quotes
Plugin URI: http://wp.rosselliot.co.nz/user-quotes/
Description: Allows registered users to submit quotes.
Version: 1.0
License: GPLv2
Author: Ross Elliot
Author URI: http://wp.rosselliot.co.nz
*/

Вы можете редактировать эту информацию в соответствии с вашими требованиями .

Вы увидите плагин в списке так:


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

Мы будем использовать следующий код инициализации для создания нашего пользовательского типа записи и пользовательской таксономии:

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
add_action(‘init’, ‘suq_plugin_init’);
 
function suq_plugin_init(){
 
  $quote_type_labels = array(
    ‘name’ => _x(‘Quotes’, ‘post type general name’),
    ‘singular_name’ => _x(‘Quote’, ‘post type singular name’),
    ‘add_new’ => _x(‘Add New Quote’, ‘quote’),
    ‘add_new_item’ => __(‘Add New Quote’),
    ‘edit_item’ => __(‘Edit Quote’),
    ‘new_item’ => __(‘Add New Quote’),
    ‘all_items’ => __(‘View Quotes’),
    ‘view_item’ => __(‘View Quote’),
    ‘search_items’ => __(‘Search Quotes’),
    ‘not_found’ => __(‘No Quotes found’),
    ‘not_found_in_trash’ => __(‘No Quotes found in Trash’),
    ‘parent_item_colon’ => ”,
    ‘menu_name’ => ‘Quotes’
  );
   
  $quote_type_args = array(
    ‘labels’ => $quote_type_labels,
    ‘public’ => true,
    ‘query_var’ => true,
    ‘rewrite’ => true,
    ‘capability_type’ => ‘post’,
    ‘has_archive’ => true,
    ‘hierarchical’ => false,
    ‘menu_position’ => null,
    ‘supports’ => array(‘title’, ‘editor’, ‘author’)
  );
   
  register_post_type(‘quotes’, $quote_type_args);
 
  $quote_category_labels = array(
    ‘name’ => _x( ‘Quote Categories’, ‘taxonomy general name’ ),
    ‘singular_name’ => _x( ‘Quote’, ‘taxonomy singular name’ ),
    ‘search_items’ => __( ‘Search Quote Categories’ ),
    ‘all_items’ => __( ‘All Quote Categories’ ),
    ‘parent_item’ => __( ‘Parent Quote Category’ ),
    ‘parent_item_colon’ => __( ‘Parent Quote Category:’ ),
    ‘edit_item’ => __( ‘Edit Quote Category’ ),
    ‘update_item’ => __( ‘Update Quote Category’ ),
    ‘add_new_item’ => __( ‘Add New Quote Category’ ),
    ‘new_item_name’ => __( ‘New Quote Name’ ),
    ‘menu_name’ => __( ‘Quote Categories’ ),
  );
 
  $quote_category_args = array(
    ‘hierarchical’ => true,
    ‘labels’ => $quote_category_labels,
    ‘show_ui’ => true,
    ‘query_var’ => true,
    ‘rewrite’ => array( ‘slug’ => ‘quote_category’ ),
  );
   
  register_taxonomy(‘quote_category’, array(‘quotes’), $quote_category_args);
   
  $default_quote_cats = array(‘humor’, ‘politics’, ‘sport’, ‘philosophy’);
   
  foreach($default_quote_cats as $cat){
   
    if(!term_exists($cat, ‘quote_category’)) wp_insert_term($cat, ‘quote_category’);
     
  }
     
}

Теперь у нас есть панель «Цитаты» на панели инструментов администратора и способ управления цитатами и их категориями.


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

1
add_shortcode(‘suq_form’, ‘suq_form_shortcode’);

Здесь мы используем функцию add_shortcode WordPress для определения шорткода с именем suq_form и функцию с именем suq_form_shortcode, которая будет вызываться всякий раз, когда WordPress встречает шорткод [suq_form] в записи или странице.

Прежде чем мы рассмотрим функции отображения и обработки форм, давайте немного поговорим о …


Поскольку наш плагин принимает данные от пользователя, мы реализуем следующие механизмы безопасности:

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

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

Здесь мы генерируем одноразовое поле, используя wp_nonce_field, которое будет включено в нашу форму как скрытое поле:

1
wp_nonce_field(‘suq_form_create_quote’, ‘suq_form_create_quote_submitted’);

Поскольку теперь это скрытое поле в нашей форме, оно будет возвращено нам при отправке формы. Затем мы можем проверить правильность одноразового номера, используя wp_verify_nonce :

1
wp_verify_nonce($_POST[‘suq_form_create_quote_submitted’], ‘suq_form_create_quote’) )

Это вернет true, если nonce подтвердит.


Это функция, вызываемая нашим шорткодом. Он отображает и обрабатывает форму отправки цитаты и форму списка / удаления цитаты. Мы разберем его по кусочкам и на шаге 5 рассмотрим вспомогательные функции.

1
2
3
4
5
6
7
8
9
function suq_form_shortcode(){
 
  if(!is_user_logged_in()){
   
    return ‘<p>You need to be logged in to post a quote.</p>’;
 
  }
 
  global $current_user;
  • проверьте, вошел ли пользователь в систему
  • захватите переменную WordPress $ current_user, которая нам понадобится для получения идентификатора пользователя
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
if (isset( $_POST[‘suq_form_create_quote_submitted’] ) && wp_verify_nonce($_POST[‘suq_form_create_quote_submitted’], ‘suq_form_create_quote’) ){
 
  $suq_quote_author = trim($_POST[‘suq_quote_author’]);
  $suq_quote_text = trim($_POST[‘suq_quote_text’]);
 
  if($suq_quote_author != ” && $suq_quote_text != ”){
  
    $quote_data = array(
      ‘post_title’ => $suq_quote_author,
      ‘post_content’ => $suq_quote_text,
      ‘post_status’ => ‘pending’,
      ‘post_author’ => $current_user->ID,
      ‘post_type’ => ‘quotes’
    );
     
 
    if($quote_id = wp_insert_post($quote_data)){
     
      wp_set_object_terms( $quote_id, (int)$_POST[‘suq_quote_category’], ‘quote_category’);
       
      echo ‘<p>Quote created and awaiting moderation!</p>’;
       
    }
     
  }else{//author or text field is empty
   
    echo ‘<p>Quote NOT saved!
   
  }
}
  • если форма создания цитаты была отправлена, будет поле suq_form_create_quote_submitted, которое было сгенерировано нашей функцией wp_nonce_field. Затем мы можем проверить одноразовый номер и приступить к обработке представленной цитаты.
  • выполнить базовую проверку, убедившись, что в текстовом поле автора цитаты и в тексте цитаты есть что-то, а если нет, отобразить сообщение об ошибке
  • создать массив, устанавливающий статус сообщения в ожидании (теперь администратор должен будет утвердить его для публикации), установить тип сообщения в кавычки (наш пользовательский тип сообщения) и установить автора цитаты для текущего пользователя, вошедшего в систему
  • если цитата была успешно вставлена, установите категорию для цитаты и отобразите сообщение об успешном завершении
01
02
03
04
05
06
07
08
09
10
11
if (isset( $_POST[‘suq_form_delete_submitted’] ) && wp_verify_nonce($_POST[‘suq_form_delete_submitted’], ‘suq_form_delete’)){
 
  if(isset($_POST[‘suq_delete_id’])){
   
    if($quotes_deleted = suq_delete_quotes($_POST[‘suq_delete_id’])){
     
      echo ‘<p>’ .
       
    }
  }
}
  • если отправлена ​​форма удаления цитаты, будет поле suq_form_delete_submitted, сгенерированное нашей функцией wp_nonce_field. Затем мы можем проверить одноразовый номер и приступить к обработке массива кавычек, проверенных на удаление
  • мы проверяем, что у нас есть некоторые кавычки, проверенные на удаление, проверяя $ _POST [‘suq_delete_id’]. Если это так, мы передаем их функции suq_delete_quotes (см. Шаг 5)
  • если цитаты были удалены, мы показываем сообщение об успехе
1
2
3
4
5
6
7
echo suq_get_create_quote_form($suq_quote_author, $suq_quote_text, $suq_quote_category);
 
if($quotes_table = suq_get_user_quotes($current_user->ID)){
 
  echo $quotes_table;
   
}
  • выводим форму создания цитаты
  • наконец, мы выводим форму списка / удаления цитаты, передавая идентификатор пользователя в функцию suq_get_user_quotes (см. шаг 5)

Здесь мы рассмотрим функции, которые генерируют формы, и функцию, которая удаляет выбранные кавычки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
function suq_get_create_quote_form($suq_quote_author = ”, $suq_quote_text = ”, $suq_quote_category = 0){
 
  $out .= ‘<form id=”create_quote_form” method=”post” action=””>’;
 
  $out .= wp_nonce_field(‘suq_form_create_quote’, ‘suq_form_create_quote_submitted’);
 
  $out .= ‘<label for=”suq_quote_author”>Who said it?</label><br/>’;
  $out .= ‘<input type=”text” id=”suq_quote_author” name=”suq_quote_author” value=”‘ . $suq_quote_author . ‘”/><br/>’;
  $out .= ‘<label for=”suq_quote_category”>Category</label><br/>’;
  $out .= suq_get_quote_categories_dropdown(‘quote_category’, $suq_quote_category) .
  $out .= ‘<label for=”suq_quote_text”>Quote</label><br/>’;
  $out .= ‘<textarea id=”suq_quote_text” name=”suq_quote_text” />’ .
  $out .= ‘<input type=”submit” id=”suq_submit” name=”suq_submit” value=”Submit Quote For Publication”>’;
 
  $out .= ‘</form>’;
 
  return $out;
   
}
  • функция принимает 3 необязательных аргумента для повторного заполнения полей формы. Это удобно для пользователя.
  • выводится одноразовое поле, которое мы проверяем при отправке формы
  • мы выводим раскрывающийся список для категорий котировок, вызывая suq_get_quote_categories_dropdown (см. следующую функцию)
1
2
3
4
5
function suq_get_quote_categories_dropdown($taxonomy, $selected){
 
  return wp_dropdown_categories(array(‘taxonomy’ => $taxonomy, ‘name’ => ‘suq_quote_category’, ‘selected’ => $selected, ‘hide_empty’ => 0, ‘echo’ => 0));
 
}
  • функция принимает 2 аргумента, включая идентификатор элемента текущей выбранной категории
  • мы используем функцию WordPress wp_dropdown_categories для создания выпадающего списка, в котором перечислены категории цитат из таксономии quote_category (наша пользовательская таксономия)
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
function suq_get_user_quotes($user_id){
 
  $args = array(
    ‘author’ => $user_id,
    ‘post_type’ => ‘quotes’,
    ‘post_status’ => ‘pending’
  );
   
  $posts = new WP_Query($args);
 
  if(!$posts->post_count) return 0;
   
  $out .= ‘<p>Your Unpublished Quotes</p>’;
   
  $out .= ‘<form method=”post” action=””>’;
   
  $out .= wp_nonce_field(‘suq_form_delete’, ‘suq_form_delete_submitted’);
   
  $out .= ‘<table id=”quotes”>’;
  $out .= ‘<thead><th>Said By</th><th>Quote</th><th>Category</th><th>Delete</th></thead>’;
     
  foreach($posts->posts as $post){
 
    $quote_cats = get_the_terms($post->ID, ‘quote_category’);
     
    foreach($quote_cats as $cat){
     
      $quote_cat = $cat->name;
     
    }
 
    $out .= wp_nonce_field(‘suq_post_delete_’ . $post->ID, ‘suq_post_delete_id_’ . $post->ID, false);
        
    $out .= ‘<tr>’;
    $out .= ‘<td>’ .
    $out .= ‘<td>’ .
    $out .= ‘<td>’ .
    $out .= ‘<td><input type=”checkbox” name=”suq_delete_id[]” value=”‘ . $post->ID . ‘” /></td>’;
    $out .= ‘</tr>’;
     
  }
 
  $out .= ‘</table>’;
     
  $out .= ‘<input type=”submit” name=”suq_delete” value=”Delete Selected Quotes!”>’;
 
  $out .= ‘</form>’;
   
  return $out;
 
}
  • принять идентификатор пользователя, потому что нам нужно получить список цитат только для текущего пользователя
  • создать $ args, чтобы указать нашего пользователя, тип публикации цитат и цитат, которые ожидают рассмотрения (еще не опубликовано администратором)
  • выполнить пользовательский запрос с помощью WP_Query
  • вернуть false, если наш запрос не возвращает кавычек
  • запустить форму и создать одноразовый номер для формы
  • цикл через кавычки, убедившись, что мы также захватить категорию цитаты
  • создать одноразовый номер для флажка удаления цитаты, назначив уникальное имя для одноразового номера путем объединения идентификатора сообщения
  • вывести строку таблицы, содержащую информацию о кавычках, а также флажок удаления

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
function suq_delete_quotes($quotes_to_delete){
 
  $quotes_deleted = 0;
 
  foreach($quotes_to_delete as $quote){
 
    if (isset($_POST[‘suq_post_delete_id_’ . $quote]) && wp_verify_nonce($_POST[‘suq_post_delete_id_’ . $quote], ‘suq_post_delete_’ . $quote)){
 
      wp_trash_post($quote);
       
      $quotes_deleted ++;
 
    }
  }
 
  return $quotes_deleted;
   
}
  • функция принимает массив идентификаторов кавычек для удаления
  • каждый идентификатор цитаты проверяется, чтобы увидеть, был ли создан для него
  • если проверяется одноразовый номер, мы удаляем кавычку, используя функцию WordPress wp_trash_post

Просто поместите эту информацию о стиле в файл style.css в папке вашей темы:

01
02
03
04
05
06
07
08
09
10
11
12
13
#suq_quote_author{
  width:300px;
}
#suq_quote_text{
  width:400px;
  height:100px;
}
#quotes{
  font-size:12px;
}
#quotes th{
  text-align:left;
}

Активируйте плагин, вставьте шорткод на страницу, войдите на свой сайт и протестируйте его.

Полный исходный код плагина и ссылка на демонстрационный сайт перечислены в верхней части этого руководства.

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


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