Как сохранять элементы меню по отдельности? (вместо того, чтобы каждый раз сохранять всё меню целиком)

Прежде всего давайте я покажу вам, что имею ввиду:

Как сохранять элементы меню по отдельности в WordPress

В каких случаях может понадобиться данный функционал?

  • Когда у нас большое количество элементов меню, а изменить требуется лишь один или два.
  • Если у вас медленное интернет-соединение или большое время ответа сервера.

Шаг 1. Создаем файл JavaScript и подключаем его в админку сайта

Допустим у себя я создал файл themes/twentyten-child/truemenu.js и подключил его при помощи wp_enqueue_script().

function true_enqueue_menu_script() {
 	wp_enqueue_script( 'truemenu', get_stylesheet_directory_uri() . '/truemenu.js', array('jquery'), null, false );
}
 
add_action( 'admin_enqueue_scripts', 'true_enqueue_menu_script' );

Шаг 2. jQuery-плагин Live Query

Нам он понадобится для автоматического добавления кнопки «Изменить» каждому элементу меню.

Почему не использовать функцию each()? Да потому что она будет работать только для существующих элементов меню. А для нас важно не только изменять существующие, но и добавлять новые пункты меню.

Сам плагин доступен по этой ссылке. А дальше уже смотрите сами — вы можете просто вставить содержимое плагина в начало файла truemenu.js или же тоже подключить его функцией wp_enqueue_script().

Шаг 3. Добавляем кнопки сохранения элементов меню и настраиваем события для них.

Вот собственно и содержимое файла truemenu.js. Этот код добавляем кнопку «Изменить» для каждого элемента меню на странице wp-admin/nav-menus.php и позволяет нам по нажатию на кнопку отправлять AJAX-запросы.

/* сюда вы можете вставить код плагина Live Query */
 
jQuery(function($){
 
	$(".menu-item-settings").livequery(function() {
		$(this).append('<a class="button button-primary true-edit-menu">Изменить</a>');
	});
 
	// если не хотите использовать Live Query plugin, тогда закомментируйте строчки сверху и раскомментируйте эти
	//$('.menu-item-settings').each(function(i){ 
	//	$(this).append('<a class="button button-primary true-edit-menu">Изменить</a>');
	//});
 
	$('.true-edit-menu').live('click',function(){
		btn = $(this); // записываем элемент кнопки в переменную
		item = btn.parent();
		var item_url = item.find('.edit-menu-item-url').val(); // ссылка меню
		var item_attrtitle = item.find('.edit-menu-item-attr-title').val(); // текст при наведении
		var item_title = item.find('.edit-menu-item-title').val(); // анкор ссылки
		var item_classes = item.find('.edit-menu-item-classes').val(); // классы CSS 
		var item_xfn = item.find('.edit-menu-item-xfn').val(); // XFN
		var item_desc = item.find('.edit-menu-item-description').val(); // описание
		var item_target = item.find('.field-link-target').find('input').attr('checked'); // открытие в новой вкладке
		var item_menuid =  item.find('.menu-item-data-db-id').val(); // ID элемента меню
		var item_parentid = item.find('.menu-item-data-parent-id').val(); // ID родительского элемента меню
		var item_menu = $('#menu').val(); // ID самого меню
		var item_pos = item.find('.menu-item-data-position').val(); // порядковый номер элемента
		$.ajax({
			type: 'POST',
			url: ajaxurl,
			data: 'action=savemenuitem&item_url=' + item_url + '&item_attrtitle=' + item_attrtitle + '&item_title=' + item_title + '&item_classes=' + item_classes + '&item_xfn=' + item_xfn + '&item_desc=' + item_desc + '&item_target=' + item_target + '&item_menuid=' + item_menuid + '&item_parentid=' + item_parentid + '&item_menu=' + item_menu + '&item_pos=' + item_pos + '&item_max=' + $('.menu-item-settings').length,
			beforeSend: function(xhr){
				btn.text('Сохраняю...');
			},
			success: function(data){
				btn.text('Изменить');
			}
		});
		return false;
	});
 
});

Шаг 4. Код обработчика PHP, который и будет сохранять элементы меню

Я использовал функцию wp_insert_post() для изменения/добавления элемента меню и wp_set_object_terms() для присвоения элемента к определенному меню. Код можете вставить в functions.php вашей темы:

function true_saveitem_callback(){
 
	// параметры для wp_insert_post() (да, элементы меню это оказывается типы постов)
	$item_args = array(
		'ID'		=> $_POST['item_menuid'],
		'post_title'    => $_POST['item_title'],
		'post_type'	=> 'nav_menu_item',
		'post_status'	=> 'publish',
		//'menu_order'	=> $_POST['item_pos'], // Я закомментировал эту строку, потому что изменение порядка элементов не работает так, как хотелось бы
		'post_content'  => $_POST['item_desc'], // описание
		'post_excerpt'   => $_POST['item_attrtitle'] // атрибут title
	);
 
	// для новых элементов важно правильно установить порядок
 	if ( 'draft' == get_post_status( intval($_POST['item_menuid']) ) ) {
 		$item_args['menu_order'] = $_POST['item_max'];
 	}
 
	// insert or update the menu element
	$item_id = wp_insert_post( $item_args );
 
	// присваиваем элемент меню (да, сами меню это таксономии)
	wp_set_object_terms( $item_id, intval($_POST['item_menu']), 'nav_menu', $append = false );
 
	// post meta parameters
	$target = ($_POST['item_target'] == 'checked') ? '_blank' : ''; 
	update_post_meta( $item_id, '_menu_item_target', $target);
	update_post_meta( $item_id, '_menu_item_menu_item_parent', $_POST['item_parentid']);
	update_post_meta( $item_id, '_menu_item_classes', $_POST['item_classes']);
	update_post_meta( $item_id, '_menu_item_xfn', esc_attr($_POST['item_xfn']));
	update_post_meta( $item_id, '_menu_item_url', esc_attr($_POST['item_url']));
 
	die();
}
 
if( is_admin() ) {
	add_action('wp_ajax_savemenuitem', 'true_saveitem_callback');
}

Если у вас возникли вопросы по использованию кода, пожалуйста, оставляйте их в комментариях.

Миша Рудрастых Разработчик WordPress WooCommerce

Миша Рудрастых

Впервые познакомился с WordPress в 2009 году, и после двух лет мучений с Joomla и самописными движками это был просто бальзам на душу. С 2014 года меня можно встретить на WordCamp — официальной конфе по WP в Москве, иногда там выступаю. Также в настоящее время веду курсы по WordPress в Epic Skills в Питере.

По теме