Когда столбец 'post_content_filtered' в базе данных очищается WordPress?

29

Некоторые плагины WordPress (хотя их очень мало) используют post_content_filteredстолбец в базе данных для сохранения некоторых данных, связанных с публикацией.

Например, Markdown при сохранении сохраняет версию уценки поста отдельно в post_content_formattedстолбце и проанализированный HTML-код в post_contentстолбце, чтобы при деактивации плагина посты не выводили уценку (поскольку HTML хранится в post_content).

Теперь я пришел к выводу, что post_content_filteredон в значительной степени используется для временного хранения, то есть содержимое в столбце теряется (или очищается), когда:

  • Вы вносите изменения в сообщение (заголовок, теги, категории и т. д.), используя параметр «Быстрое редактирование»

  • запланированный пост (автоматически) публикуется

  • Вы делаете массовые изменения в сообщениях

  • вы переключаетесь между ревизиями поста

  • сообщение сохраняется из внешнего редактора (т.е. не редактора сообщений WordPress)

Вопросов:

  1. В каких других ситуациях данные в post_content_filteredстолбце очищаются?

  2. Есть ли способ предотвратить это вообще? (Я имею в виду, есть ли способ убедиться, что данные хранятся постоянно, как post_contentобрабатывается столбец?)

это я
источник

Ответы:

29

Каждое обновление в WordPress обрабатывается wp_update_postфункцией.

Эта функция имеет некоторые значения по умолчанию, и по post_content_filteredумолчанию используется значение '' (пустая строка).

Как только значения по умолчанию объединяются с аргументами, передаваемыми в функцию через wp_parse_argsнего, это означает, что каждый раз, когда сообщение обновляется и post_content_filteredявно не передается, ему присваивается пустая строка.

Теперь мы можем спросить: когда post_content_filteredявно передается wp_update_post? Ответ: никогда не WordPress.

Итак, для вашего первого вопроса:

В каких других ситуациях очищаются данные в столбце post_content_filtered?

Краткий ответ: каждый раз, когда сообщение обновляется, по любой причине .

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

Если что-то меняется в посте, то post_content_filteredочищается; Единственное исключение - это когда post_content_filteredявно передается wp_update_post, и, как уже было сказано, WordPress никогда не делает этого.

Есть ли способ предотвратить это вообще? (Я имею в виду, есть ли способ убедиться, что данные хранятся постоянно?

Если вы создаете это поле с помощью своего кода и хотите сохранить его, вам нужно просматривать каждое обновление, выполненное WordPress, и предотвращать это изменение.

Это может звучать как тяжелая работа, но если вы прочитаете первое предложение в этом ответе « Каждое обновление поста в WordPress обрабатывается wp_update_postфункцией », вы поймете, что нужно только посмотреть на эту функцию, которая, к счастью, имеет различные хуки ,

Крюк, который я предлагаю, это wp_insert_post_dataпо двум причинам:

  • Он запускается до обновления, поэтому вам не нужно восстанавливать, но вы можете предотвратить
  • Он передает 2 параметра: данные, которые функция собирается обновить, и массив переданных параметров, которые (в случае обновления) содержат идентификатор сообщения

Таким образом, используя простую, get_postвы можете сравнить, какова публикация сейчас и как будет публикация: если вам что-то не нравится, вы можете изменить ее.

Давайте код:

add_filter( 'wp_insert_post_data', 'preserve_content_filtered', 999, 2 );

function preserve_content_filtered ( $data, $postarr ) {

    /* If this is not an update, we have nothing to do */
    if ( ! isset($postarr['ID']) || ! $postarr['ID'] ) return $data;

    /*
     * Do you want you filter per post_type?
     * You should, to prevent issues on post type like menu items.
     */
    if ( ! in_array( $data['post_type'], array( 'post', 'page' ) ) ) return $data;

    /* How post is now, before the update */
    $before = get_post( $postarr['ID'] ); 

    /* If content_filtered is already empty we have nothing to preserve */
    if ( empty( $before->post_content_filtered ) ) return $data;

    if ( empty( $data['post_content_filtered'] ) ) {
        /*
         * Hey! WordPress wants to clear our valuable post_content_filtered...
         * Let's prevent it!
         */
        $data['post_content_filtered'] = $before->post_content_filtered;
    }

    return $data;

}

Существует возможная проблема, когда предыдущая функция предотвращает каждую post_content_filtered очистку. А если вы по какой-то причине хотите это очистить?

Я сказал, что каждое изменение в посте WP обрабатывается wp_update_post, но вы не WordPress.

Вы можете написать функцию как:

function reset_post_content_filtered( $postid ) {
    global $wpdb;
    $wpdb->query( $wpdb->prepare(
        "UPDATE $wpdb->posts SET `post_content_filtered` = '' WHERE `ID` = %d", $postid
    ) );
}

Будучи $wpdbзапросом, он не запускает наш фильтр, поэтому сброс выполняется без проблем, и везде в вашем коде вам нужно выполнить сброс post_content_filtered, вы можете вызвать эту функцию.

Вы также можете создать метабокс с помощью кнопки «Очистить контент, отфильтрованный», и когда эта кнопка нажата, просто вызовите свою reset_post_content_filteredфункцию, например, через Ajax.

Gmazzap
источник