it-swarm-es.com

Cómo ordenar el área de administración de un tipo de publicación personalizada WordPress por un campo personalizado

Al editar uno de mis tipos de publicaciones personalizadas, quiero poder listar todas las entradas por un campo personalizado en lugar de la fecha en que se publican (lo cual, para un tipo de publicación personalizada probablemente no sea relevante). Recibí una pista de los comentarios de una publicación de blog sobre tipos de publicaciones personalizadas y el autor dijo que era posible y que incluso la hizo para que pudiera hacer clic en los nombres de las columnas para una clasificación personalizada. Mencionó la función posts_orderby que anoté en mis propios comentarios, pero ahora ya puedo encontrar la publicación del blog. ¿Alguna sugerencia? Vi una solución que usé

add_action('wp', 'check_page');

Y la función check_page usó add_filter para cambiar la consulta pero estoy bastante seguro de que solo funcionaría en los archivos de temas, no en el área de administración.

52
tooshel

Como probablemente pueda imaginar por la falta de respuestas proporcionadas, la solución no es exactamente trivial. Lo que he hecho es crear un ejemplo un tanto autónomo que asume un tipo de publicación personalizada de "movie" y una clave de campo personalizada de "Género".

Descargo de responsabilidad: esto funciona con WP3.0 pero no puedo estar seguro de que funcionará con versiones anteriores.

Básicamente necesita enganchar dos (2) ganchos para que funcione y otros dos (2) para que sea obvio y útil.

El primer enlace es 'restrict_manage_posts' que le permite emitir un <select> HTML en el área sobre la lista de publicaciones donde se filtran las "Acciones masivas" y "Mostrar fechas". El código proporcionado generará la funcionalidad "Ordenar por:" como se ve en este fragmento de pantalla:

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

El código usa SQL directo porque no hay una función de la API de WordPress que proporcione la lista de todas las meta_keys para un tipo de publicación (suena como un futuro trac ticket para mí ...) De todos modos, aquí está el código. Tenga en cuenta que toma el tipo de publicación de $_GET y valida para asegurarse de que es un tipo de publicación válido post_type_exists(), además de ser un tipo de publicación movie (esas dos verificaciones son excesivas, pero lo hice para mostrarle si no quiere para codificar el tipo de publicación.) Por último, uso el parámetro sortby URL ya que no está en conflicto con ninguna otra cosa en 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);
        }
    }
}

El segundo paso requerido es usar el enlace parse_query que se llama después de que WordPress decida qué consulta debe ejecutarse pero antes de ejecutar la consulta. Aquí podemos establecer valores de orderby y meta_key en el arreglo query_var de la consulta que están documentados en el Códice en el parámetro orderby para query_posts(). Probamos para asegurarnos de que:

  1. Estamos en el administrador (is_admin()),
  2. Estamos en la página que enumera las publicaciones en el administrador ($pagenow=='edit.php'),
  3. Se ha llamado a la página con un parámetro post_type URL igual a movie, y
  4. También se ha llamado a la página con un parámetro de URL sortby y que no se pasó un valor de 'Ninguno'

Si todas esas pruebas pasan, entonces establecemos query_vars (como se documenta aquí ) en meta_value y nuestro valor sortby para 'Género':

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'];
    }
}

Y eso es todo lo que necesitas hacer; no se requieren ganchos "posts_order" o "wp"! Por supuesto que realmente necesitas hacer más; necesitas agregar algunas columnas en tu página que enumera las publicaciones para que puedas ver los valores que está ordenando, de lo contrario los usuarios se confundirán mucho. Entonces agregue un gancho manage_{$post_type}_posts_columns, en este caso manage_movie_posts_columns. Este gancho pasa la matriz de columnas predeterminada y, por simplicidad, lo reemplacé con dos columnas estándar; una casilla de verificación (cb) y un nombre de publicación (title). (Puede inspeccionar posts_columns con una print_r() para ver qué más hay disponible de forma predeterminada).

Decidí agregar un "ordenado por:" para cuando haya un sortby parámetro de URL y cuando no sea 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;
}

Finalmente, usamos el gancho manage_pages_custom_column para mostrar realmente el valor cuando hay una publicación del tipo de publicación adecuada y con la prueba probablemente redundante para is_admin() y $pagenow=='edit.php'. Cuando hay un parámetro sortby URL, extraemos el valor del campo personalizado que está ordenando y lo muestra en nuestra lista. Esto es lo que parece (recuerde, estos son datos de prueba, por lo que no hay comentarios de la galería de cacahuetes en las clasificaciones de películas):

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

Y aquí está el 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;
        }
    }
}

Tenga en cuenta que esto solo recoge el primer "Género" para una movie, es decir, el primer meta_valor en el caso de múltiples valores para una clave dada. ¡Pero de nuevo no estoy seguro de cómo funcionaría de otra manera!

Y para aquellos que no estén familiarizados con dónde colocar este código, puede ponerlo en un complemento o más probablemente para el novato en el archivo functions.php en su tema actual.

Cómo esto ayuda.

66
MikeSchinkel

A partir de WordPress 3.1 (estoy usando la versión beta), las columnas ahora pueden ordenarse a través de sus títulos.

La siguiente publicación detalla cómo implementarlos.

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

8
Leo Plaw