Optionsfelder für die WordPress-Taxonomie

8

Ich versuche, die Kontrollkästchen für die Begriffe im Backend in Radiobuttons zu ändern. Ich habe dieses Thema gefunden: Ändern des Erscheinungsbilds von benutzerdefinierten Taxonomie-Eingaben , was mir dabei geholfen hat. Dadurch werden jedoch ALLE Kontrollkästchen für Begriffe zu Optionsfeldern.

Ist es möglich, dies nur für eine Taxonomie anzuwenden?

Mein Code:

add_action('add_meta_boxes','mysite_add_meta_boxes',10,2);
function mysite_add_meta_boxes($post_type, $post) {
  ob_start();
}
add_action('dbx_post_sidebar','mysite_dbx_post_sidebar');
function mysite_dbx_post_sidebar() {
  $html = ob_get_clean();
  $html = str_replace('"checkbox"','"radio"',$html);
  echo $html;
}

Vielen Dank

Maartje
quelle

Antworten:

13

Dadurch werden jedoch ALLE Kontrollkästchen für Begriffe zu Optionsfeldern.

Nicht nur das, es wird jedes Kontrollkästchen in einem Meta-Feld aktivieren - nicht ideal!

Lassen Sie uns stattdessen gezielt auf die wp_terms_checklist()Funktion abzielen , mit der die Liste der Kontrollkästchen im gesamten Administrator generiert wird (einschließlich der schnellen Bearbeitung).

/**
 * Use radio inputs instead of checkboxes for term checklists in specified taxonomies.
 *
 * @param   array   $args
 * @return  array
 */
function wpse_139269_term_radio_checklist( $args ) {
    if ( ! empty( $args['taxonomy'] ) && $args['taxonomy'] === 'category' /* <== Change to your required taxonomy */ ) {
        if ( empty( $args['walker'] ) || is_a( $args['walker'], 'Walker' ) ) { // Don't override 3rd party walkers.
            if ( ! class_exists( 'WPSE_139269_Walker_Category_Radio_Checklist' ) ) {
                /**
                 * Custom walker for switching checkbox inputs to radio.
                 *
                 * @see Walker_Category_Checklist
                 */
                class WPSE_139269_Walker_Category_Radio_Checklist extends Walker_Category_Checklist {
                    function walk( $elements, $max_depth, ...$args ) {
                        $output = parent::walk( $elements, $max_depth, ...$args );
                        $output = str_replace(
                            array( 'type="checkbox"', "type='checkbox'" ),
                            array( 'type="radio"', "type='radio'" ),
                            $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' );

Wir schließen uns dem wp_terms_checklist_argsFilter an und implementieren dann unseren eigenen benutzerdefinierten "Walker" (eine Klassenfamilie, die zum Generieren hierarchischer Listen verwendet wird). Von dort aus ist es eine einfache Zeichenfolge, die type="checkbox"durch ersetzt wird, type="radio"wenn die Taxonomie so ist, wie wir sie konfiguriert haben (in diesem Fall "Kategorie").

TheDeadMedic
quelle
2
Achtung , dies ist eine großartige Antwort, wirft jedoch ein Problem für die Schnellbearbeitung auf. Während Schnellbearbeitungs-Kontrollkästchen in Optionsfelder umgewandelt werden, wird das aktivierte Radio nicht ausgewählt, sondern die Liste gelöscht. Wenn Sie schnell bearbeiten, müssen Sie die Kategorie jedes Mal überprüfen, da sie sonst entfernt wird.
Howdy_McGee
1
@Howdy_McGee In meiner Antwort finden Sie einen Ansatz mit einigen zusätzlichen Änderungen, um die Einschränkung zu überwinden.
Nicolai
Schnelle Bearbeitung bei nicht zugewiesenem Kategoriezuweisungswert. Bitte führen Sie uns
Ravi Patel
Hier ist eine kleine Anpassung, die für WP v5.3 und höher vorgenommen werden muss: Bei function walk( $elements, $max_depth, ...$args ) { $output = parent::walk( $elements, $max_depth, ...$args ); diesen beiden Zeilen müssen die Ellipsen vor dem platziert werden, sonst $argswird ein Fehler ausgegeben . Ich werde versuchen, die Antwort oben zu bearbeiten ...
Tony Djukic
3

Das Folgende macht ziemlich genau das, was @TheDeadMedic bei seiner Antwort getan hat. Gute Antwort, hat mich auf halbem Weg dorthin gebracht, also ist dies nur eine Art Ergänzung dazu. Aus persönlichen Gründen habe ich mich dafür entschieden start_el.

→ Stellen Sie sicher, dass Sie IHRE TAXONOMIE im folgenden Code entsprechend Ihren Anforderungen ersetzen

add_filter( 'wp_terms_checklist_args', 'wpse_139269_term_radio_checklist_start_el_version', 10, 2 );
function wpse_139269_term_radio_checklist_start_el_version( $args, $post_id ) {
    if ( ! empty( $args['taxonomy'] ) && $args['taxonomy'] === 'YOUR-TAXONOMY' ) {
        if ( empty( $args['walker'] ) || is_a( $args['walker'], 'Walker' ) ) { // Don't override 3rd party walkers.
            if ( ! class_exists( 'WPSE_139269_Walker_Category_Radio_Checklist_Start_El_Version' ) ) {
                class WPSE_139269_Walker_Category_Radio_Checklist_Start_El_Version extends Walker_Category_Checklist {
                    public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
                        if ( empty( $args['taxonomy'] ) ) {
                            $taxonomy = 'category';
                        } else {
                            $taxonomy = $args['taxonomy'];
                        }

                        if ( $taxonomy == 'category' ) {
                            $name = 'post_category';
                        } else {
                            $name = 'tax_input[' . $taxonomy . ']';
                        }

                        $args['popular_cats'] = empty( $args['popular_cats'] ) ? array() : $args['popular_cats'];
                        $class = in_array( $category->term_id, $args['popular_cats'] ) ? ' class="popular-category"' : '';

                        $args['selected_cats'] = empty( $args['selected_cats'] ) ? array() : $args['selected_cats'];

                        /** This filter is documented in wp-includes/category-template.php */
                        if ( ! empty( $args['list_only'] ) ) {
                            $aria_cheched = 'false';
                            $inner_class = 'category';

                            if ( in_array( $category->term_id, $args['selected_cats'] ) ) {
                                $inner_class .= ' selected';
                                $aria_cheched = 'true';
                            }

                            $output .= "\n" . '<li' . $class . '>' .
                                '<div class="' . $inner_class . '" data-term-id=' . $category->term_id .
                                ' tabindex="0" role="checkbox" aria-checked="' . $aria_cheched . '">' .
                                esc_html( apply_filters( 'the_category', $category->name ) ) . '</div>';
                        } else {
                            $output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" .
                            '<label class="selectit"><input value="' . $category->term_id . '" type="radio" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' .
                            checked( in_array( $category->term_id, $args['selected_cats'] ), true, false ) .
                            disabled( empty( $args['disabled'] ), false, false ) . ' /> ' .
                            esc_html( apply_filters( 'the_category', $category->name ) ) . '</label>';
                        }
                    }
                }
            }
            $args['walker'] = new WPSE_139269_Walker_Category_Radio_Checklist_Start_El_Version;
        }
    }
    return $args;
}

Nun, wie @ Howdy_McGee in seinem Kommentar richtig angegeben hat, funktioniert dies nicht gut, richtig mit der Schnell- / Inline-Bearbeitung. Der obige Code behandelt das Speichern korrekt, aber das Radio bei der Inline-Bearbeitung wird nicht aktiviert. Natürlich wollen wir das, dafür habe ich folgendes getan:

→ Schreiben Sie einen JQuery-Code, um den überprüften Status zu verarbeiten.
→ Dateiname: editphp-inline-edit-tax-radio-hack.js - wird unten für die Warteschlange verwendet

jQuery(document).ready(function($) {
    var taxonomy = 'status',
        post_id = null,
        term_id = null,
        li_ele_id = null;
    $('a.editinline').on('click', function() {
        post_id = inlineEditPost.getId(this);
        $.ajax({
            url: ajaxurl,
            data: {
                action: 'wpse_139269_inline_edit_radio_checked_hack',
                'ajax-taxonomy': taxonomy,
                'ajax-post-id': post_id
            },
            type: 'POST',
            dataType: 'json',
            success: function (response) {
                term_id = response;
                li_ele_id = 'in-' + taxonomy + '-' + term_id;
                $( 'input[id="'+li_ele_id+'"]' ).attr( 'checked', 'checked' );
            }
        });
    });

});

→ Wir benötigen eine AJAX-Aktion - wie im obigen Codeblock gezeigt

add_action( 'wp_ajax_wpse_139269_inline_edit_radio_checked_hack', 'wpse_139269_inline_edit_radio_checked_hack' );
add_action( 'wp_ajax_nopriv_wpse_139269_inline_edit_radio_checked_hack', 'wpse_139269_inline_edit_radio_checked_hack' );
function wpse_139269_inline_edit_radio_checked_hack() {
    $terms = wp_get_object_terms(
        $_POST[ 'ajax-post-id' ],
        $_POST[ 'ajax-taxonomy' ],
        array( 'fields' => 'ids' )
    );
    $result = $terms[ 0 ];
    echo json_encode($result);
    exit;
    die();
}

→ Warteschlange über dem Skript
→ Ändern Sie die Pfadinformationen entsprechend Ihren Anforderungen

add_action( 'admin_enqueue_scripts', 'wpse_139269_inline_edit_radio_checked_hack_enqueue_script' );
function wpse_139269_inline_edit_radio_checked_hack_enqueue_script() {
    wp_enqueue_script(
        'editphp-inline-edit-tax-radio-hack-js',
        get_template_directory_uri() . '/your/path/editphp-inline-edit-tax-radio-hack.js',
        array( 'jquery' )
    );
}

Dies funktioniert bisher recht gut, aber nur zum ersten Mal, wenn wir die Inline-Bearbeitung ein zweites Mal öffnen, haben wir den aktivierten Status wieder verloren. Das wollen wir natürlich nicht. Um das zu umgehen, habe ich eine Methode verwendet, die ich hier von @brasofilo gefunden habe. Der aktualisierte Inline-Bearbeitungsabschnitt wird neu geladen. Dies führt dazu, dass das Radio-Kontrollkästchen korrekt angezeigt wird, unabhängig davon, wie oft es geändert wird.

→ Stellen Sie sicher, dass IHR POST-TYP im folgenden Code entsprechend Ihren Anforderungen ersetzt wird

add_action( 'wp_ajax_inline-save', 'wpse_139269_wp_ajax_inline_save', 0 );
function wpse_139269_wp_ajax_inline_save() {
    global $wp_list_table;

    check_ajax_referer( 'inlineeditnonce', '_inline_edit' );

    if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) )
        wp_die();

        if ( 'page' == $_POST['post_type'] ) {
            if ( ! current_user_can( 'edit_page', $post_ID ) )
                wp_die( __( 'You are not allowed to edit this page.' ) );
        } else {
            if ( ! current_user_can( 'edit_post', $post_ID ) )
                wp_die( __( 'You are not allowed to edit this post.' ) );
        }

        if ( $last = wp_check_post_lock( $post_ID ) ) {
            $last_user = get_userdata( $last );
            $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
            printf( $_POST['post_type'] == 'page' ? __( 'Saving is disabled: %s is currently editing this page.' ) : __( 'Saving is disabled: %s is currently editing this post.' ),    esc_html( $last_user_name ) );
            wp_die();
        }

        $data = &$_POST;

        $post = get_post( $post_ID, ARRAY_A );

        // Since it's coming from the database.
        $post = wp_slash($post);

        $data['content'] = $post['post_content'];
        $data['excerpt'] = $post['post_excerpt'];

        // Rename.
        $data['user_ID'] = get_current_user_id();

        if ( isset($data['post_parent']) )
            $data['parent_id'] = $data['post_parent'];

            // Status.
            if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
                $data['post_status'] = 'private';
            else
                $data['post_status'] = $data['_status'];

            if ( empty($data['comment_status']) )
                $data['comment_status'] = 'closed';
            if ( empty($data['ping_status']) )
                $data['ping_status'] = 'closed';

            // Exclude terms from taxonomies that are not supposed to appear in Quick Edit.
            if ( ! empty( $data['tax_input'] ) ) {
                foreach ( $data['tax_input'] as $taxonomy => $terms ) {
                    $tax_object = get_taxonomy( $taxonomy );
                    /** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
                    if ( ! apply_filters( 'quick_edit_show_taxonomy', $tax_object->show_in_quick_edit, $taxonomy, $post['post_type'] ) ) {
                        unset( $data['tax_input'][ $taxonomy ] );
                    }
                }
            }

            // Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published.
            if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) {
                $post['post_status'] = 'publish';
                $data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] );
            }

            // Update the post.
            edit_post();

            $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );

            $level = 0;
            $request_post = array( get_post( $_POST['post_ID'] ) );
            $parent = $request_post[0]->post_parent;

            while ( $parent > 0 ) {
                $parent_post = get_post( $parent );
                $parent = $parent_post->post_parent;
                $level++;
            }

            $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );

            if( $_POST['post_type'] == 'YOUR-POST-TYPE' ) {
                ?>
                    <script type="text/javascript">
                        document.location.reload(true);
                    </script>
                <?php
            }

    wp_die();
}



Hinweis: Nicht ausführlich getestet, funktioniert aber bisher gut

Nicolai
quelle
1

Mit dem meta_box_cbParameter der register_taxonomyFunktion können Sie Ihre eigene Funktion für die definieren meta_box. Mit Hilfe dieses Artikels habe ich dieses Snippet erstellt:

function YOUR_TAXONOMY_NAME_meta_box($post, $meta_box_properties){
  $taxonomy = $meta_box_properties['args']['taxonomy'];
  $tax = get_taxonomy($taxonomy);
  $terms = get_terms($taxonomy, array('hide_empty' => 0));
  $name = 'tax_input[' . $taxonomy . ']';
  $postterms = get_the_terms( $post->ID, $taxonomy );
  $current = ($postterms ? array_pop($postterms) : false);
  $current = ($current ? $current->term_id : 0);
?>
<div id="taxonomy-<?php echo $taxonomy; ?>" class="categorydiv">
  <ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
    <li class="tabs"><a href="#<?php echo $taxonomy; ?>-all"><?php echo $tax->labels->all_items; ?></a></li>
  </ul>

  <div id="<?php echo $taxonomy; ?>-all" class="tabs-panel">
    <input name="tax_input[<?php echo $taxonomy; ?>][]" value="0" type="hidden">            
    <ul id="<?php echo $taxonomy; ?>checklist" data-wp-lists="list:symbol" class="categorychecklist form-no-clear">
<?php   foreach($terms as $term){
      $id = $taxonomy.'-'.$term->term_id;?>
      <li id="<?php echo $id?>"><label class="selectit"><input value="<?php echo $term->term_id; ?>" name="tax_input[<?php echo $taxonomy; ?>][]" id="in-<?php echo $id; ?>"<?php if( $current === (int)$term->term_id ){?> checked="checked"<?php } ?> type="radio"> <?php echo show_symbol( $term->name ); ?></label></li>
<?php   }?>
    </ul>
  </div>
</div>
<?php
}

Um diese meta_box nutzen zu können, müssen Sie diesen Parameter an die register_taxonomyFunktion übergeben:

'meta_box_cb'                => 'YOUR_TAXONOMY_NAME_meta_box'

Das Schöne an diesem Code ist, dass Sie überhaupt keine Parameter übergeben müssen, da er sich auf die von der register_taxonomyFunktion an ihn übergebenen Parameter stützt . Dies sind das postObjekt und ein Array, das Informationen zur Metabox selbst enthält.

BdN3504
quelle
0

Wenn Sie es lieber mit einem Plugin zum Laufen bringen möchten, schauen Sie sich vielleicht https://wordpress.org/plugins/radio-buttons-for-taxonomies/ an.

Mit diesem Plugin können Sie die Standardtaxonomiefelder durch eine benutzerdefinierte Metabox ersetzen, die Optionsfelder verwendet. Dadurch wird jeder Beitrag effektiv auf einen einzelnen Begriff in dieser Taxonomie beschränkt.

patilswapnilv
quelle