function critere_FORUMS_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; $boucle->where[] = array("'='", "'{$mparent}'", $arg); $boucle->where[] = array("'>'", "'{$mparent}'", 0); $boucle->modificateur['plat'] = true; }
/** * Détermine l'operateur et les opérandes d'un critère non déclaré * * Lorsque l'opérateur n'est pas explicite comme sur {id_article>0} c'est * l'opérateur '=' qui est utilisé. * * Traite les cas particuliers id_parent, id_enfant, date, lang * * @param string $idb Identifiant de la boucle * @param array $boucles AST du squelette * @param Critere $crit Paramètres du critère dans cette boucle * @return array * Liste : * - string $fct Nom d'une fonction SQL sur le champ ou vide (ex: SUM) * - string $col Nom de la colonne SQL utilisée * - string $op Opérateur * - string[] $val * Liste de codes PHP obtenant les valeurs des comparaisons (ex: id_article sur la boucle parente) * Souvent un tableau d'un seul élément. * - string $args_sql Suite des arguments du critère. ? **/ function calculer_critere_infixe_ops($idb, &$boucles, $crit) { // cas d'une valeur comparee a elle-meme ou son referent if (count($crit->param) == 0) { $op = '='; $col = $val = $crit->op; if (preg_match('/^(.*)\\.(.*)$/', $col, $r)) { $val = $r[2]; } // Cas special {lang} : aller chercher $GLOBALS['spip_lang'] if ($val == 'lang') { $val = array(kwote('$GLOBALS[\'spip_lang\']')); } else { $defaut = null; if ($val == 'id_parent') { // Si id_parent, comparer l'id_parent avec l'id_objet // de la boucle superieure.... faudrait verifier qu'il existe // pour eviter l'erreur SQL $val = $boucles[$idb]->primary; // mais si pas de boucle superieure, prendre id_parent dans l'env $defaut = "\$Pile[0]['id_parent']"; } elseif ($val == 'id_enfant') { // Si id_enfant, comparer l'id_objet avec l'id_parent // de la boucle superieure $val = 'id_parent'; } elseif ($crit->cond and ($col == "date" or $col == "date_redac")) { // un critere conditionnel sur date est traite a part // car la date est mise d'office par SPIP, $defaut = "(\$Pile[0]['{$col}_default']?'':\$Pile[0]['" . $col . "'])"; } $val = calculer_argument_precedent($idb, $val, $boucles, $defaut); $val = array(kwote($val)); } } else { // comparaison explicite // le phraseur impose que le premier param soit du texte $params = $crit->param; $op = $crit->op; if ($op == '==') { $op = 'REGEXP'; } $col = array_shift($params); $col = $col[0]->texte; $val = array(); $desc = array('id_mere' => $idb); $parent = $boucles[$idb]->id_parent; // Dans le cas {x=='#DATE'} etc, defaire le travail du phraseur, // celui ne sachant pas ce qu'est un critere infixe // et a fortiori son 2e operande qu'entoure " ou ' if (count($params) == 1 and count($params[0] == 3) and $params[0][0]->type == 'texte' and @$params[0][2]->type == 'texte' and ($p = $params[0][0]->texte) == $params[0][2]->texte and ($p == "'" or $p == '"') and $params[0][1]->type == 'champ') { $val[] = "{$p}\\{$p}#" . $params[0][1]->nom_champ . "\\{$p}{$p}"; } else { foreach ($op != 'IN' ? $params : calculer_vieux_in($params) as $p) { $a = calculer_liste($p, $desc, $boucles, $parent); if (strcasecmp($op, 'IN') == 0) { $val[] = $a; } else { $val[] = kwote($a, $boucles[$idb]->sql_serveur, 'char'); } // toujours quoter en char ici } } } $fct = $args_sql = ''; // fonction SQL ? // chercher FONCTION(champ) tel que CONCAT(titre,descriptif) if (preg_match('/^(.*)' . SQL_ARGS . '$/', $col, $m)) { $fct = $m[1]; preg_match('/^\\(([^,]*)(.*)\\)$/', $m[2], $a); $col = $a[1]; if (preg_match('/^(\\S*)(\\s+AS\\s+.*)$/i', $col, $m)) { $col = $m[1]; $args_sql = $m[2]; } $args_sql .= $a[2]; } return array($fct, $col, $op, $val, $args_sql); }
/** * Calcul des critères {suivant} et {precedent} (avant l'existence d'Iterateurs). * On reprend en grande partie le fonctionnement de {pagination} avec debut_xx=@yy * en jouant de sql_seek pour se déplacer à la bonne position sur les résultats de * la boucle. * * @param string $type type de décalage : 'suivant' ou 'precedent' **/ function calculer_critere_suivant_precedent_dist($idb, &$boucles, $crit, $type) { $boucle = &$boucles[$idb]; $primary = $boucle->primary; $arg = kwote(calculer_argument_precedent($idb, $primary, $boucles)); $partie = "0;\n" ."\tif (\$id_actuel = $arg) {\n" ."\t\t".'$debut_boucle = quete_position_primary(\''.$primary.'\', $id_actuel, "'.$type.'", $result, '._q($boucle->sql_serveur).');'."\n" // pas de resultat, on cree une selection vide ."\t\t".'if ($debut_boucle === false){'."\n" ."\t\t\t".'@sql_free($result,'._q($boucle->sql_serveur).");\n" ."\t\t\t"."\$where[] = array('=','0','1');\n" // forcer 0 resultat ."\t\t\t".'$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect);'."\n" //."\t\t\t"."\$Numrows['$idb']['total'] = 0;\n" ."\t\t} else {\n" // si on a des resultats, il faut remettre le compteur a zero. ."\t\t".'if (!sql_seek($result,0,'._q($boucle->sql_serveur).")){\n" ."\t\t\t".'@sql_free($result,'._q($boucle->sql_serveur).");\n" ."\t\t\t".'$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect);'."\n" ."\t\t}\n" // donner un bon GRAND_TOTAL pour la fonction calculer_parties() // NAN ça marche pas non plus... mah que passa ? //."\t\t\t"."\$Numrows['$idb']['total'] = (\$Numrows['$idb']['total'] >= 1 ? 2 : 0);\n" ."\t\t}\n" ."\t}\n" ."\t".'$debut_boucle = intval($debut_boucle)'; $boucle->total_parties = 1; calculer_parties($boucles, $idb, $partie, '++'); // ajouter la cle primaire dans le select // sauf si pas de primaire, ou si primaire composee // dans ce cas, on ne sait pas gerer une pagination indirecte // : il faut id_xx dans le select pour la fonction quete_position_primary() $t = $boucle->id_table . '.' . $primary; if ($boucle->primary AND !preg_match('/[,\s]/',$primary) AND !in_array($t, $boucle->select)) { $boucle->select[]= $t; } // forcer le compilo à ne pas prendre en static a cause du $where fluctuant $boucle->where[]= array("'='","'1'","sql_quote(1)"); }
function calculer_critere_infixe_ops($idb, &$boucles, $crit) { // cas d'une valeur comparee a elle-meme ou son referent if (count($crit->param) == 0) { $op = '='; $col = $val = $crit->op; if (preg_match('/^(.*)\.(.*)$/', $col, $r)) $val = $r[2]; // Cas special {lang} : aller chercher $GLOBALS['spip_lang'] if ($val == 'lang') $val = array(kwote('$GLOBALS[\'spip_lang\']')); else { // Si id_parent, comparer l'id_parent avec l'id_objet // de la boucle superieure.... faudrait verifier qu'il existe // pour eviter l'erreur SQL if ($val == 'id_parent') $val = $boucles[$idb]->primary; // Si id_enfant, comparer l'id_objet avec l'id_parent // de la boucle superieure else if ($val == 'id_enfant') $val = 'id_parent'; // un critere conditionnel sur date est traite a part // car la date est mise d'office par SPIP, $val = calculer_argument_precedent($idb, $val, $boucles); if ($crit->cond AND ($col == "date" OR $col == "date_redac")) { if($val == "\$Pile[0]['".$col."']") { $val = "(\$Pile[0]['{$col}_default']?'':$val)"; } } $val = array(kwote($val)); } } else { // comparaison explicite // le phraseur impose que le premier param soit du texte $params = $crit->param; $op = $crit->op; if ($op == '==') $op = 'REGEXP'; $col = array_shift($params); $col = $col[0]->texte; $val = array(); $desc = array('id_mere' => $idb); $parent = $boucles[$idb]->id_parent; // Dans le cas {x=='#DATE'} etc, defaire le travail du phraseur, // celui ne sachant pas ce qu'est un critere infixe // et a fortiori son 2e operande qu'entoure " ou ' if (count($params)==1 AND count($params[0]==3) AND $params[0][0]->type == 'texte' AND @$params[0][2]->type == 'texte' AND ($p=$params[0][0]->texte) == $params[0][2]->texte AND (($p == "'") OR ($p == '"')) AND $params[0][1]->type == 'champ' ) { $val[]= "$p\\$p#" . $params[0][1]->nom_champ . "\\$p$p"; } else foreach ((($op != 'IN') ? $params : calculer_vieux_in($params)) as $p) { $a = calculer_liste($p, $desc, $boucles, $parent); if ($op == 'IN') $val[]= $a; else $val[]=kwote($a); } } $fct = $args_sql = ''; // fonction SQL ? if (preg_match('/^(.*)' . SQL_ARGS . '$/', $col, $m)) { $fct = $m[1]; preg_match('/^\(([^,]*)(.*)\)$/', $m[2], $a); $col = $a[1]; if (preg_match('/^(\S*)(\s+AS\s+.*)$/i', $col, $m)) { $col=$m[1]; $args_sql = $m[2]; } $args_sql .= $a[2];; } return array($fct, $col, $op, $val, $args_sql); }