AGGIORNAMENTO 2018-06-28
Mentre il codice seguente funziona principalmente bene, ecco una riscrittura del codice per WP> = 4.6.0 (usando PHP 7):
function add_course_section_filter( $which ) {
// create sprintf templates for <select> and <option>s
$st = '<select name="course_section_%s" style="float:none;"><option value="">%s</option>%s</select>';
$ot = '<option value="%s" %s>Section %s</option>';
// determine which filter button was clicked, if any and set section
$button = key( array_filter( $_GET, function($v) { return __( 'Filter' ) === $v; } ) );
$section = $_GET[ 'course_section_' . $button ] ?? -1;
// generate <option> and <select> code
$options = implode( '', array_map( function($i) use ( $ot, $section ) {
return sprintf( $ot, $i, selected( $i, $section, false ), $i );
}, range( 1, 3 ) ));
$select = sprintf( $st, $which, __( 'Course Section...' ), $options );
// output <select> and submit button
echo $select;
submit_button(__( 'Filter' ), null, $which, false);
}
add_action('restrict_manage_users', 'add_course_section_filter');
function filter_users_by_course_section($query)
{
global $pagenow;
if (is_admin() && 'users.php' == $pagenow) {
$button = key( array_filter( $_GET, function($v) { return __( 'Filter' ) === $v; } ) );
if ($section = $_GET[ 'course_section_' . $button ]) {
$meta_query = [['key' => 'courses','value' => $section, 'compare' => 'LIKE']];
$query->set('meta_key', 'courses');
$query->set('meta_query', $meta_query);
}
}
}
add_filter('pre_get_users', 'filter_users_by_course_section');
Ho incorporato diverse idee di @birgire e @cale_b che offre anche soluzioni di seguito che vale la pena leggere. In particolare, io:
- Utilizzata la
$which
variabile che è stata aggiuntav4.6.0
- Best practice utilizzata per i18n utilizzando stringhe traducibili, ad es
__( 'Filter' )
- Loop scambiato con il (più di moda?)
array_map()
, array_filter()
Erange()
- Utilizzato
sprintf()
per generare i modelli di markup
- Utilizzata la notazione di matrice parentesi quadra anziché
array()
Infine, ho scoperto un bug nelle mie precedenti soluzioni. Queste soluzioni favoriscono sempre il TOP <select>
rispetto al FONDO <select>
. Pertanto, se hai selezionato un'opzione di filtro dal menu a discesa in alto, e successivamente ne hai selezionato uno dal menu a discesa in basso, il filtro utilizzerà comunque solo il valore in alto (se non è vuoto). Questa nuova versione corregge quel bug.
AGGIORNAMENTO 2018-02-14
Questo problema è stato corretto da WP 4.6.0 e le modifiche sono documentate nei documenti ufficiali . La soluzione di seguito funziona comunque, comunque.
Cosa ha causato il problema (WP <4.6.0)
Il problema era che l' restrict_manage_users
azione veniva chiamata due volte: una volta SOPRA la tabella Users e una volta SOTTO. Ciò significa che DUE select
menu a discesa vengono creati con lo stesso nome . Quando si Filter
fa clic sul pulsante, qualunque valore si trovi nel secondo select
elemento (ovvero quello SOTTO la tabella) sovrascrive il valore nel primo, ovvero quello SOPRA la tabella.
Nel caso in cui si desideri immergersi nella fonte WP, l' restrict_manage_users
azione viene attivata dall'interno WP_Users_List_Table::extra_tablenav($which)
, che è la funzione che crea il menu a discesa nativo per modificare il ruolo di un utente. Tale funzione ha l'aiuto della $which
variabile che indica se sta creando select
il modulo sopra o sotto il modulo e gli consente di assegnare ai due menu a discesa name
attributi diversi . Sfortunatamente, la $which
variabile non viene passata restrict_manage_users
all'azione, quindi dobbiamo trovare un altro modo per differenziare i nostri elementi personalizzati.
Un modo per farlo, come suggerisce @Linnea , sarebbe quello di aggiungere un po 'di JavaScript per catturare il Filter
clic e sincronizzare i valori dei due menu a discesa. Ho scelto una soluzione solo PHP che descriverò ora.
Come sistemarlo
È possibile sfruttare la possibilità di trasformare input HTML in array di valori e quindi filtrare l'array per eliminare eventuali valori non definiti. Ecco il codice:
function add_course_section_filter() {
if ( isset( $_GET[ 'course_section' ]) ) {
$section = $_GET[ 'course_section' ];
$section = !empty( $section[ 0 ] ) ? $section[ 0 ] : $section[ 1 ];
} else {
$section = -1;
}
echo ' <select name="course_section[]" style="float:none;"><option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
$selected = $i == $section ? ' selected="selected"' : '';
echo '<option value="' . $i . '"' . $selected . '>Section ' . $i . '</option>';
}
echo '</select>';
echo '<input type="submit" class="button" value="Filter">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() &&
'users.php' == $pagenow &&
isset( $_GET[ 'course_section' ] ) &&
is_array( $_GET[ 'course_section' ] )
) {
$section = $_GET[ 'course_section' ];
$section = !empty( $section[ 0 ] ) ? $section[ 0 ] : $section[ 1 ];
$meta_query = array(
array(
'key' => 'course_section',
'value' => $section
)
);
$query->set( 'meta_key', 'course_section' );
$query->set( 'meta_query', $meta_query );
}
}
add_filter( 'pre_get_users', 'filter_users_by_course_section' );
Bonus: PHP 7 Refactor
Dato che sono entusiasta di PHP 7, nel caso in cui tu stia eseguendo WP su un server PHP 7, ecco una versione più breve e sexy usando l' operatore null coalescing??
:
function add_course_section_filter() {
$section = $_GET[ 'course_section' ][ 0 ] ?? $_GET[ 'course_section' ][ 1 ] ?? -1;
echo ' <select name="course_section[]" style="float:none;"><option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
$selected = $i == $section ? ' selected="selected"' : '';
echo '<option value="' . $i . '"' . $selected . '>Section ' . $i . '</option>';
}
echo '</select>';
echo '<input type="submit" class="button" value="Filter">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() && 'users.php' == $pagenow) {
$section = $_GET[ 'course_section' ][ 0 ] ?? $_GET[ 'course_section' ][ 1 ] ?? null;
if ( null !== $section ) {
$meta_query = array(
array(
'key' => 'course_section',
'value' => $section
)
);
$query->set( 'meta_key', 'course_section' );
$query->set( 'meta_query', $meta_query );
}
}
}
add_filter( 'pre_get_users', 'filter_users_by_course_section' );
Godere!