WordPress : des liens de navigation à l’intérieur d’une catégorie

Dans WordPress 3.0, les articles sont accompagnés de liens de navigation – deux liens, l’un vers l’article précédent, l’autre vers le suivant – grâce auxquels le lecteur peut passer d’un article à l’autre. Ces liens ne tiennent pas compte de la structure du site, ils proposent donc une navigation dans la liste de tous les articles publiés, ordonnée en ordre inverse chronologique. Pour un moteur de blogs, on comprend, mais pour un CMS, on aime moins.

Lors d’une utilisation de WordPress comme CMS, on préfèrera limiter ces liens de navigation aux articles de la catégorie courante. De plus, l’ordonnancement de la navigation devrait suivre celui de la rubrique.

Ci-dessous la classe PHP que j’utilise pour faire ce travail. Ce code est à coller dans un fichier « CtArtNavigation.php » à déposer dans votre thème WordPress.

<?php
/**
 * When the category is ordered by an article meta field (numeric), give the field name here.
 */
define('CT_MANUAL_ORDER_FIELD', 'Ordre');
class CtArtNavigation { public function __construct($sameBaseUrlInCat = false) { $this->sameBaseUrlInCat = $sameBaseUrlInCat; } /** * @param $order string Available values: 'chrono', 'rev-chrono', 'alpha', 'manual' */ public function init($order, $catId = null) { $this->doInit($order, $catId, null); } /** * @param $order string Available values: 'chrono', 'rev-chrono', 'alpha', 'manual' */ public function initExcludeCategories($order, $lstExcludedCatId) { $this->doInit($order, null, &$lstExcludedCatId); } public function printHtml() { if (isset($this->htmlCode)) echo $this->htmlCode; } private function doInit($order, $catId = null, $lstExcludedCatId = null) { $this->htmlCode = ''; if (!isset($catId) && !isset($lstExcludedCatId)) return; $htmlLinkPrevious = $this->getPostLink($order, $catId, $lstExcludedCatId, true); $htmlLinkNext = $this->getPostLink($order, $catId, $lstExcludedCatId, false); if ($htmlLinkPrevious || $htmlLinkNext) { $this->htmlCode .= '<div class="nav">' . "\n"; if ($htmlLinkPrevious) $this->htmlCode .= ' <div class="nav-previous"><span class="meta-nav">&larr;</span>&nbsp;' . $htmlLinkPrevious . "</div>\n"; if ($htmlLinkNext) $this->htmlCode .= ' <div class="nav-next">' . $htmlLinkNext . '&nbsp;<span class="meta-nav">&rarr;</span>' . "</div>\n"; $this->htmlCode .= ' <hr class="clearfloats"/>' . "\n"; $this->htmlCode .= '</div>' . "\n"; } } private function &getPostLink($order, $catId, &$lstExcludedCatId, $previous) { global $post, $wpdb; //$cat_array = wp_get_object_terms($post->ID, 'category', array('fields' => 'ids')); $revOrder = ($order === 'rev-chrono'); if ($previous === !$revOrder) { $op = '<'; $orderOp = ' desc'; } else { $op = '>'; $orderOp = ''; } switch ($order) { case 'alpha': $currentPostTitle = $post->post_title; $select = ''; $join = ''; $where = " and p.post_title $op '" . mysql_escape_string($currentPostTitle) . "'"; $orderby = "p.post_title$orderOp"; break; case 'manual': $select = ', (pm.meta_value+0) as meta_post_order'; $join = ' inner join wp_postmeta pm on p.ID = pm.post_id and pm.meta_key = \'' . CT_MANUAL_ORDER_FIELD . '\'' . ' inner join wp_posts pcur on pcur.ID = ' . $post->ID . ' inner join wp_postmeta pmcur on pcur.ID = pmcur.post_id and pmcur.meta_key = \'' . CT_MANUAL_ORDER_FIELD . '\''; $where = " and (pm.meta_value+0) $op (pmcur.meta_value+0)"; $orderby = "meta_post_order$orderOp"; break; case 'chrono': case 'rev-chrono': default: $currentPostDate = $post->post_date; $select = ', p.post_date'; $join = ''; $where = " and p.post_date $op '$currentPostDate'"; $orderby = "p.post_date$orderOp"; } if (isset($catId)) $joinCrit = " and tt.term_id = $catId"; else { if (count($lstExcludedCatId) > 0) $joinCrit = ' and tt.term_id not in (' . implode(', ', $lstExcludedCatId) . ')'; else $joinCrit = ''; } $sql = "select p.ID, p.post_title, p.post_name$select from wp_posts p inner join wp_term_relationships tr on p.ID = tr.object_id inner join wp_term_taxonomy tt on tr.term_taxonomy_id = tt.term_taxonomy_id and tt.taxonomy = 'category'$joinCrit $join where p.post_type = 'post' and p.post_status = 'publish' and tt.taxonomy = 'category' and tt.term_id <> 1$where order by $orderby LIMIT 1"; //echo "<pre>$sql</pre>"; $query_key = 'ct_adjacent_post_' . md5($sql); $result = wp_cache_get($query_key, 'counts'); if (false === $result) { $result = $wpdb->get_row($sql); if ( null === $result ) $result = ''; wp_cache_set($query_key, $result, 'counts'); } if (!$result) return false; if ($this->sameBaseUrlInCat && isset($catId)) $url = $result->post_name; else $url = get_permalink($result->ID); return '<a href="' . esc_attr($url) . '">' . esc_html($result->post_title) . '</a>'; } private $htmlCode, $sameBaseUrlInCat; }

Il reste ensuite à modifier le fichier « single.php » de votre thème WordPress. En début de fichier, collez le code d’instanciation de la classe :

<?php
// - $catId
$lstCat = (array) get_the_category(get_the_ID());
if (count($lstCat) >= 1) {
  $cat = &$lstCat[0];
  $catId = intval($cat->cat_ID);
} else
  $catId = null;
// - build the navigation require 'CtArtNavigation.php'; $ctNav = new CtArtNavigation(); $ctNav->init('alpha', $catId); $ctShowAddedTime = $ctMeta->getCatShowArtTime(); ?>

L’ordonnancement « alpha » peut être remplacé par celui de votre rubrique : « chrono », « rev-chrono », ou « manual ».

Puis, à l’intérieur de ce même fichier, remplacer les éléments div d’identifiants « nav-above » et « nav-below » par l’appel de notre classe :

<?php $ctNav->printHtml(); ?>

Et le tour est joué !

Leave a Reply

Your email address will not be published. Required fields are marked *

Mesure anti-spam. Merci de copier le code « 31I0Z5 » dans le champ ci-dessous :