Перевірте наявність оновлень відносно нової публікації в дії save_post


21

Чи можна в рамках дії save_post визначити, чи створюється нова публікація, чи наявна публікація оновлюється?


Я не думаю, що це можливо. Дивіться мій коментар нижче @ моралеїда відповідь. Чому потрібно знати, чи це нова публікація чи оновлюється? Може існувати обхід чи альтернативний підхід.
Стівен Гарріс

Відповіді:


16

Оскільки WordPress версії 3.7. - IIRC - save_postгачок - додаткова інформація про гачок та його використання у Code Reference:save_post та Codex:save_post - має третій параметр, $updateякий можна використовувати для визначення саме цього.

@param int $ post_ID Ідентифікатор допису.
@param WP_Post $ post Об’єкт повідомлення.
@param bool $ update Невже це наявна публікація, що оновлюється чи ні.


Примітка:

$updateне завжди true- ви можете побачити і протестувати його самостійно за допомогою наведеного нижче коду. Це не добре зафіксовано, хоча, можливо, далеко не оптимально названо, а отже, створює оманливі очікування. Нижче код можна використовувати для налагодження, пограйте з тим, коли потрібно перехопити виконання коду, оскільки в іншому випадку ви не побачите інформацію / повідомлення. Я думаю, що винуватцем оманливої ​​поведінки є поправка з ревізіями та автоматичними збереженнями - які можуть бути відключені, але я не рекомендую цього і не перевіряв. Не впевнений, чи це вимагає квитка на Trac , тому я не відкрив його, якщо ви так вважаєте, перейдіть за посиланням і зробіть це самостійно. Крім цього, як зазначено в коментарях, якщо у вас є конкретні проблеми, поставте нове запитання.

add_action( 'save_post', 'debug_save_post_update', 10, 3 );
function debug_save_post_update( $ID, $post, $update ) {

  echo '<pre>';
  print_r( $post ); echo '<br>';
  echo '$update == ';
  echo $update ? 'true' : 'false';

  //conditions
  if( ! $update && $post->post_status == "auto-draft" ) {
    // applies to new post
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // applies basically to the (auto saved) revision 
    //die();
  } else {
    // applies to updating a published post
    // when there is a revision, which is normally the case, 
    // standard behavior of WordPress, then it is considered 
    // an update, which is where the confusion sets in
    // there are other methods, like checking time or post status
    // depending on your use case it might be more appropriate 
    // to use one of those alternatives 
    //die();
  }

  echo '</pre>';
  //die();
}

3
$updateПараметр завжди вірно , навіть якщо це новий пост. Тож цей параметр марний. Не впевнений, чи взагалі колись це працювало, але впевнений, що пекло не працює так, як це зафіксовано в останній версії wordpress 4.8.
Соломон Клоссон

@SolomonClosson Якщо ви поглянете wp_publish_post, то так. Але це не вірно для його використання в wp_insert_post. Я написав функцію налагодження, додаю її у відповідь.
Миколай

@SolomonClosson Якщо у вас є реальна конкретна проблема, будь ласка, задайте нове запитання. Погляньте на пояснення функції налагодження, пояснення.
Миколай

У save_postгака є 3-й параметр, який завжди встановлено на TRUE, тому не впевнений, що це стосується інших гачків, не кажучи про інші гачки. Я кажу про гачок у вашій відповіді. Це неправильно.
Соломон Клоссон

@SolomonClosson Як я вже сказав, гак відбувається два рази: wp_insert_post(), wp_publish_post(). Останнє - це лише майбутні посади, $updateналаштоване завжди true. Інакше, що стосується wp_insert_post(), $updateце не завжди true.
Миколай

11

Те, як я виконую цю перевірку (в межах підключеної функції), полягає в порівнянні дати публікації та модифікованої дати (в GMT для стандартизації)

function check_new_vs_update( $post_id ){
    $myPost        = get_post($post_id);
    $post_created  = new DateTime( $myPost->post_date_gmt );
    $post_modified = new DateTime( $myPost->post_modified_gmt );

    if( abs( $post_created->diff( $post_modified )->s ) <= 1 ){
        // New post
    }else{
        // Updated post
    }
}
add_action('save_post', 'check_new_vs_update' );

Це працює, тому що навіть під час створення публікації додається "модифікована" дата, яка точно така ж, як і "створена" дата, але ми допускаємо відхилення в 1 секунду в будь-якому випадку, у випадку, якщо другий відмічається під час створення пошта.


1
Іноді post_date_gmtє 2019-03-12 01:31:30і post_modified_gmtє 2019-03-12 01:31:31. :(
He Yifei 何 一 非

1
@HeYifei 何 一 非 хороший момент, якщо обробка розпочнеться наприкінці даної секунди, це може статися. Я оновив свою відповідь, дякую
Джеймс Кушинг

Хлопці, просто інформація. Гак запускається при відновленні та видаленні посади.
Мельвін

6

Я закінчив лише перевірити наявність спеціального значення перед його встановленням. Таким чином, якщо це новостворена публікація, власні значення ще не існували б.

function attributes_save_postdata($post_id) {
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
  if ('page' == $_POST['post_type']) {
    if (!current_user_can('edit_page', $post_id)) return;
  } else {
    if (!current_user_can('edit_post', $post_id)) return;
  }
  $termid = get_post_meta($post_id, '_termid', true);
  if ($termid != '') {
    // it's a new record
    $termid = 'update';
  } else {
    // it's an existing record
  }
  update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');

Щоб це працювало, чи потрібно спочатку створити спеціальне поле за допомогою add_post_meta?
MF1

За кодексом: замість функції add_post_meta () може використовуватися [update_post_meta]. codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid

Це може бути невдалим, якщо повідомлення були створені до того, як гачок коду буде включена за допомогою активації плагіна. Старіші повідомлення не мають мета-набору, тому перше оновлення для них буде вважатися новим.
Васу Чаула

4

Приклад відповіді на іалоцин з параметром "оновлення":

function save_func($ID, $post,$update) {

   if($update == false) {
     // do something if its first time publish
   } else {
     // Do something if its update
   }
}

add_action( 'save_post', 'save_func', 10, 3 );

2
Кращим способом структурувати це буде або покласти перший блок оновлень, що дозволяє просто робити, if($update)або зберігати новий блок спочатку, але використовувати if( ! $update ). Останній отримає ОП в кращій практиці, і він надає перевагу над вашим методом стандартами кодування WordPress у таких випадках, як термінальний оператор
Джеймс Кушинг

1

Ви можете використовувати гачок дій pre_post_update для оновлення коду та save_post для нового поштового коду. Він працює до оновлення публікації.


4
save_postгак знімається як під час створення публікації, так і оновлення (після того, як WordPress збереже її до бази даних). pre_post_updateзнімається, коли повідомлення оновлюється, але перед оновленням повідомлення - це може бути важливо.
Стівен Харріс

1

Як натякнув Даршан Тонкі (і Стівен Гарріс далі докладно), ви можете скористатися pre_post_updateна свою користь.

global $___new_post;
$___new_post = true;

add_action(
  'pre_post_update',
  function() {
    global $___new_post;
    $___new_post = false;
  },
  0
);

function is_new_post() {
  global $___new_post;
  return $___new_post;
}

Причина, чому я використовував глобали, полягає в тому, що function is_new_post() use ( &$new_post )це неправдиво в PHP (шокуюче ...), тому втягування цієї змінної у область функцій не працює - отже, глобальна.

Зауважте, що це дійсно може бути надійно використане лише протягом / після save_postподії (що, як правило, достатньо, принаймні для того, що ми робимо з нею).


0

Коли спрацьовує save_post, вся інформація про цю публікацію вже доступна, тому теоретично ви могли б використовувати

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // if this is a new post get_posts($post_id) should return null
    } else {
    // $post_id already exists on the database
    }
}
add_action('save_post','f4553265_check_post');

це, проте, не перевірено. =)


3
До того часу, як ви дістанетесь до save_postсамої публікації, вона вже була б збережена в базі даних - так get_postsби поверталася поточна публікація.
Стівен Гарріс

Правда, щойно перевірив це в Кодексі. Дякую за голову.
moraleida

0

Інший підхід, який використовує вбудовану функцію і не має доповнення до бази даних get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //draft
} else { 
    //not a draft: can be published, pending, etc. 
}

Однак зауважте, що це може бути недоцільним, якщо ви згодом плануєте повернути статус "чернетки" - ваші вказівки будуть повторені наступного разу, коли ви оновите публікацію. Залежно від контексту, ви можете розглянути різні рядки, до яких можна повернутись, get_post_status()щоб створити більш відповідний сценарій.

Дивіться Codex для get_post_status () та стану публікації

Можливі значення:

  • 'опублікувати' - опублікована публікація або сторінка
  • "очікує на розгляд" - публікація очікує на розгляд
  • 'чернетка' - посада в статусі чернетки
  • "авто-чернетка" - щойно створена публікація без вмісту
  • 'майбутнє' - публікація, яку слід опублікувати в майбутньому
  • 'приватний' - не видно користувачам, які не ввійшли в систему
  • ‘успадковувати’ - перегляд. дивіться get_children.
  • 'сміття' - повідомлення знаходиться в кошику. додано до версії 2.9.

Я не думаю, що це робить те, про що вимагали. Якщо я створюю нову публікацію, а потім натискаю "Опублікувати", save_post()виконується вперше, але під час цього виконання get_post_status()вже повертає "опублікувати", а не "чернетку", навіть якщо вона опублікована лише в процесі.
cgogolin
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.