Добавление поста аяксом
function ajax_go(data, jqForm, options) { //ф-я перед отправкой запроса
jQuery('#output').html('Отправляем...'); // в див для ответа напишем "отправляем.."
jQuery('#sub').attr("disabled", "disabled"); // кнопку выключим
}
function response_go(out) { // ф-я обработки ответа от wp, в out будет элемент success(bool), который зависит от ф-и вывода которую мы использовали в обработке(wp_send_json_error() или wp_send_json_success()), и элемент data в котором будет все что мы передали аргументом к ф-и wp_send_json_success() или wp_send_json_error()
console.log(out); // для дебага
jQuery('#sub').prop("disabled", false); // кнопку включим
jQuery('#output').html(out.data); // выведем результат
}
jQuery(document).ready(function(){ // после загрузки страницы
jQuery("#child_cats").chained("#parent_cats"); // подключаем плагин для связи селект листов с терминами вложенной таксономии
add_form = jQuery('#add_object'); // запишем форму в переменную
var options = { // опции для отправки формы с помощью jquery form
data: { // дополнительные параметры для отправки вместе с данными формы
action : 'add_object_ajax', // этот параметр будет указывать wp какой экшн запустить, у нас это wp_ajax_nopriv_add_object_ajax
nonce: ajaxdata.nonce // строка для проверки, что форма отправлена откуда надо
},
dataType: 'json', // ответ ждем в json формате
beforeSubmit: ajax_go, // перед отправкой вызовем функцию ajax_go()
success: response_go, // после получении ответа вызовем response_go()
error: function(request, status, error) { // в случае ошибки
console.log(arguments); // напишем все в консоль
},
url: ajaxdata.url // куда слать форму, переменную с url мы определили вывели в нулевом шаге
};
add_form.ajaxForm(options); // подрубаем плагин jquery form с опциями на нашу форму
jQuery('#add_img').click(function(e){ // по клику на ссылку "Добавить еще фото"
e.preventDefault(); // выключим стандартное поведение ссылки
jQuery(this).before("<label class='imgs'>Дополнительные фото(произвольное) <input type='file' name='imgs[]'/></label>"); // добавим перед ссылкой еще один инпут типа файл с таким же нэймом
});
});
// подготовка Вордпресса для работы с аяксом
add_action('wp_print_scripts','include_scripts'); // действие в котором прикрепим необходимые js скрипты и передадим данные
function include_scripts(){
wp_enqueue_script('jquery'); // добавим основную библиотеку jQuery
wp_enqueue_script('jquery-form'); // добавим плагин jQuery forms, встроен в WP
wp_enqueue_script('jquery-chained', '//www.appelsiini.net/projects/chained/jquery.chained.min.js'); // добавим плагин для связанных селект листов
wp_localize_script( 'jquery', 'ajaxdata', // функция для передачи глобальных js переменных на страницу, первый аргумент означет перед каким скриптом вставить переменные, второй это название глобального js объекта в котором эти переменные будут храниться, последний аргумент это массив с самими переменными
array(
'url' => admin_url('admin-ajax.php'), // передадим путь до нативного обработчика аякс запросов в wp, в js можно будет обратиться к ней так: ajaxdata.url
'nonce' => wp_create_nonce('add_object') // передадим уникальную строку для механизма проверки аякс запроса, ajaxdata.nonce
)
);
}
// Обработка формы
add_action( 'wp_ajax_nopriv_add_object_ajax', 'add_object' ); // крепим на событие wp_ajax_nopriv_add_object_ajax, где add_object_ajax это параметр action, который мы добавили в перехвате отправки формы, add_object - ф-я которую надо запустить
add_action('wp_ajax_add_object_ajax', 'add_object'); // если нужно чтобы вся бадяга работала для админов
function add_object() {
$errors = ''; // сначала ошибок нет
$nonce = $_POST['nonce']; // берем переданную формой строку проверки
if (!wp_verify_nonce($nonce, 'add_object')) { // проверяем nonce код, второй параметр это аргумент из wp_create_nonce
$errors .= 'Данные отправлены с левой страницы '; // пишим ошибку
}
// запишем все поля
$parent_cat = (int)$_POST['parent_cats']; // переданный id термина таксономии с вложенностью (родитель)
$child_cat = (int)$_POST['child_cats']; // id термина таксономии с вложенностью (его дочка)
$tag = (int)$_POST['tag']; // id обычной таксономии
$title = strip_tags($_POST['post_title']); // запишем название поста
$content = wp_kses_post($_POST['post_content']); // контент
$string_field = strip_tags($_POST['string_field']); // произвольное поле типа строка
$text_field = wp_kses_post($_POST['text_field']); // произвольное поле типа текстарея
// проверим заполненность, если пусто добавим в $errors строку
if (!$parent_cat) $errors .= 'Не выбрано "Кастом категория-родитель"';
if (!$child_cat) $errors .= 'Не выбрано "Кастом категория-ребенок xD"';
if (!$tag) $errors .= 'Не выбрано "Кастом тэг"';
if (!$title) $errors .= 'Не заполнено поле "Тайтл"';
if (!$content) $errors .= 'Не заполнено поле "Пост контент"';
// далее проверим все ли нормально с картинками которые нам отправили
if ($_FILES['img']) { // если была передана миниатюра
if ($_FILES['img']['error']) $errors .= "Ошибка загрузки: " . $_FILES['img']['error'].". (".$_FILES['img']['name'].") "; // серверная ошибка загрузки
$type = $_FILES['img']['type'];
if (($type != "image/jpg") && ($type != "image/jpeg") && ($type != "image/png")) $errors .= "Формат файла может быть только jpg или png. (".$_FILES['img']['name'].")"; // неверный формат
}
if ($_FILES['imgs']) { // если были переданны дополнительные картинки, пробежимся по ним в цикле и проверим тоже самое
foreach ($_FILES['imgs']['name'] as $key => $array) {
if ($_FILES['imgs']['error'][$key]) $errors .= "Ошибка загрузки: " . $_FILES['imgs']['error'][$key].". (".$key.$_FILES['imgs']['name'][$key].") ";
$type = $_FILES['imgs']['type'][$key];
if (($type != "image/jpg") && ($type != "image/jpeg") && ($type != "image/png")) $errors .= "Формат файла может быть только jpg или png. (".$_FILES['imgs']['name'][$key].")";
}
}
if (!$errors) { // если с полями все ок, значит можем добавлять пост
$fields = array( // подготовим массив с полями поста, ключ это название поля, значение - его значение
'post_type' => 'my_custom_post_type', // нужно указать какой тип постов добавляем, у нас это my_custom_post_type
'post_title' => $title, // заголовок поста
'post_content' => $content, // контент
);
$post_id = wp_insert_post($fields); // добавляем пост в базу и получаем его id
update_post_meta($post_id, 'string_field', $string_field); // заполняем произвольное поле типа строка
update_post_meta($post_id, 'text_field', $text_field); // заполняем произвольное поле типа текстарея
wp_set_object_terms($post_id, $parent_cat, 'custom_tax_like_cat', true); // привязываем к пост к таксономиям, третий параметр это слаг таксономии
wp_set_object_terms($post_id, $child_cat, 'custom_tax_like_cat', true);
wp_set_object_terms($post_id, $tag, 'custom_tax_like_tag', true);
if ($_FILES['img']) { // если основное фото было загружено
$attach_id_img = media_handle_upload( 'img', $post_id ); // добавляем картинку в медиабиблиотеку и получаем её id
update_post_meta($post_id,'_thumbnail_id',$attach_id_img); // привязываем миниатюру к посту
}
if ($_FILES['imgs']) { // если дополнительные фото были загружены
$imgs = array(); // из-за того, что дефолтный массив с загруженными файлами в пхп выглядит не так как нужно, а именно вся инфа о файлах лежит в разных массивах но с одинаковыми ключами, нам нужно создать свой массив с блэкджеком, где у каждого файла будет свой массив со всеми данными
foreach ($_FILES['imgs']['name'] as $key => $array) { // пробежим по массиву с именами загруженных файлов
$file = array( // пишем новый массив
'name' => $_FILES['imgs']['name'][$key],
'type' => $_FILES['imgs']['type'][$key],
'tmp_name' => $_FILES['imgs']['tmp_name'][$key],
'error' => $_FILES['imgs']['error'][$key],
'size' => $_FILES['imgs']['size'][$key]
);
$_FILES['imgs'.$key] = $file; // записываем новый массив с данными в глобальный массив с файлами
$imgs[] = media_handle_upload( 'imgs'.$key, $post_id ); // добавляем текущий файл в медиабиблиотека, а id картинки суем в другой массив
}
update_post_meta($post_id,'multifile_field',$imgs); // привязываем все картинки к посту
}
}
if ($errors) wp_send_json_error($errors); // если были ошибки, выводим ответ в формате json с success = false и умираем
else wp_send_json_success('Все прошло отлично! Добавлено ID:'.$post_id); // если все ок, выводим ответ в формате json с success = true и умираем
die(); // умрем еще раз на всяк случ
}
<?php
// подготовим актуальные данные таксономий
$cats = get_terms('custom_tax_like_cat', 'orderby=name&hide_empty=0&parent=0'); // получим все термины(элементы) таксономии с иерархией
foreach ($cats as $cat) { // пробежим по каждому полученному термину
$parents.="<option value='$cat->term_id' />$cat->name</option>"; // суем id и название термина в строку для вывода внутри тэга select
$childs_array = get_terms('custom_tax_like_cat', 'orderby=name&hide_empty=0&parent='.$cat->term_id); // возьмем все дочерние термины к текущему
foreach ($childs_array as $child){
$childs.="<option value='$child->term_id' class='$cat->term_id' />$child->name</option>"; // делаем то же самое, класс должен быть равным id родительского термина чтобы плагин chained работал
}
}
$tags_array = get_terms('custom_tax_like_tag', 'orderby=none&hide_empty=0&parent=0'); // получим все термины таксономии без вложенности
foreach ($tags_array as $tag) { // пробежим по каждому
$tags .= '<label><input type="radio" name="tag" value="'.$tag->term_id.'">'.$tag->name.'</label>'; // суем все в radio баттоны
}
?>
<?php // Выводим форму ?>
<form method="post" enctype="multipart/form-data" id="add_object">
<label>Кастом категории-родители:
<select id="parent_cats" name="parent_cats" required>
<option value="">Не выбрано</option>
<?php echo $parents; // выводим все родительские термины ?>
</select>
</label>
<label>Кастом категории-дети:
<select id="child_cats" name="child_cats" required>
<option value="">Не выбрано</option>
<?php echo $childs; // выводим все дочерние термины, плагин chained сам покажет только нужные элементы в зависимости от выбранного родительского термина ?>
</select>
</label>
Кастом тэги
<?php echo $tags; // выводим термины таксономии без иерархии в radio ?>
<label>Тайтл(стандартное) <input type="text" name="post_title" required/></label>
<label>Пост контент(стандартное) <textarea name="post_content" required/></textarea></label>
<label>Поле типа строка(произвольное) <input type="text" name="string_field"/></label>
<label>Пост типа текст(произвольное) <textarea name="text_field"/></textarea></label>
<label>Миниатюра(стандартное): <input type="file" name="img"/></label>
<label id="first_img" class='imgs'>Дополнительные фото(произвольное): <input type='file' name='imgs[]'/></label>
<a href="#" id="add_img">Загрузить еще фото</a>
<input type="submit" name="button" value="Отправить" id="sub"/>
<div id="output"></div> <?php // сюда будем выводить ответ ?>