Butoane radio pentru taxonomii în WordPress
Încerc să schimb casetele de selectare pentru termeni în panoul de administrare în butoane radio. Am găsit acest subiect: Modificarea aspectului input-urilor pentru taxonomii personalizate care m-a ajutat să realizez asta. Totuși, acest lucru va transforma TOATE casetele de selectare în butoane radio.
Este posibil să aplic asta doar pentru o singură taxonomie?
Codul meu:
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;
}
Mulțumesc

Totuși, acest lucru va transforma TOATE casetele de bifare pentru termeni în butoane radio.
Nu numai atât, va transforma orice casetă de bifare dintr-o cutie meta - nu este ideal!
În schimb, să țintim în mod specific funcția wp_terms_checklist()
, care este folosită pentru a genera lista de casete de bifare în tot panoul de administrare (inclusiv editarea rapidă).
/**
* Folosește inputuri radio în loc de casete de bifare pentru listele de termeni în taxonomiile specificate.
*
* @param array $args
* @return array
*/
function wpse_139269_term_radio_checklist( $args ) {
if ( ! empty( $args['taxonomy'] ) && $args['taxonomy'] === 'category' /* <== Schimbă la taxonomia ta necesară */ ) {
if ( empty( $args['walker'] ) || is_a( $args['walker'], 'Walker' ) ) { // Nu suprascrie walker-e terțe.
if ( ! class_exists( 'WPSE_139269_Walker_Category_Radio_Checklist' ) ) {
/**
* Walker personalizat pentru schimbarea inputurilor checkbox în 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' );
Ne conectăm la filtrul wp_terms_checklist_args
, apoi implementăm propriul nostru "walker" personalizat (o familie de clase folosite pentru a genera liste ierarhice). De acolo, este o simplă înlocuire de șir a type="checkbox"
cu type="radio"
dacă taxonomia se potrivește cu ce am configurat-o (în acest caz "category").

Atenție, acesta este un răspuns excelent, dar prezintă o problemă pentru Editarea Rapidă. Deși transformă casetele de selectare din editarea rapidă în butoane radio, nu selectează butonul radio bifat, ci în schimb golește lista. Dacă folosești editarea rapidă, trebuie să selectezi categoria de fiecare dată, altfel va fi eliminată.

@Howdy_McGee Vezi răspunsul meu pentru o abordare cu modificări suplimentare care depășesc această limitare.

Editarea rapidă la atribuirea categoriei nu setează valoarea. Vă rugăm să ne ghidați

Iată o mică ajustare care trebuie făcută pentru WP v5.3 și versiunile superioare:
function walk( $elements, $max_depth, ...$args ) {
$output = parent::walk( $elements, $max_depth, ...$args );
Aceste două linii trebuie să aibă punctele de suspensie plasate în fața $args
, altfel va genera o eroare.
Voi încerca să editez răspunsul de mai sus...

Există o cerere de funcționalitate pentru a integra această funcționalitate în nucleul WordPress, care este marcată ca "acceptată" dar a fost inactivă de ceva timp. Ați putea să vă exprimați părerea / să ajutați la implementare: https://core.trac.wordpress.org/ticket/14877

Urmează ceea ce face @TheDeadMedic în răspunsul său bun, care m-a adus pe jumătate acolo, așa că acesta este un fel de completare la acesta. Din preferință personală am ales să o fac cu start_el
.
→ asigurați-vă că înlocuiți YOUR-TAXONOMY în codul de mai jos conform nevoilor dumneavoastră
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' ) ) { // Nu suprascrie walker-ele terților.
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'];
/** Acest filtru este documentat în 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;
}
Acum, așa cum @Howdy_McGee a menționat corect în comentariul său, acest lucru nu funcționează frumos, corect cu editarea rapidă/inline. Codul de mai sus gestionează salvarea corect, dar radio-ul la editarea inline nu este bifat. Desigur, vrem asta, pentru asta am făcut următoarele:
→ scrieți un cod JQuery pentru a gestiona starea bifată
→ nume fișier: editphp-inline-edit-tax-radio-hack.js - folosit mai jos pentru încărcare
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' );
}
});
});
});
→ avem nevoie de o acțiune AJAX - așa cum se vede în blocul de cod de mai sus
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();
}
→ încărcarea scriptului de mai sus
→ schimbați informațiile despre cale conform nevoilor dumneavoastră
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' )
);
}
Aceasta funcționează destul de bine până acum, dar doar pentru prima dată, când deschidem editarea inline a doua oară, am pierdut din nou starea bifată. Evident, nu vrem asta. Pentru a ocoli aceasta, am folosit o metodă pe care am găsit-o aici de la @brasofilo. Ceea ce face este reîncărcarea secțiunii editate inline actualizate. Acest lucru duce la afișarea corectă a casetei de radio, indiferent de câte ori este schimbată.
→ asigurați-vă că înlocuiți YOUR-POST-TYPE în codul de mai jos conform nevoilor dumneavoastră
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( __( 'Nu aveți permisiunea de a edita această pagină.' ) );
} else {
if ( ! current_user_can( 'edit_post', $post_ID ) )
wp_die( __( 'Nu aveți permisiunea de a edita acest post.' ) );
}
if ( $last = wp_check_post_lock( $post_ID ) ) {
$last_user = get_userdata( $last );
$last_user_name = $last_user ? $last_user->display_name : __( 'Cineva' );
printf( $_POST['post_type'] == 'page' ? __( 'Salvarea este dezactivată: %s editează în prezent această pagină.' ) : __( 'Salvarea este dezactivată: %s editează în prezent acest post.' ), esc_html( $last_user_name ) );
wp_die();
}
$data = &$_POST;
$post = get_post( $post_ID, ARRAY_A );
// Deoarece vine din baza de date.
$post = wp_slash($post);
$data['content'] = $post['post_content'];
$data['excerpt'] = $post['post_excerpt'];
// Redenumire.
$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 termenii din taxonomii care nu ar trebui să apară în Editare Rapidă.
if ( ! empty( $data['tax_input'] ) ) {
foreach ( $data['tax_input'] as $taxonomy => $terms ) {
$tax_object = get_taxonomy( $taxonomy );
/** Acest filtru este documentat în 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() nu funcționează pentru draft-uri, așa că vom pretinde că postul nostru este publicat.
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'] );
}
// Actualizează postul.
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();
}
Notă: Nu a fost testat extensiv, dar până acum funcționează bine

Puteți utiliza parametrul meta_box_cb
al funcției register_taxonomy
pentru a defini propria funcție pentru meta_box
. Cu ajutorul acestui articol am creat acest fragment de cod:
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
}
Pentru a utiliza acest meta_box, trebuie să pasați acest parametru funcției register_taxonomy
:
'meta_box_cb' => 'YOUR_TAXONOMY_NAME_meta_box'
Frumusețea acestui cod este că nu trebuie să pasați niciun parametru, deoarece se bazează pe parametrii transmiși de funcția register_taxonomy
. Aceștia sunt obiectul post
și un array care conține informații despre metabox în sine.

Răspuns excelent în general. Dar atenție: Aveți <?php echo show_symbol( $term->name ); ?> ca output, nu ar trebui să fie <?php echo $term->name; ?>? Nu am găsit nicio informație despre o funcție cu acest nume. Și ca sugestie: Deoarece afișați toate categoriile disponibile, probabil nu este necesar să afișați tab-urile.

Dacă preferați să utilizați un plugin pentru această funcționalitate, puteți încerca https://wordpress.org/plugins/radio-buttons-for-taxonomies/.
Acest plugin vă permite să înlocuiți casetele implicite pentru taxonomii cu un metabox personalizat care utilizează butoane radio... limitând efectiv fiecare articol la un singur termen din acea taxonomie.
