
【Gutenberg】公開済みの記事のプレビューの変更が反映されない場合の対処方法
メタボックス を使用している場合 かつ 公開後の投稿の場合、変更した内容がプレビューで反映されない場合があります。
すでにIssueとして挙がっているので今後本体側で修正される可能性が高いですが、それまでは自分で修正する必要があります。
解決方法
子テーマの functions.php などにコードを追加します。
PHP の修正なので注意が必要です。
add_filter( 'wp_insert_post_data', function ( $data ) {
if ( isset( $_GET['meta-box-loader'] ) ) {
unset( $data["post_modified"] );
unset( $data["post_modified_gmt"] );
}
return $data;
} );
原因
プレビュー用のリビジョンの削除されることが直接の原因です。
プレビュー用のリビジョンの削除される原因
wp-admin/edit-form-blocks.php の以下の個所で post_modified_gmt の比較が想定された動作になっていないため、プレビュー用のリビジョンが消されてしまいます。
$autosave = wp_get_post_autosave( $post_ID );
if ( $autosave ) {
if ( mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) {
$editor_settings['autosave'] = array(
'editLink' => get_edit_post_link( $autosave->ID ),
);
} else {
wp_delete_post_revision( $autosave->ID );
}
}
post_modified_gmt の比較が正しくない原因
投稿の保存は『記事の内容の保存』と『メタボックスの保存』に分かれています。
プレビューの時には『記事の内容の保存』の時にプレビュー用のリビジョンが作成されます。
そして『記事の内容の保存』が終わった後に『メタボックスの保存』が行われます。
この『メタボックスの保存』の時に元の記事が更新されるため、プレビュー用のリビジョンよりも元の記事のほうが post_modified_gmt が新しくなります。
したがって
mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false )
による比較は false になり
wp_delete_post_revision( $autosave->ID )
が実行されます。
解決方法1
『メタボックスの保存』の時に元の記事の post_modified_gmt を更新しないようにすればプレビュー用のリビジョンが消されることはありません。
『メタボックスの保存』の時は $_GET['meta-box-loader'] が 1 になります。
この meta-box-loader による判定が行われている use_block_editor_for_post に合わせて isset( $_GET['meta-box-loader'] ) が true の場合に『メタボックスの保存』が実行中であると判定することにします。
また保存する値は wp_insert_post_parent フィルタで変更できます。
以上のことから前述の以下のコードで解決できることがわかります。
add_filter( 'wp_insert_post_data', function ( $data ) {
if ( isset( $_GET['meta-box-loader'] ) ) {
unset( $data["post_modified"] );
unset( $data["post_modified_gmt"] );
}
return $data;
} );
post_modified は判定に使用されていませんが、post_modified_gmt に合わせて更新しないようにしています。
一部テーマやプラグインに関して
更新日時を変更しなかったり自由に変更できるようにしたりするメタボックスを追加するテーマやプラグインを導入している場合は、上記対応では正しく動かない場合があります。
さらに具体的には『記事の内容の保存』の時に更新日時を変更せず、『メタボックスの保存』の時にメタボックスから送信される値で更新日時を変更するような動作の場合です。
そのようなテーマやプラグインは大抵の場合オートセーブが考慮されていないため、プレビュー用のリビジョンも元の記事も更新日時が変更されなくなってしまいます。
解決方法2
『メタボックスの保存』の時にプレビュ用のリビジョンの更新日時を必ず元の記事よりも未来に設定するようにすれば解決します。
add_action( 'save_post', function ( $post_id, $post ) {
if ( isset( $_GET['meta-box-loader'] ) ) {
$autosave = wp_get_post_autosave( $post_id );
if ( $autosave ) {
$filter = function ( $data ) use ( &$filter, $post ) {
remove_filter( 'wp_insert_post_data', $filter );
$data["post_modified"] = gmdate( 'Y-m-d H:i:s', strtotime( $post->post_modified ) + 1 );
$data["post_modified_gmt"] = gmdate( 'Y-m-d H:i:s', strtotime( $post->post_modified_gmt ) + 1 );
return $data;
};
add_filter( 'wp_insert_post_data', $filter );
wp_update_post( $autosave );
}
}
}, 10, 2 );
元の記事の更新日時に+1秒して保存します。
2019/4/9 追記
クラシックエディタではプレビュー時にメタボックスを保存していなかったため、Gutenbergもそれに合わせてプレビュー時の保存をやめることで対応するとのことです。
一方でレビュワーはクラシックエディタでは保存していたと言っています。
にもかかわらず承認しているのはメタボックスよりも本文が反映されないことのほうが重要なので妥協した感じでしょうか
そもそもメタボックスの保存によってプレビューの時点で投稿が更新されてしまう動作自体も不自然であり長年議論されていたようです。
2019/4/17 追記
Gutenbergプラグイン v5.5 で修正済みです。
プレビュー時のメタデータの保存は今後再度実装予定のようです。
2019/5/8 追記
WordPress v5.2 で反映されました。
もしこのページにある修正を追加していた場合は戻したほうがよいです。
2019/6/7 追記
ACFプラグインを使用しているとプレビューが効かないことがあるようです。
いまだにちらほらと効かないという報告があるようです。
もし発生条件などがわかる場合は報告することで修正の手助けになるので、ぜひIssueから報告してください。
