web-dev-qa-db-ja.com

データベースの 'post_content_filtered'列がWordPressによってクリアされるのはいつですか?

WordPressプラグインの中には(ごくわずかですが)データベース内のpost_content_filtered列を使用して投稿に関するデータを保存するものがあります。

たとえば、 Markdown on Savepost_content_formatted列に投稿のマークダウンバージョンとpost_content列に解析済みHTMLを別々に保存するので、プラグインが無効になったときに投稿がMarkdownと表示されないようになります。 post_content)に格納されています。

さて、私はpost_content_filteredが一時的な記憶のためにほとんど使われていることに気づきました、すなわち、以下の場合、列の内容は失われます(またはクリアされます)。

  • [クイック編集]オプションを使用して投稿(タイトル、タグ、カテゴリなど)に変更を加えます。

  • 予定投稿が(自動的に)公開されます

  • 投稿を一括編集します

  • 投稿のリビジョンを切り替える

  • 投稿が外部エディタ(WordPress投稿エディタではない)から保存されている

質問:

  1. post_content_filtered列のデータは他にどのような状況でクリアされますか?

  2. これがまったく起こらないようにする方法はありますか? (つまり、データが永続的に格納されるようにする方法、post_content列の処理方法はありますか?)

27
its_me

WordPressのすべての投稿更新はwp_update_post関数によって処理されます。

この関数にはいくつかのデフォルトがあり、post_content_filteredのデフォルト値は ''(空の文字列)です。

デフォルトがwp_parse_argsを介してfunctionに渡される引数とマージされると、投稿が更新され、post_content_filteredが明示的に渡されないたびに、空の文字列に設定されます。

post_content_filteredが明示的にwp_update_postに渡されるのはいつか?答えは:決してWordPressによる)。

それであなたの最初の質問のために:

Post_content_filtered列のデータは他にどのような状況でクリアされますか?

簡単な答えは:何らかの理由で投稿が更新されるたびに{_。

1つのフィールドのみを変更するis更新、特にすべてのステータスの変更は更新です。たとえば、公開するドラフト、公開する予定、公開する予定、ゴミ箱に公開する(削除後など)などです。 ..

投稿に何か変更があった場合、post_content_filteredはクリアされます。唯一の例外は、post_content_filteredが明示的にwp_update_postに渡される場合です。すでに述べたように、これはWordPressによって行われることはありません。

これがまったく起こらないようにする方法はありますか? (つまり、データが永続的に保存されていることを確認する方法はありますか。

あなたがあなたのコードでそのフィールドを作成し、そしてあなたがそれを保存したいのなら、あなたはWordPressによって実行されたevery updateを見て、そしてその変更を防ぐ必要があります。

これは大変な作業のように思えるかもしれませんが、この答えの最初の文「WordPressのすべての投稿更新はwp_update_post functionによって処理される」を読むと、必要なことはその関数を見ることだけです幸いなことに、さまざまなフックがあります。

私が提案するフックは、2つの理由からwp_insert_post_dataです。

  • それは更新の前にを実行するので、あなたは回復する必要はありませんがあなたは防ぐことができます
  • それは2つのパラメータを渡します:関数が更新しようとしているデータと渡されたパラメータの配列です。(更新の場合は)投稿のIDを含みます。

ですから、単純な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;

}

前の関数がeverypost_content_filteredのクリーニングを妨げる可能性のある問題があります。そして、なんらかの理由でyouをクリアしたい場合は、

すべての[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をリ​​セットする必要がある場合は、この関数を呼び出すことができます。

また、 'Clear content filtered'ボタンを使ってメタボックスを作成することもできます。このボタンがクリックされたときにはreset_post_content_filtered関数を呼び出すだけです。 Ajaxを介して。

28
gmazzap