サポート » プラグイン » アクションフックのタイミング?

  • 解決済 shokun0803

    (@shokun0803)


    簡単な承認システムプラグインを作っているのですが、投稿された記事が修正されたときに「承認済み」を「未承認」に変更し、post_statusをprivateに変更しようとしています。

    公開されている(post_status->publish)記事を修正したときedit_postでフックして未承認に変更することはできました。また、同時にpost_statusをprivateに変更することもできます。
    しかし、非公開の記事(post_status->private)を一般公開に変更したときも「更新」のボタンを押すためedit_postでフックしていると未承認・非公開に戻されてしまいます。

    記事編集画面で「編集をして更新ボタンを押した」のか、「公開情報を変更だけして更新ボタンを押した」のかを区別する方法はありますか?

    ちなみに、記事を作成・編集する権限アカウントと公開する権限アカウントは同一です。承認するためだけのアカウントが別に作成してある状況です。(承認権限者に公開の権限はありません)

13件の返信を表示中 - 1 - 13件目 (全13件中)
  • モデレーター jim912

    (@jim912)

    shokun0803さん、こんにちは。

    下記、スレッドが参考になるのではと思います。

    レビュー待ち記事のメール通知

    少々乱暴な回答ですが、これだけでご理解いただけると思いますので。

    すみません、勉強不足で。

    「公開情報を変更だけして更新ボタンを押した」はadd_action('private_to_publish', 'approval_system_publish');でいいのかなと思いますが、
    「編集をして更新ボタンを押した」がいまいち良く解かりません。add_action('edit_post', 'approval_system_setup');だと更新ボタンを押したすべてに反応してしまうので・・・
    上記のprivate_to_publishの場合も渡されるのはpostIDくらいですよね?edit_postでフックしてからprivate_to_publishでさらにフックできるのか?とか考えましたが・・・

    承認のカラミは抜けてますが、
    公開済の記事の内容が変更されたときに、
    post_status を private にするだけなら
    以下を functions.php に追加すれば OK です。 

    function my_insert_post_data($data, $postarr){
      extract($postarr, EXTR_SKIP);
      if(!empty($ID)){ // update post
        $post = get_post($ID);
        $previous_status = get_post_field('post_status', $ID);
        if($post->post_content != $data['post_content']){
          if($post->post_status == 'publish'){
        	// TODO:「承認済み」を「未承認」に変更
    
    	$data['post_status'] = 'private';
          }
        }
      }
      return $data;
    }
    add_filter('wp_insert_post_data', 'my_insert_post_data', 10, 2);

    jim912さん、kzさん、ありがとうございます。
    ほぼ要求に近い動きは実現できました。
    add_actionにこだわっていてadd_filterにまで頭が回っていませんでした。

    まだ、非公開のまま認証をもらったあと、修正をしてそのまま公開しても未承認にならない動きがあるので、もう少し練らないといけませんが、公開ボタンで未承認に変更されてしまう動きは修正できました。

    最近はどんどんフォーラム回答のレベルが高くなっていて、皆様に頭が上がりません、ありがとうございます。

    すみません・・・再度開かせてもらいました。

    上記で教えていただいたソースなのですが、if($post->post_content != $data['post_content']){で投稿画面を開いたときと、更新ボタンを押したときのpost_contentの中身を比べて、違いがあればという処理だと思うのですが、現在、編集画面を開いて公開情報を変更し公開ボタンを押した場合(本文に変更を加えてない場合)でも、何も触らずに更新ボタンを押しただけでも、この条件式の中を必ず通ってしまうようです。

    「中身を比べて、違いがあれば」という考え方がそもそも間違っているのでしょうか?
    $previous_status = get_post_field('post_status', $ID);の存在もよくわかっていなくて、wp-includesのpost.phpにget_post_fieldがあるなどは追えましたが、$previous_statusが結局何を行っているかまで追えませんでした。(他で使われていませんし・・・)

    今回のような、公開ボタンや更新ボタンを押した場合のフック、つまり画面変移を伴うような処理をフックした場合に、その関数の中で使われている変数の内容を調べる(表示する)ような方法がわからなく、実際に行われている処理を可視化して追えません。。。
    そのような場合にもデバッグをできるような方法はあるのでしょうか・・・

    まだまだスキルが伴いません(汗)上記教えていただいたソースで記事が修正されたか修正されていないかを判断する方法はどうすればよいのでしょう?

    公開情報を変更し公開ボタンを押した場合

    ステータス,公開状態,公開日時 を色々変えて[公開/投稿を更新/更新]クリックを
    何度か試行しましたが、本文を変更しない限り[非公開]にはならない模様です。

    if($post->post_content != $data['post_content']){
          if($post->post_status == 'publish'){
        	// TODO:「承認済み」を「未承認」に変更
    
    	$data['post_status'] = 'private';
          }
        }

    if($post->post_status == 'publish'){
    周りに他のコードを付加してるかもとか、
    「「承認済み」を「未承認」に変更」の処理を洗うと良いかもです。

    $previous_status = get_post_field('post_status', $ID);は検証の名残コードと思われます。ごめんなさい。

    周りに他のコードを付加してるかもとか

    付加してます。というか付加しているのでif($post->post_content != $data['post_content']){が何を判定しているのか余計にわからなくなりました(汗)

    if( $post->post_content != $data['post_content'] && $current_user->user_level == 3 ) {
      if( $post->post_status == 'publish' ) { // A
        if( $post->post_type == 'post' ) {
          $data['post_status'] = 'private';
        }
        update_post_meta($ID, '承認', '未承認');
      } elseif( $current_user->user_level == 3 && $meta_values[0] == "未承認" && $post->post_type == 'post' ) { // B
        $data['post_status'] = 'private';
      } elseif( ( $post->post_status == 'private' || $post->post_status == 'future' ) && $meta_values[0] == "承認済み" ) { // C
        if( $post->post_type == 'post' ) {
          $data['post_status'] = 'private';
        }
        update_post_meta($ID, '承認', '未承認');
      }
    } elseif( $current_user->user_level == 3 && $meta_values[0] == "未承認" && $post->post_type == 'post' ) {
      if( $post->post_status != 'private' && $post->post_status != 'trashe' ) {
        $data['post_status'] = 'private';
      }
    }

    少々ソースがあれなのはご勘弁を・・・この状況で非公開・承認済みの投稿を公開に変更して公開ボタンを押すと「C」が動作します。
    つまりif( $post->post_content != $data['post_content'] && $current_user->user_level == 3 ) {の部分が必ずTRUEになるということですよね?

    この条件分岐は$post = get_post($ID);で取得した$post内のpost_contentと、$dataで渡ってきたpost_contentを比較しているのだと思いますが、ここは本文(post_content)を修正しなければTRUEにならないものだと思っていますが違いますか?

    本文を修正せずに更新ボタンを押しただけなら$post->post_content != $data['post_content']がTRUEにならないので「C」は通らないと思っていたのですがどうしても「C」を通ってしまいます・・・やっぱり考え方が間違っていますでしょうか・・・

    $post->post_content != $data['post_content']の内容が一致しているのか不一致なのか検証ができないのでいまいちよくわかっていないのかもしれませんね(涙)
    どこを通っているのかまでの処理は洗っているのですけど、そこから先に進めません。。。

    カスタムフィールドでデバッグ。ちゃんと動きますよー。
    ※ユーザーレベルチェックは不等号にしてます。

    function my_insert_post_data($data, $postarr){
      extract($postarr, EXTR_SKIP);
      if(!empty($ID)){ // update post
        global $current_user; // $current_user = wp_get_current_user();
        $post = get_post($ID);
        $meta_values = get_post_meta($ID, '承認'); // テキトウ
    
        update_post_meta($ID, 'user_level', $current_user->user_level); // trace
        update_post_meta($ID, 'old', $post->post_content); // trace
        update_post_meta($ID, 'new', $data['post_content']); // trace
        update_post_meta($ID, 'old vs new', $post->post_content != $data['post_content'] ? 'different' : 'same');
        if( $post->post_content != $data['post_content'] && $current_user->user_level >= 3 ) {
          update_post_meta($ID, 'content is', 'modified, and user_level >= 3');  // trace
          if( $post->post_status == 'publish' ) { // A
            update_post_meta($ID, 'route', 'A'); // trace
            if( $post->post_type == 'post' ) {
              $data['post_status'] = 'private';
            }
            update_post_meta($ID, '承認', '未承認');
          }
          else if( $current_user->user_level >= 3 && $meta_values[0] == "未承認" && $post->post_type == 'post' ) { // B
            update_post_meta($ID, 'route', 'B'); // trace
            $data['post_status'] = 'private';
          }
          else if( ( $post->post_status == 'private' || $post->post_status == 'future' ) && $meta_values[0] == "承認済み" ) { // C
            update_post_meta($ID, 'route', 'C'); // trace
            if( $post->post_type == 'post' ) {
              $data['post_status'] = 'private';
            }
            update_post_meta($ID, '承認', '未承認');
          }
        }
        else{
          update_post_meta($ID, 'content is', 'same, or user level < 3');  // trace
    
          if( $current_user->user_level >= 3 && $meta_values[0] == "未承認" && $post->post_type == 'post' ) { // D
            update_post_meta($ID, 'route', 'D'); // trace
            if( $post->post_status != 'private' && $post->post_status != 'trash' ) {
              $data['post_status'] = 'private';
            }
          }
        }
      }
      return $data;
    }
    add_filter('wp_insert_post_data', 'my_insert_post_data', 10, 2);

    ほほう・・・
    検証にカスタムフィールドを使うのですね、神ですね、目から鱗ですね(汗)
    がんばってみます!

    金曜日まであれだけ動いていなかったコードが月曜から動いている・・・
    一日たっても苦情があがってこないところを見るとやはり動いている・・・
    なんで、どうして(泣)

    kzさん、ありがとうございました。お手数おかけしました。

    またまたあけちゃいます・・・

    だめな原因がわかりました。解決方法は分かりませんが・・・

    本文が短いテスト用の文章などの場合は何も問題が起こりません。
    しかし、普通に投稿しようと写真などを入れた文章になるとdifferentになることがわかりました。
    上記kzさんの検証用のコードで、

    update_post_meta($ID, 'old', md5($post->post_content)); // trace
    update_post_meta($ID, 'new', md5($data['post_content'])); // trace

    の部分をmd5して比較すると確かに違う結果が出ました。短い文章だと違いがでませんでした。

    ちなみに、カスタムフィールドに入ったoldとnewの文字をコピペして簡単なphpソースで比較だけを行った場合、md5しても違いは出ませんでした。つまりは改行コードや他の何か見えないコードが違いを吐いているような感じがしますが、検討もつきません・・・
    trimとかしてみてもmd5の結果が同じになりませんので、文章途中の改行やスペースに問題があるのかもしれませんが、わかりません。

    コピペした文章をmd5した結果と、$data['post_content']をmd5した結果は一致しています。$post->post_contentのmd5結果だけが違ってしまうようです。

    何を調べれば文章の違いを見分けられるでしょうか・・・

    途中経過報告です。

    $post->post_contentは本文中にクウォーテーションが含まれているとdifferentになります。
    magic_quotes_gpcが関係しているのかどうかわかりませんが、stripslashes($post->post_content)とかしてもmd5が同じになることはありませんでした。

    引き続き調査していますが、原因がわかる方のご協力お願いいたします。

    自己解決のご報告です。

    上記の件はnewとoldを見間違えていたようで、stripslashes($data['post_content'])することでmd5でも同じ結果を出すことができました。
    そのまま分岐に導入して無事動作確認まで行えました。

    大変お騒がせいたしました、ありがとうございました。

13件の返信を表示中 - 1 - 13件目 (全13件中)
  • トピック「アクションフックのタイミング?」には新たに返信することはできません。