Table des matières

Astuces pour DotClear

Modifier "Lire la suite"

Dans le fichier list.php, chercher la ligne

<?php dcPostAbstract(); ?>

et la remplacer par :

<?php dcPostAbstract('%s','<p><a href="%s">Le texte que je veux</a></p>'); ?>

Si vous souhaitez en profiter pour appliquer un style différent de celui des liens courants, vous pouvez ajouter une classe dans la modification. Par exemple :

<?php dcPostAbstract('%s','<p class="suite"><a href="%s">La suite de l\'article</a></p>'); ?>

Vous pourrez ensuite donner des paramètres de style à .suite a dans la feuille de style de votre thème.

Inverser l'ordre des billets

Objet

Sur la page d'accueil, présenter les billets du plus ancien (en haut) au plus récent (en bas).

Mise en oeuvre

Au début de votre fichier template.php, dans la partie "body", ajouter ceci :

<?php if ($mode == 'home') {
    $news = $blog->getLastNews(dc_nb_post_per_page,$cat_id,'post_dt ASC');
    $news->setBlog($blog);
  } ?>

Il est possible de façon similaire de modifier l'ordre pour les modes 'cat' et 'month'.

Inverser l’ordre des commentaires et trackbacks

Objet

Lors de l’affichage des billets, afficher les commentaires comme les billets en page d’accueil, du plus récent au plus ancien.

Mise en œuvre

Dans le fichier post.php, chercher la ligne d’ouverture du traitement des trackbacks

<?php if ($trackbacks->isEmpty()) : /* Message si aucun trackback */ ?>

et modifier comme ceci

<?php $comments = $blog->getComments($post_id,'DESC'); /* ordre des commentaires et trackbacks */
$trackbacks = $comments->extractTrackbacks(); /* séparer les commentaires des trackbacks */
if ($trackbacks->isEmpty()) : /* Message si aucun trackback */ ?>

Pour n’impacter que les commentaires et pas les trackbacks, placer les deux lignes ajoutées ci-dessus avant

if ($comments->isEmpty()) : /* Message si aucun commentaire */

au lieu de l’ouverture du traitement des trackbacks. C’est prêt, servez sans attendre ;-)

Ouvrir les liens dans une autre fenêtre

Objet

Faire en sorte que les liens de la section "liens" (oui oui) s'ouvrent dans une nouvelle fenêtre.

Mise en oeuvre

L'astuce suivante a pour but d'afficher une case que l'utilisateur peut cocher si il souhaite que les liens exterieurs au site soient ouverts dans une autre fenêtre

Mettre ce qui suit dans un fichier scripts.js dans le repertoire de son theme :

// JavaScript targeters adapted from holovaty.com via padawan.info
function linksInNewWindow(a) {
var b=a?"site":"_self";
var c=document.links;
for(var i=0;i<c.length;i++) {if(c[i].href.search("site.com")==-1) c[i].target=b};
var date=new Date();
date.setTime(date.getTime()+(14*24*60*60*1000));
document.cookie=a?"newwin=true; expires="+date.toGMTString()+";":"newwin=false;";
}

Et mettre dans le fichier template.php :

<script type="text/javascript" src="http://chemin/vers/le/scripts.js" charset="ISO-8859-1"></script>

Dans l'entête du fichier, et :

<label for="linksnewwin">Ouvrir les liens dans une nouvelle fenêtre</label>
<input type="checkbox" onclick="linksInNewWindow(this.checked);" onkeypress="linksInNewWindow(this.checked);" id="linksnewwin" />

A l'endroit où l'on veut placer la boite à cocher

Supprimer la mention de l'auteur

Objet

Sur la liste des billets ou sur l'affichage d'un billet, ne pas faire apparaitre le nom de l'auteur. Utile pour éviter de surcharger l'affichage lorsque l'on est le seul auteur des billets d'un blog.

Mise en oeuvre

Dans le fichier list.php de votre thème ou du thème default s'il n'existe pas pour votre thème, chercher la ligne :

<p class="post-info"><?php dcPostAuthor(); ?>

,

et remplacer par :

<p class="post-info">
<!-- 
<?php dcPostAuthor(); ?>,
-->

puis répéter la même opération avec le fichier post.php de votre thème ou du thème default s'il n'existe pas pour votre thème.

Insérer un compte à rebours en jours jusqu'à une date donnée

Objet

Faire apparaître un compte à rebours jusqu'à une date donnée. Peut servir pour la sortie d'un film, un anniversaire particulier, …

Mise en oeuvre

Créer un fichier texte nommé countdown.php avec le contenu suivant :

<?php
 
function CountDownInDays($year, $month, $day) {
 
$newDate = mktime(0,0,0, $month, $day, $year);
$actDate = time();
 
$diffDate = ($newDate-$actDate);
$days = floor($diffDate / 24 / 60 / 60 );
 
 
return ($days + 1);
}
?>

Copier ce fichier dans le dossier contenant votre template (là ou se trouve le fichier template.php)

Dans le fichier template.php, là ou vous souhaitez faire apparaitre un compte à rebours, disons jusqu'au 13 mai 2005, insérez :

<?php include dirname(__FILE__).'/countdown.php'; ?>
<?php echo CountDownInDays(2005, 5, 13); ?>

Astuce rédigée par Tortue GT

N'afficher qu'une catégorie sur la page d'accueil

Objet

Faire en sorte de n'afficher que les billets appartenant à la catégorie de son choix en page d'accueil.

Mise en oeuvre

Donc admettons que j'ai fait des catégories diverses et variés mais je ne veux que dotclear m'affiche que la catégorie Annonces sur la page d'accueil (vous changerez annonce par le nom de votre catégorie phare faites gaffe au respect des majuscules)

tout d'abord vous devez avoir un home.php voici un très bon tutoriel sur comment en obtenir un : http://petit.dotclear.net/pages/2004/12/02/27-creer-une-page-daccueil-differente

maintenant que vous avez un fichier home.php editez le et remplacez le par ca :

<?php $news = $blog->getLastNews(20,'Annonces','post_dt DESC'); //20 est le nombre de post que vous 
//voulez qu'il affiche et Annonces le texte a remplacer par votre catégorie phare ...
 
 
while ($news->fetch()) : ?>
 
    <div class="post">
        <?php dcDayDate('<p class="day-date">%s</p>'); ?>
 
        <h2 id="p<?php dcPostID(); ?>" class="post-title"><a
        href="<?php dcPostURL(); ?>"><?php dcPostTitle(); ?></a></h2>
 
        <p class="post-info">Par <?php dcPostAuthor(); ?>,
        <?php dcPostDate(); ?> &agrave; <?php dcPostTime(); ?>
        <span>::</span> <a href="<?php dcPostCatURL(); ?>"><?php dcPostCatTitle(); ?></a>
        </p>
 
        <div class="post-content" <?php dcPostLang(); ?>>
            <?php dcPostAbstract('%s'); ?>
        </div>
 
        <p class="post-info-co"><a href="<?php dcPostURL(); ?>#co"
        title="commentaires pour : <?php dcPostTitle(); ?>"><?php
        dcPostNbComments('aucun commentaire','un commentaire','%s commentaires');
        ?></a>
        <span>::</span> <a href="<?php dcPostURL(); ?>#tb"
        title="trackbacks pour : <?php dcPostTitle(); ?>"><?php
        dcPostNbTrackbacks('aucun trackback','un trackback','%s trackbacks');
        ?></a></p>
    </div>
<?php endwhile; ?>

Exclure une catégorie de la page d'accueil

Objet

Faire en sorte que les billets appartenant à la catégorie de son choix n'apparaissent pas en page d'accueil.

Mise en oeuvre

Donc admettons que j'ai fait des catégories diverses et variés mais que je ne veux que dotclear m'affiche la catégorie Pensebete sur la page d'accueil (vous changerez bien entendu Pensebete par le nom de votre catégorie à éviter, faites gaffe au respect des majuscules)

tout d'abord vous devez avoir un home.php voici un tres bon tutoriel sur comment en obtenir un : http://petit.dotclear.net/pages/2004/12/02/27-creer-une-page-daccueil-differente

maintenant que vous avez un fichier home.php editez le et remplacez le par ça :

<?php 
    $request = $blog->SQL (" AND C.cat_libelle_url <> 'Pensebete' ", 'post_dt DESC', dc_nb_post_per_page);
    $news = $blog->con->select($request,'xblogpost'); 
    $news->setBlog($blog);
 
while ($news->fetch()) : ?>
 
    <div class="post">
        <?php dcDayDate('<p class="day-date">%s</p>'); ?>
 
        <h2 id="p<?php dcPostID(); ?>" class="post-title"><a
        href="<?php dcPostURL(); ?>"><?php dcPostTitle(); ?></a></h2>
 
        <p class="post-info">Par <?php dcPostAuthor(); ?>,
        <?php dcPostDate(); ?> &agrave; <?php dcPostTime(); ?>
        <span>::</span> <a href="<?php dcPostCatURL(); ?>"><?php dcPostCatTitle(); ?></a>
        </p>
 
        <div class="post-content" <?php dcPostLang(); ?>>
            <?php dcPostAbstract('%s'); ?>
        </div>
 
        <p class="post-info-co"><a href="<?php dcPostURL(); ?>#co"
        title="commentaires pour : <?php dcPostTitle(); ?>"><?php
        dcPostNbComments('aucun commentaire','un commentaire','%s commentaires');
        ?></a>
        <span>::</span> <a href="<?php dcPostURL(); ?>#tb"
        title="trackbacks pour : <?php dcPostTitle(); ?>"><?php
        dcPostNbTrackbacks('aucun trackback','un trackback','%s trackbacks');
        ?></a></p>
    </div>
<?php endwhile; ?>

Ouverture d'un lien dans une nouvelle fenêtre (en javascript)

<a href="http://votrelien.com" hreflang="fr" onclick="window.open(this.href,'_blank');return false;">Votre Lien</a>

Même résultat qu'un lien target="_blank" mais en gardant une compatibilité XHTML 1.0 Strict.

N'afficher que les billets de la langue par défaut à l'accueil

Afin de n'afficher que la langue par défaut à l'affichage initial du blog il suffit de remplacer dans le fichier prepend.php de votre theme ou du theme par defaut à la ligne 35 :

$lang = (!empty($_GET['l'])) ? $_GET['l'] : NULL;

par

$lang = (!empty($_GET['l'])) ? $_GET['l'] : dc_default_lang;

Enlever les "Aucun commentaire" ou "Aucun trackback" affichés sous chaque billet

La première chose à faire est de désactiver commentaires et/ou trackbacks dans les outils de l'interface d'admin en cliquant sur Configuration de DoctClear?. Il vous suffit de changer la valeur proposée dans "Permettre les commentaires" et/ou "Permettre les trackbacks".

Ensuite s'attaquer au code… Quelques fichiers sont à modifier : post.php, list.php et si le fichier est créé, home.php qui reprend les mêmes modifications que list.php.

post.php

si l'on veut enlever les trackbacks

<div id="trackbacks">
	<h3 id="tb">Trackbacks</h3>
	<?php if ($trackbacks->isEmpty()) : /* Message si aucune trackback */?>
		<p>Aucun trackback.</p>
	<?php endif; ?>
 
	<?php while ($trackbacks->fetch()) : /* Liste des trackbacks */
		// On met le numéro du trackback dans une variable
		$tb_num = $trackbacks->int_index+1;
	?>
		<p id="c<?php dcTBID(); ?>" class="comment-info">
		<span class="comment-number"><a href="#c<?php dcTBID(); ?>"><?php echo $tb_num; ?>.</a></span>
		Le <?php dcTBDate(); ?> à
		<?php dcTBTime(); ?>, de
		<strong><?php dcTBAuthor(); ?></strong></p>
 
		<?php /* on affiche le trackback */ ?>
		<blockquote>
		<?php dcTBContent(); ?>
		</blockquote>
	<?php endwhile; ?>
 
 
	<?php /*Le lien pour ajouter un trackback si ceux-ci sont autorisés*/ ?>
	<?php if (dcPostOpenTrackbacks() && dc_allow_trackbacks) : ?>
		<p>Pour faire un trackback sur ce billet :
		<?php echo dcPostTrackBackURI(); ?></p>
	<?php else: ?>
		<p>Les trackbacks pour ce billet sont fermés.</p>
	<?php endif; ?>
</div>

si l'on veut enlever les commentaires :

<div id="comments">
	<h3 id="co">Commentaires</h3>
	<?php if ($comments->isEmpty()) : /* Message si aucune commentaire */	?>
		<p>Aucun commentaire pour le moment.</p>
	<?php endif; ?>
 
	<?php while ($comments->fetch()) : /* Boucle de commentaires */
		// On met le numéro du commentaire dans une variable
		$co_num = $comments->int_index+1;
	?>
		<p id="c<?php dcCommentID(); ?>" class="comment-info">
		<span class="comment-number"><a href="#c<?php dcCommentID(); ?>"><?php echo $co_num; ?>.</a></span>
		Le <?php dcCommentDate(); ?> à
		<?php dcCommentTime(); ?>, par
		<strong><?php dcCommentAuthor(); ?></strong></p>
 
		<?php /* on affiche le commentaire */ ?>
		<blockquote>
		<?php dcCommentContent(); ?>
		</blockquote>
	<?php endwhile; ?>
 
	<h3>Ajouter un commentaire</h3>
	<?php if (dcPostOpenComments() && dc_allow_comments) : /* Si les commentaires sont permis */?>
		<?php if (dc_allow_comments) : /* Si les commentaires sont permis */?>
			<?php include dirname(__FILE__).'/form.php'; ?>
		<?php endif; ?>
	<?php else : ?>
		<p>Les commentaires pour ce billet sont fermés.</p>
	<?php endif; ?>
</div>

list.php

si l'on veut enlever les trackbacks

<code php><span>::</span> <a href="<?php dcPostURL(); ?>#tb"
title="trackbacks pour : <?php dcPostTitle(); ?>"><?php
dcPostNbTrackbacks('aucun trackback','un trackback','%s trackbacks');
?></a></code>

si l'on veut enlever les commentaires :

<a href="<?php dcPostURL(); ?>#co"
	title="commentaires pour : <?php dcPostTitle(); ?>"><?php
	dcPostNbComments('aucun commentaire','un commentaire','%s commentaires');
	?></a>

Remplacer des titres en images

Suite à une recherche sur le web et une demande auprès d'Alex, je vous propose de découvrir les étapes à suivre pour mettre en place le remplacement des titres en images. Je tiens à rappeler que cela fut mis en place et intégré avec intelligence au sein du thème Tutti Frutti.

1. Placer dans le fichier prepend.php dans le répertoire du thème utilisé ou, s'il n'est pas présent dans celui-ci, dans le répertoire du thème default, juste avant la balise ?>, les 2 fonctions suivantes :

function myWordWrap($txt,$font,$size,$width)
 
{
 
// Définition du nombre de ligne de l'image
 
$nbre_ligne = 1;
 
   /*
       word-wrapper.  gets bounding box sizes for each word in a string, then 
       strings words together up to desired width. calls strpos and 
       imagettfbbox only once per word - so very fast. 
       this version reconcatenates the words with a <br> character where 
       the line break should be.
   */
 
   $txt.=" "; // guaranteed to find end of line
   $spaces=array();
   $wids=array();
   $i=0;
 
   while(true)
 
   {
 
       $j=strpos(substr($txt,$i)," ");
 
       if(!($j===false))
 
       {
 
           $spaces[]=$j+$i;
 
@           $bbox=imagettfbbox($size,0,$font,substr($txt,$i,$j+1));
 
           $left=($bbox[0]>$bbox[6])?$bbox[6]:$bbox[0];
           $right=($bbox[2]>$bbox[4])?$bbox[2]:$bbox[4];
           $wids[]=$right-$left;
           $i=$j+$i+1;
 
       }
 
       else    break;
 
   }
 
   $lastspace=-1;
   $cum=0;
   $t2="";
 
   for($i=0;$i<count($spaces);$i++)
 
   {
 
       if((($cum>0)&&($cum+$wids[$i])>$width)) // time for a line break
 
       {
 
           $t2.="\n";
           $nbre_ligne++;
           $cum=0;
           $i--;
 
       }
 
       else
 
       {
 
           // we'll always get at least one word (even if too wide) thanks to
           // ($cum>0) test above
 
           $t2.=substr($txt,$lastspace+1,$spaces[$i]-$lastspace);
           $cum+=$wids[$i];
           $lastspace=$spaces[$i];
 
       }
   }
 
   $image_created = array("$t2","$nbre_ligne");
   return $image_created;
 
}
 
 
function create_title($titre,$couleur_texte,$couleur_fond,$taille_texte,$chemin_police)
 
                {         
 
//              echo "Chemin police : $chemin_police";
 
 
//Définition de la largeur maximum de l'image générée
 
                $width_max = 500;
 
 
//Définition du nom de l'image en fonction du titre et des attributs passés dans la fonction
 
                //$titre_affiche = strtoupper($titre);
 
                $titre_affiche = $titre;
                $nom_image = md5($titre.$chemin_police.$taille_texte.$couleur_fond.$couleur_texte);
                $chemin_repertoire = $_SERVER['DOCUMENT_ROOT']."/".substr($GLOBALS['img_path'],1)."titres";
 
 
 
if(!file_exists($chemin_repertoire))
 
                {
 
@            mkdir($chemin_repertoire,0777) or die("Impossible de créer le répertoire d'image titre '$chemin_repertoire'");
 
                }
 
$chemin_image = $chemin_repertoire."/".$nom_image.".png";               
 
if(!file_exists($chemin_image))
 
                               {
 
                // Test de la taille de l'image et définition du nombre de ligne
 
                               $tableau = myWordWrap($titre_affiche,$chemin_police,$taille_texte,$width_max);
 
                               $titre_image = $tableau[0];
                               $nbre_ligne = $tableau[1];
 
 
                // Calcul de la taille de l'image
 
@                            $taille_image = imagettfbbox($taille_texte,0,$chemin_police,"$titre_image");
                               $taille_image_largeur = (abs($taille_image[0])+abs($taille_image[2])+5);
                               if($taille_image_largeur > $width_max) $taille_image_largeur = $width_max;
                               $taille_image_hauteur = (abs($taille_image[6])+abs($taille_image[7])+2) * $nbre_ligne;
 
 
                // Création du cadre d'image
 
                               $img = imagecreate($taille_image_largeur,$taille_image_hauteur);
 
                // Définition de la couleur du texte
 
                               $couleur_texte = hexdec(str_replace('#','',$couleur_texte));
                               $couleur_texte = imagecolorallocate($img,($couleur_texte & 0xFF0000) >> 16,($couleur_texte & 0x00FF00) >> 8,($couleur_texte & 0x0000FF));
 
 
                // Définition de la couleur du fond
 
                               $couleur_fond = hexdec(str_replace('#','',$couleur_fond));
                               $couleur_fond = imagecolorallocate($img,($couleur_fond & 0xFF0000) >> 16,($couleur_fond & 0x00FF00) >> 8,($couleur_fond & 0x0000FF));
 
 
                // Remplissage du fond de l'image avec la couleur définie avant
 
                               imagefill($img,0,0,$couleur_fond);
 
 
                // Ajout du texte, affichage ligne par ligne si le texte compporte plus d'une ligne
 
                               if($nbre_ligne > 1)
 
                                               {
 
                                               $titre_image = explode("\n",$titre_image);
                                               $i = 0;
 
                                               while($i != $nbre_ligne)
                                                               {
                                               imagettftext($img,$taille_texte,0,0,$taille_texte + (20*$i),$couleur_texte,$chemin_police,$titre_image[$i]);
                                                               $i++;
                                                               }
                                               }
                               else
                                               {
@                                            imagettftext($img,$taille_texte,0,0,$taille_texte,$couleur_texte,$chemin_police,"$titre_image");
                                               }
 
 
// Création de l'image et écriture sur le serveur
 
                               @imagepng($img,$chemin_image) or die ("Impossible d'écrire dans le répertoire d'images...");
                               imagedestroy($img);
                               }
 
$chemin_image = $GLOBALS['img_path']."titres/".$nom_image.".png";
 
if(file_exists($_SERVER['DOCUMENT_ROOT'].$chemin_image))
 
                {
                $taille_image = getimagesize($_SERVER['DOCUMENT_ROOT'].$chemin_image);
                $taille_image_largeur = $taille_image[0];
                $taille_image_hauteur = $taille_image[1];
 
    echo "<span style=\"display:none\">$titre</span><img src=\"".$chemin_image."\" style=\"border:0px;\" alt=\"$titre\" />"; //width:".$taille_image_largeur."px;height:".$taille_image_hauteur."px;\" /></span>";
                }
else
                {
                echo $titre;
                }
}

2. Choisir la police (exemple : ta_police.ttf) et la copier dans le répertoire du thème utilisé.

3. Dans le fichier list.php du thème utilisé ou dans celui du thème default, remplacer la ligne 31 (normalement) :

href="<?php dcPostURL(); ?>"><?php dcPostTitle(); ?></a></h2>

Par :

href="<?php dcPostURL(); ?>"><?php create_title($GLOBALS['news']->f('post_titre'),"#ccccccc","#FFFFFF","12",$_SERVER['DOCUMENT_ROOT'].$GLOBALS['theme_uri'].$GLOBALS['__theme']."/ta_police.ttf");?></a></h2>

4. Dans le fichier post.php du thème utilisé ou dans celui de default, remplacer ligne 25 (normalement) :

<h2 class="post-title"><?php dcPostTitle(); ?></h2>

Par :

<h2 class="post-title"><?php create_title($GLOBALS['news']->f('post_titre'),"#cccccc","#FFFFFF","12",$_SERVER['DOCUMENT_ROOT'].$GLOBALS['theme_uri'].$GLOBALS['__theme']."/ta_police.ttf"); ?></h2>

5. Utiliser le code ci-dessous pour appeler une image à la place d'un titre dans ton template.php

<?php create_title("Ton Texte blablabla","#cccccc","#ffffff","12",$_SERVER['DOCUMENT_ROOT'].$GLOBALS['theme_uri'].$GLOBALS['__theme']."/ta_police.ttf");?>

Avec comme valeurs dans les exemples ci-dessus #cccccc la couleur du texte, #FFFFFF la couleur de fond, 12 la taille du texte, et ensuite le chemin de la police de caractères (nommé ta_police.ttf ci-dessus).

6. Admirer le travail !

Thème multilingue

Le thème multilingue est une adaptation du thème par défaut de la version 1.2 : identique, à ceci près qu'il utilise le mécanisme interne de DotClear pour la localisation. Il ne contient que deux langues, l'anglais et le français, mais il est possible d'en ajouter. Le thème s'adaptera alors à la langue définie dans la configuration de DotClear. Pour l'utiliser, il faut remplacer le thème default/ par celui-ci, de cette façon, tous les thèmes ne contenant que des feuilles de style pourront immédiatement en profiter.

Le fichier prepend.php contient une ligne qui, si elle est décommentée, permet au thème de s'adapter à la langue demandée par le visiteur (depuis le menu des langues présent si vous avez écrit des articles dans plusieurs langues.)

On constate aisément que ce template est beaucoup plus lourd à gérer pour qui voudrait le modifier, ce qui explique que malgré la présence du mécanisme de localisation dans Dotclear 1.2, le thème fourni avec l'application reste localisé dans une seule langue.

Créer des sous-catégories

Code à copier et mettre dans le prepend.php de votre thème.

/**
 
 @Function dcLeveledMenu
 
 Cette fonction affiche la liste des catégories, ordonnées par 
 leur description. La liste générée est une liste non ordonnée (<ul>), il est donc
 très simple de la mettre en forme par la suite.
 
 @param array  filter tableau de catégories (dans leurs formes Url) à ne pas afficher (array())
 @param string  block Chaine de substitution pour pour la liste ('<ul>%s</ul>')
 @param string  item  Chaine de substitution pour un élément ('<li>%s</li>')
 @param string  sub_block Chaine de substitution pour la sous-liste ('<li><ul>%s</ul></li>')
 @param string  sub_item  Chaine de substitution pour un sous-élément ('<li>%s</li>')
 @param string  indicateur_o Indicateur d'un sous menu-ouvert ('[-] ')
 @param string  indicateur_f Indicateur d'un sous menu-fermé ('[+] ')
 */
function dcLeveledMenu ($filter=array(),$block='<ul id="menus">%s</ul>',$item='<li style="border: none;">%s</li>', $sub_block='<li><ul>%s</ul></li>',$sub_item='<li> %s</li>',$indicateur_o = '[-] ', $indicateur_f = '[+] ') {
global $rs_cat, $cat_id, $lang, $blog, $mode, $news;
 
 // redéfinition de cat_id dans le cas du mode post (met en gras la catégorie active dans le cadre d'un billet)
 if($mode == "post") $cat_id = $news->f('cat_libelle_url');
 
 // Récupération du tableau des catégories à exclure
 if (is_string($filter) && strlen($filter) > 0) $filter = array($filter);
 
 // Prise en compte de la langue des billets
 $comp_url = '';
  if ($lang) {
  $comp_url = $lang.'/';
 }
 //Construction de l'arboressence
 $tab_arbo = array();
 $tab_parents =array();
 
 // Si il existe des catégories
 if (!$rs_cat->isEmpty()) {
  // Parcours des catégories
  while (!$rs_cat->EOF()) {
   // Si la catégorie n'est pas à exclure 
   if (!in_array($rs_cat->f('cat_libelle_url'),$filter)) {
    // Copie de la description, de l'url et du titre
    $desc = $rs_cat->f('cat_desc');
    $url = $rs_cat->f('cat_libelle_url');
    $libelle = $rs_cat->f('cat_libelle');
    // Si la description n'est pas renseignée, c'est une catégorie racine
    if($desc=='') $desc='!!racine!!';
    // Copie dans le tableau temporaire pour la suite
    $tab_arbo[$desc][$url] = $libelle;
   }
   // Enregistrement suivant
   $rs_cat->moveNext();
  }
  // place le curseur au premier enregistrement
  $rs_cat->moveStart();
  // Récupération dans un tableau de seules les catégories racines (permer de garder l'ordredes catégories pour la suite)
  $tab_parents = array_keys($tab_arbo);
 
  // Construction de la liste 
  $res = '';  
  // Parcours du tableau
  while(list($key, $value) = each($tab_arbo['!!racine!!'])){
   $new_value = $value;
   // Si catégorie active
   if($cat_id == $value) {
    // Si il y a des sous catégories, place l'indicateur ouvert
    if(is_array($tab_arbo[$value])) $new_value = $indicateur_o . $value;
    // Création du lien 
    $lien = '<a href="'.sprintf($blog->front_url['cat'],$comp_url.$key).'">'.$new_value.'</a>';
    // Met le lien en gras
    $tmp = sprintf("<strong>%s</strong>",$lien);
    //Met le lien en forme
    $res .= sprintf($item,$lien);
   }
   // Si pas catégorie active
   else{
    // Si il y a des sous catégories et une des sous catégories est la catégorie active, place l'indicateur ouvert 
    if(is_array($tab_arbo[$value])&& array_key_exists($cat_id,$tab_arbo[$value])) $new_value = $indicateur_o . $value;
    // Sinon si il y a des sous-catégories (non actives) place l'indicateur fermé
    else if (is_array($tab_arbo[$value])) $new_value = $indicateur_f . $value;
    // Crée le lien
    $lien = '<a href="'.sprintf($blog->front_url['cat'],$comp_url.$key).'">'.$new_value.'</a>';
    // Met le lien en forme
    $res .= sprintf($item,$lien);
   }
   // Si il y a des sous-catégories et la catégorie parent est active ou une sous catégorie est active (= sous menu déplié)
   if(is_array($tab_arbo[$value]) && ($cat_id == $value || array_key_exists($cat_id,$tab_arbo[$value]))){
    $sub_res = '';
    // Parcours le sous-tableau
    while(list($k,$v) = each($tab_arbo[$value])){
     // Crée le lien avec > devant
     $lien = '<a href="'.
      sprintf($blog->front_url['cat'],$comp_url.$k).
      '"> &gt; '.$v.'</a>'; // &gt; spécifique à passemontagne !!
     // Si sous-catégorie active, crée le lien avec >> devant
     if($cat_id == $k){
      $lien = '<a href="'.
      sprintf($blog->front_url['cat'],$comp_url.$k).
      '"> &gt;&gt; '.$v.'</a>'; // &gt;&gt; spécifique à passemontagne !!
      // Met le lien en forme
      $sub_res .= sprintf($sub_item,$lien);
     }
     else
      // Met le lien en forme
      $sub_res .= sprintf($sub_item,$lien);
    }
    // Met le block de sous-catégories en forme
    $res .= sprintf($sub_block, $sub_res);
   } 
  }
  // Met le block du menu en forme et l'écrit
  printf($block,$res);
 }  
}

Pour inclure une catégorie dans une autre, mettre le nom de la catégorie parent dans la description de la catégorie enfant (une catégorie parent n'a pas de description). Ensuite il reste à appeler à appeler dcLeveledMenu dans le template.php à la place de dcCatList.

C'est tout !!

PS. Il y a une grosse copie de related. Merci pour l'original.