Как добавить массовое редактирование постов в WordPress


Недавно был пост как добавить свои колонки на страницу с постами в WordPress. Его можно прочитать здесь. А сейчас будет продолжение.

Наша задача сегодня – сделать возможность быстрого редактирования кастомных мета-полей у большого количества постов в WordPress.

Задача будет реализована в 5 этапов:

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

1 этап – создадим колонки

Сам этап описан вот в этой статье. Дублировать текст не буду и оставлю только код.

add_filter( 'manage_kuhni_posts_columns', 'rb_kuhni_price_columns' );

function rb_kuhni_price_columns( $column_array ) {

	$column_array['price'] 		= 'Цена - Базовая';
	$column_array['price_std'] 	= 'Цена - Стандартная';
	$column_array['price_pr'] 	= 'Цена - Премиум';

	return $column_array;
}

add_action( 'manage_posts_custom_column', 'rb_kuhni_price_columns_populate', 10, 2 );

function rb_kuhni_price_columns_populate( $columns, $post_id ) {

	switch( $columns ) :
		case 'price': {
			echo number_format( get_post_meta( $post_id, 'price', true ), 0, '.', ' ');
			break;
		}
		case 'price_std': {
			echo number_format( get_post_meta( $post_id, 'price_std', true ), 0, '.', ' ');
			break;
		}
		case 'price_pr': {
			echo number_format( get_post_meta( $post_id, 'price_pr', true ), 0, '.', ' ');
			break;
		}
	endswitch;

}

Результат этого действия будет такой:

Отображение значение мета-полей в кастомных колонках

Наша главная задача данного этапа была – добавить наши поля в колонки. Если вам не нужно, чтобы колонки отображались, то вы можете просто отключить их в блоке настройки:

Экран с настройками экрана в админке WordPress

2 этап – добавляем поля в блок быстрого редактирования

add_action('bulk_edit_custom_box',  'rb_quick_edit_fields', 10, 2);

function rb_quick_edit_fields( $column_name, $post_type ) {

	if ( 'kuhni' === $post_type ) {

		switch( $column_name ) :

			case 'price_std': {

				wp_nonce_field( 'rb_kuhni_bulk_nonce', 'rb_kuhni_nonce' );

				echo '<fieldset class="inline-edit-col-left">
						<div class="inline-edit-col">
							<div class="inline-edit-group wp-clearfix">
								<label class="inline-edit-status alignleft">
									<span class="title">Увеличить все цены на</span>
									<span class="input-text-wrap"><input type="number" name="price-increase" autocomplete="off" value=""></span>
								</label>
							</div>
						</div>
					</fieldset>';

				break;

			}

			case 'price_pr': {

				echo '<fieldset class="inline-edit-col-left">
						<div class="inline-edit-col">
							<div class="inline-edit-group wp-clearfix">
								<label class="inline-edit-status alignleft">
									<span class="title">Увеличить все цены в процентах</span>
									<span class="input-text-wrap"><input type="number" name="price-increase-percent" autocomplete="off" value=""></span>
								</label>
							</div>
						</div>
					</fieldset>';

				break;

			}

		endswitch;

	}

}

Используем хук – bulk_edit_custom_box, но если нам нужно просто добавить в быстрое редактирование 1 поста, то можем использовать ту же функцию, что указана выше, но другой хук – quick_edit_custom_box.

Также я использую функцию wp_nonce_field(), чтобы добавить поле с дополнительной проверкой.

В итоге получаем вот такой результат:

Блок быстрого редактирования в админке WordPress

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

3 этап – добавляем скрипт в админку

К сожалению, хука с сохранением информации из этих полей я не нашёл, зато нашёл много других способов как можно сохранять информацию, а именно посредством js и конкретно ajax.

Для того, чтобы у нас в админке выводились скрипты или стили – нужно использовать хук – admin_enqueue_scripts, – об этом написано здесь.

add_action( 'admin_enqueue_scripts', 'rb_add_scripts_to_admin' );

function rb_add_scripts_to_admin(){

    //подключаем скрипты
	wp_enqueue_script( 'admin-script', get_stylesheet_directory_uri() .'/js/admin-bulk.js' );

}

Ниже будет приведён код скрипта, который мы подключаем в админке. Сам файл я назвал – admin-bulk.js:

jQuery(function($){
	$( 'body' ).on( 'click', 'input[name="bulk_edit"]', function() {

      let bulk_edit_row = $( 'tr#bulk-edit' ),
          post_ids = new Array(),
          priceIncrease = bulk_edit_row.find( 'input[name="price-increase"]' ).val(),
          priceIncreasePercent = bulk_edit_row.find( 'input[name="price-increase-percent"]' ).val(),
          featured = bulk_edit_row.find( 'input[name="featured"]' ).attr('checked') ? 1 : 0;


      bulk_edit_row.find( '#bulk-titles' ).children().each( function() {
        post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );
      });
	  
      //формируем объект с данными, которые будут передаваться
      let data  = {
        action: 'rb_kuhni_save_bulk',
        post_ids: post_ids, 
        price_increase: priceIncrease, 
        price_increase_percent: priceIncreasePercent, 
        rb_nonce: $('#rb_kuhni_nonce').val() 
      };
	  
      //передаём данные в обработчик
      $.ajax({
        url: ajaxurl, // кстати тут повезло, тк в админке есть переменная со ссылкой на родной обработчик WordPress
        type: 'POST',
        data: data
      });
      
      
	});
});

4 этап – финал. Сохранение значений

Сейчас осталось последнее действие – нам нужно сделать обработчик ajax запроса.

add_action( 'wp_ajax_rb_kuhni_save_bulk', 'rb_save_bulk_edit_hook' );

function rb_save_bulk_edit_hook() {

	//тут мы проверяем наш nonce
	if ( ! wp_verify_nonce( $_POST['rb_nonce'], 'rb_kuhni_bulk_nonce' ) ) {
		die();
	}

	// проверяем, что передаются id постов, иначе нет смысла что-то делать
	if( empty( $_POST[ 'post_ids' ] ) ) {
		die();
	}

	// запускаем цикл для каждого id поста, переданного ранее
	foreach( $_POST[ 'post_ids' ] as $curr_post_id ) {

		$price_increase = ! empty( $_POST[ 'price_increase' ] ) ? sanitize_text_field( $_POST['price_increase'] ) : '';
		$price_increase_percent = ! empty( $_POST[ 'price_increase_percent' ] ) ? sanitize_text_field( $_POST['price_increase_percent'] ) : '';

		// Тут мы просто прибавляем к одному значению - другое
		if( $price_increase ) {

			$final_price = $price_increase + get_post_meta( $curr_post_id, 'price', true );
			$final_price_std = $price_increase + get_post_meta( $curr_post_id, 'price_std', true );
			$final_price_pr = $price_increase + get_post_meta( $curr_post_id, 'price_pr', true );

			update_post_meta( $curr_post_id, 'price', $final_price );
			update_post_meta( $curr_post_id, 'price_std', $final_price_std );
			update_post_meta( $curr_post_id, 'price_pr', $final_price_pr );

		}
		
		// Тут мы увеличиваем текущее число на количество проыентов
		if( $price_increase_percent ) {

			$final_price = get_post_meta( $curr_post_id, 'price', true ) + ( $price_increase_percent * get_post_meta( $curr_post_id, 'price', true ) / 100  );
			$final_price_std = get_post_meta( $curr_post_id, 'price_std', true ) + ( $price_increase_percent * get_post_meta( $curr_post_id, 'price_std', true ) / 100  );
			$final_price_pr = get_post_meta( $curr_post_id, 'price_pr', true ) + ( $price_increase_percent * get_post_meta( $curr_post_id, 'price_pr', true ) / 100  );

			update_post_meta( $curr_post_id, 'price', $final_price );
			update_post_meta( $curr_post_id, 'price_std', $final_price_std );
			update_post_meta( $curr_post_id, 'price_pr', $final_price_pr );

		}

	}

	die();
}

Также я использую функцию wp_verify_nonce(), чтобы проверить поле с дополнительной проверкой.

В целом мы тут просто получаем данные из файла admin-bulk.js и увеличиваем данные в мета-полях всех выбранных постов на указанное значение.