Пример создания простой фронтенд формы публикации записи. Публиковать могут как авторизованные, так и анонимы. Фома позволяет только публиковать записи без возможности редактирования. В дальнейшем я буду добавлять еще различные примеры создания форм: публикации с фронтенда, в админке, страницы настроек, фильтры товаров, контактные формы, формы бронирования, регистрации и авторизации, многоступенчатые формы, с зависимыми списками, динамические ajax формы, формы в модальных окнах и т.д.
Плагин предназначен только для создания форм, внешнего оформления и интерактива полей и не отвечает за сохранение и заполнение сохраненных данных, что с одной стороны является недостатком для людей не умеющих программировать, а с другой преимуществом для разработчиков.
На основе данного примера мы разберем:
1. создание полей и вывод формы через шорткод
2. валидация полей на клиенте и на сервере
3. сохранение данных формы, т.е. это создание новой записи.
4. Инструкции по заполнению полей формы тут не будет, так как в примере нет редактирования записи.
По поводу валидции полей на клиенте: по сути если есть серверная, то на клиенте она просто не нужна, так как выглядит внешне это все одинаково, но для облегчения нагрузки на сервер, скорости отображения ошибок и вообще в качестве документации, я покажу как ее реализовать. Просто сама по себе она работать на форонтенде не будет, даже несмотря, но то, что у поля указаны 'required' => true. Автоматическая клиентская валидация работает только для полей в админке, когда не создается форма с нуля, а создаются только поля для уже существующих форм добавления типов записей, таксономий, пользователей, виджетов, настроек меню, комментариев.
Шорткод для вывода формы: [fcfb_form id="demo5" reset_template="1"]
Создание полей формы
add_filter('fcfb_form__demo5', 'demo5_form', 10, 2);
function demo5_form($args)
{
$args[] = [
'type' => 'container',
'label' => 'Добавить запись в блог',
'id' => 'addpost',
'fields' => [
[
'type' => 'text',
'id' => 'post_name',
'label' => 'Название записи',
'required' => true,
'min' => 4,
'max' => 100,
],
[
'type' => 'textarea',
'id' => 'post_content',
'label' => 'Описание записи',
'required' => true,
'ww' => '100%',
'min' => 20,
'max' => 10000,
],
[
'type' => 'multiselect',
'id' => 'categories',
'label' => 'Категория',
'source' => 'taxonomy',
'max' => 2,
'required' => true,
'query' => [
'taxonomy' => 'category',
'hide_empty' => false,
'exclude' => [1], //исключаем "без рубрики"
],
],
[
'type' => 'math_captcha',
'id' => 'code',
'label' => 'Ответ на вопрос',
],
[
'type' => 'checkbox',
'after' => 'Ознакомлен с политикой безопасности в отношении обработки персональных данных',
'id' => 'privacy_policy',
'required' => true,
'sw' => 3,
'ww' => '100%',
],
[
'type' => 'submit',
'id' => 'btn',
//деактивируем кнопку пока не будет отмечена галочка политики
'conditions' => [
'logic' => 'disabled',
'or' => [['rules' => [['id' => 'privacy_policy', 'values' => ['1'], 'compare' => '=']]]],
],
],
],
];
return $args;
}
Валидация полей на клиенте + скролл к первому полю с ошибкой
function my_custom_footer_script()
{
?>
<script>
jQuery(function($) {
//проверка полей форм до отправки ajax запроса
function noticeField(formData, event) {
const $form = $(event.currentTarget);
//проверка есть ли поля с ошибками
if(fcfb.submit.validFields($form)) {
//если ошибки есть, то скролл к первому полю с ошибкой
fcfb.submit.scrollNoticeField($form);
//блокируем ajax отправку данных на сервер
return false;
}
return formData;
}
fcfb.addFilter('fcfbAjaxSubmitBefore_demo5', function(formData, event) {
return noticeField(formData, event);
});
});
</script>
<?php
}
add_action('wp_footer', 'my_custom_footer_script');
Валидация на сервере и публикация поста
function fcfb_action_demo5_action()
{
if (empty(fcfb_post()['demo5'])) {
exit();
}
check_ajax_referer('demo5', 'fcfb-nonce');
$fields = fcfb_post()['demo5'];
//обновление каптчи
$output['math_captcha_refresh'] = fcfb_math_captcha_refresh('medium', 100, 30);
if ($n2 = fcfb_v_required($fields['post_name'], 'Название записи')) {
$output['errorFields']["[post_name]"] = $n2;
} else {
$n2 = fcfb_v_length($fields['post_name'], 4, 100, 'Название записи');
if ($n2) {
$output['errorFields']["[post_name]"] = $n2;
}
}
if ($n3 = fcfb_v_required($fields['post_content'], 'Описание записи')) {
$output['errorFields']["[post_content]"] = $n3;
} else {
$n4 = fcfb_v_length($fields['post_content'], 20, 10000, 'Описание записи');
if ($n4) {
$output['errorFields']["[post_content]"] = $n4;
}
}
if ($n5 = fcfb_v_required($fields['categories'][0], 'Категория')) {
$output['errorFields']["[categories][]"] = $n5;
} else {
$n6 = fcfb_v_array_count($fields['categories'], 1, 2, 'Категория');
if ($n6) {
$output['errorFields']["[categories][]"] = $n6;
}
}
if ($n7 = fcfb_v_required($fields['code']['user_answer'], 'Ответ на вопрос')) {
$output['errorFields']["[code][user_answer]"] = $n7;
} else {
$n8 = fcfb_validate_math_captcha($fields['code']);
if ($n8) {
$output['errorFields']["[code][user_answer]"] = $n8;
}
}
//если есть ошибки валидации, отправляем их и прекращаем выполнение
if (!empty($output['errorFields'])) {
//скролл к первому полю с ошибкой
$output['scrollField'] = [
'delay' => 100,
'top' => 200,
];
exit(json_encode($output));
}
//если ошибок нет, то добавляем пост
// 1. Очищаем и подготавливаем данные для безопасности
$post_title = sanitize_text_field($fields['post_name']);
$post_content = sanitize_textarea_field($fields['post_content']);
$post_categories = array_map('intval', array_filter((array) $fields['categories']));
// 2. Собираем массив данных для создания поста
$post_data = [
'post_title' => $post_title,
'post_content' => $post_content,
'post_category' => $post_categories, // Массив ID категорий
'post_status' => 'pending', // Статус "на рассмотрении".
'post_author' => 1, // ID автора, по умолчанию это админ
'post_type' => 'post', // Тип записи (стандартный пост)
];
// 3. Вставляем пост в базу данных
$new_post_id = wp_insert_post($post_data, true);
// 4. Проверяем, не произошла ли ошибка при добавлении
if (is_wp_error($new_post_id)) {
// Если произошла ошибка, отправляем уведомление об этом над формой
$output['noticesForm'] = [
[
'content' => $new_post_id->get_error_message(),
'type' => 'error',
],
];
exit(json_encode($output));
}
// Если пост успешно создан, отправляем позитивный ответ
//восстанавливаем форму в первоначальное состояние
$output['reset'] = 100;
//выводим уведомление в попапе
$output['popup'] = [
'id' => 'add_result',
'content' => 'Запись успешно отправлена на проверку!',
];
//удаление уведомлений над формой (если ранее была ошибка)
$output['noticesFormRemove'] = 100;
exit(json_encode($output));
}
add_action('wp_ajax_fcfb_action_demo5', 'fcfb_action_demo5_action');
add_action('wp_ajax_nopriv_fcfb_action_demo5', 'fcfb_action_demo5_action');