ATUALIZAÇÃO 28/06/2018
Enquanto o código abaixo funciona principalmente bem, aqui está uma reescrita do código para WP> = 4.6.0 (usando o 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');
Incorporei várias idéias de @birgire e @cale_b, que também oferecem soluções abaixo que valem a pena ser lidas. Especificamente, eu:
- Usou a
$which
variável que foi adicionada emv4.6.0
- Prática recomendada usada para o i18n usando seqüências de caracteres traduzíveis, por exemplo
__( 'Filter' )
- Laços trocado pelo (mais elegante?)
array_map()
, array_filter()
Erange()
- Usado
sprintf()
para gerar os modelos de marcação
- Usou a notação de matriz entre colchetes em vez de
array()
Por fim, descobri um bug em minhas soluções anteriores. Essas soluções sempre favorecem o TOP <select>
sobre o BOTTOM <select>
. Portanto, se você selecionou uma opção de filtro na lista suspensa superior e, em seguida, selecionou uma na lista suspensa inferior, o filtro ainda usará apenas o valor que estiver acima (se não estiver em branco). Esta nova versão corrige esse bug.
ATUALIZAÇÃO 14-02-2018
Esse problema foi corrigido desde o WP 4.6.0 e as alterações estão documentadas nos documentos oficiais . A solução abaixo ainda funciona, no entanto.
O que causou o problema (WP <4.6.0)
O problema era que a restrict_manage_users
ação era chamada duas vezes: uma vez ACIMA da tabela Usuários e uma vez ABAIXO. Isso significa que DUAS select
listas suspensas são criadas com o mesmo nome . Quando o Filter
botão é clicado, qualquer valor que esteja no segundo select
elemento (ou seja, abaixo da tabela) substitui o valor no primeiro, ou seja, acima da tabela.
Caso você queira mergulhar na origem do WP, a restrict_manage_users
ação é acionada de dentro WP_Users_List_Table::extra_tablenav($which)
, que é a função que cria a lista suspensa nativa para alterar a função de um usuário. Essa função tem a ajuda da $which
variável que informa se está criando select
o formulário acima ou abaixo do formulário e permite atribuir aos dois menus suspensos name
atributos diferentes . Infelizmente, a $which
variável não é passada para a restrict_manage_users
ação, portanto, precisamos criar outra maneira de diferenciar nossos próprios elementos personalizados.
Uma maneira de fazer isso, como sugere @Linnea , seria adicionar um pouco de JavaScript para capturar o Filter
clique e sincronizar os valores das duas caixas suspensas. Eu escolhi uma solução somente PHP que descreverei agora.
Como corrigi-lo
Você pode tirar proveito da capacidade de transformar entradas HTML em matrizes de valores e filtrar a matriz para se livrar de quaisquer valores indefinidos. Aqui está o código:
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' );
Bônus: Refator do PHP 7
Como estou entusiasmado com o PHP 7, caso você esteja executando o WP em um servidor PHP 7, aqui está uma versão mais curta e mais sexy usando o operador coalescente nulo??
:
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' );
Aproveitar!