seredniy
10/21/2016 - 8:15 PM

Добавление поста аяксом

Добавление поста аяксом

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 // сюда будем выводить ответ ?>