Distributor: NetworkSiteConnection :: update_syndicatedの実行がGutenberg / RESTコンテキストで早すぎます

作成日 2019年10月03日  ·  6コメント  ·  ソース: 10up/distributor

バグを説明する
グーテンベルクを使用してマルチサイト(内部ネットワーク接続)の別のサイトに配布された投稿を更新する場合、メタ、用語などの更新はプッシュされません。 ここでの問題は、 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' ) )ようなものが真である場合は、そのメソッドを中止することで処理できる可能性があります。 しかし、おそらくそれよりも賢い方法があると思います。 ;)

とにかく、素晴らしいプラグインに感謝します。興味があれば、この問題を喜んでお手伝いします。

再現する手順

  1. WordPressマルチサイトで、Gutenbergを使用して、少なくともタイトル、カテゴリ、注目の画像を含む投稿を作成します。 (重要なことですが、グーテンベルクでレガシーメタボックスを使用しないでください。これにより、WPで別の保存がトリガーされ、バックコンパットが処理され、この問題が解消されます)
  2. この投稿をネットワーク内の別のサイトに配布し、見栄えがよいことを確認します。
  3. タイトル、カテゴリ、注目の画像を変更し、投稿を更新します。
  4. 他のサイトの配布された投稿をチェックして、タイトルは変更されているが、カテゴリや注目の画像は変更されていないことを確認してください。
  5. 投稿のタイトルのみを更新します。
  6. 他のサイトの配布された投稿をチェックして、タイトルが変更され、ステップ3で保存されたカテゴリと注目の画像が配布されていることを確認します(ステップ5の実行時にすでに保存されているため)。

予想される行動

メタ、用語などは更新時に配布する必要があります。

環境情報

  • ディストリビューターバージョン:開発ブランチからの最新。
  • テーマとバージョン:Twenty Nineteen 1.4
  • その他のインストール済みプラグインとバージョン:なし。
  • WordPress 5.2.3
bug

最も参考になるコメント

@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' )ようなものです
  • また、これらのフックは異なる引数を使用するため(1つは投稿ID、もう1つは投稿オブジェクト)、それを処理する必要があります。 get_postはIDまたはオブジェクトのいずれかを受け入れるため、 get_post( $post_id )を呼び出すのと同じくらい簡単なはずです。

このアプローチについて質問がある場合(または懸念がある場合)はお知らせください。 私はまだこれをテストしていませんが、理論的には、これは機能し、二重更新が発生するのを防ぐはずだと思います。

全てのコメント6件

@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' )ようなものです
  • また、これらのフックは異なる引数を使用するため(1つは投稿ID、もう1つは投稿オブジェクト)、それを処理する必要があります。 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

このページは役に立ちましたか?
0 / 5 - 0 評価