web-dev-qa-db-ja.com

階層的分類法にタグインターフェースを使用しますか?

カスタム分類法は素晴らしいです。私はたくさんの新しい分類法を登録し、私たちの階層的分類法をWordPress a la XMLにインポートするインポーターを書きました。問題は、1つの分類に約1,100の用語があり、1,100の事柄のチェックリストを閲覧することは残酷で珍しい処罰です。

階層的な分類法を使用して、代わりにTagインタフェース(オートコンプリート付きの検索ボックス)を使用する方法はありますか?

更新:Bainternetの答えからのこのコードは、そこにほとんどの道を行き来します(指定された分類法のためのタグ・インターフェースを追加します。ポストセーブ時に保存されません。投稿に以前に用語が含まれていた場合、それらは保存時に削除されます。だから私はまだ答えを探しています。 (分類法がhierarchichalsetをfalseに設定して登録されている場合でも、これと同じコードで用語を保存できますが、問題のポイントは階層的分類法でタグインターフェースを使用することです)

//remove default metabox
//change TAXONOMY_NAME to your taxonomy name
add_action( 'admin_menu' , 'remove_post_custom_fields' );
function remove_post_custom_fields() {
    remove_meta_box( 'issuediv' , 'post' , 'normal' ); 
}



//add our custom meta box
add_action( 'add_meta_boxes', 'my_add_custom_box' );

 function my_add_custom_box() {
    add_meta_box( 
//      'myplugin_sectionid',
        'tagsdiv-issue',
        __( 'New and Improved Issue Tags', 'textdomain' ),
        'tags_like_custom_tax',
        'post' 
    );
 }

 //call back function to display the metabox
 //change TAXONOMY_NAME to your taxonomy name 
 function tags_like_custom_tax(){
     $tax_name = 'issue';
     global $post;
     $taxonomy = get_taxonomy($tax_name);
     $disabled = !current_user_can($taxonomy->cap->assign_terms) ? 'disabled="disabled"' : '';
     ?>
     <div class="tagsdiv" id="<?php echo $tax_name; ?>">
        <div class="jaxtag">
            <div class="nojs-tags hide-if-js">
                <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p>
                <textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php echo $disabled; ?>><?php echo get_terms_to_edit( $post->ID, $tax_name ); // textarea_escaped by esc_attr() ?></textarea>
            </div>
            <?php if ( current_user_can($taxonomy->cap->assign_terms) ) { ?>
            <div class="ajaxtag hide-if-no-js">
                <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->name; ?></label>
                <div class="taghint"><?php echo $taxonomy->labels->add_new_item; ?></div>
                <p><input type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" value="" />
                <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" tabindex="3" /></p>
            </div>
            <p class="howto"><?php echo esc_attr( $taxonomy->labels->separate_items_with_commas ); ?></p>
            <?php } ?>
        </div>
        <div class="tagchecklist"></div>
    </div>
          <?php if ( current_user_can($taxonomy->cap->assign_terms) ) { ?>
            <p class="hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->choose_from_most_used; ?></a></p>
          <?php } 
}

元の質問はWordpressフォーラムの投稿 からここ で借用されています。

3
supertrue

これが私のやり方です。ロードされているページが管理ページかどうかをチェックする条件を追加するだけです。管理ページの場合は、hierarchyをfalseに設定し、それ以外の場合はhierarchyをtrueに設定します。そのようです:

$args = array( 
    'hierarchical' => true,
    'labels' => $labels,
    'show_ui' => true,
    'query_var' => true,
    'rewrite' => array( 
          'slug' => 'genre'
    ), 
 )

if( is_admin() ) {
    $args['hierarchical'] = false;
}

register_taxonomy('genre', array('book'), $args);

それはあなたにアイデアを与えるはずです。これのマイナス面はあなたが管理インターフェースを使って用語に親の関係を追加することができないということです。要求にpost-new.phpまたはpost.phpが含まれているかどうかを確認するなど、is_admin()条件式でより具体的になることがあります。

1
kingkool68

私が見つけた唯一の方法は、デフォルトのメタボックスを削除してあなた自身のものを作成することです、これが私が使ったコードです:

//remove default metabox
//change TAXONOMY_NAME to your taxonomy name
add_action( 'admin_menu' , 'remove_post_custom_fields' );
function remove_post_custom_fields() {
    remove_meta_box( 'TAXONOMY_NAMEdiv' , 'post' , 'normal' ); 
}



//add our custom meta box
add_action( 'add_meta_boxes', 'my_add_custom_box' );

 function my_add_custom_box() {
    add_meta_box( 
        'myplugin_sectionid',
        __( 'My Taxonomy Section Title', 'textdomain' ),
        'tags_like_custom_tax',
        'post' 
    );
 }

 //call back function to display the metabox
 //change TAXONOMY_NAME to your taxonomy name 
 function tags_like_custom_tax(){
     $tax_name = 'TAXONOMY_NAME';
     global $post;
     $taxonomy = get_taxonomy($tax_name);
     $disabled = !current_user_can($taxonomy->cap->assign_terms) ? 'disabled="disabled"' : '';
     ?>
     <div class="tagsdiv" id="<?php echo $tax_name; ?>">
        <div class="jaxtag">
            <div class="nojs-tags hide-if-js">
                <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p>
                <textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php echo $disabled; ?>><?php echo get_terms_to_edit( $post->ID, $tax_name ); // textarea_escaped by esc_attr() ?></textarea>
            </div>
            <?php if ( current_user_can($taxonomy->cap->assign_terms) ) { ?>
            <div class="ajaxtag hide-if-no-js">
                <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $box['title']; ?></label>
                <div class="taghint"><?php echo $taxonomy->labels->add_new_item; ?></div>
                <p><input type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" value="" />
                <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" tabindex="3" /></p>
            </div>
            <p class="howto"><?php echo esc_attr( $taxonomy->labels->separate_items_with_commas ); ?></p>
            <?php } ?>
        </div>
        <div class="tagchecklist"></div>
    </div>
          <?php if ( current_user_can($taxonomy->cap->assign_terms) ) { ?>
            <p class="hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->choose_from_most_used; ?></a></p>
          <?php } 
}

節約に関しては、あなたはそれについて心配する必要はありません、WordPressはあなたのためにそれをします。

更新、カテゴリでテストしたところ、うまくいきました。

enter image description here

1
Bainternet

階層的分類法では、複数の同一語が存在する可能性があるため、WPが保存時にterm_idを取得した場合にのみ追加できます(categoryのデフォルトメタボックスが機能する方法を調べてください)。これらの用語が階層ツリーの異なるブランチにある場合は、用語名。

非階層的用語では、これは不可能です。ここで指摘されたように 、ここで 、非階層的タクソノミから用語を追加するとき、それらのIDはterm_exists()によって用語名を介して検索されます。固有の用語名がある場合にのみ機能します。だから私はkingkool68の答えがもっと複​​雑な分類学の状況で働いているとは思わない。

そのため、タグスタイルのUIと階層分類メタボックスの「内部の仕組み」の組み合わせを使用してこの作業を行いました。私はこれをBainternetの例に基づいています。ここでの私のカスタム分類法は「カバレッジ」です。これは投稿、添付ファイル、そしてページに追加することができます。

PHP

//remove default metabox
add_action('admin_menu', function() {
    remove_meta_box('coveragesdiv', ['post', 'attachment', 'page'], 'normal');
});

//add our custom meta box
add_action('add_meta_boxes', function() {
    add_meta_box(
        'tagsdiv-coverages',
        __('Coverage', 'textdomain'),
        'coveragesMetaboxShow',
        ['post', 'attachment', 'page'],
        'side'
    );
});

//enqueue js for custom autosuggest/remove terms
add_action('admin_enqueue_scripts', function() {
    $screen = get_current_screen();

    if ($screen->base == 'post' && (in_array($screen->post_type, ['post', 'headlines', 'attachment', 'page']))) {
        wp_enqueue_script('coveragesMetaBoxJS', plugin_dir_url(__FILE__) . '../js/admin/coveragesMetaBox.js', ['jquery', 'jquery-ui-autocomplete']);
        wp_localize_script('coveragesMetaBoxJS', 'coveragesMetaBoxAjax', ['url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('coveragesMetaBoxNonce')]);  
    }
});

//show metabox
function coveragesMetaboxShow() {
    global $post;
    $tax_name = 'coverages';
    $taxonomy = get_taxonomy($tax_name);
    $bCanAssignTerms = current_user_can($taxonomy->cap->assign_terms);
    $aryTerms = get_the_terms($post->ID, $tax_name);
    ?>
    <style type="text/css">
        .tagchecklist.coverages             { margin-bottom:0; }
        .tagchecklist.coverages.disabled    { margin-left:0; }
        .tagchecklist.coverages input       { display:none; }   
    </style>
    <div class="tagsdiv" id="<?php echo $tax_name; ?>">
        <?php if ($bCanAssignTerms) { ?>
            <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $tax_name; ?></label>           
            <p>
                <input type="text" id="new-tag-<?php echo $tax_name; ?>" class="newtag form-input-tip" autocomplete="off" value="" style="width:100%; float:none;">
            </p>
            <!-- needed so WP deletes all term relations on save if all terms where removed from UI -->
            <input type="hidden" name="tax_input[<?php echo $tax_name; ?>][]" value="0">
        <?php } ?>      
        <ul class="tagchecklist <?php echo $tax_name; if (!$bCanAssignTerms) { echo ' disabled'; } ?>" role="list">         
        <?php
            foreach($aryTerms AS $term) {
                echo '<li id="tax'.$term->term_id.'"><input value="'.$term->term_id.'" name="tax_input['.$tax_name.'][]" type="checkbox" checked>';
                if ($bCanAssignTerms) {
                    echo '<button type="button" class="ntdelbutton"><span class="remove-tag-icon" aria-hidden="true"></span></button>';
                }
                else {
                    echo '&bull;';
                }
                echo '&nbsp;'.$term->name.'</li>';          
            }
        ?>          
        </ul>
    </div>  
    <?php
}

//custom autosuggest search; based on WP core https://developer.wordpress.org/reference/functions/wp_ajax_ajax_tag_search/
//no suitable hooks/filters there :(
add_action('wp_ajax_coveragesTagSearch', function() {
    if (isset($_GET['nonce']) && wp_verify_nonce($_GET['nonce'], 'coveragesMetaBoxNonce')) {
         if ( ! isset( $_GET['tax'] ) ) {
              wp_die( 0 );
         }

         $taxonomy = sanitize_key( $_GET['tax'] );
         $tax = get_taxonomy( $taxonomy );

         if ( ! current_user_can( $tax->cap->assign_terms ) ) {
              wp_die( -1 );
         }

         $s = wp_unslash( $_GET['term'] );

         $comma = _x( ',', 'tag delimiter' );
         if ( ',' !== $comma )
              $s = str_replace( $comma, ',', $s );
         if ( false !== strpos( $s, ',' ) ) {
              $s = explode( ',', $s );
              $s = $s[count( $s ) - 1];
         }
         $s = trim( $s ); 
         $term_search_min_chars = 2; 
         if ( ( $term_search_min_chars == 0 ) || ( strlen( $s ) < $term_search_min_chars ) ){
              wp_die();
         }

         $results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'id=>name', 'hide_empty' => false, 'number' => 20 ) );  
         //change result format from associative array to array of objects; needed in jQuery.autocomplete's select event to get the term_id
         $aryResults = [];
         foreach ($results AS $term_id=>$term_name) {
             $objTerm = new stdClass;
             $objTerm->id = $term_id;
             $objTerm->value = $term_name;
             $aryResults[] = $objTerm;
         }
         echo json_encode($aryResults, JSON_NUMERIC_CHECK);
    }
    wp_die();
}); 

JS

jQuery(function() {
    //remove term from UI
    jQuery('.tagchecklist.coverages .ntdelbutton').on('click', function() {
        jQuery(this).parent().remove();
    });

    //custom term autocomplete
    jQuery('#new-tag-coverages').autocomplete({
        minLength:2,
        source:coveragesMetaBoxAjax.url + '?action=coveragesTagSearch&tax=coverages&nonce=' + coveragesMetaBoxAjax.nonce,
        select:function(event, ui) {
            jQuery('.tagchecklist.coverages').append('<li id="tax' + ui.item.id + '"><input value="' + ui.item.id + '" name="tax_input[coverages][]" type="checkbox" checked><button type="button" class="ntdelbutton"><span class="remove-tag-icon" aria-hidden="true"></span></button>&nbsp;' + ui.item.value + '</li>');
            //when selecting a term with the mouse from the autosuggest list, the close-event is triggered *after* the target value is set :(
            window.setTimeout(function() { jQuery(event.target).val(''); }, 100);
        },      
        close:function(event, ui) {
            jQuery(event.srcElement).val('');
        }
    });
});
0

選択したタグのterm_idをjQuery(AJAX)で取得する隠し入力を追加して、関数wp_set_object_termsを使用して投稿の用語として保存することができると思います。

この問題に関連する別の質問を投稿しました。 WPネイティブタグはメタボックスを示唆しています。タグIDはどのように処理されますか?

0
Adige72

私は解決策を見つけ、階層タクソノミーでタグインターフェースをどのように使用するか

まず、is_edit_page()関数を作成する必要があります。

/**
 * is_edit_page 
 * function to check if the current page is a post edit page
 * 
 * @author Ohad Raz <[email protected]>
 * 
 * @param  string  $new_edit what page to check for accepts new - new post page ,edit - edit post page, null for either
 * @return boolean
 */
function is_edit_page($new_edit = null){
    global $pagenow;
    //make sure we are on the backend
    if (!is_admin()) return false;


    if($new_edit == "edit")
        return in_array( $pagenow, array( 'post.php',  ) );
    elseif($new_edit == "new") //check for new post page
        return in_array( $pagenow, array( 'post-new.php' ) );
    else //check for either new or edit
        return in_array( $pagenow, array( 'post.php', 'post-new.php' ) );
}

* から取ったコードはこちら

今、あなたは kingkool68 によって巧妙に作られたコードを使うことができます:

$args = array(
    //...
    'hierarchical' => true,
    //...
);
if( is_edit_page() ) {
    $args['hierarchical'] = false;
}

階層構造は保存されますが、タグのように分類ページを編集ページに表示します(コンマ区切り)。

0
Bogdan