web-dev-qa-db-ja.com

用語チェックリストウォーカー - 親カテゴリを無効にする

現在私はトップレベルのカテゴリーがランディングページのように振る舞っている構造を持っているので、それらに直接投稿を割り当ててはいけません。私がやりたいのは、トップレベルの用語を無効にして、ユーザーにサブ用語(子)のチェックだけを許可することです。チェックボックスをラジオボタン に変換するウォーカーをここで見つけました が、トップレベルの親を変更するだけでは十分に理解できないので、そのまま続けます。カスケードこのウォーカーで何が起こっているのかを「管理者パネルの用語メタボックスでトップレベルの用語を無効にするにはどうすればよいですか」という主な質問とともに、誰かが分析できないことを望んでいました

/**
 * Use radio inputs instead of checkboxes for term checklists in specified taxonomies.
 * https://wordpress.stackexchange.com/questions/139269/wordpress-taxonomy-radio-buttons
 *
 * @param   array   $args
 * @return  array
 */
function wpse_139269_term_radio_checklist( $args ) {
    if ( ! empty( $args['taxonomy'] ) && ($args['taxonomy'] === 'product_cat') ) {
        if ( empty( $args['walker'] ) || is_a( $args['walker'], 'Walker' ) ) {
            if ( ! class_exists( 'WPSE_139269_Walker_Category_Radio_Checklist' ) ) {
                class WPSE_139269_Walker_Category_Radio_Checklist extends Walker_Category_Checklist {
                    function walk( $elements, $max_depth, $args = array() ) {
                        $output = parent::walk( $elements, $max_depth, $args );

                        foreach($elements as $element){
                            if($element->parent == 0){
                                $output = str_replace(
                                    array( 'type="checkbox"', "type='checkbox'" ),
                                    array( 'type="checkbox"', "type='checkbox' disabled='disabled'" ),
                                    $output
                                );
                            }
                        }

                        return $output;
                    }
                }
            }

            $args['walker'] = new WPSE_139269_Walker_Category_Radio_Checklist;
        }
    }

    return $args;
}
add_filter( 'wp_terms_checklist_args', 'wpse_139269_term_radio_checklist' );

elementsは配列内のすべての項を保持しているので、その要素が自分のforeachに親を持つかどうかをテストするために、出力を置き換えて無効フラグを追加しようとします。

1
Howdy_McGee

私が質問を完全に誤解していたので編集しました。


Termが親かどうかを知るには、term post parentにアクセスする必要があるので、walk()の代わりにもっと特殊なメソッドを置き換えるのが良いでしょう。

そうは言っても、OPのコードはWalker_Category_Checklistクラスが定義されていないために致命的なエラーを回避するために関数内でクラス定義を使用することを理解しています。

だから私はカスタムウォーカーのインスタンスを返すカスタム関数を書く方が良いと思います:

add_filter( 'wp_terms_checklist_args', 'wpse_149328_set_walker' );  

function wpse_149328_set_walker( $args ) {
  if (
    ! empty( $args['taxonomy'] )
    && ( $args['taxonomy'] === 'product_cat' ) // only for 'product_cat' taxonomy
    && ( ! isset( $args['walker'] ) || ! $args['walker'] instanceof Walker )
  ) {
    $args['checked_ontop'] = FALSE;
    $args['walker'] = get_Walker_Category_No_Parent();
  }
  return $args;
}

それではget_Walker_Category_No_Parent()とカスタムウォーカーをコーディングしましょう。

function get_Walker_Category_No_Parent() {

  class Walker_Category_No_Parent extends Walker_Category_Checklist {

   function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
      if ( (int) $category->parent === 0 ) {
         $this->doing_parent = esc_html( $category->name );
      } else {
        parent::start_el( $output, $category, $depth, $args, $id );
      }
    }

    function end_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
      if ( ! isset( $this->doing_parent ) || empty( $this->doing_parent ) ) {
        parent::end_el( $output, $category, $depth, $args, $id );
      }
    }

    function start_lvl( &$output, $depth = 0, $args = array() ) {
      if ( isset( $this->doing_parent ) && ! empty( $this->doing_parent ) ) {
        $output .= '<li><strong>' . $this->doing_parent . '</strong></li>';
        $this->doing_parent = FALSE;
      }
      parent::start_lvl( $output, $depth = 0, $args );
    }

  }
  return new Walker_Category_No_Parent;
}

このウォーカーは、親カテゴリをテキストとして出力し、それらにいくつかの子がある場合にのみ出力します。

2
gmazzap