save_post для включения фильтра wp_insert_post_data, сбора информации о метаполе и предотвращения бесконечного цикла

Я пытаюсь изменить заголовок сообщения, но хочу включить информацию из мета-поля, значение которого не сохраняется в базе данных до тех пор, пока сообщения не будут сохранены. Помимо этого, он отлично работает как фильтр wp_insert_post_data .

 // add_filter('wp_insert_post_data', 'tr_change_show_title', 99, 2); function tr_change_show_title($data, $postarr) { if('post' != $data['post_type']) { // don't bother if its an auto-draft, as the post title may not have been completed yet, or in the trash if ( !in_array( $data['post_status'], array( 'auto-draft', 'trash' ) )) $child_ID = $postarr['ID']; // Child post id $parent_ID = get_post_meta($child_ID, "_wpcf_belongs_booking_id", true); // parent ID $post_type = $data['post_type']; if ($post_type == 'show' && get_post_type($parent_ID) == 'booking') { $parent_title = get_the_title($parent_ID); $data['post_title'] = $parent_title; // save the parent title first } if (function_exists('types_render_field')) { //this isn't working as the meta field isn't saved yet $show_time = types_render_field( "show-time", array("post_id"=>"$child_ID", "raw"=>"true") ); if ($show_time){ $data['post_title'] .= ' : ' . $show_time; // Append Show time to title } } $data['post_title'] .= ': show-' . $child_ID; // add the original post id } return $data; } 

Я прочитал код и этот пост wpse: https://wordpress.stackexchange.com/a/54713/13551 https://codex.wordpress.org/Function_Reference/wp_update_post

Я понимаю, что бесконечный цикл – это риск. Чтобы этого избежать, мы отцепляемся, а затем перебираем save_post до и после мяса нашей работы. Я придумал следующее, но не понимаю, почему Im все еще работает в бесконечном цикле.

 add_action( 'save_post', 'tr_save_post_show_title', 99 ); function tr_save_post_show_title($post_ID){ if ( !wp_is_post_revision( $post_ID ) ) { // do nothing if a revision // Prevent infinite loop remove_action('save_post', 'tr_save_post_show_title'); // Add our filter add_filter('wp_insert_post_data', 'tr_change_show_title', 99, 2); write_log(array( 'ID' => $post_ID)); // Re-save the post this time with filter wp_update_post( array( 'ID' => $post_ID), true ); // true for error catching // Catch errors if (is_wp_error($post_id)) { $errors = $post_id->get_error_messages(); foreach ($errors as $error) { write_log($error); } } // re-hook the save_post action add_action('save_post', 'tr_save_post_show_title'); } } 

Solutions Collecting From Web of "save_post для включения фильтра wp_insert_post_data, сбора информации о метаполе и предотвращения бесконечного цикла"

Вы подключаете tr_change_show_title к фильтру внутри самой функции, которая может создавать бесконечный цикл. Все элементы удаления / добавления действий и фильтров внутри функций должны быть удалены; вместо этого следует проверить, должны ли обновляться данные сообщения или нет. В вашем случае вы должны проверить, имеет ли название значение, которое вы хотите или нет, если не запустить wp_update_post с новым значением:

 add_action( 'save_post', 'tr_save_post_show_title', 99, 2 ); function tr_save_post_show_title( $post_ID, $post ){ if ( !wp_is_post_revision( $post_ID ) ) { // do nothing if a revision $meta = get_post_meta($post_ID, "your-meta-key", true ); if( $meta != '' ) { $desired_title = "Whatever you want as title"; // Check the title value to check if it should be modified if( $post->post_title != $desired_title ) { $post->post_title = $desired_title; wp_update_post( $post, true ); } } } } 

Вы беспокоитесь о выполнении этой функции после того, как мета-поле было сохранено / обновлено. Если мета-поле находится в том виде, в котором вы редактируете сообщение, вы можете получить доступ к значению мета-поля, как и любое другое мета-поле. В любом случае, если вы хотите быть уверенным, что мета-поле было сохранено / обновлено, вы можете использовать updated_{$meta_type}_meta action hook вместо save_post ; как преимущество, в этом действительном крюке у вас есть прямой доступ к текущему метазначению (если есть):

 add_action( 'updated_post_meta', 'tr_save_post_show_title', 99, 4 ); function tr_save_post_show_title( $meta_id, $object_id, $meta_key, $meta_value ) { if ( $meta_key == 'the_meta_key_here' && $meta_value != '' && $object_id && ! wp_is_post_revision( $object_id ) ) { //write_log(array( 'ID' => $post_id )); // Get post data $post = get_post( $object_id ); if( $post ) { $desired_title = 'Combine here the $post->post_title with $meta_value as you desire.'; // Check the title value to check if it should be modified if( $post->post_title != $desired_title ) { $post->post_title = $desired_title; wp_update_post( $post ); } } } } 

Что касается вклада @ cybmeta, я думаю, что плагин Types может бросать нам Curveball.

Он прав в том, что вы не можете (по крайней мере в этом контексте) добавить фильтр в точку save_post без создания бесконечного цикла.

Поскольку я пытаюсь получить доступ к значению мета-поля, его предложение для updated_post_meta может быть уместным, но, похоже, не работает, поскольку мета-ключ недоступен при запуске hook. Это снова может быть проблемой с тем, как типы настраивают настраиваемые поля.

В конце концов я исправил свой оригинальный подход. Независимо от какого-либо влияния типов, приведенным ниже, это рабочий пример изменения заголовка сообщения в точке save_post , включающий значение мета-поля и предотвращение бесконечного цикла. Поскольку save_post является последним действием в цепочке, он должен запускаться после всех других изменений базы данных, и поэтому вы должны чувствовать себя уверенно, что WP_Post Object будет содержать любые значения WP_Post Object и все изменения, сделанные любыми предыдущими фильтрами или действиями. Если бы мне не нужна текущая информация из моих мета-полей, достаточно было бы простую фильтрацию через wp_insert_post_data .

 add_action('save_post', 'tr_save_post_show_title', 99, 2); function tr_save_post_show_title ($post_ID, $post) { if($post->post_type == 'show' && !in_array($post -> post_status, array('auto-draft', 'revision', 'trash'))) { // don't bother if our CPT post is an auto-draft, a revision or in the trash $parent_ID = get_post_meta($post_ID, "_wpcf_belongs_booking_id", true); // Types relationship $current_title = $post -> post_title; // Get current post title saved in DB $post_showtime = get_post_meta($post_ID, "wpcf-show-time", true ); // our custom meta field if ($post_showtime == ''){ $post_showtime = 'To be confirmed'; } if ($parent_ID && get_post_type($parent_ID) == 'booking') { // Check to see if Types a parent relationship has been assigned. $show_post_title = get_the_title($parent_ID); // get the id of the parent post if ($show_post_title != ''){ $show_post_title .= ': ' . $post_showtime; } } else if (!$parent_ID){ // when a parent is not assigned $show_title = "Show not yet assigned to venue: " . $post_showtime; } if ($current_title != $show_post_title ){ // The current title does not match what we would like it to be // Prevent infinite loop remove_action('save_post', 'tr_save_post_show_title'); // Re-save the post with our new title wp_update_post( array( 'ID' => $post_ID, 'post_title' => $show_post_title ), false ); // true for error catching // re-hook the save_post action add_action('save_post', 'tr_save_post_show_title', 99, 2); // Catch any errors with our custom logging function http://goo.gl/P9HbcK if (is_wp_error($post_ID)) { $errors = $post_id->get_error_messages(); foreach ($errors as $error) { write_log($error); } } } } } 

Интересно, что save_post_<post_type> который выполняется непосредственно перед save_post как save_post не получал самые последние значения из мета-поля.

Мой подход к этой проблеме заключается в доступе к «сырым» метаданным непосредственно из $ _POST [metabox_id] в wp_insert_post_data фильтрах. Я признаю, что этот подход больше подходит для моего проекта, где сообщения генерируются полностью из метаданных и их нужно повторно отображать каждый раз. Жесткий кто-то может сочтет это полезным.