サポート » 使い方全般 » meta_queryのKEYに入れるカスタムフィールドが配列になっています

  • ユーザー権限の「編集者」たちに、それぞれ特定の記事だけ編集権限を渡したく、
    各記事にカスタムフィールドで、フィールド名「manageArea」を作り、
    「ユーザー」→「編集者」と設定し、
    それに設定された編集者を、pre_get_postで管理画面の一覧表示を制限しようと企みました。(カスタムフィールドはAdvanced custom fieldで設置しました)

    function manager_posts( $wp_query ) {
        if(current_user_can('editor')){
    		global $pagenow;
    
    		if ( is_admin() && $wp_query->is_main_query() && $pagenow == 'edit.php') {
    			$user = wp_get_current_user();
    			$wp_query->set('meta_query',
                                    array(
                                        array(
                                        'key' => 'manageArea',
                                        'value' => "$user->nice_name",
               )
             )
          );
        }
    
    	}
    }
    add_action( 'pre_get_posts', 'manager_posts' );

    としてみましたが表示されず、カスタムフィールド値(manageArea)を見ると配列になっていました。

    array(11) {
      ["ID"]=>
      string(1) "3"
      ["user_firstname"]=>
      string(0) ""
      ["user_lastname"]=>
      string(0) ""
      ["nickname"]=>
      string(13) "ログイン名"
      ["user_nicename"]=>
      string(13) "ログイン名"
      ["display_name"]=>
      string(13) "ログイン名"

    このようなKEYになるべくカスタムフィールドが配列になっているもので、
    絞り込みをかけることは可能なのでしょうか。
    もしくは、他に絶妙な方法はありますでしょうか。
    ご教示頂きましたら幸いです。
    よろしくお願い致します。

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

    (@jim912)

    この対策ですと、記事の一覧には表示されなくなりますが、編集権限を制限しているわけではないので、記事の編集画面などで、URLのpostの数値を打ち替えることにより、簡単に範囲外の記事を編集することができてしまいます。

    根本的な対策としては、user_has_cap フィルターにフックし、$capabilitiesの値を変更することで、編集権限を停止させることが可能です。

    $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this );

    この user_has_cap フィルターですが、$this->allcaps がユーザーが有する全ての権限、$capsが、操作に必要となる全ての権限、$args はどの権限のチェックを行っているかなどの引数となります。記事の編集権限をチェックする場合、$args は以下のような内容になっています。

    array(3) {
      [0]=>
      string(9) "edit_post"
      [1]=>
      int(2)
      [2]=>
      int(157)
    }

    0 が、権限名、1 がユーザーのID、2 が記事のID です。

    これらの条件から、
    $capabilities[$caps[0]] が false になれば、記事の編集権限を奪うことができるはずです。

    トピック投稿者 scanner0928

    (@scanner0928)

    jim912様

    アドバイスありがとうございます。
    ただ、かなり高度すぎてほとんど理解できておりません(^^

    お教えいただいたコードは、どこで実行するものなのでしょうか。
    $capabilitiesの値は、それぞれの記事が持っているものでしょうか。
    お聞きしてばかりですが、お導きいただきましたら幸いです。

    この対策ですと、記事の一覧には表示されなくなりますが、編集権限を制限しているわけではないので、記事の編集画面などで、URLのpostの数値を打ち替えることにより、簡単に範囲外の記事を編集することができてしまいます。

    そのとおりなのですが、上記のとおり、高度な処理が理解できておりませんので、
    編集者たちは身内ですのでそのあたりの制限よりも、まずは実装できればというレベルでございます。

    モデレーター jim912

    (@jim912)

    たぶん、コードとしては、以下のような感じになるはずです。
    検証は一切していないので、自己責任で検証してください。

    function filter_edit_post_cap( $capabilities, $caps, $args ) {
    	// edit_post のチェックの時のみ動作
    	if ( 'edit_post' == $args[0] ) {
    		$user = wp_get_current_user();
    		$manageArea = get_field( 'manageArea', $args[2] );
    		// manageArea カスタムフィールドが設定されていて、ユーザーのIDが同値であれば
    		if ( $manageArea && isset( $manageArea['ID'] ) && $manageArea['ID'] == $user->ID ) {
    			// 必要な権限を無効化
    			$capabilities[$caps[0]] = false;
    		}
    	}
    	return $capabilities;
    }
    add_filter( 'user_has_cap', 'filter_edit_post_cap', 10, 3 );

    pre_get_posts でのコードであれば、meta_query で compare を LIKE で指定することにより、概ね絞り込むことが可能なはずです。というのは、配列のデータをpostmeta テーブルの meta_value に保存させる際には、シリアライズという文字列化を行って、保存しているため、部分検索で一致させることが可能だからです。
    概ねと言ったのは、完全一致でないため、他のユーザーが他の項目で同一の文字列を使っていた場合にヒットしてしまう可能性があるためです。

    トピック投稿者 scanner0928

    (@scanner0928)

    jim912様

    ご指導、ありがとうございます。
    いただいたコードを参照し、まずは実装してみたところ動作致しました。
    ただ、該当者の記事だけが「編集できない」ようになっていたので、
    下記のように逆に致しました。
    また、「もしエリアマネージャーなら」の分岐も追加しております。

    function filter_edit_post_cap( $capabilities, $caps, $args ) {
    
    	// edit_post のチェックの時のみ動作
    	if ( 'edit_post' == $args[0] ) {
    		if(current_user_can('area_manager')){
    		$user = wp_get_current_user();
    		$manageArea = get_field( 'manageArea', $args[2] );
    		// manageArea カスタムフィールドが設定されていて、ユーザーのIDが同値であれば
    		if ( !$manageArea ){
    			$capabilities[$caps[0]] = false;
    		}else if ( isset( $manageArea['ID'] ) && $manageArea['ID'] != $user->ID ) {
    			// 必要な権限を無効化
    			$capabilities[$caps[0]] = false;
    		}
    		}
    	}
    	return $capabilities;
    }
    add_filter( 'user_has_cap', 'filter_edit_post_cap', 10, 3 );

    こちらで希望の動きになっております。
    これを元に、どういう仕組になっているか勉強致します。
    ありがとうございました。

    現状、エリアマネージャーの管理画面では、
    全記事がリストされ、編集権限がある記事だけリンクがあります。
    これを編集権限がある記事だけ表示にすることは可能でしょうか。
    トップで書いた、meta_queryを用い、複合的に処理するのでしょうか。

    もしお時間がありましたら、ご教示いただきますようよろしくお願い致します。
    ありがとうございます。

4件の返信を表示中 - 1 - 4件目 (全4件中)
  • トピック「meta_queryのKEYに入れるカスタムフィールドが配列になっています」には新たに返信することはできません。