Когда WordPress очищает столбец "отфильтрованный контент" в базе данных?


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

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

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

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

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

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

  • Вы переключаетесь между редакциями публикации

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

Вопросы:

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

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

Author: its_me, 2013-09-08

1 answers

Каждое обновление публикации в 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 причинам:

  • Он запускается до обновления, поэтому вам не нужно восстанавливать , но вы можете предотвратить
  • Он передает 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.

 31
Author: gmazzap, 2015-09-13 16:56:32