web-dev-qa-db-fra.com

Archives de date pour le type d'article personnalisé

J'ai vu beaucoup de questions/messages à ce sujet, mais je n'ai pas encore trouvé de solution décente. Fondamentalement, j'essaie de faire ce que wp_get_archives fait, mais pour un type de publication personnalisé (personnellement, je ne sais pas pourquoi wp_get_archives ne prend pas en charge les types de publication personnalisés!).

Le code que j'utilise actuellement est le suivant

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 );

Ce code affiche les dates (par exemple, avril 2014, mars 2014), etc. Ce qui est formidable, mais cliquer sur les liens ne fait que placer un 404. L'URL créée pour chaque lien de date est/2014/04 /. Cependant, cela devrait être quelque chose comme/événements/2014/04 /.

Existe-t-il un moyen d'inclure des "événements" dans l'URL afin que le modèle archive-events.php puisse être utilisé, et y a-t-il une raison pour laquelle les liens génèrent actuellement un 404?

Un grand merci pour toute aide

2
wickywills

Vous pouvez également filtrer 'month_link' pour les archives mensuelles, 'year_link' pour les archives annuelles et 'day_link' pour les archives quotidiennes.

Vous pouvez également écrire une fonction qui étend wp_get_archives pour utiliser des CPT, en ajoutant des filtres à 'getarchives_where' et au lien d’archive.

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

Veuillez lire les commentaires en ligne pour plus d'informations sur le fonctionnement de la fonction.

Maintenant, il y a un problème. Les URL telles que /events/2014/04/ sont non reconnues par WordPress. Vous devez donc ajouter les règles de réécriture qui gèrent ce type d’URL.

Encore une fois, vous pouvez écrire une fonction qui ajoute ces règles pour vous:

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

Cette fonction génère les règles, mais vous devez également les ajouter et les vider.

Il est maintenant recommandé de vider les règles d'activation du thème (ou du plugin) et de les enregistrer sur init, de sorte que vous devriez faire quelque chose comme:

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' );

Une fois que vous avez ajouté ces fonctions à votre functions.php (et que vous avez désactivé et réactivé votre thème pour que 'after_switch_theme' soit exécuté), vous pouvez afficher les archives à l'aide de:

wp_get_cpt_archives( 'events' );

Et il affichera les archives de l'événement CPT, et le lien sera quelque chose de /events/2014/04/.

Cela fonctionne aussi pour les archives annuelles ou quotidiennes:

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

En utilisant mes deux fonctions, vous disposez d’un moyen extrêmement facile de faire fonctionner wp_get_archives avec les CPT.

Notez que all le code nécessite ici PHP 5.3+.

4
gmazzap

Je pense que G.M a donné tout ce dont vous avez besoin. J'ai écrit un article blog sur la génération de permalien pour les archives de dates CPT, mais je n'ai pas encore eu le temps de récupérer l'autre partie pre_get_posts dans un formulaire d'article blog.

Il y a essentiellement 3 pièces dans le puzzle:

  1. Générer vos règles de réécriture pour lire les chaînes de date /2014/04/30, /2014/, etc.
  2. Demander à votre WP_Query de reconnaître les vars de requête.
  3. et créer les liens de pagination/archive pour les widgets de la barre latérale (dont traite mon message).
0
Eric Holmes