it-swarm-pt.tech

Como classificar a área de administração de um tipo de postagem personalizada do WordPress por um campo personalizado

Ao editar um dos meus tipos de postagem personalizados, quero poder listar todas as entradas por um campo personalizado em vez da data em que são publicadas (o que, para um tipo de postagem personalizado, provavelmente não é relevante). Eu recebi uma pista dos comentários de uma postagem no blog sobre tipos de postagem personalizados e o autor disse que era possível e que ele até fez isso para que você pudesse clicar nos nomes das colunas para uma classificação personalizada. Ele mencionou a função posts_orderby que observei em meus próprios comentários, mas agora posso encontrar a postagem do blog mais. Alguma sugestão? Eu vi uma solução que usava

add_action('wp', 'check_page');

E a função check_page usou add_filter para alterar a consulta, mas tenho certeza que funcionaria apenas nos arquivos de tema, não na área de administração.

52
tooshel

Como você provavelmente pode imaginar pela falta de respostas fornecidas, a solução não é exatamente trivial. O que eu fiz foi criar um exemplo um tanto auto-contido que assume um tipo de post customizado de "movie" e uma chave de campo customizada de "Genre".

Disclaimer: isso funciona com o WP3.0, mas não posso ter certeza de que funcionará com versões anteriores.

Você basicamente precisa ligar dois (2) ganchos para fazê-lo funcionar e outros dois (2) para torná-lo óbvio e útil.

O primeiro gancho é 'restrict_manage_posts', que permite emitir um HTML <select> na área acima da lista de posts onde os filtros "Bulk Actions" e "Show Dates" são filtrados. O código fornecido gerará a funcionalidade "Classificar por:" conforme visto neste snippet de tela:

How to Create Sort By functionality for a Custom Post Type in the WordPress Admin
(fonte: mikeschinkel.com )

O código usa SQL direto porque não há uma função API do WordPress para fornecer a lista de todas as meta_keys para um tipo de post (soa como um ticket futuro trac para mim ...) Enfim, aqui está o código. Note que ele pega o tipo de post de $_GET e valida para ter certeza de que é um tipo de post válido post_type_exists() além de ser um tipo de post movie (essas duas verificações são exageradas, mas eu fiz isso para mostrar como você não quer para codificar o tipo de postagem.) Por fim, uso o parâmetro URL sortby, pois ele não entra em conflito com mais nada no WordPress:

add_action('restrict_manage_posts','restrict_manage_movie_sort_by_genre');
function restrict_manage_movie_sort_by_genre() {
    if (isset($_GET['post_type'])) {
        $post_type = $_GET['post_type'];
        if (post_type_exists($post_type) && $post_type=='movie') {
            global $wpdb;
            $sql=<<<SQL
SELECT pm.meta_key FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON p.ID=pm.post_id
WHERE p.post_type='movie' AND pm.meta_key='Genre'
GROUP BY pm.meta_key
ORDER BY pm.meta_key
SQL;
            $results = $wpdb->get_results($sql);
            $html = array();
            $html[] = "<select id=\"sortby\" name=\"sortby\">";
            $html[] = "<option value=\"None\">No Sort</option>";
            $this_sort = $_GET['sortby'];
            foreach($results as $meta_key) {
                $default = ($this_sort==$meta_key->meta_key ? ' selected="selected"' : '');
                $value = esc_attr($meta_key->meta_key);
                $html[] = "<option value=\"{$meta_key->meta_key}\"$default>{$value}</option>";
            }
            $html[] = "</select>";
            echo "Sort by: " . implode("\n",$html);
        }
    }
}

A segunda etapa obrigatória é usar o gancho parse_query que é chamado depois que o WordPress decide qual consulta deve ser executada, mas antes de executar a consulta. Aqui podemos definir valores de orderby e meta_key no array query_var da consulta que são documentados no Codex no parâmetro orderby para query_posts(). Nós testamos para garantir que:

  1. Estamos no admin (is_admin()),
  2. Estamos na página que lista posts no admin ($pagenow=='edit.php'),
  3. A página foi chamada com um parâmetro de URL post_type igual a movie e
  4. A página também foi chamada com um parâmetro de URL sortby e não foi passado um valor de 'None'

Se todos esses testes passarem, então setamos query_vars (como documentado here ) para meta_value e nosso valor sortby para 'Genre':

add_filter( 'parse_query', 'sort_movie_by_meta_value' );
function sort_movie_by_meta_value($query) {
    global $pagenow;
    if (is_admin() && $pagenow=='edit.php' &&
        isset($_GET['post_type']) && $_GET['post_type']=='movie' && 
        isset($_GET['sortby'])  && $_GET['sortby'] !='None')  {
        $query->query_vars['orderby'] = 'meta_value';
        $query->query_vars['meta_key'] = $_GET['sortby'];
    }
}

E isso é tudo que você precisa fazer; não é necessário nenhum gancho "posts_order" ou "wp"! Claro que você realmente precisa fazer mais; você precisa adicionar algumas colunas na sua página que lista as postagens para que você possa realmente ver os valores que está classificando, caso contrário os usuários ficarão muito confusos. Então adicione um gancho manage_{$post_type}_posts_columns, neste caso manage_movie_posts_columns. Esse gancho é passado na matriz padrão de colunas e, para simplificar, eu o substituí por duas colunas padrão; uma caixa de seleção (cb) e um nome de postagem (title). (Você pode inspecionar posts_columns com print_r() para ver o que mais está disponível por padrão).

Decidi adicionar um "Sorted By:" para quando houver um parâmetro de URL sortby e quando não for None:

add_action('manage_movie_posts_columns', 'manage_movie_posts_columns');
function manage_movie_posts_columns($posts_columns) {
    $posts_columns = array(
        'cb' => $posts_columns['cb'],
        'title' => 'Movie Name',
        );
    if (isset($_GET['sortby']) && $_GET['sortby'] !='None') 
        $posts_columns['meta_value'] = 'Sorted By';

    return $posts_columns;
}

Por fim, usamos o gancho manage_pages_custom_column para realmente exibir o valor quando há um post do tipo de postagem apropriado e com o teste provavelmente redundante para is_admin() e $pagenow=='edit.php'. Quando há um parâmetro de URL sortby, extraímos o valor do campo personalizado que está sendo classificado por um display em nossa lista. Aqui está o que parece (lembre-se, este é o teste de dados, portanto, nenhum comentário da galeria de amendoim nas classificações do filme! :):

Custom Columns added for a Custom Post Type in the WordPress Admin
(fonte: mikeschinkel.com )

E aqui está o código:

add_action('manage_pages_custom_column', 'manage_movie_pages_custom_column',10,2);
function manage_movie_pages_custom_column($column_name,$post_id) {
    global $pagenow;
    $post = get_post($post_id);
    if ($post->post_type=='movie' && is_admin() && $pagenow=='edit.php')  {
        switch ($column_name) {
            case 'meta_value':
                if (isset($_GET['sortby']) && $_GET['sortby'] !='None') {
                    echo get_post_meta($post_id,$_GET['sortby'],true);
                }
                break;
        }
    }
}

Note que isto só pega o primeiro "Genre" para um movie, ou seja, o primeiro meta_value no caso de múltiplos valores para uma dada chave. Mas, novamente, não sei como funcionaria de outra maneira!

E para aqueles que não estão familiarizados com onde colocar esse código, você pode colocá-lo em um plugin ou mais provável para o novato no arquivo functions.php em seu tema atual.

Como isso ajuda?.

66
MikeSchinkel

A partir do WordPress 3.1 (eu estou usando a versão beta) as colunas agora podem ser classificadas através de seus títulos.

A postagem a seguir detalha como implementá-los.

http://scribu.net/wordpress/custom-sortable-columns.html

8
Leo Plaw