Du flux par tags multiples
par Sunshine, 9 réactions
Publication 3 ans samedi 14 avril 2007 à 23:53
Rubrique Internet
Réactions 9
Lien permanent #158
Syndication suivre les réactions | suivre les billets connexes
Mots-clés DotClear, développement web, PHP, RSS, tags
Billets connexes
Mise à jour : l'astuce proposée ci-dessous a donné lieu à un plugin réalisé et testé sur DotClear 1.2.6.
DotClear (que je sache, dans sa version 1.2.x) est une bien jolie chose. C'est un projet communautaire visant à rendre accessible le partage sur l'Internet, grâce aux blogs. Chacun peut contribuer à son développement. Tout le monde. Alors pourquoi pas moi ?
Depuis les premières minutes suivant l'installation de DotClear, j'ai commencé à le bricoler. Bon, n'étant pas très discipliné, je me suis tout de suite plongé dans le fond de la chose, en bidouillant à ma sauce les multiples plugins que j'avais adoptés, ainsi que le design dont il est inutile de parler tant il a été changé (changé à tel point que j'en ai créé un de toute pièce).
Certains, et j'en suis flatté, m'ont demandé de partager mon thème. Le problème est que chacun des éléments visibles sur le site a été modifié d'une manière ou d'une autre, ce qui fait qu'il m'est impossible d'exporter d'un coup, et de manière fonctionnelle, mon thème. Peut-être que c'est crado comme façon de faire, mais tant pis ! Je pourrais, néanmoins, faire part des astuces que j'ai mises au point pour améliorer l'ergonomie du blog (taille du texte modifiable, nouveaux éléments dans la sidebar, liaison entre plugins etc). Mais je n'en éprouve pas l'envie. Mon code est cependant toujours accessible, rassurez-vous.
Là, en revanche, et c'est l'objet de ce billet, je vais vous faire part d'une astuce, du fait d'une demande certaine. En effet, il va s'agir de générer l'URL d'un fil RSS en fonction du choix de certains mots-clés (tags) préalablement associés à certains billets…
Revenons-en à nos moutons : générer un fil RSS grâce aux tags ou mots-clés. Je m'explique.
Outre les flux RSS par catégorie qui indexent les derniers billet d'une catégorie donnée, outre les flux de galeries d'images, je propose les flux par tags multiples. En effet, parmi tous les tags définis, le visiteur choisit ceux qui l'intéressent et génère le fil en fonction de ces-derniers. Ce fil liste donc les derniers billets contenant au moins un des tags choisis par le visiteur. L'intérêt est de permettre à chaque visiteur de préciser le choix du contenu duquel il souhaite être tenu au courant.
Pour être sûr de bien comprendre de quoi il s'agit, je vous invite à créer votre fil personnalisé en fonction de mes tags (cette page est accessible via la sidebar, par le lien Tous les tags).
0. Réalisation concrète
Parce que trêve de blabla, je vous l'accorde.
En clair, le but de la manoeuvre est de générer une adresse de flux RSS de la forme http://monsite/rss-meta.php?limite=x&key=tag?value=tag1,tag2,tag3 où x est le nombre de billets à afficher dans le fil. Ce qui suit ne constitue en rien un plugin. Ce sont des modifications manuelle qui offrent in fine une nouvelle fonctionnalité. Dans les prochaines semaines, un plugin sera réalisé (cf. dernier paragraphe).
I. Prélude : fichiers existants à modifier
Ainsi, abordons des considérations plus techniques afin de réaliser cette modeste modification.
Les plugins nécessaires à la réalisation de cette astuce et les fichiers à modifier sont :
- Métadonnées de billets dit twMeta
functions.php(dans/ecrire/tools/twpostmeta)rss-meta.php(dans/ecrire/tools/twpostmeta)- Tags dit twTags
functions.php(dans/ecrire/tools/twtags)- Related, pour créer la page du formulaire de création du fil
II. Greffons à insérer ou code à modifier
Avant toute manipulation, procédez à la sauvegarde des fichiers mentionnés, au cas où un problème surviendrait. On n'est jamais trop prudent !
II.1 Le fichier functions.php (dans /ecrire/tools/twpostmeta)
Remplacez le code suivant (à la fin du fichier)
# Récupère les $limit derniers billets dont le champ $key est défini et a la valeur $value
function getLastNews($key, $value, $limit = 20, $order = 'post_dt DESC', $lang='', $pub_mode = 1)
{
global $blog, $con;
$reqPlus = 'AND meta_key = "' . $con->escapeStr($key) . '" AND meta_value = "' . $con->escapeStr($value) . '" ';
if ($pub_mode)
$reqPlus .= 'AND post_pub = '.(integer) $pub_mode.' ';
if ($lang != '')
$reqPlus .= 'AND post_lang = "'.$con->escapeStr($lang).'" ';
$strReq = 'SELECT P.post_id, post_chapo, post_chapo_wiki, post_content, '.
'post_content_wiki, post_notes, post_titre, post_titre_url, '.
'post_dt, post_upddt, post_creadt, post_pub, '.
'post_open_comment, post_open_tb, nb_comment, nb_trackback, '.
'post_lang, post_selected, U.user_id, U.user_nom, '.
'U.user_prenom, U.user_pseudo, U.user_email, '.
'DATE_FORMAT(post_dt,"%Y%m%d") AS postdate, '.
'DATE_FORMAT(post_dt,"%H:%i") AS posthour, '.
'DATE_FORMAT(post_dt,"%d") AS postday, '.
'DATE_FORMAT(post_dt,"%m") AS postmonth, '.
'DATE_FORMAT(post_dt,"%Y") AS postyear, '.
'P.cat_id, C.cat_libelle, C.cat_libelle_url '.
'FROM '.DB_PREFIX.'post P, '.DB_PREFIX.'categorie C, '.
DB_PREFIX.'user U ,'.DB_PREFIX.'post_meta M '.
'WHERE P.cat_id = C.cat_id AND U.user_id = P.user_id AND P.post_id = M.post_id '.
$reqPlus.
'ORDER BY '.$con->escapeStr($order).' ';
if ($limit != '')
{
$limit = (preg_match('/^[0-9]+$/',$limit)) ? '0,'.$limit : $limit;
$strReq .= 'LIMIT '.$limit.' ';
}
if (($rs = $con->select($strReq,$GLOBALS['blog']->rs_blogpost)) !== false)
{
$rs->setBlog($GLOBALS['blog']);
return $rs;
}
else
exit($strReq);
return false;
}
par la fonction suivante :
# Récupère les $limit derniers billets dont le champ $key est défini et a la valeur $value
function getLastNews($key, $value, $limit = 20, $order = 'post_dt DESC', $lang='', $pub_mode = 1)
{
global $blog, $con;
$arrayvalue = explode(',',$value); // On sépare les tags présents dans l'url du fil
if (count($arrayvalue) == 1) {
$reqPlus = 'AND meta_key = "' . $con->escapeStr($key) . '" AND meta_value = "' . $con->escapeStr($arrayvalue[0]) . '" '; // S'il n'y a qu'un seul tag, la fonction est la même que l'originale
}
else {
$reqPlus = 'AND meta_key = "' . $con->escapeStr($key) . '" AND (meta_value = "' . $con->escapeStr($arrayvalue[0]) . '" ';
for ($i=1; $i < count( $arrayvalue ); $i++) {
$reqPlusPlus .= 'OR meta_value = "' .trim($con->escapeStr($arrayvalue[$i])). '" '; // Sinon, on sélectionne tous les billets contenant au moins un des tags choisis
}
$reqPlusPlus .= ') ';
}
if ($pub_mode)
$reqPlus2 = 'AND post_pub = '.(integer) $pub_mode.' ';
if ($lang != '')
$reqPlus2 .= 'AND post_lang = "'.$con->escapeStr($lang).'" ';
$strReq = 'SELECT DISTINCT P.post_id, post_chapo, post_chapo_wiki, post_content, '. /* Notez que la requête est ''SELECT DISTINCT'' et non ''SELECT''. On évite ainsi les doublons dans les résultats (car un même tag peut être attribué à des billets différents) */
'post_content_wiki, post_notes, post_titre, post_titre_url, '.
'post_dt, post_upddt, post_creadt, post_pub, '.
'post_open_comment, post_open_tb, nb_comment, nb_trackback, '.
'post_lang, post_selected, U.user_id, U.user_nom, '.
'U.user_prenom, U.user_pseudo, U.user_email, '.
'DATE_FORMAT(post_dt,"%Y%m%d") AS postdate, '.
'DATE_FORMAT(post_dt,"%H:%i") AS posthour, '.
'DATE_FORMAT(post_dt,"%d") AS postday, '.
'DATE_FORMAT(post_dt,"%m") AS postmonth, '.
'DATE_FORMAT(post_dt,"%Y") AS postyear, '.
'P.cat_id, C.cat_libelle, C.cat_libelle_url '.
'FROM '.DB_PREFIX.'post P, '.DB_PREFIX.'categorie C, '.
DB_PREFIX.'user U ,'.DB_PREFIX.'post_meta M '.
'WHERE P.cat_id = C.cat_id AND U.user_id = P.user_id AND P.post_id = M.post_id '.
$reqPlus.$reqPlusPlus.$reqPlus2. // On a ajouté nos requêtes supplémentaires
'ORDER BY '.$con->escapeStr($order).' ';
if ($limit != '')
{
$limit = (preg_match('/^[0-9]+$/',$limit)) ? '0,'.$limit : $limit;
$strReq .= 'LIMIT '.$limit.' ';
}
if (($rs = $con->select($strReq,$GLOBALS['blog']->rs_blogpost)) !== false)
{
$rs->setBlog($GLOBALS['blog']);
return $rs;
}
else
exit($strReq);
return false;
}
II.2 Le fichier rss-meta.php (dans /ecrire/tools/twpostmeta)
Remplacez les deux lignes suivantes :
# Dernières nouvelles $news = twPostMeta::getLastNews($key, $value, 10,'post_dt DESC',$lang);
par les quelques lignes :
# Dernières nouvelles
if (is_numeric($_GET['limit']) === TRUE) { // On vérifie que la limite présente dans l'URL du fil est bien un nombre
$value = str_replace(',',', ',$value); // Pour des raisons cosmétiques...
$news = twPostMeta::getLastNews($key, $value, $_GET['limit'],'post_dt DESC',$lang); // On fait appelle à la nouvelle fonction getLastNews(), permettant les tags multiples
} else { exit("<pre>Erreur : la limite soumise n'est pas numérique.<pre>"); } // Si la variable ''limit'' passée par l'URL n'est pas un nombre, on arrête le script
II.3 Le fichier functions.php (dans /ecrire/tools/twtags)
Nous allons créer deux fonctions par analogie à deux fonctions existantes. Ces fonctions génèrent le nuage de tags dans lequel chaque tag est associé à une case à cocher. Ce nuage permet de sélectionner les mots-clés d'intérêt, ceux-là même qui définissent notre fameux flux RSS.
Pour ce faire, ajouter, en fin de fichier, le code suivant.
// tagListPolyRss() et tagCloudPolyRss(), sur le modèle de tagList() et tagCloud()
function tagListPolyRss($block = '<ul>%s</ul>', $item = '<li>%s</li>', $levels = 5)
{
global $blog, $tag_id;
$rec = twTags::_recordset();
if ($rec)
{
$max = 0;
while ($rec->fetch())
{
if ($rec->f('cnt') > $max)
$max = $rec->f('cnt');
}
$rec->moveStart();
$res = '';
$i=0;
while ($rec->fetch())
{
$tag = $rec->f('meta_value');
$tagclean = $tag;
$link = '<input type="checkbox" id="'.$tagclean.'" name="tag'.$i.'" value="'.$tagclean.'"/> <label for="'.$tagclean.'">' . htmlspecialchars($tag) . '</label>'; // Les fameuses cases à cocher sont définies ici
if ($tag_id == $tag)
$link = $link;
$level = ceil($levels * $rec->f('cnt') / $max);
$res .= sprintf($item, $link.' ', $level);
$i++;
}
printf($block, $res);
}
}
function tagCloudPolyRss($levels = 5, $block='<ul>%s</ul>', $item='<li class="level-%2$d">%1$s</li>')
{
twTags::tagListPolyRss($block, $item, $levels);
}
III. Création de la page annexe : le formulaire de création du fil
Si les modifications ont bien été faites, il convient maintenant de les exploiter. Pour ce faire, nous allons créer une page annexe grâce au plugin Related, dit "Pages connexes" (notons que le terme connexe n'est pas très approprié car le plugin permet d'accéder à n'importe quelle page créée par le webmaster, ces pages n'ayant riene de "connexe" au blog ; bref).
Le code suivant étant le mien et comporte certains éléments propres à mes pages, il convient de l'adapter pour l'inclure parfaitement à votre gabarit.
<div class="post">
<h2 class="post-title" id="generer">Générer un fil (bétâ)</h2>
<p>Vous pouvez, aussi, générer un fil RSS filtrant les billets libélés comme vous le souhaitez. Choisissez une combinaison de tags afin de créer un fil permettant de lister les billets contenant tous les tags choisis.</p>
<form action="#generer" method="post">
<div class="tags com">
<?php twTags::tagCloudPolyRss($levels = 8, $block = '<p class="commentaire">%s</p>', $item = '<span class="level-%2$d">%1$s</span> '); ?>
</div><fieldset>
<p><label for="limite" class="bold">Longueur du fil RSS (limite) :</label></p>
<select id="limite" name="limit">
<option value="1">1</option>
<option value="5">5</option>
<option value="10" selected="selected">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</option>
<option value="30">30</option>
</select> <p><input type="submit" value="Générer le fil" name="generer" /></p></fieldset>
</form>
<?php
if ($_POST['generer']) { // Si l'on demande de générer l'URL (<=> si le bouton ''Génerer'' est cliqué)
$i=0;
for ($i=0;$i<=100;$i++) { // 100 est une marge arbitraire, nécessairement supérieure au nombre de tags définis pour le blog. Il s'agit en fait d'une boucle censée balayée l'ensemble des tags, d'où l'intérêt d'un nombre bien supérieur au nombre de tag (je n'ai pas de fonction donnant le nombre total de tags définis)
$tagnum = 'tag'.$i;
if ($_POST[$tagnum] != '') {
$str .= $_POST[$tagnum].',';
$strclean = substr($str,0,strlen($str)-1);
}
else { }
}
$urlgeneree = $_SERVER['HTTP_HOST'].'/blog/rss-meta.php?limit='.$_POST['limit'].'&key=tag&value='.$strclean;
?>
<?php // On reconstruit une chaine énumérant les tags choisit (ceci est accessoire et en rien nécessaire au fonctionnement du script, c'est vraiment "pour faire joli")
$arraytags = explode(',',$strclean);
for ($x=0;$x<count($arraytags);$x++) { // Cette boucle permet
if ($x == count($arraytags)-2) {
$chn .= '<strong>'.$arraytags[$x].'</strong> et ';
}
else { $chn .= '<strong>'.$arraytags[$x].'</strong>, '; }
}
$chnclean = substr($chn,0,strlen($chn)-2);
?>
<div>
<p>Tags choisis : <?php echo $chnclean; ?></p><!--> cette phrase peut être enlevée (elle suit la partie en PHP juste au dessus, elle-même accessoire)<-->
<p><br /><a href="http://<?php echo $urlgeneree; ?>" hreflang="rss">Abonnez-vous directement</a> ou copiez <label for="urlgeneree" class="bold">l'adresse suivante</label> dans votre agrégateur favoris :</p>
<p><br /><input id="urlgeneree" style="padding:3px;" onclick="select(this)" type="text" size="70" value="<?php echo 'http://'.$urlgeneree; ?>" /></p></div>
<?php
}
?>
</div>
IV. Activation, conclusion et perspective
Après avoir placé la page que vous venez de créer dans le dossier /share/related, allez activer son accès via le panneau d'administration du plugin.
Par souci de commodité, je vous conseille de placer votre fichier rss-meta.php dans le même dossier que votre fichier rss.php (souvent à la racine du blog). Le code que je vous propose ne fonctionne que dans le cas où rss-meta.php est placé à la racine du blog.
En vous rendant sur cette page, vous devriez voir un nuage de tags à côté desquels se trouve une case à cocher. Vous n'avez plus qu'à générer le fil et y souscrire. Pour le visiteur intéressé, ce système offre donc une plus grande marge de liberté au niveau de la gestion de l'information, et c'est tant mieux !
On notera cependant un inconvéniant inhérent au fait que l'URL soit variable : l'impossibilité de gérer ces nouveaux fils par des services tiers tel que FeedBurner.
Cette modification est quelque peu barbare, je le conçois. Malheureusement, elle reflète assez bien le type de modifications que j'apporte ici ou là dans mon blog. Néanmoins, je réaliserai un plugin intègre, évitant toutes ces manipulations fastidieuses. Créez un flux à partir des tags ''développement web'' et ''DotClear'', abonnez-vous y et comme ça vous serez tenu au courant de la sortie du plugin ! Quel meilleur destin pour cette fonction de flux RSS que de servir à sa propre fin ?
je narrive pas a retrouver ma place au classement



Réactions
Réagir