MISE À JOUR 2018-06-28
Alors que le code ci-dessous fonctionne généralement bien, voici une réécriture du code pour WP> = 4.6.0 (en utilisant 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');
J'ai incorporé plusieurs idées de @birgire et @cale_b qui propose également des solutions ci-dessous qui valent la peine d'être lues. Plus précisément, je:
- Utilisé la
$which
variable qui a été ajoutée dansv4.6.0
- Meilleure pratique utilisée pour i18n en utilisant des chaînes traduisibles, par exemple
__( 'Filter' )
- Boucles échangées pour la (plus à la mode?)
array_map()
, array_filter()
Etrange()
- Utilisé
sprintf()
pour générer les modèles de balisage
- A utilisé la notation du tableau entre crochets au lieu de
array()
Enfin, j'ai découvert un bug dans mes solutions précédentes. Ces solutions privilégient toujours le TOP par <select>
rapport au BAS <select>
. Donc, si vous avez sélectionné une option de filtre dans la liste déroulante supérieure, puis que vous en avez sélectionné une dans la liste déroulante inférieure, le filtre n'utilisera toujours que la valeur en haut (si elle n'est pas vide). Cette nouvelle version corrige ce bogue.
MISE À JOUR 2018-02-14
Ce problème a été corrigé depuis WP 4.6.0 et les modifications sont documentées dans les documents officiels . Cependant, la solution ci-dessous fonctionne toujours.
Qu'est-ce qui a causé le problème (WP <4.6.0)
Le problème était que l' restrict_manage_users
action est appelée deux fois: une fois au-dessus de la table des utilisateurs et une fois en dessous. Cela signifie que DEUX select
listes déroulantes sont créées avec le même nom . Lorsque le Filter
bouton est cliqué, la valeur du deuxième select
élément (c'est-à-dire celui EN-DESSOUS du tableau) remplace la valeur du premier, c'est-à-dire celle AU-DESSUS du tableau.
Si vous souhaitez plonger dans la source WP, l' restrict_manage_users
action est déclenchée de l'intérieur WP_Users_List_Table::extra_tablenav($which)
, qui est la fonction qui crée la liste déroulante native pour modifier le rôle d'un utilisateur. Cette fonction a l'aide de la $which
variable qui lui indique si elle crée le select
dessus ou le dessous du formulaire, et lui permet de donner aux deux listes déroulantes des name
attributs différents . Malheureusement, la $which
variable n'est pas transmise à l' restrict_manage_users
action, nous devons donc trouver une autre façon de différencier nos propres éléments personnalisés.
Une façon de le faire, comme le suggère @Linnea , serait d'ajouter du JavaScript pour capturer le Filter
clic et synchroniser les valeurs des deux listes déroulantes. J'ai choisi une solution PHP uniquement que je vais décrire maintenant.
Comment le réparer
Vous pouvez profiter de la possibilité de transformer les entrées HTML en tableaux de valeurs, puis de filtrer le tableau pour éliminer toutes les valeurs non définies. Voici le code:
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
Étant donné que je suis enthousiasmé par PHP 7, au cas où vous exécuteriez WP sur un serveur PHP 7, voici une version plus courte et plus sexy utilisant l' opérateur de coalescence nulle??
:
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' );
Prendre plaisir!