[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / aveline / aveline_fonctions.php
diff --git a/www/plugins/auto/aveline/aveline_fonctions.php b/www/plugins/auto/aveline/aveline_fonctions.php
new file mode 100644 (file)
index 0000000..b72099f
--- /dev/null
@@ -0,0 +1,620 @@
+<?php\r
+\r
+if (!defined("_ECRIRE_INC_VERSION")) return;\r
+\r
+// Filtre pour afficher les statistiques d'un mot-clé\r
+// Code inspiré de la fonction presenter_groupe_mots_boucle dans ecrire/inc/grouper_mots.php\r
+function filtre_statistiques_mot_dist($id_mot){\r
+       include_spip('base/abstract_sql');\r
+       $texte_lie = array();\r
+       $id_mot = intval($id_mot);\r
+       \r
+       $na = sql_countsel('spip_mots_articles',"id_mot=$id_mot");\r
+       if ($na == 1)\r
+               $texte_lie[] = _T('info_1_article');\r
+       else if ($na > 1)\r
+               $texte_lie[] = $na." "._T('info_articles_02');\r
+\r
+       $nb = sql_countsel('spip_mots_breves',"id_mot=$id_mot");\r
+       if ($nb == 1)\r
+               $texte_lie[] = _T('info_1_breve');\r
+       else if ($nb > 1)\r
+               $texte_lie[] = $nb." "._T('info_breves_03');\r
+\r
+       $ns = sql_countsel('spip_mots_syndic',"id_mot=$id_mot");\r
+       if ($ns == 1)\r
+               $texte_lie[] = _T('info_1_site');\r
+       else if ($ns > 1)\r
+               $texte_lie[] = $ns." "._T('info_sites');\r
+\r
+       $nr = sql_countsel('spip_mots_rubriques',"id_mot=$id_mot");\r
+       if ($nr == 1)\r
+               $texte_lie[] = _T('info_une_rubrique_02');\r
+       else if ($nr > 1)\r
+               $texte_lie[] = $nr." "._T('info_rubriques_02');\r
+\r
+       $texte_lie = pipeline('afficher_nombre_objets_associes_a',array('args'=>array('objet'=>'mot','id_objet'=>$id_mot),'data'=>$texte_lie));\r
+       $texte_lie = join($texte_lie,", ");\r
+       return $texte_lie;\r
+}\r
+\r
+// Critère compteur_publie\r
+// Provient de http://www.spip-contrib.net/Classer-les-articles-par-nombre-de-commentaires\r
+\r
+function critere_compteur_publie($idb, &$boucles, $crit){\r
+ $op='';\r
+ $boucle = &$boucles[$idb];\r
+ $params = $crit->param;\r
+ $type = array_shift($params);\r
+ $type = $type[0]->texte;\r
+ if(preg_match(',^(\w+)([<>=])([0-9]+)$,',$type,$r)){\r
+     $type=$r[1];\r
+     $op=$r[2];\r
+     $op_val=$r[3];\r
+ }\r
+ $type_id = 'compt.id_'.$type;\r
+ $type_requete = $boucle->type_requete;\r
+ $id_table = $boucle->id_table . '.' . $boucle->primary;\r
+ $boucle->select[]= 'COUNT('.$type_id.') AS compteur_'.$type;\r
+ $boucle->from['compt']="spip_".$type;\r
+ $boucle->from_type['compt']= "LEFT";\r
+ // On passe par cette jointure pour que les articles avec 0 commentaires soient comptés\r
+ // Merci notation !\r
+ $boucle->join["compt"]= array("'$boucle->id_table'","'$boucle->primary'","'$boucle->primary'","'compt.statut='.sql_quote('publie')");\r
+ $boucle->group[]=$id_table;\r
+ if ($op)\r
+     $boucle->having[]= array("'".$op."'", "'compteur_".$type."'",$op_val);\r
+} \r
+\r
+// On préfixe avec AVELINE pour éviter conflit avec d'autres plugins\r
+// comme afficher_objet qui définit sont propre #COMPTEUR_ARTICLES\r
+\r
+function balise_AVELINE_COMPTEUR_FORUM_dist($p) {\r
+       $p->code = '$Pile[$SP][\'compteur_forum\']';\r
+       $p->interdire_scripts = false;\r
+       return $p;\r
+}\r
+\r
+function balise_AVELINE_COMPTEUR_ARTICLES_dist($p) {\r
+       $p->code = '$Pile[$SP][\'compteur_articles\']';\r
+       $p->interdire_scripts = false;\r
+       return $p;\r
+}\r
+\r
+// Critère archives pour afficher uniquement les objets d'une date donnée, par exemple en passant à l'URL ?archives=2010-02\r
+// Repris du plugin minical\r
+// Adapté pour gérer les évènements en cours\r
+function critere_archives($idb, &$boucles, $crit, $var_date = 'archives') {\r
+       $boucle = &$boucles[$idb];\r
+       if ($boucle->id_table == 'evenements') {\r
+               $boucle->where[] =\r
+               array("'AND'",\r
+                       array("'<='", "'date_debut'", "sql_quote(archives_debut(\$Pile[0]['".$var_date."']))"),\r
+                       array("'>='", "'date_fin'", "sql_quote(archives_fin(\$Pile[0]['".$var_date."']))"),\r
+               );\r
+       } else {\r
+               $champ_date = "'" . $boucle->id_table ."." .$GLOBALS['table_date'][$boucle->type_requete] . "'";\r
+               $boucle->where[] = array(\r
+                       'REGEXP',\r
+                       $champ_date, \r
+                       "sql_quote(('^' . interdire_scripts(entites_html(\$Pile[0]['".$var_date."']))))"\r
+               );\r
+       }\r
+}\r
+\r
+// Tester si le critère archives est de la forme AAAA, AAAA-MM ou AAAA-MM-JJ\r
+function archives_debut($date) {\r
+       if (!$date or $date=='tout')\r
+               return '2038-01-19 23:59:59';\r
+       switch (count(explode('-',$date))) {\r
+               case 1:\r
+                       return date('Y-12-31 23:59:59', strtotime($date));\r
+                       break;\r
+               case 2:\r
+                       return date('Y-m-31 23:59:59', strtotime($date));\r
+                       break;\r
+               case 3:\r
+                       return date('Y-m-d 23:59:59', strtotime($date));\r
+                       break;\r
+       }\r
+}\r
+function archives_fin($date) {\r
+       if (!$date or $date=='tout')\r
+               return '1970-01-01 00:00:00';\r
+       switch (count(explode('-',$date))) {\r
+               case 1:\r
+                       return date('Y-01-01 00:00:00', strtotime($date));\r
+                       break;\r
+               case 2:\r
+                       return date('Y-m-01 00:00:00', strtotime($date));\r
+                       break;\r
+               case 3:\r
+                       return date('Y-m-d 00:00:00', strtotime($date));\r
+                       break;\r
+       }\r
+}\r
+\r
+// Balise #ME\r
+// Source : http://www.spip-contrib.net/me-Moi-and-myself\r
+\r
+/***\r
+ * (c)James 2006, Licence GNU/GPL\r
+ * |me compare un id_auteur, par exemple,\r
+ * d'une boucle FORUMS avec les auteurs d'un article\r
+ * et renvoie la valeur booleenne true (vrai) si on trouve\r
+ *  une correspondance\r
+ * utilisation: \r
+ * <div id="forum#ID_FORUM"[(#ID_ARTICLE|me{#ID_AUTEUR}|?{' ', ''})class="me"]>\r
+ ***/\r
+function me($id_article, $id_auteur, $sioui = true, $sinon = false) {\r
+       static $deja = false;\r
+       static $auteurs = array();\r
+       if(!$deja) {\r
+               $r = spip_query("SELECT id_auteur\r
+                       FROM spip_auteurs_articles\r
+                       WHERE id_article=$id_article");\r
+               while($row = spip_fetch_array($r))\r
+                       $auteurs[] = intval($row['id_auteur']);\r
+               $deja = true;\r
+       }\r
+       return in_array($id_auteur, $auteurs)?$sioui:$sinon;\r
+}\r
+\r
+function balise_ME($p){\r
+       $p->code = "me(".\r
+               champ_sql('id_article', $p).', '.\r
+               champ_sql('id_auteur', $p).', '.\r
+               "'me', '')";\r
+       return $p;\r
+}\r
+\r
+// #AVELINE_PAGINATION\r
+// S'appelle dans une noisette ainsi [<p class="pagination">(#AVELINE_PAGINATION{'debut'})</p>] ou [<p class="pagination">(#AVELINE_PAGINATION{'fin'})</p>]\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/pagination.yaml'\r
+\r
+function balise_AVELINE_PAGINATION_dist($p) {\r
+       $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];\r
+\r
+       $pos = interprete_argument_balise(1,$p);\r
+       \r
+       $connect = $p->boucles[$b]->sql_serveur;\r
+       $pas = $p->boucles[$b]->total_parties;\r
+       $f_pagination = chercher_filtre('pagination');\r
+       $type = $p->boucles[$b]->modificateur['debut_nom'];\r
+       $modif = ($type[0]!=="'") ? "'debut'.$type"\r
+         : ("'debut" .substr($type,1));\r
+       \r
+       if ($pos=="'debut'")\r
+               $p->code = "(\$Pile[0]['selection']=='pagination' && (\$Pile[0]['position_pagination']=='debut' || \$Pile[0]['position_pagination']=='deux')) ? ".sprintf(CODE_PAGINATION, $f_pagination,$b, $type, $modif, $pas, true, "\$Pile[0]['style_pagination']", _q($connect), '')." : ''";\r
+       else\r
+               $p->code = "(\$Pile[0]['selection']=='pagination' && (\$Pile[0]['position_pagination']=='fin' || \$Pile[0]['position_pagination']=='deux')) ? ".sprintf(CODE_PAGINATION, $f_pagination,$b, $type, $modif, $pas, true, "\$Pile[0]['style_pagination']", _q($connect), '')." : ''";\r
+       return $p;\r
+}\r
+\r
+// Critère aveline_pagination\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/pagination.yaml'\r
+// Ajouter {aveline_pagination} à la boucle\r
+\r
+function critere_aveline_pagination_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       // definition de la taille de la page\r
+       $pas = "((\$Pile[0]['selection']=='pagination') ? \$Pile[0]['pas_pagination'] : ((\$Pile[0]['selection']=='limite') ? \$Pile[0]['limite'] : 1000000))";\r
+       // On ajoute id_noisette à la variable de pagination\r
+       $type = !isset($crit->param[0][1]) ? "'$idb'.'_'.\$Pile[0]['id_noisette']" : calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucle->id_parent);\r
+       $debut = ($type[0]!=="'") ? "'debut'.$type" \r
+         : ("'debut" .substr($type,1));\r
+       \r
+       $boucle->modificateur['debut_nom'] = $type;\r
+       $partie =\r
+                // tester si le numero de page demande est de la forme '@yyy'\r
+                'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n"\r
+               ."\tif(substr(\$debut_boucle,0,1)=='@'){\n"\r
+               ."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$result,'._q($boucle->sql_serveur).');'."\n"\r
+               ."\t\t".'if (!sql_seek($result,0,'._q($boucle->sql_serveur).")){\n"\r
+               ."\t\t\t".'@sql_free($result,'._q($boucle->sql_serveur).");\n"\r
+               ."\t\t\t".'$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect);'."\n"\r
+               ."\t\t}\n"\r
+               ."\t}\n"\r
+               ."\t".'$debut_boucle = intval($debut_boucle)';\r
+\r
+\r
+       $boucle->total_parties = $pas;\r
+       calculer_parties($boucles, $idb, $partie, 'p+');\r
+       // ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id\r
+       // sauf si pas de primaire, ou si primaire composee\r
+       // dans ce cas, on ne sait pas gerer une pagination indirecte\r
+       $t = $boucle->id_table . '.' . $boucle->primary;\r
+       if ($boucle->primary\r
+               AND !preg_match('/[,\s]/',$boucle->primary)\r
+               AND !in_array($t, $boucle->select))\r
+         $boucle->select[]= $t;\r
+}\r
+\r
+// Si le plugin notation n'est pas actif, on définit un critère {notation} ne faisant rien\r
+// pour ne pas avoir d'erreur avec les boucles appelant ce critère\r
+// on définit également moyenne (égal alors à id) \r
+if (!defined('_DIR_PLUGIN_NOTATION')) {\r
+       function critere_notation_dist($idb, &$boucles, $crit){\r
+               $boucle = &$boucles[$idb];\r
+               $table = $boucle->id_table;\r
+               $id = $boucle->primary;\r
+               $boucle->select[]= "$table.$id AS moyenne";\r
+       }\r
+}\r
+\r
+\r
+// #AVELINE_CHOIX_TRI\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/choix_tri-objet.yaml'\r
+// Appel : #AVELINE_CHOIX_TRI{'objet','debut_ou_fin'}\r
+// S'utilise en conjonction avec le critère tri de Bonux\r
+// Les possibilités de tri pour chaque objet sont définis directement dans le code de la balise\r
+// pour récupérer les variables d'environnement adéquates.\r
+\r
+function balise_AVELINE_CHOIX_TRI_dist($p) {\r
+       $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];\r
+\r
+       // s'il n'y a pas de nom de boucle, on ne peut pas trier\r
+       if ($b === '') {\r
+               erreur_squelette(\r
+                       _T('zbug_champ_hors_boucle',\r
+                               array('champ' => '#TRI')\r
+                       ), $p->id_boucle);\r
+               $p->code = "''";\r
+               return $p;\r
+       }\r
+       $boucle = $p->boucles[$b];\r
+\r
+       // s'il n'y a pas de tri_champ, c'est qu'on se trouve\r
+       // dans un boucle recursive ou qu'on a oublie le critere {tri}\r
+       if (!isset($boucle->modificateur['tri_champ'])) {\r
+               erreur_squelette(\r
+                       _T('zbug_tri_sans_critere',\r
+                               array('champ' => '#TRI')\r
+                       ), $p->id_boucle);\r
+               $p->code = "''";\r
+               return $p;\r
+       }\r
+\r
+       $suffixe = $boucle->modificateur['tri_nom'];\r
+       $objet = interprete_argument_balise(1,$p);\r
+       $pos = interprete_argument_balise(2,$p);\r
+       $tri_actuel = $boucle->modificateur['tri_champ'];\r
+       $sens_actuel = $boucle->modificateur['tri_sens'];\r
+       \r
+       // Définir les choix possibles\r
+       $choix = "array()";\r
+       if ($objet == "'article'")\r
+               $choix = "array(\r
+                       array('affiche' => \$Pile['0']['choix_tri_titre'], 'tri' => 'titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_titre')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_rang'], 'tri' => 'num titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_rang')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_popularite'], 'tri' => 'popularite', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_populaires')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_date'], 'tri' => 'date', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_recents')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_anciens'], 'tri' => 'date', 'sens' => 1, 'libelle' => _T('avelinepublic:les_plus_anciens')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_date_modif'], 'tri' => 'date_modif', 'sens' => -1, 'libelle' => _T('avelinepublic:modifies_recemment')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_commentes'], 'tri' => 'compteur_forum', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_commentes')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_visistes'], 'tri' => 'visites', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_visites')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_note'], 'tri' => 'moyenne', 'sens' => -1, 'libelle' => _T('avelinepublic:les_mieux_notes')),\r
+                       array('affiche' => \$Pile['0']['recherche'], 'tri' => 'points', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_pertinents'))\r
+               )";\r
+       if ($objet == "'breve'")\r
+               $choix = "array(\r
+                       array('affiche' => \$Pile['0']['choix_tri_titre'], 'tri' => 'titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_titre')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_rang'], 'tri' => 'num titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_rang')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_date'], 'tri' => 'date_heure', 'sens' => -1, 'libelle' => _T('avelinepublic:b_les_plus_recentes')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_anciens'], 'tri' => 'date_heure', 'sens' => 1, 'libelle' => _T('avelinepublic:b_les_plus_anciennes')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_commentes'], 'tri' => 'compteur_forum', 'sens' => -1, 'libelle' => _T('avelinepublic:b_les_plus_commentees')),\r
+                       array('affiche' => \$Pile['0']['recherche'], 'tri' => 'points', 'sens' => -1, 'libelle' => _T('avelinepublic:b_les_plus_pertinents'))\r
+               )";\r
+       if ($objet == "'auteur'")\r
+               $choix = "array(\r
+                       array('affiche' => \$Pile['0']['choix_tri_nom'], 'tri' => 'nom', 'sens' => 1, 'libelle' => _T('avelinepublic:par_nom')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_nb_articles'], 'tri' => 'compteur_articles', 'sens' => -1, 'libelle' => _T('avelinepublic:par_nb_articles')),\r
+                       array('affiche' => \$Pile['0']['recherche'], 'tri' => 'points', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_pertinentes'))\r
+               )";\r
+       if ($objet == "'rubrique'")\r
+               $choix = "array(\r
+                       array('affiche' => \$Pile['0']['choix_tri_titre'], 'tri' => 'titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_titre')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_commentes'], 'tri' => 'compteur_forum', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_commentes')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_date_heure'], 'tri' => 'date_heure', 'sens' => -1, 'libelle' => _T('avelinepublic:modifiees_recemment')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_note'], 'tri' => 'moyenne', 'sens' => -1, 'libelle' => _T('avelinepublic:les_mieux_notes')),\r
+                       array('affiche' => \$Pile['0']['recherche'], 'tri' => 'points', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_pertinents'))\r
+               )";\r
+       if ($objet == "'evenement'")\r
+               $choix = "array(\r
+                       array('affiche' => \$Pile['0']['choix_tri_date'], 'tri' => 'date_debut', 'sens' => -1, 'libelle' => _T('avelinepublic:par_date_decroissante')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_anciens'], 'tri' => 'date_debut', 'sens' => 1, 'libelle' => _T('avelinepublic:par_date_croissante')),\r
+                       array('affiche' => \$Pile['0']['choix_tri_titre'], 'tri' => 'titre', 'sens' => 1, 'libelle' => _T('avelinepublic:par_titre')),\r
+                       array('affiche' => \$Pile['0']['recherche'], 'tri' => 'points', 'sens' => -1, 'libelle' => _T('avelinepublic:les_plus_pertinents'))\r
+               )";\r
+       \r
+       $p->code = "calculer_balise_AVELINE_CHOIX_TRI($suffixe,$choix,$pos,$tri_actuel,$sens_actuel,\$Pile[0]['choix_tri'],\$Pile[0]['position_choix_tri'])";\r
+       return $p;\r
+}\r
+\r
+function calculer_balise_AVELINE_CHOIX_TRI($suffixe,$choix,$pos,$tri_actuel,$sens_actuel,$choix_tri,$position_choix_tri) {\r
+       // Doit-on afficher les tri perso ?\r
+       if (!$choix_tri || ($pos == 'debut' && $position_choix_tri == 'fin') || ($pos == 'fin' && $position_choix_tri == 'debut'))\r
+               return '';\r
+       \r
+       $retour = array();\r
+       foreach($choix as $c) {\r
+               // Cas où on demande la note moyenne et que notation n'est pas activé\r
+               if ($c['tri'] == 'moyenne' && !defined('_DIR_PLUGIN_NOTATION'))\r
+                       $c['affiche'] = '';\r
+               if ($c['affiche']) {\r
+                       $lien = parametre_url(self(),'tri'.$suffixe,$c['tri']);\r
+                       $lien = parametre_url($lien,'sens'.$suffixe,$c['sens']);\r
+                       $retour[] = lien_ou_expose($lien,$c['libelle'],$c['tri']==$tri_actuel && $c['sens']==$sens_actuel);\r
+               }\r
+       }\r
+       return implode(' <span class="sep separateur">|</span> ',$retour);\r
+}\r
+\r
+// Surcharge du critère tri pour ajouter id_noisette aux variables de personnalisation du tri\r
+/**\r
+ * {tri [champ_par_defaut][,sens_par_defaut][,nom_variable]}\r
+ * champ_par_defaut : un champ de la table sql\r
+ * sens_par_defaut : -1 ou inverse pour decroissant, 1 ou direct pour croissant\r
+ * nom_variable : nom de la variable utilisee (par defaut tri_nomboucle)\r
+ * \r
+ * {tri titre}\r
+ * {tri titre,inverse}\r
+ * {tri titre,-1}\r
+ * {tri titre,-1,truc}\r
+ * \r
+ * @param unknown_type $idb\r
+ * @param unknown_type $boucles\r
+ * @param unknown_type $crit\r
+ */\r
+function critere_tri($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       $id_table = $boucle->id_table;\r
+\r
+       // definition du champ par defaut\r
+       $_champ_defaut = !isset($crit->param[0][0]) ? "''" : calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent);\r
+       $_sens_defaut = !isset($crit->param[1][0]) ? "1" : calculer_liste(array($crit->param[1][0]), array(), $boucles, $boucle->id_parent);\r
+       // On ajoute _id_noisette à la variable de tri\r
+       $_variable = !isset($crit->param[2][0]) ? "'$idb'.'_'.\$Pile[0]['id_noisette']" : calculer_liste(array($crit->param[2][0]), array(), $boucles, $boucle->id_parent);\r
+\r
+       $_tri = "((\$t=(isset(\$Pile[0]['tri'.$_variable]))?\$Pile[0]['tri'.$_variable]:$_champ_defaut)?tri_protege_champ(\$t):'')";\r
+       \r
+       $_sens_defaut = "(is_array(\$s=$_sens_defaut)?(isset(\$s[\$st=$_tri])?\$s[\$st]:reset(\$s)):\$s)";\r
+       $_sens ="((intval(\$t=(isset(\$Pile[0]['sens'.$_variable]))?\$Pile[0]['sens'.$_variable]:$_sens_defaut)==-1 OR \$t=='inverse')?-1:1)";\r
+\r
+       $boucle->modificateur['tri_champ'] = $_tri;\r
+       $boucle->modificateur['tri_sens'] = $_sens;\r
+       $boucle->modificateur['tri_nom'] = $_variable;\r
+       // faut il inserer un test sur l'existence de $tri parmi les champs de la table ?\r
+       // evite des erreurs sql, mais peut empecher des tri sur jointure ...\r
+       $boucle->hash .= "\r
+       \$senstri = '';\r
+       \$tri = $_tri;\r
+       if (\$tri){\r
+               \$senstri = $_sens;\r
+               \$senstri = (\$senstri<0)?' DESC':'';\r
+       };\r
+       ";\r
+       $field = serialize(array_keys($boucle->show['field']));\r
+       $boucle->select[] = "\".tri_champ_select(\$tri).\"";\r
+       $boucle->order[] = "tri_champ_order(\$tri,'$id_table','$field').\$senstri";\r
+}\r
+\r
+\r
+// Critère aveline_branche\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/branche-objet.yaml'\r
+// Ajouter {aveline_branche} à la boucle\r
+function critere_aveline_branche_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       \r
+       $id_article = calculer_argument_precedent($idb, 'id_article', $boucles);\r
+       $id_syndic = calculer_argument_precedent($idb, 'id_syndic', $boucles);\r
+       $id_rubrique = calculer_argument_precedent($idb, 'id_rubrique', $boucles);\r
+       $id_secteur = calculer_argument_precedent($idb, 'id_secteur', $boucles);\r
+\r
+       //Trouver une jointure\r
+       $desc = $boucle->show;\r
+       //Seulement si necessaire\r
+       if (!array_key_exists('id_rubrique', $desc['field'])) {\r
+               $cle_rubrique = trouver_jointure_champ('id_rubrique', $boucle);\r
+       } else $cle_rubrique = $boucle->id_table;\r
+       \r
+       $table = $boucle->id_table;\r
+       \r
+       $boucle->where[] = "aveline_calcul_branche($id_article,$id_syndic,$id_rubrique, $id_secteur, $cle_rubrique, $table, \$Pile[0]['branche'], \$Pile[0]['rubrique_specifique'], \$Pile[0]['branche_specifique'], \$Pile[0]['secteur_specifique'], \$Pile[0]['article_specifique'], \$Pile[0]['site_specifique'], \$Pile[0]['filtre_rub'], \$Pile[0]['filtre_art'])";\r
+       \r
+}\r
+\r
+function aveline_calcul_branche($id_article,$id_syndic,$id_rubrique,$id_secteur,$cle_rubrique,$table, $branche,$rubrique_specifique,$branche_specifique,$secteur_specifique, $article_specifique, $site_specifique, $filtre_rub, $filtre_art) {\r
+       if ($filtre_rub) {\r
+               $branche = 'branche_specifique';\r
+               $branche_specifique = 'rubrique|'.$filtre_rub;\r
+       }\r
+       if ($filtre_art) {\r
+               $branche = 'article_specifique';\r
+               $article_specifique = 'article|'.$filtre_art;\r
+       }\r
+       switch ($table) {\r
+               case 'articles':\r
+                       $cle_secteur = $table;\r
+                       $champ_secteur = 'id_secteur';\r
+                       break;\r
+               case 'breves':\r
+                       $cle_secteur = $table;\r
+                       $champ_secteur = 'id_rubrique';\r
+       }\r
+       switch ($branche) {\r
+               case 'meme_article':\r
+                       return $id_article ? array('=',"$table.id_article",$id_article) : array ();\r
+                       break;\r
+               case 'article_specifique':\r
+                       return $article_specifique ? sql_in("$table.id_article",picker_selected($article_specifique,'article')) : array();\r
+                       break;\r
+               case 'meme_site':\r
+                       return $id_syndic ? array('=',"$table.id_syndic",$id_syndic) : array ();\r
+                       break;\r
+               case 'site_specifique':\r
+                       return $site_specifique ? sql_in("$table.id_syndic",$site_specifique) : array();\r
+                       break;\r
+               case 'meme_rubrique':\r
+                       return $id_rubrique ? array('=',"$cle_rubrique.id_rubrique",$id_rubrique) : array ();\r
+                       break;\r
+               case 'rubrique_specifique':\r
+                       return $rubrique_specifique ? sql_in("$cle_rubrique.id_rubrique",picker_selected($rubrique_specifique,'rubrique')) : array();\r
+                       break;\r
+               case 'branche_actuelle':\r
+                       return $id_rubrique ? sql_in("$cle_rubrique.id_rubrique",calcul_branche_in($id_rubrique)) : array();\r
+                       break;\r
+               case 'branche_specifique':\r
+                       return $branche_specifique ? sql_in("$cle_rubrique.id_rubrique",calcul_branche_in(picker_selected($branche_specifique,'rubrique'))) : array();\r
+                       break;\r
+               case 'meme_secteur':\r
+                       return $id_secteur ? array('=',"$cle_secteur.$champ_secteur",$id_secteur) : array();\r
+                       break;\r
+               case 'secteur_specifique':\r
+                       return $secteur_specifique ? sql_in("$cle_secteur.$champ_secteur",$secteur_specifique) : array();\r
+                       break;\r
+               default:\r
+                       return array();\r
+       }\r
+}\r
+\r
+// Critère aveline_lang\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/restreindre_langue.yaml''\r
+// Ajouter {aveline_lang} à la boucle\r
+// N'appliquer qu'à des tables ayant un champ 'lang'\r
+function critere_aveline_lang_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       \r
+       //Trouver une jointure (pour les évènements par exemple)\r
+       $desc = $boucle->show;\r
+       //Seulement si necessaire\r
+       if (!array_key_exists('lang', $desc['field'])) {\r
+               $id_table = trouver_jointure_champ('lang', $boucle);\r
+       } else $id_table = $boucle->id_table;\r
+       \r
+       $boucle->where[] = "aveline_calcul_lang($id_table,\$Pile[0]['restreindre_langue'],\$Pile[0]['lang'])";\r
+}\r
+\r
+function aveline_calcul_lang($id_table,$restreindre_langue,$lang) {\r
+       if ($restreindre_langue)\r
+               return array('=',"$id_table.lang",sql_quote($lang));\r
+       else\r
+               return array();\r
+}\r
+\r
+\r
+// Critère aveline_exclure_objet_encours\r
+// Le YAML de la noisette doit contenir - 'inclure:inc-yaml/exclure_objet_en_cours-objet.yaml''\r
+// Ajouter {aveline_exclure_objet_encours} à la boucle\r
+function critere_aveline_exclure_objet_encours_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       $id_table = $boucle->id_table;\r
+       $id_objet = $boucle->primary;\r
+       \r
+       $boucle->where[] = "aveline_calcul_exclure_objet($id_table,$id_objet,\$Pile[0][$id_objet],\$Pile[0]['exclure_objet_en_cours'])";\r
+}\r
+\r
+function aveline_calcul_exclure_objet($id_table,$id_objet,$id_en_cours,$exclure_objet_en_cours) {\r
+       if ($exclure_objet_en_cours)\r
+               return array('!=',"$id_table.$id_objet",intval($id_en_cours));\r
+       else\r
+               return array();\r
+}\r
+\r
+// Critère aveline_selecteurs_archives_mois et aveline_selecteurs_archives_annees\r
+// Utilisée pour les sélecteurs d'archives\r
+// Balise disponible #NB_ARCHIVES\r
+function critere_aveline_selecteur_archives_mois_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       $champ_date = $boucle->id_table ."." . $GLOBALS['table_date'][$boucle->type_requete];\r
+       $id_objet = $boucle->id_table ."." . $boucle->primary;\r
+       $boucle->select[] = "COUNT($id_objet) AS nb_archives";\r
+       $boucle->group[] = "YEAR($champ_date)";\r
+       $boucle->group[] = "MONTH($champ_date)";\r
+}\r
+\r
+function critere_aveline_selecteur_archives_annee_dist($idb, &$boucles, $crit) {\r
+       $boucle = &$boucles[$idb];\r
+       $champ_date = $boucle->id_table ."." . $GLOBALS['table_date'][$boucle->type_requete];\r
+       $id_objet = $boucle->id_table ."." . $boucle->primary;\r
+       $boucle->select[] = "COUNT($id_objet) AS nb_archives";\r
+       $boucle->group[] = "YEAR($champ_date)";\r
+}\r
+\r
+/** Balise #NB_ARCHIVES associee aux criteres aveline_selecteur_archives_mois et aveline_selecteur_archives_annees */\r
+function balise_NB_ARCHIVES_dist($p) {\r
+       $p->code = '$Pile[$SP][\'nb_archives\']';\r
+       $p->interdire_scripts = false;\r
+       return $p;\r
+}\r
+\r
+/**\r
+ * Calculer l'initiale d'un nom ou d'un titre\r
+ * \r
+ * @param <type> $nom\r
+ * @return <type>\r
+ */\r
+function aveline_initiale($nom){\r
+       return spip_substr(trim(strtoupper($nom)),0,1);\r
+}\r
+\r
+\r
+/**\r
+ * Afficher l'initiale pour la navigation par lettres\r
+ * adptée du plugin afficher_objets\r
+ * \r
+ * @staticvar string $memo\r
+ * @param <type> $url\r
+ * @param <type> $initiale\r
+ * @param <type> $compteur\r
+ * @param <type> $debut\r
+ * @param <type> $pas\r
+ * @return <type>\r
+ */\r
+function aveline_afficher_initiale($url,$initiale,$compteur,$debut,$pas){\r
+       static $memo = null;\r
+       $res = '';\r
+       if (!$memo \r
+               OR (!$initiale AND !$url)\r
+               OR ($initiale!==$memo['initiale'])\r
+               ){\r
+               $newcompt = intval(floor(($compteur-1)/$pas)*$pas);\r
+               if ($memo){\r
+                       $on = (($memo['compteur']<=$debut)\r
+                               AND (\r
+                                               $newcompt>$debut OR ($newcompt==$debut AND $newcompt==$memo['compteur'])\r
+                                               ));\r
+                       $res = lien_ou_expose($memo['url'],$memo['initiale'],$on,'lien_pagination');\r
+               }\r
+               if ($initiale)\r
+                       $memo = array('initiale'=>$initiale,'url'=>$url,'compteur'=>$newcompt);\r
+       }\r
+       return $res;\r
+}\r
+\r
+// Personnalisation pour Aveline\r
+// pour diriger au choix vers le lien de l'évènement ou vers la page Agenda\r
+\r
+function aveline_agenda_mini($i) {\r
+       $args = func_get_args();\r
+       $une_date = array_shift($args); // une date comme balise\r
+       $sinon = array_shift($args);\r
+       if (!$une_date) return $sinon;\r
+       $type = 'mini';\r
+       $agenda = Agenda_memo_full(0);\r
+       $evt = array();\r
+       foreach (($args ? $args : array_keys($agenda)) as $k) {\r
+               if (is_array($agenda[$k]))\r
+                       foreach($agenda[$k] as $d => $v) { \r
+                               if (count($v)>1)\r
+                                       foreach ($v as $cle => $ligne)\r
+                                               $v[0]['URL'] = generer_url_public('agenda','archives='.substr($d,0,4).'-'.substr($d,4,2).'-'.substr($d,6,2));\r
+                               $evt[$d] = $evt[$d] ? (array_merge($evt[$d], $v)) : $v;\r
+                       }\r
+       }\r
+       $la_date = mktime(0, 0, 0, mois($une_date), 1, annee($une_date));\r
+       include_spip('inc/agenda');\r
+       return http_calendrier_init($la_date, $type, '', '', '', array('', $evt));\r
+}\r
+\r
+?>
\ No newline at end of file