Pulsanti radio per tassonomia in WordPress

26 mar 2014, 15:01:35
Visualizzazioni: 18.6K
Voti: 11

Sto cercando di cambiare i checkbox per i termini nel backend in pulsanti radio. Ho trovato questo argomento: Modificare l'aspetto degli input per tassonomie personalizzate che mi ha aiutato a farlo. Tuttavia, questo trasformerà TUTTI i checkbox dei termini in pulsanti radio.

È possibile applicare questo cambiamento solo per una tassonomia specifica?

Il mio codice:

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;
}

grazie

1
Commenti

C'è una richiesta di funzionalità per integrare questa funzionalità nel core di WordPress, che è contrassegnata come "accettata" ma è inattiva da un po' di tempo. Potresti voler partecipare alla discussione / aiutare a svilupparla: core.trac.wordpress.org/ticket/14877

Mike Eng Mike Eng
20 nov 2021 06:02:53
Tutte le risposte alla domanda 4
5
20

Tuttavia, questo convertirà TUTTE le caselle di controllo dei termini in pulsanti radio.

Non solo, convertirà qualsiasi casella di controllo in una meta box - non ideale!

Invece, puntiamo specificamente alla funzione wp_terms_checklist(), che viene utilizzata per generare l'elenco delle caselle di controllo nell'area di amministrazione (inclusa la modifica rapida).

/**
 * Utilizza input radio invece di caselle di controllo per gli elenchi di termini nelle tassonomie specificate.
 *
 * @param   array   $args
 * @return  array
 */
function wpse_139269_term_radio_checklist( $args ) {
    if ( ! empty( $args['taxonomy'] ) && $args['taxonomy'] === 'category' /* <== Cambia con la tua tassonomia richiesta */ ) {
        if ( empty( $args['walker'] ) || is_a( $args['walker'], 'Walker' ) ) { // Non sovrascrivere walker di terze parti.
            if ( ! class_exists( 'WPSE_139269_Walker_Category_Radio_Checklist' ) ) {
                /**
                 * Walker personalizzato per convertire gli input checkbox in 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' );

Agganciamo il filtro wp_terms_checklist_args, quindi implementiamo il nostro "walker" personalizzato (una famiglia di classi utilizzate per generare elenchi gerarchici). Da lì, è una semplice sostituzione di stringa da type="checkbox" a type="radio" se la tassonomia corrisponde a quella che abbiamo configurato (in questo caso "category").

26 mar 2014 15:57:07
Commenti

Attenzione, questa è una risposta eccellente ma presenta un problema per la Modifica Rapida. Sebbene trasformi le caselle di controllo della modifica rapida in pulsanti radio, non seleziona il pulsante radio selezionato, invece svuota l'elenco. Se usi la modifica rapida, devi selezionare la categoria ogni volta, altrimenti verrà rimossa.

Howdy_McGee Howdy_McGee
2 giu 2015 21:02:06

@Howdy_McGee Vedi la mia risposta per un approccio con alcune modifiche aggiuntive per superare questa limitazione.

Nicolai Grossherr Nicolai Grossherr
15 lug 2015 16:30:59

La modifica rapida sull'assegnazione della categoria non imposta il valore. Per favore, guidaci

Ravi Patel Ravi Patel
6 dic 2018 16:40:07

Ecco una piccola modifica necessaria per WP v5.3 e versioni successive: function walk( $elements, $max_depth, ...$args ) { $output = parent::walk( $elements, $max_depth, ...$args );

Queste due righe devono avere i puntini di sospensione posizionati davanti a $args altrimenti genererà un errore.

Cercherò di modificare la risposta sopra...

Tony Djukic Tony Djukic
5 apr 2020 04:45:16

C'è una richiesta di funzionalità per integrare questa funzionalità nel core di WordPress, che è contrassegnata come "accettata" ma è rimasta inattiva per un po'. Potresti voler intervenire/aiutare a svilupparla: https://core.trac.wordpress.org/ticket/14877

Mike Eng Mike Eng
20 nov 2021 05:28:34
0

Il seguente codice fa praticamente quello che @TheDeadMedic ha fatto nella sua risposta, ottima risposta che mi ha portato a metà strada, quindi questo è un po' un'aggiunta ad essa. Per preferenza personale ho scelto di farlo con start_el.

→ assicurati di sostituire YOUR-TAXONOMY nel codice qui sotto secondo le tue esigenze

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' ) ) { // Non sovrascrivere walker di terze parti.
            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'];

                        /** Questo filtro è documentato 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;
}

Come @Howdy_McGee ha correttamente affermato nel suo commento, questo non funziona bene con la modifica rapida/inline. Il codice sopra gestisce correttamente il salvataggio, ma il radio nella modifica inline non viene selezionato. Ovviamente lo vogliamo, per questo ho fatto così:

→ scrivere del codice jQuery per gestire lo stato checked
→ nome file: editphp-inline-edit-tax-radio-hack.js - usato qui sotto per l'enqueue

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' );
            }
        });
    });

});

→ abbiamo bisogno di un'azione AJAX - come visto nel blocco di codice sopra

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();
}

→ enqueue dello script sopra
→ cambia le informazioni del percorso secondo le tue esigenze

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' )
    );
}

Questo funziona abbastanza bene finora, ma solo la prima volta: quando apri la modifica inline una seconda volta abbiamo perso nuovamente lo stato checked. Ovviamente non lo vogliamo. Per aggirare il problema ho usato un metodo che ho trovato qui da @brasofilo. Ciò che fa è ricaricare la sezione di modifica inline aggiornata. Questo porta al radio checkbox che viene mostrato correttamente, non importa quante volte viene cambiato.

→ assicurati di sostituire YOUR-POST-TYPE nel codice qui sotto secondo le tue esigenze

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( __( 'Non sei autorizzato a modificare questa pagina.' ) );
        } else {
            if ( ! current_user_can( 'edit_post', $post_ID ) )
                wp_die( __( 'Non sei autorizzato a modificare questo articolo.' ) );
        }

        if ( $last = wp_check_post_lock( $post_ID ) ) {
            $last_user = get_userdata( $last );
            $last_user_name = $last_user ? $last_user->display_name : __( 'Qualcuno' );
            printf( $_POST['post_type'] == 'page' ? __( 'Salvataggio disabilitato: %s sta attualmente modificando questa pagina.' ) : __( 'Salvataggio disabilitato: %s sta attualmente modificando questo articolo.' ),    esc_html( $last_user_name ) );
            wp_die();
        }

        $data = &$_POST;

        $post = get_post( $post_ID, ARRAY_A );

        // Poiché proviene dal database.
        $post = wp_slash($post);

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

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

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

            // Stato.
            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';

            // Escludi termini da tassonomie che non dovrebbero apparire in Modifica Rapida.
            if ( ! empty( $data['tax_input'] ) ) {
                foreach ( $data['tax_input'] as $taxonomy => $terms ) {
                    $tax_object = get_taxonomy( $taxonomy );
                    /** Questo filtro è documentato 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() non funziona per le bozze, quindi simuleremo che il nostro articolo sia pubblicato.
            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'] );
            }

            // Aggiorna l'articolo.
            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();
}



Nota: Non testato in modo estensivo, ma finora funziona bene

15 lug 2015 16:29:44
1

Puoi utilizzare il parametro meta_box_cb della funzione register_taxonomy per definire la tua funzione personalizzata per il meta_box. Con l'aiuto di questo articolo ho creato questo snippet:

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
}

Per utilizzare questo meta_box, devi passare questo parametro alla funzione register_taxonomy:

'meta_box_cb'                => 'YOUR_TAXONOMY_NAME_meta_box'

La bellezza di questo codice è che non devi passare alcun parametro, poiché si basa sui parametri passati dalla funzione register_taxonomy. Questi sono l'oggetto post e un array contenente le informazioni sul metabox stesso.

11 set 2014 16:39:35
Commenti

Ottima risposta in generale. Ma attenzione: hai <?php echo show_symbol( $term->name ); ?> come output, non dovrebbe essere <?php echo $term->name; ?>? Non ho trovato nulla su una funzione con quel nome. E come suggerimento: visto che stai mostrando tutte le categorie disponibili, probabilmente non è necessario stampare le schede.

André R. Kohl André R. Kohl
26 giu 2021 13:55:39
0

Se preferisci farlo funzionare con un plugin, potresti dare un'occhiata a https://wordpress.org/plugins/radio-buttons-for-taxonomies/

Questo plugin ti permette di sostituire le caselle di tassonomia predefinite con un metabox personalizzato che utilizza pulsanti radio... limitando efficacemente ogni articolo a un singolo termine in quella tassonomia.

30 ago 2018 10:32:02