バグを説明する
グーテンベルクを使用してマルチサイト(内部ネットワーク接続)の別のサイトに配布された投稿を更新する場合、メタ、用語などの更新はプッシュされません。 ここでの問題は、 NetworkSiteConnection
クラスのupdate_syndicated
メソッドがsave_post
アクションにフックされていることのようです。 これは、クラシックエディターを使用する場合は正常に機能しますが、Gutenbergを使用し、投稿がREST-apiを介して保存される場合、 save_post
フックが早く起動するようです。 見てみるとupdate_item
の方法WP_REST_Posts_Controller
クラス1があることがわかりますwp_update_post
トリガーとなるsave_post
アクションはライン697で呼び出され、そして唯一のその後ですREST-apiによって処理されるメタ、用語など。 これは、ディストリビューターがupdate_item
メソッドを実行しているとき、メタ、用語などがまだ更新/保存されていないことを意味します。
回避策として、mu-pluginに次のコードを追加しました。
add_action(
'rest_after_insert_post',
function( WP_Post $post ): void {
\Distributor\InternalConnections\NetworkSiteConnection::update_syndicated( $post->ID );
}
);
これは、投稿が保存時に2回配布されることを意味するため、最適ではありません。大したことではありませんが、 update_syndicated
が2回実行されるため、保存が少し遅くなります。
この問題の最善の解決策は、グーテンベルクとクラシックエディターの両方で機能させることです。 もちろん、 update_syndicated
メソッドを( save_post
rest_after_insert_{$post_type}
アクションとrest_after_insert_{$post_type}
フックすることもできます。 show_in_rest = trueであるすべてのpost_typesに対するアクション。 これは、 update_syndicated
メソッドが2回実行されることを意味しますが、 ( ( defined( 'REST_REQUEST' ) && REST_REQUEST ) && doing_action( 'save_post' ) )
ようなものが真である場合は、そのメソッドを中止することで処理できる可能性があります。 しかし、おそらくそれよりも賢い方法があると思います。 ;)
とにかく、素晴らしいプラグインに感謝します。興味があれば、この問題を喜んでお手伝いします。
再現する手順
予想される行動
メタ、用語などは更新時に配布する必要があります。
環境情報
@lakrisgubben非常に詳細な問題とこれに関する調査に感謝します、それは大いに感謝されます! 私はこれを次のマイルストーンリリースに取り入れて、これを解決できるかどうかを確認していますが、PRを作成できれば、次のリリースへのレビューを通じて喜んで取得します。 再度、感謝します!
返信ありがとうございます@jeffpaul! これに関するPRを手伝ってくれてうれしいですが、それを行うには、コードベースに精通している誰かからの入力をお願いします。これにより、すべての人が満足できる方法で修正が行われるようになります。 :)
@lakrisgubbenこれを私たちの注意を
正直なところ、ここに優れたアプローチがあるかどうかはわかりません。グーテンベルクのしくみにほとんど依存しているからです。 これは既知の問題であり(https://github.com/WordPress/gutenberg/issues/12903のスレッドについてはこちらを参照)、同様のシナリオで適切なアプローチを見つけようとしているようです。
これが私が提案することです、それはあなたのアプローチにかなり似ています:
is_using_gutenberg
ヘルパーメソッドがあります。 update_syndicate
メソッド内でこれを使用して、投稿がグーテンベルクを使用しているかどうかを判断できると思いますupdate_syndicate
メソッドを呼び出す、 rest_after_insert_{$post_type}
にフックされた新しいアクションを追加できます。 そして、早く戻って、残りのコードが実行されないようにします(そして、二重の更新を取得しません)update_syndicate
メソッドがrest_after_insert_{$post_type}
フックによって呼び出されると、その時点ですべてのコードが実際に実行されていることがわかります。 つまり、 \Distributor\Utils\is_using_gutenberg( $post ) && doing_action( 'save_post' )
ようなものですget_post
はIDまたはオブジェクトのいずれかを受け入れるため、 get_post( $post_id )
を呼び出すのと同じくらい簡単なはずです。このアプローチについて質問がある場合(または懸念がある場合)はお知らせください。 私はまだこれをテストしていませんが、理論的には、これは機能し、二重更新が発生するのを防ぐはずだと思います。
@dkotter詳細な返信ありがとうございます! 私はあなたの提案に基づいて修正を実装することに突き刺しました、そして私が前に考えていなかった別の問題を見つけました。 :)
次のようなものを追加します
if ( \Distributor\Utils\is_using_gutenberg( $post ) && doing_action( 'save_post' ) ) {
add_action( "rest_after_insert_{$post->post_type}", array( '\Distributor\InternalConnections\NetworkSiteConnection', 'update_syndicated' ) );
return;
}
シンジケート記事の更新を、従来のエディターとレガシーメタボックスを使用しないグーテンベルクの両方で機能させます。 ただし、レガシーメタボックスでGutenbergを使用すると、 rest_after_insert_{$post->post_type}
フックをトリガーしないRESTリクエストの後に実行される別のPOSTリクエストに保存されるため、壊れます。つまり、レガシーメタボックスのメタデータは更新時にシンジケートされません。
あなたが言うように、この状況を処理するための素晴らしい方法はないようですが、上記のifステートメントに! isset( $_GET['meta-box-loader'] )
を追加すると、少なくともそれは機能します。 これは、グーテンベルクとレガシーメタボックスを使用している場合、更新された投稿が2回シンジケートされることを意味しますが、部分的にシンジケートされるよりも優れていると思います。
したがって、これをupdate_syndicated
メソッドに追加すると(テストできた限り)、クラシックエディターとグーテンベルクの両方でこれをうまく機能させ、レガシーメタボックスを使用してグーテンベルクで「大丈夫」になります。
if ( \Distributor\Utils\is_using_gutenberg( $post ) && doing_action( 'save_post' ) && ! isset( $_GET['meta-box-loader'] ) ) {
add_action( "rest_after_insert_{$post->post_type}", array( '\Distributor\InternalConnections\NetworkSiteConnection', 'update_syndicated' ) );
return;
}
@dkotterは、この解決策が妥当だと思われる場合、またはこの問題に対処する別の方法を考えられる場合は、私に知らせてください。そうすれば、私はそのPRを行うことができます。
@lakrisgubbenそれをテストしてくれてありがとう。 カスタムメタボックスがある場合(他のプロジェクトで問題が発生している)、グーテンベルクが2つのリクエストを行ったことは知っていましたが、その場合はrest
フックが起動しないことに気づかなかったと思います(メタがregister_post_meta
を使用して登録され、 show_in_rest
値がtrueの場合に発生します)。
カスタムメタを処理している場合は、 meta-box-loader
変数を常に設定する必要があるようですが、これに依存するのは理想的ではないようです。 しかし、これを解決するための中心的な方法はないようであり、私が言及した他のすべてのアプローチはさらに理想的ではないように思われるので、これはまともな方法だと思います。
あなたがそれをまとめる時間があれば、PRをテストして幸せです。 ここでのすべての努力に感謝します!
@dkotterのPRでの最初のパスはこちら: https :
最も参考になるコメント
@lakrisgubbenこれを私たちの注意を
正直なところ、ここに優れたアプローチがあるかどうかはわかりません。グーテンベルクのしくみにほとんど依存しているからです。 これは既知の問題であり(https://github.com/WordPress/gutenberg/issues/12903のスレッドについてはこちらを参照)、同様のシナリオで適切なアプローチを見つけようとしているようです。
これが私が提案することです、それはあなたのアプローチにかなり似ています:
is_using_gutenberg
ヘルパーメソッドがあります。update_syndicate
メソッド内でこれを使用して、投稿がグーテンベルクを使用しているかどうかを判断できると思いますupdate_syndicate
メソッドを呼び出す、rest_after_insert_{$post_type}
にフックされた新しいアクションを追加できます。 そして、早く戻って、残りのコードが実行されないようにします(そして、二重の更新を取得しません)update_syndicate
メソッドがrest_after_insert_{$post_type}
フックによって呼び出されると、その時点ですべてのコードが実際に実行されていることがわかります。 つまり、\Distributor\Utils\is_using_gutenberg( $post ) && doing_action( 'save_post' )
ようなものですget_post
はIDまたはオブジェクトのいずれかを受け入れるため、get_post( $post_id )
を呼び出すのと同じくらい簡単なはずです。このアプローチについて質問がある場合(または懸念がある場合)はお知らせください。 私はまだこれをテストしていませんが、理論的には、これは機能し、二重更新が発生するのを防ぐはずだと思います。