Archivos de fecha para tipo de publicación personalizada

2

He visto muchas preguntas / publicaciones con respecto a esto, pero todavía tengo que encontrar una solución decente. Básicamente, estoy tratando de hacer lo que wp_get_archives hace, pero para un tipo de publicación personalizada (personalmente, no estoy seguro de por qué wp_get_archives no admite tipos de publicación personalizados).

El código que estoy usando actualmente es el siguiente

functions.php

function Cpt_getarchives_where_filter( $where , $r ) {
  $post_type = 'events';
  return str_replace( "post_type = 'post'" , "post_type = '$post_type'" , $where );
}

sidebar-events.php

add_filter( 'getarchives_where' , 'Cpt_getarchives_where_filter' , 10 , 2 );
wp_get_archives();
remove_filter('getarchives_where' , 'Cpt_getarchives_where_filter' , 10 );

Este código muestra las fechas (p. ej., abril de 2014, marzo de 2014), etc., lo cual es genial, pero hacer clic en los enlaces solo va a un 404. La URL que se crea en cada enlace de fecha es / 2014/04 /, sin embargo debería ser algo como / eventos / 2014/04 /.

¿Hay alguna forma de incluir 'eventos' en la URL para que se pueda usar la plantilla archive-events.php, y hay alguna razón por la que los enlaces actualmente generan un 404?

Muchas gracias por cualquier ayuda

    
pregunta wickywills 30.04.2014 - 12:24

2 respuestas

4

Lo que desee puede hacerse también filtrando 'month_link' para archivos mensuales, 'year_link' para archivos anuales y 'day_link' para archivos diarios.

También puede escribir una función que amplíe wp_get_archives para trabajar con CPT, agregando filtros a 'getarchives_where' y al enlace de archivo.

function wp_get_cpt_archives( $cpt = 'post', $args = array() ) {
  // if cpt is post run the core get archives
  if ( $cpt === 'post' ) return wp_get_archives($args); 
  // if cpt doesn't exists return error
  if ( ! post_type_exists($cpt) ) return new WP_Error('invalid-post-type');
  $pto = get_post_type_object($cpt);
  // if cpt doesn't have archive return error
  if ( ! $pto = get_post_type_object( $cpt ) ) return false;
  $types = array('monthly' => 'month', 'daily' => 'day', 'yearly' => 'year');
  $type = isset( $args['type'] ) ?  $args['type'] : 'monthly';
  if ( ! array_key_exists($type, $types) ) {
    // supporting only 'monthly', 'daily' and 'yearly' archives
     return FALSE;
  }
  $done_where = $done_link = FALSE;
  // filter where
  add_filter( 'getarchives_where' , function( $where ) use (&$done_where, $cpt) {
    if ( $done_where ) return $where;
    return str_replace( "post_type = 'post'" , "post_type = '{$cpt}'" , $where );
  });
  // filter link
  add_filter( "{$types[$type]}_link", function( $url ) use (&$done_link, $pto, $cpt) {
    if ( $done_link ) return $url;
     // if no pretty permalink add post_type url var
     // if ( get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
     if ( ! get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
       return add_query_arg( array( 'post_type' => $cpt ), $url );
     } else { // pretty permalink
       global $wp_rewrite;
       $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
       $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
       $home = untrailingslashit( home_url( $base ) );
       return str_replace( $home,  home_url( $base . $slug ), $url );
     }
  });
  // get original echo arg and then set echo to false  
  $notecho = isset($args['echo']) && empty($args['echo']);
  $args['echo'] = FALSE; 
  // get archives
  $archives = wp_get_archives($args);
  // prevent filter running again
  $done_where = $done_link = TRUE;
  // echo or return archives
  if ( $notecho ) {
    return $archives;
  } else {
    echo $archives;
  }
}

Lea los comentarios en línea para obtener más información sobre cómo funciona la función.

Ahora hay un problema. La url como /events/2014/04/ no es reconocida por WordPress, por lo que debe agregar las reglas de reqrite que manejan ese tipo de urls.

Nuevamente, puedes escribir una función que agregue esas reglas para ti:

function generate_cpt_archive_rules( $cpt ) {
  if ( empty($cpt) || ! post_type_exists($cpt) ) return;
  global $wp_rewrite;
  $pto = get_post_type_object($cpt);
  if ( ! $pto->has_archive ) return;
  $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
  $base = trailingslashit( $base );
  $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
  $year = ltrim( $base . $slug . '/([0-9]{4})/?$', '/' );
  $month = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/?$', '/' );
  $day = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/([0-9]{2})/?$', '/' );
  $index = 'index.php?post_type=' . $cpt;
  $rules[$year] =  $index . '&m=$matches[1]';
  $rules[$month] = $index . '&m=$matches[1]$matches[2]';
  $rules[$day] = $index . '&m=$matches[1]$matches[2]$matches[3]';
  $page = 2;
  foreach ( array( $year, $month, $day ) as $rule ) {
    $paged = str_replace( '/?$', '/page/([0-9]{1,})/?$', $rule);
    $rules[$paged] = $rules[$rule] . '&paged=$matches[' . $page . ']';
    $page++;
  }
  return $rules;
}

Esta función genera las reglas, sin embargo, también es necesario agregarlas y eliminarlas.

Ahora se recomienda vaciar las reglas sobre la activación del tema (o complemento) y registrarlas en init, por lo que deberías hacer algo como:

function register_cpt_dates_rules() {
  $cpts = array( 'events' );
  foreach ( $cpts as $cpt ) {
    foreach ( generate_cpt_archive_rules( $cpt ) as $rule => $rewrite ) {
      add_rewrite_rule( $rule, $rewrite, 'top' );
    }
  }
}
// flushing on theme switch
add_action('after_switch_theme', function() {
  register_cpt_dates_rules();
  $GLOBALS['wp_rewrite']->flush_rules();
});
// registering on init
add_action( 'init', 'register_cpt_dates_rules' );

Una vez que haya agregado estas funciones a su functions.php (y haya desactivado y activado nuevamente su tema para hacer que 'after_switch_theme' se ejecute), puede mostrar los archivos usando:

wp_get_cpt_archives( 'events' );

Y mostrará los archivos para el evento CPT, y el enlace será algo /events/2014/04/ .

Funciona también para archivos anuales o diarios:

wp_get_cpt_archives( 'events', array( 'type'=>'yearly' ) );
wp_get_cpt_archives( 'events', array( 'type'=>'daily' ) );

Al usar mis dos funciones, tienes una forma súper fácil de hacer que wp_get_archives funcione con CPT.

Tenga en cuenta que todos el código aquí requiere PHP 5.3+.

    
respondido por el gmazzap 30.04.2014 - 16:19
0

Creo que G.M ha dado todo lo que necesitas. Escribí una publicación de blog en la generación de enlace permanente para los archivos de fechas CPT, pero Aún no he tenido tiempo de obtener la otra parte pre_get_posts en una publicación de blog.

Hay básicamente 3 piezas en el rompecabezas:

  1. Generando sus reglas de reescritura para leer las cadenas de fecha /2014/04/30 , /2014/ , etc.
  2. Lograr que su WP_Query reconozca las variables de consulta.
  3. y creando los enlaces de paginación / archivo para los widgets de la barra lateral (que cubre mi publicación).
respondido por el Eric Holmes 30.04.2014 - 17:02

Lea otras preguntas en las etiquetas