Skip to content
Extraits de code Groupes Projets
Bifurcation depuis spip / spip
20369 validations de retard le dépôt en amont.
inc-criteres.php3 16,93 Kio
<?php

//
// Definition des {criteres} d'une boucle
//

// Ce fichier ne sera execute qu'une fois
if (defined("_INC_CRITERES")) return;
define("_INC_CRITERES", "1");


// {racine}
// http://www.spip.net/@racine
function critere_racine_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];

	if ($param != 'racine' OR $not)
		return array(_T('info_erreur_squelette'), $param);

	$boucle->where[] = $boucle->id_table.".id_parent='0'";

}

// {exclus}
// http://www.spip.net/@exclus
function critere_exclus_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];

	if ($param != 'exclus' OR $not)
		return array(_T('info_erreur_squelette'), $param);

	$boucle->where[] = $boucle->id_table . '.' . $boucle->primary."!='\"."
	. calculer_argument_precedent($idb,$boucle->primary, $boucles) .
	 ".\"'";

}

// {doublons} ou {unique}
// http://www.spip.net/@doublons
function critere_doublons_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];

	if (!preg_match("/(doublons|unique)[[:space:]]*([a-z_0-9]*)/i",
	$param, $match))
		return array(_T('info_erreur_squelette'), $param);

	$boucle->doublons = $boucle->type_requete . $match[2];
	$boucle->where[] = '" .' .
		"calcul_mysql_in('".$boucle->id_table . '.' . $boucle->primary."', "
		.'"0".$doublons[\''.$boucle->doublons."'], 'NOT') . \"";
}

// {lang_select}
// http://www.spip.net/@lang_select
function critere_lang_select_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if (preg_match('/lang_select(=(oui|non))?$/i', $param, $match)) {
		if (!$lang_select = $match[2])
			$lang_select = 'oui';
		if ($not)
			$lang_select = ($lang_select=='oui')?'non':'oui';
		$boucle->lang_select = $lang_select;
	}
	else return array(_T('info_erreur_squelette'), $param);
}

// {debut_xxx}
// http://www.spip.net/@debut_
function critere_debut_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if (ereg('^debut([-_a-zA-Z0-9]+),([0-9]*)$', $param, $match)) {
		$debut_lim = "debut".$match[1];
		$boucle->limit =
			'intval($GLOBALS["'.$debut_lim.'"]).",'.$match[2] .'"' ;
	}
	else return array(_T('info_erreur_squelette'), $param);
}

// {recherche}
// http://www.spip.net/@recherche
function critere_recherche_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	$boucle->from[] = "index_".$boucle->id_table." AS rec";
	$boucle->select[] = 'SUM(rec.points + 100*(" .' . 
		'calcul_mysql_in("rec.hash",
		calcul_branche($hash_recherche_strict),"") . "))
		AS points';

	// horrible hack du aux id_forum = spip_forum et id_article=spip_articleS
	// en fait il faudrait la fonction inverse de table_objet()
	$id = 'id_'.preg_replace('/s$/', '', $boucle->id_table);

	// rec.id_article = articles.id_article
	$boucle->where[] = "rec.".$id
	. "=" . $boucle->id_table.'.'.$id;

	// group by articles.id_article
	$boucle->group = $boucle->id_table . '.' . $boucle->primary;
	$boucle->select[] = $boucle->id_table . '.' . $boucle->primary; # pour postgres, neuneu ici

	// et la recherche trouve
	$boucle->where[] = '" .' . 'calcul_mysql_in("rec.hash",
		calcul_branche($hash_recherche),"") . "';

	// oui cette boucle est une boucle recherche, le noter dans la pile
	// (certes, c'est un peu lourd comme ecriture)
	$boucles[$idb]->hash = true;
}

// {inverse}
// http://www.spip.net/@inverse
function critere_inverse_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	// Classement par ordre inverse
	if ($param == 'inverse' AND !$not) {
		if ($boucle->order)
			$boucle->order .= ".' DESC'";
		else 
			return array(_L("inversion d'un ordre inexistant"), 
				     "BOUCLE" . $idb);
	} else
		return array(_T('info_erreur_squelette'), $param);
}

// {traduction}
// http://www.spip.net/@traduction
function critere_traduction_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if ($param == 'traduction') {
		$boucle->where[] = $boucle->id_table.".id_trad > 0";
		$boucle->where[] = $boucle->id_table.".id_trad ='\"."
		. calculer_argument_precedent($idb, 'id_trad',
			$boucles)
		. ".\"'";

	} else
		return array(_T('info_erreur_squelette'), $param);
}

// {origine_traduction}
// http://www.spip.net/@origine_traduction
function critere_origine_traduction_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if ($param == 'origine_traduction')
		$boucle->where[] = $boucle->id_table.".id_trad = "
		. $boucle->id_table . '.' . $boucle->primary;
	else
		return array(_T('info_erreur_squelette'), $param);
}


// {meme_parent}
// http://www.spip.net/@meme_parent
function critere_meme_parent_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if ($param != 'meme_parent')
		return array(_T('info_erreur_squelette'), $param);
	else {
		if ($boucle->type_requete == 'rubriques') {
			$boucle->where[] = $boucle->id_table.".id_parent='\"."
			. calculer_argument_precedent($idb, 'id_parent',
			$boucles)
			. ".\"'";
		} else if ($boucle->type_requete == 'forums') {
			$boucle->where[] = $boucle->id_table.".id_parent='\"."
			. calculer_argument_precedent($idb, 'id_parent',
			$boucles)
			. ".\"'";
			$boucle->where[] = $boucle->id_table.".id_parent > 0";
			$boucle->plat = true;
		} else
			return array(_L("{meme_parent} ne s'applique qu'aux boucles (FORUMS) ou (RUBRIQUES)"), "BOUCLE" . $idb);
	}
}

// {branche ?}
// http://www.spip.net/@branche
function critere_branche_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if (preg_match('/branche[[:space:]]*([?])?$/i', $param, $regs)) {
		$c = "calcul_mysql_in('".$boucle->id_table.".id_rubrique',
		calcul_branche(" . calculer_argument_precedent($idb,
		'id_rubrique', $boucles) . "), '')";
		if (!$regs[1])
			$where = "\". $c .\"" ;
		else
			$where = "\".("
			. calculer_argument_precedent($idb, 'id_rubrique',
			$boucles)."? $c : 1).\"";

		if ($not)
			$boucle->where[] = "NOT($where)";
		else
			$boucle->where[] = $where;
	} else
		return array(_T('info_erreur_squelette'), $param);
}

// Tri : {par xxxx}
// http://www.spip.net/@par
function critere_par_dist($idb, &$boucles, $param, $not) {
	$boucle = &$boucles[$idb];
	if ($not)
		return array(_T('info_erreur_squelette'), $param);

	preg_match('/par[[:space:]]*(.*)/ims', $param, $regs);
	$tri = trim($regs[1]);

	// par hasard
	if ($tri == 'hasard') {
		// on pourrait peut-etre passer a "RAND() AS alea" ?
		$boucle->select[] = "MOD(".$boucle->id_table . '.' . $boucle->primary." * UNIX_TIMESTAMP(),
		32767) & UNIX_TIMESTAMP() AS alea";
		$boucle->order = "'alea'";
	}

	// par titre_mot
	else if ($tri == 'titre_mot') {
		$boucle->order= "'mots.titre'";
	}

	// par type_mot
	else if ($tri == 'type_mot'){
		$boucle->order= "'mots.type'";
	}
	// par points
	else if ($tri == 'points'){
		$boucle->order= "'points'";
	}
	// par num champ(, suite)
	else if (ereg("^num[[:space:]]+([^,]*)(,.*)?",$tri, $match2)) {
		$boucle->select[] = "0+".$boucle->id_table.".".$match2[1]." AS num";
		$boucle->order = "'num".texte_script($match2[2])."'";
	}
	// par champ
	else if (ereg("^[a-z][a-z0-9]*$", $tri)) {
		if ($tri == 'date')
			$tri = $GLOBALS['table_date'][$boucle->type_requete];
		$boucle->order = "'".$boucle->id_table.".".$tri."'";
	}
	// tris par critere bizarre
	// (formule composee, virgules, etc).
	// autoriser le hack {par $GLOBALS["tri"]}
	else
		$boucle->order = "\"$tri\"";
}




//
// La fonction d'aiguillage sur le nom du criteres
//

function calculer_criteres ($idb, &$boucles) {

	foreach($boucles[$idb]->param as $param) {
		// Analyse du critere
		preg_match("/^([!]?)[[:space:]]*(debut|([a-z_]+))/ism",
			$param, $match);
		$critere = $match[2];
		$not = ($match[1] == '!');

		// critere personnalise ?
		$f = "critere_".$critere;
		if (!function_exists($f))
			$f .= '_dist';

		// fonction critere standard ?
		if (!function_exists($f))
			$f = 'calculer_critere_DEFAUT';
		$res = $f($idb, $boucles, $param, $not);
		if (is_array($res)) return $res; # erreur
		
	}
}

# Criteres numriques et de comparaison

function calculer_critere_DEFAUT($idb, &$boucles, $param, $not) {
  global $tables_relations, $table_primary, $table_des_tables, $table_date, $tables_des_serveurs_sql;
	$boucle = &$boucles[$idb];				# nom de la boucle
	$type = $boucle->type_requete;			# articles
	$id_table = $boucle->id_table;	# articles ->   'table';
	$primary = $boucle->primary;
	$id_field = $id_table . '.' . $primary; 

	if (ereg('^([0-9]+)/([0-9]+)$', $param, $match)) {
			$boucle->partie = $match[1];
			$boucle->total_parties = $match[2];
			$boucle->mode_partie = '/';
		}
		else if (ereg('^(([0-9]+)|n)(-([0-9]+))?,(([0-9]+)|n)(-([0-9]+))?$', $param, $match)) {
			if (($match[2]!='') && ($match[6]!=''))
				$boucle->limit = $match[2].','.$match[6];
			else {
				$boucle->partie =
					($match[1] != 'n') ? $match[1] :
					($match[4] ? $match[4] : 0);
				$boucle->total_parties =
					($match[5] != 'n') ? $match[5] :
					($match[8] ? $match[8] : 0);
				$boucle->mode_partie =
				(($match[1]=='n')?'-':'+').(($match[5]=='n')?'-':'+');
			}
		}

		// Restriction de valeurs (implicite ou explicite)
		else if (eregi('^([a-z_]+\(?[a-z_]*\)?) *(\??)((!?)(<=?|>=?|==?|IN) *"?([^<>=!"]*))?"?$', $param, $match)) {
			$op = $match[5];
			// Variable comparee
			$col = $match[1];
			$fct = '';
			if (ereg("([a-z_]+)\(([a-z_]+)\)", $col,$match3))
			  {
				$col = $match3[2];
				$fct = $match3[1];
			  }
			$col_table = $id_table;
			// Valeur de comparaison
			if ($match[3]) {
				if (strtoupper($op) != 'IN') {
					$val = calculer_param_dynamique($match[6], $boucles, $idb);
					if (is_array($val)) return $val;
				}
				else {
				// traitement special des valeurs textuelles
					ereg("^ *\(?(.*[^)])\)? *$",$match[6], $val2);
					$val2 = split(" *, *", $val2[1]);
					foreach ($val2 as $v) {
						$v = calculer_param_dynamique($v, $boucles, $idb);
						if (is_array($v)) return $v;
						if (strpos('"0123456789',$v[0]) !== false)
							$val3[] = $v;
						else
							$val3[] = "'$v'";
					}
					$val = join(',', $val3);
				}
			}
			
			else {
				$val = $match[1];

		// Cas special {lang} : aller chercher $GLOBALS['spip_lang']
				if ($val == 'lang')
					$val = '".$GLOBALS[\'spip_lang\']."';
				else {
				// Si id_parent, comparer l'id_parent avec l'id_objet
				// de la boucle superieure
					if ($val == 'id_parent')
						$val = $primary;
				// Si id_enfant, comparer l'id_objet avec l'id_parent
				// de la boucle superieure
					else if ($val == 'id_enfant')
						$val = 'id_parent';
					$val = calculer_argument_precedent($idb, $val, $boucles) ;
					if (ereg('^\$',$val))
						$val = '" . addslashes(' . $val . ') . "';
					else
						$val = addslashes($val);
				}

			}

			// Traitement general des relations externes
			if ($s = $tables_relations[$type][$col]) {
				$col_table = $s;
				$boucle->from[] = "$col_table AS $col_table";
				$boucle->where[] = "$id_field=$col_table." . $primary;
				$boucle->group = $id_field;
				$boucle->select[] = $id_field; # pour postgres, neuneu ici
				$boucle->lien = true;
			}
			// Cas particulier pour les raccourcis 'type_mot' et 'titre_mot'
			else if ($type != 'mots'
			AND ($col == 'type_mot' OR $col == 'titre_mot'
			OR $col == 'id_groupe')) {
				if ($type == 'forums')
					$col_lien = "forum";
				else if ($type == 'syndication')
					$col_lien = "syndic";
				else
					$col_lien = $type;
				$boucle->from[] = "mots_$col_lien AS lien_mot";
				$boucle->from[] = 'mots AS mots';
				$boucle->where[] = "$id_field=lien_mot." . $primary;
				$boucle->where[] = 'lien_mot.id_mot=mots.id_mot';
				$boucle->group = $id_field;
				$boucle->select[] = $id_field; # pour postgres, neuneu ici
				$col_table = 'mots';

				$boucle->lien = true;
				if ($col == 'type_mot')
					$col = 'type';
				else if ($col == 'titre_mot')
					$col = 'titre';
				else if ($col == 'id_groupe')
					$col = 'id_groupe';
			}

			// Cas particulier : selection des documents selon l'extension
			if ($type == 'documents' AND $col == 'extension')
				$col_table = 'types_documents';
			// HACK : selection des documents selon mode 'image'
			// (a creer en dur dans la base)
			else if ($type == 'documents' AND $col == 'mode'
			AND $val == 'image')
				$val = 'vignette';
			// Cas particulier : lier les articles syndiques
			// au site correspondant
			else if ($type == 'syndic_articles' AND
			!ereg("^(id_syndic_article|titre|url|date|descriptif|lesauteurs)$",$col))
				$col_table = 'syndic';

			// Cas particulier : id_enfant => utiliser la colonne id_objet
			if ($col == 'id_enfant')
				$col = $primary;
			// Cas particulier : id_secteur = id_rubrique pour certaines tables
			if (($type == 'breves' OR $type == 'forums') AND $col == 'id_secteur')
				$col = 'id_rubrique';

			// Cas particulier : expressions de date
			if (ereg("^(date|mois|annee|age|age_relatif|jour_relatif|mois_relatif|annee_relatif)(_redac)?$", $col, $regs)) {
				$col = $regs[1];
				if ($regs[2]) {
					$date_orig = $id_table . ".date_redac";
					$date_compare = '\'" . normaliser_date(' .
					calculer_argument_precedent($idb, 'date_redac', $boucles) .
					') . "\'';
				}
				else {
					$date_orig = "$id_table." . $table_date[$type];
					$date_compare = '\'" . normaliser_date(' .
					  calculer_argument_precedent($idb, 'date', $boucles) .
					  ') . "\'';
				}

				if ($col == 'date')
					$col = $date_orig;
				else if ($col == 'mois') {
					$col = "MONTH($date_orig)";
					$col_table = '';
				}
				else if ($col == 'annee') {
					$col = "YEAR($date_orig)";
					$col_table = '';
				}
				else if ($col == 'age') {
					$col = calculer_param_date("now()", $date_orig);
					$col_table = '';
				}
				else if ($col == 'age_relatif') {
					$col = calculer_param_date($date_compare, $date_orig);
					$col_table = '';
				}
				else if ($col == 'jour_relatif') {
					$col = "LEAST(TO_DAYS(" .$date_compare . ")-TO_DAYS(" .
					$date_orig . "), DAYOFMONTH(" . $date_compare .
					")-DAYOFMONTH(" . $date_orig . ")+30.4368*(MONTH(" .
					$date_compare . ")-MONTH(" . $date_orig .
					"))+365.2422*(YEAR(" . $date_compare . ")-YEAR(" .
					$date_orig . ")))";
					$col_table = '';
				}
				else if ($col == 'mois_relatif') {
					$col = "MONTH(" . $date_compare . ")-MONTH(" .
					$date_orig . ")+12*(YEAR(" . $date_compare .
					")-YEAR(" . $date_orig . "))";
					$col_table = '';
				}
				else if ($col == 'annee_relatif') {
					$col = "YEAR(" . $date_compare . ")-YEAR(" .
					$date_orig . ")";
					$col_table = '';
				}
			}

			if ($type == 'forums' AND
			($col == 'id_parent' OR $col == 'id_forum'))
				$boucle->plat = true;

			// Operateur de comparaison

			if (!$op)
				$op = '=';
			else if ($op == '==')
				$op = 'REGEXP';
			else if (strtoupper($op) == 'IN') {
				// traitement special des valeurs textuelles
				$where = "$col IN ($val)";
				if ($match[4] == '!') {
					$where = "NOT ($where)";
				} else {
					if (!$boucle->order) {
						$boucle->order = 'rang';
						$boucle->select[] =
						"FIND_IN_SET($col, \\\"$val\\\") AS rang";
					}
				}
				$boucle->where[] = $where;
				$op = '';
			}

			if ($col_table)
				$col = "$col_table.$col";

			if ($op) {
				if ($fct) $col = "$fct($col)";
				if ($match[4] == '!')
					$where = "NOT ($col $op '$val')";
				else
					$where = "($col $op '$val')";

				// operateur optionnel {lang?}
				if ($match[2]) {
					$champ = calculer_argument_precedent($idb, $match[1], $boucles) ;
					$where = "\".($champ ? \"$where\" : 1).\"";
				}

				$boucle->where[] = $where;
			}

		} // fin du if sur les restrictions de valeurs

		// Special rubriques
		else if ($param == 'meme_parent') {
			$boucle->where[] = "$id_table.id_parent='\"." .
				calculer_argument_precedent($idb, 'id_parent', $boucles) . ".\"'";
			if ($type == 'forums') {
				$boucle->where[] = "$id_table.id_parent > 0";
				$boucle->plat = true;
			}
		}
		else if (ereg("^branche *(\??)", $param, $regs)) {
			$c = "calcul_mysql_in('$id_table.id_rubrique',
			calcul_branche(" . calculer_argument_precedent($idb, 'id_rubrique',
			$boucles) . "), '')";
			if (!$regs[1])
				$boucle->where[] = "\". $c .\"" ;
			else
				$boucle->where[] = "\".(".calculer_argument_precedent($idb, 'id_rubrique', $boucles)."? $c : 1).\"";
		}
}


function calculer_param_date($date_compare, $date_orig) {
	return
	"LEAST((UNIX_TIMESTAMP(" .
	$date_compare .
	")-UNIX_TIMESTAMP(" .
	$date_orig .
	"))/86400,\n\tTO_DAYS(" .
	$date_compare .
	")-TO_DAYS(" .
	$date_orig .
	"),\n\tDAYOFMONTH(" .
	$date_compare .
	")-DAYOFMONTH(" .
	$date_orig .
	")+30.4368*(MONTH(" .
	$date_compare .
	")-MONTH(" .
	$date_orig .
	"))+365.2422*(YEAR(" .
	$date_compare .
	")-YEAR(" .
	$date_orig .
	")))";
}

# Le caractere denotant un variable passee dans l'URL

define("_REF_HTTP_GET_VAR", '%');

//
// Calculer les parametres
//
function calculer_param_dynamique($val, &$boucles, $idb) {
	if (ereg(NOM_DE_CHAMP, $val, $regs)) {
	  	$champ = new Champ;
		$champ->nom_boucle = $regs[2];
		$champ->nom_champ = $regs[3];
		$champ->etoile = $regs[4];
		$champ->id_boucle = $idb;
		$champ->boucles = &$boucles;
		$champ->id_mere = $idb;
		$champ = calculer_champ($champ);
		return '" . addslashes(' . $champ . ') . "';

	} else {
		if ($val[0]==_REF_HTTP_GET_VAR)
		  return '" . addslashes($Pile[0][\''. substr($val,1)  ."']) . \"";
		else
		  return addslashes($val);
	}
}


?>