Dépôt officiel du core SPIP Les plugins-dist faisant partie de la distribution SPIP sont présents dans https://git.spip.net/spip/[nom du plugin dist] https://www.spip.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1923 lines
64 KiB

<?php
18 years ago
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
7 years ago
* Copyright (c) 2001-2016 *
18 years ago
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
11 years ago
/**
* Définition des {criteres} d'une boucle
*
* @package SPIP\Compilateur\Criteres
**/
11 years ago
if (!defined('_ECRIRE_INC_VERSION')) return;
11 years ago
/**
* Une Regexp repérant une chaine produite par le compilateur,
* souvent utilisée pour faire de la concaténation lors de la compilation
* plutôt qu'à l'exécution, i.e. pour remplacer 'x'.'y' par 'xy'
**/
define('_CODE_QUOTE', ",^(\n//[^\n]*\n)? *'(.*)' *$,");
11 years ago
/**
* Compile le critère {racine}
*
* Ce critère sélectionne les éléments à la racine d'une hiérarchie,
* c'est à dire ayant id_parent=0
*
* @link http://www.spip.net/@racine
*
* @param string $idb
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @param array $crit
* Paramètres du critère dans cette boucle
* @return
* AST complété de la gestion du critère
**/
function critere_racine_dist($idb, &$boucles, $crit){
global $exceptions_des_tables;
18 years ago
$not = $crit->not;
$boucle = &$boucles[$idb];
$id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ?
$exceptions_des_tables[$boucle->id_table]['id_parent'] :
'id_parent';
$c = array("'='", "'$boucle->id_table."."$id_parent'", 0);
$boucle->where[] = ($crit->not ? array("'NOT'", $c) : $c);
}
11 years ago
/**
* Compile le critère {exclus}
*
* Exclut du résultat l’élément dans lequel on se trouve déjà
*
* @link http://www.spip.net/@exclus
*
* @param string $idb
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @param array $crit
* Paramètres du critère dans cette boucle
* @return
* AST complété de la gestion du critère
**/
function critere_exclus_dist($idb, &$boucles, $crit){
18 years ago
$not = $crit->not;
$boucle = &$boucles[$idb];
$id = $boucle->primary;
18 years ago
if ($not OR !$id)
return (array('zbug_critere_inconnu', array('critere' => $not.$crit->op)));
$arg = kwote(calculer_argument_precedent($idb, $id, $boucles));
$boucle->where[] = array("'!='", "'$boucle->id_table."."$id'", $arg);
}
11 years ago
/**
* Compile le critère {doublons} ou {unique}
*
* Ce critères enlève de la boucle les éléments déjà sauvegardés
* dans un précédent critère {doublon} sur une boucle de même table.
11 years ago
*
* Il est possible de spécifier un nom au doublon tel que {doublons sommaire}
*
11 years ago
* @link http://www.spip.net/@doublons
*
* @param string $idb
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @param array $crit
* Paramètres du critère dans cette boucle
* @return
* AST complété de la gestion du critère
**/
function critere_doublons_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
$primary = $boucle->primary;
// la table nécessite une clé primaire, non composée
if (!$primary OR strpos($primary, ',')){
return (array('zbug_doublon_sur_table_sans_cle_primaire'));
}
$not = ($crit->not ? '' : 'NOT');
// le doublon s'applique sur un type de boucle (article)
$nom = "'" . $boucle->type_requete. "'";
// compléter le nom avec un nom précisé {doublons nom}
// on obtient $nom = "'article' . 'nom'"
if (isset($crit->param[0])) {
$nom .= "." . calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
}
// code qui déclarera l'index du stockage de nos doublons (pour éviter une notice PHP)
$init_comment = "\n\n\t// Initialise le(s) critère(s) doublons\n";
$init_code = "\tif (!isset(\$doublons[\$d = $nom])) { \$doublons[\$d] = ''; }\n";
// on crée un sql_in avec la clé primaire de la table
// et la collection des doublons déjà emmagasinés dans le tableau
// $doublons et son index, ici $nom
// debut du code "sql_in('articles.id_article', "
$debut_in = "sql_in('".$boucle->id_table.'.'.$primary."', ";
// lecture des données du doublon "$doublons[$doublon_index[] = "
// Attention : boucle->doublons désigne une variable qu'on affecte
$debut_doub = '$doublons[' . (!$not ? '' : ($boucle->doublons."[]= "));
// le debut complet du code des doublons
$debut_doub = $debut_in . $debut_doub;
// nom du doublon "('article' . 'nom')]"
$fin_doub = "($nom)]";
// si on trouve un autre critère doublon,
// on fusionne pour avoir un seul IN, et on s'en va !
foreach ($boucle->where as $k => $w) {
if (strpos($w[0], $debut_doub)===0) {
// fusionner le sql_in (du where)
$boucle->where[$k][0] = $debut_doub . $fin_doub.' . '.substr($w[0], strlen($debut_in));
// fusionner l'initialisation (du hash) pour faire plus joli
$x = strpos($boucle->hash, $init_comment);
$len = strlen($init_comment);
$boucle->hash =
substr($boucle->hash, 0, $x + $len) . $init_code . substr($boucle->hash, $x + $len);
return;
}
}
// mettre l'ensemble dans un tableau pour que ce ne soit pas vu comme une constante
$boucle->where[] = array($debut_doub . $fin_doub.", '".$not."')");
// déclarer le doublon s'il n'existe pas encore
$boucle->hash .= $init_comment . $init_code;
# la ligne suivante avait l'intention d'eviter une collecte deja faite
# mais elle fait planter une boucle a 2 critere doublons:
# {!doublons A}{doublons B}
# (de http://article.gmane.org/gmane.comp.web.spip.devel/31034)
# if ($crit->not) $boucle->doublons = "";
}
/**
* Compile le critère {lang_select}
*
* Permet de restreindre ou non une boucle en affichant uniquement
* les éléments dans la langue en cours. Certaines boucles
* tel que articles et rubriques restreignent par défaut sur la langue
* en cours.
*
* Sans définir de valeur au critère, celui-ci utilise 'oui' comme
* valeur par défaut.
*
* @param string $idb
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @param array $crit
* Paramètres du critère dans cette boucle
* @return
* AST complété de la gestion du critère
**/
function critere_lang_select_dist($idb, &$boucles, $crit){
if (!isset($crit->param[1][0]) OR !($param = $crit->param[1][0]->texte)) $param = 'oui';
if ($crit->not) $param = ($param=='oui') ? 'non' : 'oui';
$boucle = &$boucles[$idb];
18 years ago
$boucle->lang_select = $param;
}
// {debut_xxx}
// http://www.spip.net/@debut_
// http://doc.spip.org/@critere_debut_dist
function critere_debut_dist($idb, &$boucles, $crit){
list($un, $deux) = $crit->param;
$un = $un[0]->texte;
$deux = $deux[0]->texte;
if ($deux){
$boucles[$idb]->limit = 'intval($Pile[0]["debut'.
$un.
'"]) . ",'.
$deux.
'"';
} else calculer_critere_DEFAUT_dist($idb, $boucles, $crit);
}
// {pagination}
// {pagination 20}
// {pagination #ENV{pages,5}} etc
// {pagination 20 #ENV{truc,chose}} pour utiliser la variable debut_#ENV{truc,chose}
// http://www.spip.net/@pagination
// http://doc.spip.org/@critere_pagination_dist
function critere_pagination_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
// definition de la taille de la page
$pas = !isset($crit->param[0][0]) ? "''"
: calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent);
if (!preg_match(_CODE_QUOTE, $pas, $r)){
$pas = "((\$a = intval($pas)) ? \$a : 10)";
} else {
$r = intval($r[2]);
$pas = strval($r ? $r : 10);
}
$type = !isset($crit->param[0][1]) ? "'$idb'"
: calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucle->id_parent);
$debut = ($type[0]!=="'") ? "'debut'.$type"
: ("'debut".substr($type, 1));
$boucle->modificateur['debut_nom'] = $type;
$partie =
// tester si le numero de page demande est de la forme '@yyy'
'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n"
."\tif(substr(\$debut_boucle,0,1)=='@'){\n"
."\t\t".'$debut_boucle = $Pile[0]['.$debut.'] = quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$iter);'."\n"
."\t\t".'$iter->seek(0);'."\n"
."\t}\n"
."\t".'$debut_boucle = intval($debut_boucle)';
$boucle->hash .= '
$command[\'pagination\'] = array((isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : null), ' . $pas . ');';
$boucle->total_parties = $pas;
calculer_parties($boucles, $idb, $partie, 'p+');
// ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id
// sauf si pas de primaire, ou si primaire composee
// dans ce cas, on ne sait pas gerer une pagination indirecte
$t = $boucle->id_table.'.'.$boucle->primary;
if ($boucle->primary
AND !preg_match('/[,\s]/', $boucle->primary)
AND !in_array($t, $boucle->select)
)
$boucle->select[] = $t;
}
// {recherche} ou {recherche susan}
// http://www.spip.net/@recherche
// http://doc.spip.org/@critere_recherche_dist
function critere_recherche_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
if (!$boucle->primary OR strpos($boucle->primary, ',')){
erreur_squelette(_T('zbug_critere_sur_table_sans_cle_primaire',array('critere'=>'recherche')), $boucle);
return;
}
if (isset($crit->param[0]))
$quoi = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
else
$quoi = '(isset($Pile[0]["recherche"])?$Pile[0]["recherche"]:(isset($GLOBALS["recherche"])?$GLOBALS["recherche"]:""))';
$_modificateur = var_export($boucle->modificateur, true);
$boucle->hash .= '
// RECHERCHE'
.($crit->cond ? '
if (!strlen('.$quoi.')){
list($rech_select, $rech_where) = array("0 as points","");
} else' : '').'
{
$prepare_recherche = charger_fonction(\'prepare_recherche\', \'inc\');
list($rech_select, $rech_where) = $prepare_recherche('.$quoi.', "'.$boucle->id_table.'", "'.$crit->cond.'","'.$boucle->sql_serveur.'",'.$_modificateur.',"'.$boucle->primary.'");
}
';
$t = $boucle->id_table.'.'.$boucle->primary;
if (!in_array($t, $boucles[$idb]->select))
$boucle->select[] = $t; # pour postgres, neuneu ici
// jointure uniquement sur le serveur principal
// (on ne peut joindre une table d'un serveur distant avec la table des resultats du serveur principal)
if (!$boucle->sql_serveur){
$boucle->join['resultats'] = array("'".$boucle->id_table."'", "'id'", "'".$boucle->primary."'");
$boucle->from['resultats'] = 'spip_resultats';
}
$boucle->select[] = '$rech_select';
//$boucle->where[]= "\$rech_where?'resultats.id=".$boucle->id_table.".".$boucle->primary."':''";
// et la recherche trouve
$boucle->where[] = '$rech_where?$rech_where:\'\'';
}
// {traduction}
// http://www.spip.net/@traduction
// (id_trad>0 AND id_trad=id_trad(precedent))
// OR id_article=id_article(precedent)
// http://doc.spip.org/@critere_traduction_dist
function critere_traduction_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
$prim = $boucle->primary;
$table = $boucle->id_table;
$arg = kwote(calculer_argument_precedent($idb, 'id_trad', $boucles));
$dprim = kwote(calculer_argument_precedent($idb, $prim, $boucles));
$boucle->where[] =
array("'OR'",
array("'AND'",
array("'='", "'$table.id_trad'", 0),
array("'='", "'$table.$prim'", $dprim)
),
array("'AND'",
array("'>'", "'$table.id_trad'", 0),
array("'='", "'$table.id_trad'", $arg)
)
);
}
// {origine_traduction}
// (id_trad>0 AND id_article=id_trad) OR (id_trad=0)
// http://www.spip.net/@origine_traduction
// http://doc.spip.org/@critere_origine_traduction_dist
function critere_origine_traduction_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
$prim = $boucle->primary;
$table = $boucle->id_table;
$c =
array("'OR'",
array("'='", "'$table."."id_trad'", "'$table.$prim'"),
array("'='", "'$table.id_trad'", "'0'")
);
$boucle->where[] = ($crit->not ? array("'NOT'", $c) : $c);
}
// {meme_parent}
// http://www.spip.net/@meme_parent
// http://doc.spip.org/@critere_meme_parent_dist
function critere_meme_parent_dist($idb, &$boucles, $crit){
global $exceptions_des_tables;
$boucle = &$boucles[$idb];
$arg = kwote(calculer_argument_precedent($idb, 'id_parent', $boucles));
$id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ?
$exceptions_des_tables[$boucle->id_table]['id_parent'] :
'id_parent';
$mparent = $boucle->id_table.'.'.$id_parent;
if ($boucle->type_requete=='rubriques' OR isset($exceptions_des_tables[$boucle->id_table]['id_parent'])){
$boucle->where[] = array("'='", "'$mparent'", $arg);
}
// le cas FORUMS est gere dans le plugin forum, dans la fonction critere_FORUMS_meme_parent_dist()
else {
return (array('zbug_critere_inconnu', array('critere' => $crit->op.' '.$boucle->type_requete)));
}
}
/**
* Sélectionne dans une boucle les éléments appartenant à une branche d'une rubrique
*
* Calcule une branche d'une rubrique et conditionne la boucle avec.
* Cherche l'identifiant de la rubrique dans les boucles parentes ou par jointure
* et calcule la liste des identifiants de rubrique de toute la branche
*
* @link http://www.spip.net/@branche
*
* @param string $idb
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @param array $crit
* Paramètres du critère dans cette boucle
* @return
* AST complété de la condition where au niveau de la boucle,
* restreignant celle ci aux rubriques de la branche
**/
function critere_branche_dist($idb, &$boucles, $crit){
18 years ago
$not = $crit->not;
$boucle = &$boucles[$idb];
$arg = calculer_argument_precedent($idb, 'id_rubrique', $boucles);
//Trouver une jointure
$champ = "id_rubrique";
$desc = $boucle->show;
//Seulement si necessaire
if (!array_key_exists($champ, $desc['field'])){
$cle = trouver_jointure_champ($champ, $boucle);
$trouver_table = charger_fonction("trouver_table", "base");
$desc = $trouver_table($boucle->from[$cle]);
if (count(trouver_champs_decomposes($champ, $desc))>1){
$decompose = decompose_champ_id_objet($champ);
$champ = array_shift($decompose);
$boucle->where[] = array("'='", _q($cle.".".reset($decompose)), '"'.sql_quote(end($decompose)).'"');
}
}
else $cle = $boucle->id_table;
$c = "sql_in('$cle".".$champ', calcul_branche_in($arg)"
.($not ? ", 'NOT'" : '').")";
$boucle->where[] = !$crit->cond ? $c :
("($arg ? $c : ".($not ? "'0=1'" : "'1=1'").')');
}
// {logo} liste les objets qui ont un logo
// http://doc.spip.org/@critere_logo_dist
function critere_logo_dist($idb, &$boucles, $crit){
$not = $crit->not;
$boucle = &$boucles[$idb];
$c = "sql_in('".
$boucle->id_table.'.'.$boucle->primary
."', lister_objets_avec_logos('".$boucle->primary."'), '')";
if ($crit->cond) $c = "($arg ? $c : 1)";
18 years ago
if ($not)
$boucle->where[] = array("'NOT'", $c);
18 years ago
else
$boucle->where[] = $c;
}
// c'est la commande SQL "GROUP BY"
// par exemple <boucle(articles){fusion lang}>
16 years ago
// http://doc.spip.org/@critere_fusion_dist
function critere_fusion_dist($idb, &$boucles, $crit){
if ($t = isset($crit->param[0])){
$t = $crit->param[0];
if ($t[0]->type=='texte'){
$t = $t[0]->texte;
if (preg_match("/^(.*)\.(.*)$/", $t, $r)){
$t = table_objet_sql($r[1]);
$t = array_search($t, $boucles[$idb]->from);
if ($t) $t .= '.'.$r[2];
}
} else {
$t = '".'
.calculer_critere_arg_dynamique($idb, $boucles, $t)
.'."';
}
}
if ($t){
$boucles[$idb]->group[] = $t;
if (!in_array($t, $boucles[$idb]->select))
$boucles[$idb]->select[] = $t;
} else
return (array('zbug_critere_inconnu', array('critere' => $crit->op.' ?')));
}
// c'est la commande SQL "COLLATE"
// qui peut etre appliquee sur les order by, group by, where like ...
16 years ago
// http://doc.spip.org/@critere_collecte_dist
function critere_collecte_dist($idb, &$boucles, $crit){
if (isset($crit->param[0])){
$_coll = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
$boucle = $boucles[$idb];
$boucle->modificateur['collate'] = "($_coll ?' COLLATE '.$_coll:'')";
$n = count($boucle->order);
if ($n && (strpos($boucle->order[$n-1], 'COLLATE')===false))
$boucle->order[$n-1] .= " . ".$boucle->modificateur['collate'];
} else
return (array('zbug_critere_inconnu', array('critere' => $crit->op." ".count($boucles[$idb]->order))));
}
16 years ago
// http://doc.spip.org/@calculer_critere_arg_dynamique
function calculer_critere_arg_dynamique($idb, &$boucles, $crit, $suffix = ''){
$boucle = $boucles[$idb];
$alt = "('".$boucle->id_table.'.\' . $x'.$suffix.')';
$var = '$champs_'.$idb;
$desc = (strpos($boucle->in, "static $var =")!==false);
if (!$desc){
$desc = $boucle->show['field'];
$desc = implode(',', array_map('_q', array_keys($desc)));
$boucles[$idb]->in .= "\n\tstatic $var = array(".$desc.");";
}
if ($desc) $alt = "(in_array(\$x, $var) ? $alt :(\$x$suffix))";
$arg = calculer_liste($crit, array(), $boucles, $boucle->id_parent);
return "((\$x = preg_replace(\"/\\W/\",'', $arg)) ? $alt : '')";
}
// Tri : {par xxxx}
// http://www.spip.net/@par
// http://doc.spip.org/@critere_par_dist
function critere_par_dist($idb, &$boucles, $crit){
return critere_parinverse($idb, $boucles, $crit);
}
// http://doc.spip.org/@critere_parinverse
function critere_parinverse($idb, &$boucles, $crit, $sens = ''){
global $exceptions_des_jointures;
$boucle = &$boucles[$idb];
if ($crit->not) $sens = $sens ? "" : " . ' DESC'";
$collecte = (isset($boucle->modificateur['collecte'])) ? " . ".$boucle->modificateur['collecte'] : "";
foreach ($crit->param as $tri){
$order = $fct = ""; // en cas de fonction SQL
// tris specifies dynamiquement
if ($tri[0]->type!='texte'){
// calculer le order dynamique qui verifie les champs
$order = calculer_critere_arg_dynamique($idb, $boucles, $tri, $sens);
// et si ce n'est fait, ajouter un champ 'hasard'
// pour supporter 'hasard' comme tri dynamique
$par = "rand()";
$parha = $par." AS hasard";
if (!in_array($parha, $boucle->select))
$boucle->select[] = $parha;
} else {
$par = array_shift($tri);
$par = $par->texte;
// par multi champ
if (preg_match(",^multi[\s]*(.*)$,", $par, $m)){
$champ = trim($m[1]);
// par multi L1.champ
if (strpos($champ, '.')) {
$cle = '';
// par multi champ (champ sur une autre table)
} elseif (!array_key_exists($champ, $boucle->show['field'])){
$cle = trouver_jointure_champ($champ, $boucle);
// par multi champ (champ dans la table en cours)
} else {
$cle = $boucle->id_table;
}
if ($cle) { $cle .= '.'; }
$texte = $cle.$champ;
$boucle->select[] = "\".sql_multi('".$texte."', \$GLOBALS['spip_lang']).\"";
$order = "'multi'";
// par num champ(, suite)
} else if (preg_match(",^num (.*)$,m", $par, $m)) {
$champ = trim($m[1]);
// par num L1.champ
if (strpos($champ, '.')) {
$cle = '';
// par num champ (champ sur une autre table)
} elseif (!array_key_exists($champ, $boucle->show['field'])){
$cle = trouver_jointure_champ($champ, $boucle);
// par num champ (champ dans la table en cours)
} else {
$cle = $boucle->id_table;
}
if ($cle) { $cle .= '.'; }
$texte = '0+'. $cle . $champ;
$suite = calculer_liste($tri, array(), $boucles, $boucle->id_parent);
if ($suite!=="''")
$texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')"." . \"";
$as = 'num'.($boucle->order ? count($boucle->order) : "");
$boucle->select[] = $texte." AS $as";
$order = "'$as'";
} else {
if (!preg_match(",^".CHAMP_SQL_PLUS_FONC.'$,is', $par, $match)){
return (array('zbug_critere_inconnu', array('critere' => $crit->op." $par")));
} else {
if (count($match)>2){
$par = substr($match[2], 1, -1);
$fct = $match[1];
}
// par hasard
if ($par=='hasard'){
$par = "rand()";
$boucle->select[] = $par." AS alea";
$order = "'alea'";
}
// par titre_mot ou type_mot voire d'autres
else if (isset($exceptions_des_jointures[$par])){
list($table, $champ) = $exceptions_des_jointures[$par];
$order = critere_par_joint($table, $champ, $boucle, $idb);
if (!$order)
return (array('zbug_critere_inconnu', array('critere' => $crit->op." $par")));
}
else if ($par=='date'
AND $desc = $boucle->show
AND $desc['date']
){
$m = $desc['date'];
$order = "'".$boucle->id_table.".".$m."'";
}
// par champ. Verifier qu'ils sont presents.
elseif (preg_match("/^([^,]*)\.(.*)$/", $par, $r)) {
// cas du tri sur champ de jointure explicite
$t = array_search($r[1], $boucle->from);
if (!$t){
$t = trouver_jointure_champ($r[2], $boucle, array($r[1]));
}
if (!$t){
return (array('zbug_critere_inconnu', array('critere' => $crit->op." $par")));
} else $order = "'".$t.'.'.$r[2]."'";
} else {
$desc = $boucle->show;
if ($desc['field'][$par])
$par = $boucle->id_table.".".$par;
// sinon tant pis, ca doit etre un champ synthetise (cf points)
$order = "'$par'";
}
}
}
}
if (preg_match('/^\'([^"]*)\'$/', $order, $m)){
$t = $m[1];
if (strpos($t, '.') AND !in_array($t, $boucle->select)){
$boucle->select[] = $t;
}
} else $sens = '';
if ($fct){
if (preg_match("/^\s*'(.*)'\s*$/", $order, $r))
$order = "'$fct(".$r[1].")'";
else $order = "'$fct(' . $order . ')'";
}
$t = $order.$collecte.$sens;
if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r))
$t = $r[1].$r[2];
$boucle->order[] = $t;
}
}
15 years ago
// http://doc.spip.org/@critere_par_joint
function critere_par_joint($table, $champ, &$boucle, $idb){
$t = array_search($table, $boucle->from);
if (!$t) $t = trouver_jointure_champ($champ, $boucle);
return !$t ? '' : ("'".$t.'.'.$champ."'");
}
// {inverse}
// http://www.spip.net/@inverse
// http://doc.spip.org/@critere_inverse_dist
function critere_inverse_dist($idb, &$boucles, $crit){
$boucle = &$boucles[$idb];
// Classement par ordre inverse
if ($crit->not)
critere_parinverse($idb, $boucles, $crit);
else
{
$order = "' DESC'";
// Classement par ordre inverse fonction eventuelle de #ENV{...}
if (isset($crit->param[0])){
$critere = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
$order = "(($critere)?' DESC':'')";
}
$n = count($boucle->order);
if (!$n){