Update of /home/spip-cvs/spip
In directory alan:/tmp/cvs-serv5332
Modified Files:
inc-admin.php3 inc-calcul.php3 inc-reqsql-squel.php3
Added Files:
inc-balises.php3 inc-calcul-outils.php3 inc-compilo-debug.php3
inc-compilo-index.php3 inc-compilo.php3 inc-criteres.php3
Removed Files:
inc-arg-squel.php3 inc-calcul-squel.php3 inc-calcul_html4.php
inc-calcul_mysql3.php inc-form-squel.php3
Log Message:
codes mouvants (ce n'est qu'un début)
http://thread.gmane.org/gmane.comp.web.spip.devel/20211
à noter : critere {doublons a} indépendant de {doublons b}
--- NEW FILE: inc-criteres.php3 ---
<?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($param, $not, &$boucle, $infos) {
global $table_des_tables;
if ($param != 'racine' OR $not)
return "erreur";
$boucle->where[] = $infos['id_table'].".id_parent='0'";
}
// {exclus}
// http://www.spip.net/@exclus
function critere_exclus_dist($param, $not, &$boucle, $infos) {
if ($param != 'exclus' OR $not)
return "erreur";
$boucle->where[] = $infos['id_field']."!='\"."
. calculer_argument_precedent($infos['idb'],
$infos['primary'], $infos['boucles']) . ".\"'";
}
// {doublons} ou {unique}
// http://www.spip.net/@doublons
function critere_doublons_dist($param, $not, &$boucle, $infos) {
if (!preg_match("/(doublons|unique)[[:space:]]*([a-z_0-9]*)/i",
$param, $match))
return "erreur";
$boucle->doublons = $infos['type'].$match[2];
$boucle->where[] = '" .' .
"calcul_mysql_in('".$infos['id_field']."', "
.'"0".$doublons[\''.$boucle->doublons."'], 'NOT') . \"";
}
// {lang_select}
// http://www.spip.net/@lang_select
function critere_lang_select_dist($param, $not, &$boucle, $infos) {
if (preg_match('/lang_select(=(oui|non))?$/i', $param, $match)) {
if (!$lang_select = $match[3])
$lang_select = 'oui';
if ($not)
$lang_select = ($lang_select=='oui')?'non':'oui';
$boucle->lang_select = $lang_select;
}
else return "erreur";
}
// {debut_xxx}
// http://www.spip.net/@debut_
function critere_debut_dist($param, $not, &$boucle, $infos) {
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 "erreur";
}
// {recherche}
// http://www.spip.net/@recherche
function critere_recherche_dist($param, $not, &$boucle, $infos) {
$boucle->from[] = "index_".$infos['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$/', '', $infos['id_table']);
// rec.id_article = articles.id_article
$boucle->where[] = "rec.".$id
. "=" . $infos['id_table'].'.'.$id;
// group by articles.id_article
$boucle->group = $infos['id_field'];
// 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)
$infos['boucles'][$infos['idb']]->hash = true;
}
// {inverse}
// http://www.spip.net/@inverse
function critere_inverse_dist($param, $not, &$boucle, $infos) {
// Classement par ordre inverse
if ($param == 'inverse' AND !$not) {
if ($boucle->order)
$boucle->order .= ".' DESC'";
else
return _L(" : inversion d'un ordre inexistant");
} else
return 'erreur';
}
// {traduction}
// http://www.spip.net/@traduction
function critere_traduction_dist($param, $not, &$boucle, $infos) {
if ($param == 'traduction') {
$boucle->where[] = $infos['id_table'].".id_trad > 0";
$boucle->where[] = $infos['id_table'].".id_trad ='\"."
. calculer_argument_precedent($infos['idb'], 'id_trad',
$infos['boucles'])
. ".\"'";
} else
return 'erreur';
}
// {origine_traduction}
// http://www.spip.net/@origine_traduction
function critere_origine_traduction_dist($param, $not, &$boucle, $infos) {
if ($param == 'origine_traduction')
$boucle->where[] = $infos['id_table'].".id_trad = "
. $infos['id_field'];
else
return "erreur";
}
// {meme_parent}
// http://www.spip.net/@meme_parent
function critere_meme_parent_dist($param, $not, &$boucle, $infos) {
if ($param != 'meme_parent')
return "erreur";
else {
if ($infos['type'] == 'rubriques') {
$boucle->where[] = $infos['id_table'].".id_parent='\"."
. calculer_argument_precedent($infos['idb'], 'id_parent',
$infos['boucles'])
. ".\"'";
} else if ($infos['type'] == 'forums') {
$boucle->where[] = $infos['id_table'].".id_parent='\"."
. calculer_argument_precedent($infos['idb'], 'id_parent',
$infos['boucles'])
. ".\"'";
$boucle->where[] = $infos['id_table'].".id_parent > 0";
$boucle->plat = true;
} else
return _L("erreur {meme_parent} ne s'applique pas à
d'autres boucles que (FORUMS) ou (RUBRIQUES)");
}
}
// {branche ?}
// http://www.spip.net/@branche
function critere_branche_dist($param, $not, &$boucle, $infos) {
if (preg_match('/branche[[:space:]]*([?])?$/i', $param, $regs)) {
$c = "calcul_mysql_in('".$infos['id_table'].".id_rubrique',
calcul_branche(" . calculer_argument_precedent($infos['idb'],
'id_rubrique', $infos['boucles']) . "), '')";
if (!$regs[1])
$where = "\". $c .\"" ;
else
$where = "\".("
. calculer_argument_precedent($infos['idb'], 'id_rubrique',
$infos['boucles'])."? $c : 1).\"";
if ($not)
$boucle->where[] = "NOT($where)";
else
$boucle->where[] = "$where";
} else
return "erreur";
}
// Tri : {par xxxx}
// http://www.spip.net/@par
function critere_par_dist($param, $not, &$boucle, $infos) {
if ($not)
return "erreur";
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(".$infos['id_field']." * 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+".$infos['id_table'].".".$match2[1]." AS num";
$boucle->order = "'num".texte_script($match2[2])."'";
}
// par champ
else if (ereg("^[a-z0-9]+$", $tri)) {
if ($tri == 'date')
$tri = $GLOBALS['table_date'][$infos['type']];
$boucle->order = "'".$infos['id_table'].".".$tri."'";
}
// tris par critere bizarre
// (formule composee, virgules, etc).
else {
$boucle->order = "'".texte_script($tri)."'";
}
}
function calculer_criteres ($idb, &$boucles) {
global $tables_relations, $table_primary, $table_des_tables, $table_date;
$boucle = &$boucles[$idb]; # nom de la boucle
$type = $boucle->type_requete; # articles
$params = $boucle->param;
$id_table = $table_des_tables[$type]; # articles -> 'table'
$primary = $table_primary[$type]; # id_article -> 'id'
$id_field = $id_table . "." . $primary; # articles.id_article -> 'table_id'
// les infos complementaires a passer aux fonctions critere_xxx
$infos = array(
'type' => $type, # (articles)
'id_table' => $id_table, # 'table'
'id_field' => $id_field, # 'table_id'
'primary' => $primary, # 'id'
'boucles' => &$boucles, # boucles
'idb' => $idb # 'nom_boucle'
);
// Cas specifique pour la hierarchie : on cree des criteres supplementaires
// $hierarchie sera calculee par une fonction de inc-calcul-mysql
if ($type == 'hierarchie') {
$boucle->where[] = 'id_rubrique IN ($hierarchie)';
$boucle->select[] = 'FIND_IN_SET(id_rubrique, \'$hierarchie\')-1 AS rang';
$boucle->order = 'rang';
// Supprimer le parametre id_article/id_rubrique/id_syndic
// qui est superfetatoire (mais indique dans la doc)
$params2 = array();
foreach($params as $param)
if (!ereg('^id_(article|syndic|rubrique)$', $param))
$params2[]=$param;
$params = $params2;
$boucle->hierarchie = '$hierarchie = calculer_hierarchie('
.calculer_argument_precedent($idb, 'id_rubrique', $boucles)
.', false);';
}
//
// Traitement de la liste des criteres
//
if (is_array($params)) {
foreach($params as $param) {
// Analyse du critere
preg_match("/^([!]?)[[:space:]]*(debut|([a-z_]+))/ism",
$param, $match);
$critere = $match[2];
$not = ($match[1] == '!');
// synonymes ?
$synonymes = array('unique'=>'doublons');
if ($synonymes[$critere]) $critere = $synonymes[$critere];
// critere personnalise ?
$f = "critere_".$critere;
if (!function_exists($f))
$f .= '_dist';
// fonction critere standard ?
if (function_exists($f)) {
if ($erreur = $f($param, $not, $boucle, $infos)) {
include_local('inc-admin.php3');
erreur_squelette(_T('info_erreur_squelette'),
_L(" : erreur dans le critere {$param} : $erreur"),
$idb);
}
}
# Criteres a passer en fonction critere_xxx_dist
else 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_]+) *(\??)((!?)(<=?|>=?|==?|IN) *"?([^<>=!"]*))?"?$', $param, $match)) {
// Variable comparee
$col = $match[1];
$col_table = $id_table;
// Valeur de comparaison
if ($match[3])
$val = calculer_param_dynamique($match[6], $boucles, $idb);
else {
$val = $match[1];
// Si id_parent, comparer l'id_parent avec l'id_objet
// de la boucle superieure
if ($val == 'id_parent')
$val = $table_primary[$type];
// 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." . $table_primary[$type];
$boucle->group = $id_field;
$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." . $table_primary[$type];
$boucle->where[] = 'lien_mot.id_mot=mots.id_mot';
$boucle->group = $id_field;
$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 = $table_primary[$type];
// 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
$op = $match[5];
if (!$op)
$op = '=';
else if ($op == '==')
$op = 'REGEXP';
else if (strtoupper($op) == 'IN') {
// traitement special des valeurs textuelles
$val2 = split(",", $val);
foreach ($val2 as $v) {
$v = trim($v);
if (ereg("^[0-9]+$",$v))
$val3[] = $v;
else
$val3[] = "'$v'";
}
$val = join(',', $val3);
$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 ($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).\"";
}
// Selection du classement
else if (ereg('^par[[:space:]]+([^}]*)$', $param, $match)) {
$tri = trim($match[1]);
if ($tri == 'hasard') { // par hasard
$boucle->select[] = "MOD($id_field * UNIX_TIMESTAMP(),
32767) & UNIX_TIMESTAMP() AS alea";
$boucle->order = 'alea';
}
else if ($tri == 'titre_mot') { // par titre_mot
$boucle->order= 'mots.titre';
}
else if ($tri == 'type_mot'){ // par type_mot
$boucle->order= 'mots.type';
}
else if ($tri == 'points'){ // par points
$boucle->order= 'points';
}
else if (ereg("^num[[:space:]]+([^,]*)(,.*)?",$tri, $match2)) {
// par num champ
$boucle->select[] = "0+$id_table.".$match2[1]." AS num";
$boucle->order = "num".$match2[2];
}
else if (ereg("^[a-z0-9]+$", $tri)) { // par champ
if ($tri == 'date')
$tri = $table_date[$type];
$boucle->order = "$id_table.$tri";
}
else {
// tris par critere bizarre
// (formule composee, virgules, etc).
$boucle->order = $tri;
}
}
}
}
}
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 .
")))";
}
//
// Calculer les parametres
//
function calculer_param_dynamique($val, &$boucles, $idb) {
if (ereg("^#([A-Za-z0-9_-]+)$", $val, $m)) {
$c = calculer_champ('',$m[1], $idb, $boucles,$idb);
if (ereg("[$]Pile[[][^]]+[]][[]'[^]]*'[]]", $c, $v))
return $v[0];
else {
# erreur
include_local("inc-admin.php3");
erreur_squelette(_L("parametre dynamique inexistant ?"), '', $idb);
}
} else {
if (ereg('^\$(.*)$',$val,$m))
return '$Pile[0][\''. $m[1] ."']";
else
return $val;
}
}
?>
Index: inc-calcul.php3
RCS file: /home/spip-cvs/spip/inc-calcul.php3,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -d -r1.96 -r1.97
--- inc-calcul.php3 27 Aug 2004 04:27:02 -0000 1.96
+++ inc-calcul.php3 28 Aug 2004 23:17:42 -0000 1.97
@@ -15,8 +15,10 @@
include_ecrire("inc_lang.php3");
include_ecrire("inc_documents.php3");
include_ecrire("inc_forum.php3");
-include_local("inc-calcul_mysql3.php");
-include_local("inc-calcul_html4.php");
+include_local("inc-calcul-outils.php3");
+
+#include_local("inc-calcul_html"); # anciens noms des fichiers
+#include_local("inc-calcul_mysql");
// Ce fichier peut contenir une affectation de $dossier_squelettes indiquant
@@ -66,7 +68,12 @@
}
// sinon le compiler
- include_local("inc-calcul-squel.php3");
+ if ($GLOBALS['tradition']) {
+ include_local("inc-calcul-squel.php3");
+ }
+ else {
+ include_local("inc-compilo.php3");
+ }
if (!lire_fichier ($sourcefile, $skel)) {
// erreur webmaster : $fond ne correspond a rien
include_ecrire ("inc_presentation.php3");
@@ -152,6 +159,7 @@
// Calculer la page a partir du main() du skel compile
$page = $fonc(array('cache' =>$cache),
array($contexte),
+ /* obsolete avec les doublons de inc-compilo */
array(
'articles' => '0',
'rubriques' => '0',
@@ -295,7 +303,7 @@
serialize($page['signal']))." -->\n";
// Enregistrer le fichier cache
- if ($delais > 0)
+ if ($delais > 0 AND empty($GLOBALS['HTTP_POST_VARS']))
ecrire_fichier($chemin_cache, $signal.$page['texte']);
return $page;
@@ -303,66 +311,6 @@
-# Fonctions appelees par les squelettes (insertion dans le code trop lourde)
-
-tester_variable('espace_logos',3); // HSPACE=xxx VSPACE=xxx pour les logos (#LOGO_ARTICLE)
-tester_variable('espace_images',3); // HSPACE=xxx VSPACE=xxx pour les images integrees
-
-//
-// Retrouver le logo d'un objet (et son survol)
-//
-
-function cherche_image($id_objet, $type_objet) {
- // cherche l'image liee a l'objet
- $on = cherche_image_nommee($type_objet.'on'.$id_objet);
-
- // cherche un survol
- $off =(!$on ? '' :
- cherche_image_nommee($type_objet.'off'.$id_objet));
-
- if (!$on)
- return false;
-
- return array($on, $off);
-}
-
-function cherche_logo_objet ($type, $id_objet, $on = false, $off = false, $flag_fichier=false) {
-
-spip_log("cherche logo $type $id_objet $on $off $flag_fichier");
- switch($type) {
- case 'ARTICLE':
- $logo = cherche_image($id_objet, 'art');
- break;
- case 'AUTEUR':
- $logo = cherche_image($id_objet, 'aut');
- break;
- case 'BREVE':
- $logo = cherche_image($id_objet, 'breve');
- break;
- case 'SITE':
- $logo = cherche_image($id_objet, 'site');
- break;
- case 'MOT':
- $logo = cherche_image($id_objet, 'mot');
- break;
- // recursivite
- case 'RUBRIQUE':
- if (!($logo = cherche_image ($id_objet, 'rub'))
- AND $id_objet > 0)
- $logo = cherche_logo_objet('RUBRIQUE',
- sql_parent($id_objet), true, true);
- break;
- default:
- spip_log("cherche_logo_objet: type '$type' inconnu");
- }
-
- // Quelles images sont demandees ?
- if (!$on) unset($logo[0]);
- if (!$off) unset($logo[1]);
-
- if ($logo[0] OR $logo[1])
- return $logo;
-}
// Fonction appelee par le skel pour assembler les balises
@@ -383,4 +331,59 @@
return $texte;
}
+### A passer peut-etre dans inc_db_mysql
+// Cette fonction est systematiquement appelee par les squelettes
+// pour constuire une requete SQL de type "lecture" (SELECT) a partir
+// de chaque boucle.
+// Elle construit et exe'cute une reque^te SQL correspondant a` une balise
+// Boucle ; elle notifie une erreur SQL dans le flux de sortie et termine
+// le processus.
+// Sinon, retourne la ressource interrogeable par fetch_row ou fetch_array.
+// Elle peut etre re'de'finie pour s'interfacer avec d'autres serveurs SQL
+// Recoit en argument:
+// - le tableau des champs a` ramener
+// - le tableau des tables a` consulter
+// - le tableau des conditions a` remplir
+// - le crite`re de regroupement
+// - le crite`re de classement
+// - le crite`re de limite
+// - une sous-requete e'ventuelle (MySQL > 4.1)
+// - un compteur de sous-requete
+// - le nom de la table
+// - le nom de la boucle (pour le message d'erreur e'ventuel)
+
+
+function spip_abstract_select (
+ $select = array(), $from = array(), $where = '',
+ $groupby = '', $orderby = '', $limit = '',
+ $sousrequete = '', $cpt = '',
+ $table = '', $id = '') {
+
+ $DB = 'spip_';
+ $q = " FROM $DB" . join(", $DB", $from)
+ . (is_array($where) ? ' WHERE ' . join(' AND ', $where) : '')
+ . ($groupby ? " GROUP BY $groupby" : '')
+ . ($orderby ? "\nORDER BY $orderby" : '')
+ . ($limit ? "\nLIMIT $limit" : '');
+
+ if (!$sousrequete)
+ $q = " SELECT ". join(", ", $select) . $q;
+ else
+ $q = " SELECT S_" . join(", S_", $select)
+ . " FROM (" . join(", ", $select)
+ . ", COUNT(".$sousrequete.") AS compteur " . $q
+ .") AS S_$table WHERE compteur=" . $cpt;
+
+ //
+ // Erreur ? C'est du debug, ou une erreur du serveur
+ //
+ if (!($result = @spip_query($q))) {
+ include_local('inc-admin.php3');
+ echo erreur_requete_boucle($q, $id, $table);
+ }
+
+ # spip_log(spip_num_rows($result));
+ return $result;
+}
+
?>
--- NEW FILE: inc-compilo-index.php3 ---
<?php
// Definition des classes Boucle, Texte, Inclure, etc.,
// et fonctions de recherche et de reservation
// dans l'arborescence des boucles
// Ce fichier ne sera execute qu'une fois
if (defined("_INC_COMPILO_INDEX")) return;
define("_INC_COMPILO_INDEX", "1");
//
// encodage d'une boucle SPIP en un objet PHP
//
class Boucle {
var $type = 'boucle';
var $id_boucle, $id_parent;
var $cond_avant, $milieu, $cond_apres, $cond_altern;
var $lang_select;
var $type_requete;
var $param;
var $separateur;
var $doublons;
var $partie, $total_parties,$mode_partie;
var $externe = ''; # appel a partir d'une autre boucle (recursion)
// champs pour la construction de la requete SQL
var $tout = false;
var $plat = false;
var $select;
var $from;
var $where;
var $limit;
var $group = '';
var $order = '';
var $date = 'date' ;
var $hash = false ;
var $lien = false;
var $sous_requete = false;
var $compte_requete = 1;
var $hierarchie = '';
// champs pour la construction du corps PHP
var $return;
var $numrows = false;
}
class Texte {
var $type = 'texte';
var $texte;
}
class Inclure {
var $type = 'include';
var $fichier;
var $params;
}
class Champ {
var $type = 'champ';
var $nom_champ;
var $cond_avant, $cond_apres; // tableaux d'objets
var $fonctions;
}
//
// Structure de donnees pour parler aux fonctions calcul_champ_TOTO
//
class ParamChamp {
var $fonctions;
var $nom_champ;
var $id_boucle;
var $boucles;
var $id_mere;
var $type_requete;
var $code; // code du calcul
var $process; // processeurs standards, exemple 'propre(%s)'
var $etoile; // le champ a ete appele avec une etoile (booleen)
var $type; // 'num'erique, 'h'=texte (html) ou 'p'=script (php) ?
// -> definira les pre et post-traitements obligatoires
function retour() {
// Annuler les traitements si le champ est etoile
if ($this->etoile) unset($this->process);
$code_filtre = applique_filtres(
$this->fonctions,
$this->code,
$this->id_boucle,
$this->boucles,
$this->id_mere,
$this->type,
$this->process
);
return $code_filtre;
}
}
// index_pile retourne la position dans la pile du champ SQL $nom_champ
// en prenant la boucle la plus proche du sommet de pile (indique par $idb).
// Si on ne trouve rien, on considere que ca doit provenir du contexte
// (par l'URL ou l'include) qui a ete recopie dans Pile[0]
// (un essai d'affinage a debouche sur un bug vicieux)
// Si ca reference un champ SQL, on le memorise dans la structure $boucles
// afin de construire un requete SQL minimale (plutot qu'un brutal 'SELECT *')
include_ecrire('inc_serialbase.php3');
function index_pile($idb, $nom_champ, &$boucles) {
global $exceptions_des_tables, $table_des_tables, $tables_principales;
// Recherche d'un champ dans un etage superieur
$i = 0;
if ($c=strpos($nom_champ, ':')) {
$idbs = substr($nom_champ, 0, $c);
$nom_champ = substr($nom_champ, $c+1);
while (($idb != $idbs) && $idb) {
$i++;
$idb = $boucles[$idb]->id_parent;
}
}
$c = strtolower($nom_champ);
// attention a la boucle nommee 0 ....
while ($idb!== '') {
#spip_log("Cherche: $nom_champ '$idb' '$c'");
$r = $boucles[$idb]->type_requete;
// indirection (pour les rares cas ou le nom de la table est /= du type)
$t = $table_des_tables[$r];
if (!$t)
$t = $r; // pour les tables non Spip
// $t est le nom PHP de cette table
#spip_log("Go: idb='$idb' r='$r' c='$c' nom='$nom_champ'");
$desc = $tables_principales[$t];
if (!$desc) {
include_local("inc-admin.php3");
erreur_squelette(_L("Table SQL absente de \$tables_principales dans inc_serialbase"), $r, "'$idb'");
}
$excep = $exceptions_des_tables[$r][$c];
if ($excep) {
// entite SPIP alias d'un champ SQL
if (!is_array($excep)) {
$e = $excep;
}
// entite SPIP alias d'un champ dans une autre table SQL
else {
$t = $excep[0];
$e = $excep[1];
}
}
else {
// $e est le type SQL de l'entree (ici utile comme booleen)
// entite SPIP homonyme au champ SQL
if ($desc['field'][$c])
$e = $c;
else
$e = '';
}
#spip_log("Dans $idb ($t $e): $desc");
// On l'a trouve
if ($e) {
$boucles[$idb]->select[] = $t . "." . $e;
return '$Pile[$SP' . ($i ? "-$i" : "") . '][\'' . $e . '\']';
}
// Sinon on remonte d'un cran
$idb = $boucles[$idb]->id_parent;
$i++;
}
#spip_log("Pas vu $nom_champ dans les " . count($boucles) . " boucles");
// esperons qu'il y sera
return('$Pile[0][\''.$nom_champ.'\']');
}
// cette fonction sert d'API pour demander le champ '$champ' dans la pile
function champ_sql($champ, $p) {
return index_pile($p->id_boucle, $champ, $p->boucles);
}
# calculer_champ genere le code PHP correspondant a la balise Spip $nom_champ
# Retourne une EXPRESSION php
function calculer_champ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere, $etoile = false) {
// Preparer les parametres
$p = new ParamChamp;
$p->fonctions = $fonctions;
$p->nom_champ = $nom_champ;
$p->id_boucle = $id_boucle;
$p->boucles = &$boucles;
$p->id_mere = $id_mere;
$p->type = 'html';
$p->process = '';
$p->type_requete = $boucles[$id_boucle]->type_requete;
// regarder s'il existe une fonction personnalisee balise_NOM()
$f = 'balise_' . $nom_champ;
if (function_exists($f))
$p = $f($p);
else {
// regarder s'il existe une fonction standard balise_NOM_dist()
$f = 'balise_' . $nom_champ . '_dist';
if (function_exists($f))
$p = $f($p);
else {
// S'agit-il d'un logo ? Une fonction speciale les traite tous
if (ereg('^LOGO_', $nom_champ))
$p = calcul_balise_logo($p);
else {
// On regarde ensuite s'il y a un champ SQL homonyme,
// et on definit le type et les traitements
$p->code = champ_sql($nom_champ, $p);
if (($p->code) && ($p->code != '$Pile[0][\''.$nom_champ.'\']')) {
// Par defaut basculer en numerique pour les #ID_xxx
if (substr($nom_champ,0,3) == 'ID_') $p->type = 'num';
}
else {
// si index_pile a ramene le choix par defaut,
// ca doit plutot etre un champ SPIP non SQL,
// ou ni l'un ni l'autre => on le renvoie sous la forme brute '#TOTO'
$p->code = "'#$nom_champ'";
$p->type = 'php'; // pas de traitement
}}}}
// Aller chercher les processeurs standards definis dans inc-champ-squel
if (!$etoile)
$p->process = champs_traitements($nom_champ);
// Retourner l'expression php correspondant au champ + ses filtres
return $p->retour();
}
// Genere l'application d'une liste de filtres
function applique_filtres ($fonctions, $code, $id_boucle, $boucles, $id_mere, $type ='html', $process='') {
// pretraitements standards
switch ($type) {
case 'num':
$code = "intval($code)";
break;
case 'php':
break;
case 'html':
default:
$code = "trim($code)";
break;
}
// traitements standards
if (strpos($process, '%s') !== false)
$code = str_replace('%s', $code, $process);
// Appliquer les filtres perso
if ($fonctions) {
foreach($fonctions as $fonc) {
if ($fonc) {
$arglist = '';
if (ereg('([^\{\}]*)\{(.+)\}$', $fonc, $regs)) {
$fonc = $regs[1];
$args = $regs[2];
while (ereg('([^,]+),?(.*)$', $args, $regs)) {
$args = $regs[2];
$arg = trim($regs[1]);
if ($arg) {
if ($arg[0] =='#')
$arg = calculer_champ(array(), substr($arg,1),
$id_boucle, $boucles, $id_mere);
else if ($arg[0] =='$')
$arg = '$Pile[0][\'' . substr($arg,1) . "']";
$arglist .= ','.$arg;
}
}
}
if (function_exists($fonc))
$code = "$fonc($code$arglist)";
else
$code = "'".texte_script(
_T('erreur_filtre', array('filtre' => $fonc))
)."'";
}
}
}
// post-traitement securite
if ($type == 'html')
$code = "interdire_scripts($code)";
return $code;
}
//
// Reserve les champs necessaires a la comparaison avec le contexte donne par
// la boucle parente ; attention en recursif il faut les reserver chez soi-meme
// ET chez sa maman
//
function calculer_argument_precedent($idb, $nom_champ, &$boucles) {
// recursif ?
if ($boucles[$idb]->externe)
index_pile ($idb, $nom_champ, $boucles); // reserver chez soi-meme
// reserver chez le parent et renvoyer l'habituel $Pile[$SP]['nom_champ']
return index_pile ($boucles[$idb]->id_parent, $nom_champ, $boucles);
}
?>
Index: inc-admin.php3
RCS file: /home/spip-cvs/spip/inc-admin.php3,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- inc-admin.php3 27 Aug 2004 04:54:12 -0000 1.23
+++ inc-admin.php3 28 Aug 2004 23:17:42 -0000 1.24
@@ -265,7 +265,8 @@
//
function erreur_squelette($message, $fautif, $lieu) {
global $auteur_session, $debug_messages;
-
+ static $runs;
+
// Drapeau pour interdire d'ecrire les fichiers dans le cache
# define('spip_erreur_fatale', 'erreur_squelette');
# En fait, a partir du moment ou l'erreur est dans le squelette,
@@ -289,6 +290,9 @@
$debug_messages .= "<div style='position: fixed; top: 10px; left: 10px;
z-index: 10000; background-color: pink;'>$message</div>";
}
+
+ // Eviter les boucles infernales
+ if (++$runs > 4) die ($debug_messages);
}
?>
Index: inc-reqsql-squel.php3
RCS file: /home/spip-cvs/spip/inc-reqsql-squel.php3,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- inc-reqsql-squel.php3 27 Aug 2004 04:27:02 -0000 1.8
+++ inc-reqsql-squel.php3 28 Aug 2004 23:17:42 -0000 1.9
@@ -134,7 +134,7 @@
"', $boucle->where) . '"')) .
"), # WHERE
'".addslashes($boucle->group)."', # GROUP
- '".addslashes($boucle->order)."', # ORDER
+ " . ($boucle->order ? $boucle->order : "''") .", # ORDER
" . (strpos($boucle->limit, 'intval') === false ?
"'$boucle->limit'" :
$boucle->limit). ", # LIMIT
--- inc-calcul_mysql3.php DELETED ---
--- NEW FILE: inc-calcul-outils.php3 ---
(This appears to be a binary file; contents omitted.)
--- inc-arg-squel.php3 DELETED ---
--- inc-calcul_html4.php DELETED ---
--- inc-calcul-squel.php3 DELETED ---
--- NEW FILE: inc-compilo.php3 ---
<?php
//
// Fichier principal du compilateur de squelettes
//
// Ce fichier ne sera execute qu'une fois
if (defined("_INC_COMPILO")) return;
define("_INC_COMPILO", "1");
// Definition de la structure $p, et fonctions de recherche et de reservation
// dans l'arborescence des boucles
include_local("inc-compilo-index.php3"); # index ? structure ? pile ?
#include_local("inc-bcl-squel.php3"); # (anciens noms des fichiers)
#include_local("inc-index-squel.php3");
// definition des balises
include_local("inc-balises.php3");
#include_local("inc-logo-squel.php3");
#include_local("inc-vrac-squel.php3");
#include_local("inc-form-squel.php3");
// definition des criteres
include_local("inc-criteres.php3");
#include_local("inc-arg-squel.php3");
// gestion des balises de forums
include_local("inc-forum.php3");
// a traiter (essentiellement, ce sont des definitions standard de spip:
// inc-compilo-standard/spip/redac ?
include_local("inc-reqsql-squel.php3");
include_local("inc-champ-squel.php3");
// outils pour debugguer le compilateur
#include_local("inc-compilo-debug.php3"); # desactive
//
// Calculer un <INCLURE()>
//
function calculer_inclure($fichier, $params, $id_boucle, &$boucles) {
global $dossier_squelettes;
$criteres = '';
if ($params) {
foreach($params as $param) {
if (ereg("^([_0-9a-zA-Z]+)[[:space:]]*(=[[:space:]]*([^}]+))?$", $param, $args)) {
$var = $args[1];
$val = ereg_replace('^["\'](.*)["\']$', "\\1", trim($args[3]));
$val = addslashes(addslashes($val));
// Cas de la langue : passer $spip_lang
// et non table.lang (car depend de {lang_select})
if ($var =='lang') {
if ($val)
$l[] = "\'lang\' => \'$val\'";
else
$l[] = "\'lang\' => \''.\$GLOBALS[spip_lang].'\'";
}
// Cas normal {var=val}
else
if ($val)
$l[] = "\'$var\' => \'$val\'";
else
$l[] = "\'$var\' => \'' . addslashes(" . index_pile($id_boucle, $var, $boucles) . ") .'\'";
}
$criteres = join(", ",$l);
}
}
return "\n'<".
"?php\n\t\$contexte_inclus = array($criteres);\n\t".
"\$fichier_inclus = \'$fichier\';\n" .
(($dossier_squelettes) ?
("
if (@file_exists(\'$dossier_squelettes/$fichier\')){
include(\'$dossier_squelettes/$fichier\');
} else {
include(\'$fichier\');
} " ) :
("\tinclude(\'$fichier\');")) .
"\n?'." . "'>'";
}
//
// Traite une partie "texte" d'un squelette (c'est-a-dire tout element
// qui ne contient ni balise, ni boucle, ni <INCLURE()> ; le transforme
// en une EXPRESSION php (qui peut etre l'argument d'un Return ou la
// partie droite d'une affectation). Ici sont analyses les elements
// multilingues des squelettes : <:xxx:> et <multi>[fr]coucou</multi>
//
function calculer_texte($texte, $id_boucle, &$boucles, $id_mere) {
$code = "'".ereg_replace("([\\\\'])", "\\\\1", $texte)."'";
// bloc multi
if (eregi('<multi>', $texte)) {
$ouvre_multi = 'extraire_multi(';
$ferme_multi = ')';
} else {
$ouvre_multi = $ferme_multi = '';
}
// Reperer les balises de traduction <:toto:>
while (eregi("<:(([a-z0-9_]+):)?([a-z0-9_]+)(\|[^>]*)?:>", $code, $match)) {
//
// Traiter la balise de traduction multilingue
//
$chaine = strtolower($match[3]);
if (!($module = $match[2]))
// ordre standard des modules a explorer
$module = 'local/public/spip';
$c = applique_filtres(explode('|',
substr($match[4],1)),
"_T('$module:$chaine')",
$id_boucle,
$boucles,
$id_mere,
'php'); // ne pas manger les espaces avec trim()
$code = str_replace($match[0], "'$ferme_multi.$c.$ouvre_multi'", $code);
}
return $ouvre_multi . $code . $ferme_multi;
}
//
// calculer_boucle() produit le corps PHP d'une boucle Spip,
// essentiellement une boucle while (ou une double en cas de hierarchie)
// remplissant une variable $t0 retourne'e en valeur
//
function calculer_boucle($id_boucle, &$boucles) {
global $table_primary, $table_des_tables;
$boucle = &$boucles[$id_boucle];
$type_boucle = $boucle->type_requete;
list($return,$corps) = $boucle->return;
// Boucle recursive : simplement appeler la boucle interieure
if ($type_boucle == 'boucle')
return ("$corps\n return $return;");
// La boucle doit-elle selectionner la langue ?
// 1. par defaut
$lang_select = (
$type_boucle == 'articles' OR $type_boucle == 'rubriques'
OR $type_boucle == 'hierarchie' OR $type_boucle == 'breves'
);
// 2. si forcer_lang, le defaut est non
if ($GLOBALS['forcer_lang']) $lang_select = false;
// 3. demande explicite
if ($boucle->lang_select == 'oui') $lang_select = true;
if ($boucle->lang_select == 'non') $lang_select = false;
// 4. penser a demander le champ lang
if ($lang_select)
$boucle->select[] = (($id_table = $table_des_tables[$type_boucle]) ? $id_table.'.' : '') .'lang';
// Qui sommes-nous ?
$primary_key = $table_primary[$type_boucle];
// Calculer les invalideurs si c'est une boucle non constante
$constant = ereg("^'[^']*'$",$return);
if ((!$primary_key) || $constant)
$invalide = '';
else {
$id_table = $table_des_tables[$type_boucle];
$boucle->select[] = "$id_table.$primary_key";
$invalide = "\n \$Cache['$primary_key']";
if ($primary_key != 'id_forum')
$invalide .= "[\$Pile[\$SP]['$primary_key']] = 1;";
else
$invalide .= "[calcul_index_forum(" .
// Retournera 4 [$SP] mais force la demande du champ a MySQL
index_pile($id_boucle, 'id_article', $boucles) . ',' .
index_pile($id_boucle, 'id_breve', $boucles) . ',' .
index_pile($id_boucle, 'id_rubrique', $boucles) .',' .
index_pile($id_boucle, 'id_syndic', $boucles) . ")] = 1;";
$invalide .= ' // invalideurs';
}
// Cas {1/3} {1,4} {n-2,1}...
$flag_parties = ($boucle->partie AND $boucle->total_parties);
$flag_cpt = $flag_parties || // pas '$compteur' a cause du cas 0
strpos($corps,'compteur_boucle') ||
strpos($return,'compteur_boucle');
//
// Creer le debut du corps de la boucle :
//
if ($flag_cpt)
$debut = "\n \$compteur_boucle++;";
if ($flag_parties)
$debut .= '
if ($compteur_boucle >= $debut_boucle
AND $compteur_boucle <= $fin_boucle) {';
if ($lang_select AND !$constant)
$debut .= '
if ($x = $Pile[$SP]["lang"]) $spip_lang = $x; // lang_select';
$debut .= $invalide;
if ($boucle->doublons)
$debut .= "\n \$doublons['".$boucle->doublons."'] .= ','. " .
index_pile($id_boucle, $primary_key, $boucles)
. "; // doublons";
//
// L'ajouter au corps
//
$corps = $debut . $corps;
// Separateur ?
if ($boucle->separateur) {
$corps .= "\n \$t1 = $return;
\$t0 .= ((\$t1 && \$t0) ? '"
. $boucle->separateur
. "' : '')
. \$t1;";
} else if ($constant && !$debut) {
$corps .= $return;
} else {
$corps .= "\n \$t0 .= $return;";
}
// Fin de parties
if ($flag_parties)
$corps .= "\n }\n";
// Gestion de la hierarchie (voir inc-arg-squel)
if ($boucle->hierarchie)
$texte .= "\n ".$boucle->hierarchie;
// hack doublons documents : s'il y a quelque chose dans
// $GLOBALS['doublons_documents'], c'est que des documents ont
// ete vus par integre_image() ou autre fournisseur officiel de
// doublons : on les transfere alors vers la vraie variable
$texte .= '
global $spip_lang, $doublons_documents;
$doublons[\'documents\'].=$doublons_documents; $doublons_documents="";';
// Recherche : recuperer les hash a partir de la chaine de recherche
if ($boucle->hash) {
$texte .= '
// RECHERCHE
list($hash_recherche, $hash_recherche_strict) = requete_hash($GLOBALS["recherche"]);';
}
// si le corps est une constante, ne plus appeler le serveur
if (ereg("^'[^']*'$",$corps)) {
// vide ?
if ($corps == "''") {
if (!$boucle->numrows)
return 'return "";';
else
$corps = "";
} else {
$boucle->numrows = true;
$corps = "\n ".'for($x=$Numrows["'.$id_boucle.'"];$x>0;$x--)
$t0 .= ' . $corps .';';
}
} else {
$corps = '
// RESULTATS
while ($objet = @spip_fetch_array($result)) {'
. "\n\t\t\$Pile[\$SP] = \$objet;"
. "\n$corps\n }\n";
// Memoriser la langue avant la boucle pour la restituer apres
if ($lang_select) {
$texte .= "\n \$old_lang = \$spip_lang;";
$corps .= "\n \$spip_lang = \$old_lang;";
}
}
//
// Requete
//
$init = "\n\n // REQUETE\n ";
// hack critere recherche : ignorer la requete en cas de hash vide
if ($boucle->hash)
$init .= "if (\$hash_recherche) ";
$init .= "\$result = " . calculer_requete($boucle);
$init .= "\n ".'$t0 = "";
$SP++;';
if ($flag_cpt)
$init .= "\n \$compteur_boucle = 0;";
if ($flag_parties)
$init .= calculer_parties($boucle->partie,
$boucle->mode_partie,
$boucle->total_parties,
$id_boucle);
else if ($boucle->numrows)
$init .= "\n \$Numrows['$id_boucle'] = @spip_num_rows(\$result);";
//
// Conclusion et retour
//
$conclusion = "\n @spip_free_result(\$result);";
$conclusion .= "\n return \$t0;";
return $texte . $init . $corps . $conclusion;
}
//
// fonction traitant les criteres {1,n} (analyses dans inc-criteres)
//
## a deplacer dans inc-criteres ??
function calculer_parties($partie, $mode_partie, $total_parties, $id_boucle) {
// Notes :
// $debut_boucle et $fin_boucle sont les indices SQL du premier
// et du dernier demandes dans la boucle : 0 pour le premier,
// n-1 pour le dernier ; donc total_boucle = 1 + debut - fin
// nombre total avant partition
$retour = "\n\n // Partition\n "
.'$nombre_boucle = @spip_num_rows($result);';
ereg("([+-/])([+-/])?", $mode_partie, $regs);
list(,$op1,$op2) = $regs;
// {1/3}
if ($op1 == '/') {
$retour .= "\n "
.'$debut_boucle = 1 + ceil(($nombre_boucle * '
. ($partie - 1) . ')/' . $total_parties . ");\n "
. '$fin_boucle = ceil (($nombre_boucle * '
. $partie . ')/' . $total_parties . ");";
}
// {1,x}
if ($op1 == '+') {
$retour .= "\n "
. '$debut_boucle = ' . $partie . ';';
}
// {n-1,x}
if ($op1 == '-') {
$retour .= "\n "
. '$debut_boucle = $nombre_boucle - ' . $partie . ';';
}
// {x,1}
if ($op2 == '+') {
$retour .= "\n "
. '$fin_boucle = $debut_boucle + ' . $partie . ' - 1;';
}
// {x,n-1}
if ($op2 == '-') {
$retour .= "\n "
. '$fin_boucle = $debut_boucle+($nombre_boucle-'.$partie.')-1;';
}
// Rabattre $fin_boucle sur le maximum
$retour .= "\n "
.'$fin_boucle = min($fin_boucle, $nombre_boucle);';
// calcul du total boucle final
$retour .= "\n "
.'$Numrows[\''.$id_boucle.'\'] = $fin_boucle - $debut_boucle + 1;';
return $retour;
}
// Production du code PHP a partir de la sequence livree par le phraseur
// $boucles est passe par reference pour affectation par index_pile.
// Retourne un tableau de 2 elements:
// 1. 'code' = une expression PHP,
// 2. 'entete' = une suite d'instructions PHP a executer
// avant d'evaluer l'expression (a rendre obsolete tant que possible).
function calculer_liste($tableau, $prefix, $id_boucle, $niv, &$boucles, $id_mere) {
if ((!$tableau))
return array("''",'');
$t = '$t' . ($niv+1);
for ($i=0; $i<=$niv; $i++) $tab .= "\t";
foreach ($tableau as $objet) {
// c = 'code' ; m = 'entete'
// rendu[0] = (code, entete) du principal
// rendu[1] = (code, entete) du "avant"
// rendu[2] = (code, entete) du "apres"
// rendu[3] = (code, entete) du "alternatif"
unset($rendu);
unset($commentaire);
switch($objet->type) {
// texte seul
case 'texte':
$rendu[0][0] = calculer_texte($objet->texte, $id_boucle, $boucles, $id_mere);
break;
// inclure
case 'include':
$rendu[0][0] = calculer_inclure($objet->fichier,
$objet->params,
$id_boucle,
$boucles);
$commentaire = "<INCLURE($objet->fichier)>";
break;
// boucle
case 'boucle':
$nom = $objet->id_boucle;
// avant
$rendu[1] = calculer_liste($objet->cond_avant, $prefix,
$id_boucle, $niv+2, $boucles, $nom);
// apres
$rendu[2] = calculer_liste($objet->cond_apres, $prefix,
$id_boucle, $niv+2, $boucles, $nom);
// alternatif
$rendu[3] = calculer_liste($objet->cond_altern, $prefix,
$id_boucle, $niv+1,$boucles, $nom);
$rendu[0][0] = $prefix . ereg_replace("-","_", $nom)
. '($Cache, $Pile, $doublons, $Numrows, $SP)';
$commentaire = "BOUCLE$nom";
break;
// balise SPIP
default:
$rendu[0][0] = calculer_champ($objet->fonctions,
$objet->nom_champ,
$id_boucle,
$boucles,
$id_mere,
$objet->etoile);
$commentaire = "#$objet->nom_champ".($objet->etoile?'*':'');
// avant
$rendu[1] = calculer_liste($objet->cond_avant, $prefix,
$id_boucle, $niv+2,$boucles, $id_mere);
// apres
$rendu[2] = calculer_liste($objet->cond_apres, $prefix,
$id_boucle, $niv+2,$boucles, $id_mere);
break;
} // switch
// Assembler les elements en simplifiant si possible
// le resultat (lisibilite et rapidite)
$utiliser_f = false;
for ($i = 0; $i<=3; $i++) {
if ($rendu[$i][0] == '' OR $rendu[$i][0] == "''") {
$rendu[$i][0] = "''";
} else {
// Ajouter l'entete eventuel
if ($rendu[$i][1])
$rendu[$i][0] =
"eval('".texte_script($rendu[$i][1])."')."
."/"."* entete *"."/"
."\n$tab".$rendu[$i][0];
// Noter le recours eventuel ˆ _f
if ($i>0)
$utiliser_f = true;
}
}
if ($commentaire)
$rendu[0][0] = "/"."* $commentaire *"."/ ".$rendu[0][0];
//
// (_f(1,principal) ? avant._f().apres : _f().alternatif)
// _f() fonctionne avec une pile ; cette structure logique permet
// de n'evaluer que ce qui doit l'etre (ne pas evaluer avant/apres
// si on veut utiliser sinon, et vice-versa)
if ($utiliser_f)
$code = "(_f(1,".$rendu[0][0].") ? "
. (($rendu[1][0]=="''") ? "" :
"\n$tab\t/"."* << *"."/".$rendu[1][0]." .")
. "_f()"
. (($rendu[2][0]=="''") ? "" :
". ".$rendu[2][0]."/"."* >> *"."/")
. " : _f()"
. (($rendu[3][0]=="''") ? "" :
" /"."* sinon: *"."/.".$rendu[3][0])
.")";
else
// eviter les conditionnelles qui forkent le resultat
// si le code est '$a ? $b : $c', le parenthesage est obligatoire
// quand on est lie a d'autres chaines par des . tout nus
// NB/astuce: s'il y a un entete, la formule eval('...').$a ? $b : $c
// fonctionne a l'identique de $a ? $b : $c
if (strpos($rendu[0][0], '?'))
$code = "(".$rendu[0][0].")";
else
$code = $rendu[0][0];
$codes[] = $code;
} // foreach
return array(join ("\n$tab. ", $codes), '');
}
// Prend en argument le source d'un squelette, sa grammaire et un nom.
// Retourne une fonction PHP/SQL portant ce nom et calculant une page HTML.
// Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment:
// - 1er: element 'cache' => nom (du fichier ou` mettre la page)
// - 2e: element 0 contenant un environnement ('id_article => $id_article, etc)
// Elle retourne alors un tableau de 4 e'le'ments:
// - 'texte' => page HTML, application du squelette a` l'environnement;
// - 'squelette' => le nom du squelette
// - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique
// - 'invalideurs' => de'pendances de cette page, pour invalider son cache.
// (voir son utilisation, optionnelle, dans invalideur.php)
// En cas d'erreur, elle retourne un tableau des 2 premiers elements seulement
function calculer_squelette($squelette, $nom, $gram, $sourcefile) {
// Phraser le squelette, selon sa grammaire
// pour le moment: "html" seul connu (HTML+balises BOUCLE)
$boucles = '';
spip_timer('calcul_skel');
include_local("inc-$gram-squel.php3");
$racine = parser($squelette, '',$boucles);
// include_local('inc-debug.php3');
// afftable($racine);
// affboucles($boucles);
// Commencer par reperer les boucles appelees explicitement par d'autres
// car elles indexent leurs arguments de maniere derogatoire
if ($boucles) foreach($boucles as $id => $boucle) {
if ($boucle->type_requete == 'boucle') {
$rec = &$boucles[$boucle->param];
if (!$rec) {
include_local('inc-admin.php3');
erreur_squelette(_T('info_erreur_squelette'),
_L($boucle->param.' : boucle recursive non definie'), $id);
} else {
$rec->externe = $id;
$boucles[$id]->return =
calculer_liste(array($rec),
$nom,
$boucle->param,
1,
$boucles,
$id);
}
}
}
if ($boucles) foreach($boucles as $id => $boucle) {
if ($boucle->type_requete != 'boucle') {
calculer_criteres($id, $boucles);
$boucles[$id]->return = calculer_liste($boucle->milieu,
$nom,
$id,
1,
$boucles,
$id);
}
}
// idem pour la racine
list ($return,$corps) = calculer_liste($racine, $nom, '',0, $boucles, '');
// Corps de toutes les fonctions PHP,
// en particulier les requetes SQL et TOTAL_BOUCLE
// de'terminables seulement maintenant
// Les 3 premiers parame`tres sont passe's par re'fe'rence
// (sorte d'environnements a` la Lisp 1.5)
// sauf pour la fonction principale qui recoit les initialisations
$code = '';
if ($boucles) {
foreach($boucles as $id => $boucle)
$boucles[$id]->return = calculer_boucle($id, $boucles);
foreach($boucles as $id => $boucle) {
// Reproduire la boucle en commentaire
$pretty = "BOUCLE$id(".strtoupper($boucle->type_requete).")";
if (is_array($boucle->param))
$pretty .= " {".join("} {", $boucle->param)."}";
$pretty = ereg_replace("[\r\n]", " ", $pretty);
// Puis envoyer son code
$code .= "\n//\n// <$pretty>\n//\n"
."function $nom" . ereg_replace("-","_",$id) .
'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
$boucle->return .
"\n}\n\n";
}
}
$secondes = spip_timer('calcul_skel');
spip_log("calcul skel $sourcefile ($secondes)");
if (is_array($boucles))
$aff_boucles = join (', ', array_keys($boucles));
else
$aff_boucles = "pas de boucle";
return "
/*
* Squelette : $sourcefile
* Date : ".http_gmoddate(@filemtime($sourcefile))." GMT
* Compile : ".http_gmoddate(time())." GMT ($secondes)
* Boucles : ".$aff_boucles."
*/
$code
//
// Fonction principale du squelette $sourcefile
//
function $nom (\$Cache, \$Pile, \$ignore_les_doublons_inc_calcul_php3, \$Numrows='', \$SP=0) {
$corps
\$t0 = $return;
return array(
'texte' => \$t0,
'squelette' => '$nom',
'process_ins' => ((strpos(\$t0,'<'.'?')=== false) ? 'html' : 'php'),
'invalideurs' => \$Cache
);
}
";
}
?>
--- NEW FILE: inc-balises.php3 ---
<?php
//
// Ce fichier regroupe la quasi totalite des definitions de #BALISES de spip
// Pour chaque balise, il est possible de surcharger, dans mes_fonctions.php3,
// la fonction balise_TOTO_dist par une fonction balise_TOTO() respectant la
// meme API : recoit en entree plein de donnees, les modifie et les retourne.
// Le format du bloc de donnees $p est un objet de la class ParamChamp,
// definie dans inc-compilo-index.php3
//
## NB: les fonctions de forum sont definies dans inc-forum.php3
// Ce fichier ne sera execute qu'une fois
if (defined("_INC_BALISES")) return;
define("_INC_BALISES", "1");
function balise_NOM_SITE_SPIP_dist($p) {
$p->code = "lire_meta('nom_site')";
$p->type = 'php';
return $p;
}
function balise_EMAIL_WEBMASTER_dist($p) {
$p->code = "lire_meta('email_webmaster')";
$p->type = 'php';
return $p;
}
function balise_CHARSET_dist($p) {
$p->code = "lire_meta('charset')";
$p->type = 'php';
return $p;
}
function balise_LANG_LEFT_dist($p) {
$p->code = "lang_dir(\$spip_lang,'left','right')";
$p->type = 'php';
return $p;
}
function balise_LANG_RIGHT_dist($p) {
$p->code = "lang_dir(\$spip_lang,'right','left')";
$p->type = 'php';
return $p;
}
function balise_LANG_DIR_dist($p) {
$p->code = "lang_dir(\$spip_lang,'ltr','rtl')";
$p->type = 'php';
return $p;
}
function balise_PUCE_dist($p) {
$p->code = "propre('- ')";
$p->type = 'php';
return $p;
}
// #DATE
// Cette fonction sait aller chercher dans le contexte general
// quand #DATE est en dehors des boucles
// http://www.spip.net/fr_article1971.html
function balise_DATE_dist ($p) {
$_date = champ_sql('date', $p);
$p->code = "$_date";
$p->process = 'vider_date(%s)';
$p->type = 'php';
return $p;
}
// #DATE_REDAC
// http://www.spip.net/fr_article1971.html
function balise_DATE_REDAC_dist ($p) {
$_date = champ_sql('date_redac', $p);
$p->code = "$_date";
$p->process = 'vider_date(%s)';
$p->type = 'php';
return $p;
}
// #DATE_MODIF
// http://www.spip.net/fr_article1971.html
function balise_DATE_MODIF_dist ($p) {
$_date = champ_sql('date_modif', $p);
$p->code = "$_date";
$p->process = 'vider_date(%s)';
$p->type = 'php';
return $p;
}
// #DATE_NOUVEAUTES
// http://www.spip.net/fr_article1971.html
function balise_DATE_NOUVEAUTES_dist($p) {
$p->code = "((lire_meta('quoi_de_neuf') == 'oui' AND lire_meta('majnouv')) ? normaliser_date(lire_meta('majnouv')) : \"'0000-00-00'\")";
$p->process = 'vider_date(%s)';
$p->type = 'php';
return $p;
}
function balise_URL_SITE_SPIP_dist($p) {
$p->code = "lire_meta('adresse_site')";
$p->type = 'php';
return $p;
}
function balise_URL_ARTICLE_dist($p) {
$_type = $p->type_requete;
// Cas particulier des boucles (SYNDIC_ARTICLES)
if ($_type == 'syndic_articles') {
$p->code = champ_sql('url', $p);
}
// Cas general : chercher un id_article dans la pile
else {
$_id_article = champ_sql('id_article', $p);
$p->code = "generer_url_article($_id_article)";
if ($p->boucles[$p->id_boucle]->hash)
$p->code = "url_var_recherche(" . $p->code . ")";
}
$p->type = 'html';
return $p;
}
function balise_URL_RUBRIQUE_dist($p) {
$p->code = "generer_url_rubrique(" .
champ_sql('id_rubrique',$p) .
")" ;
if ($p->boucles[$p->id_boucle]->hash)
$p->code = "url_var_recherche(" . $p->code . ")";
$p->type = 'html';
return $p;
}
function balise_URL_BREVE_dist($p) {
$p->code = "generer_url_breve(" .
champ_sql('id_breve',$p) .
")";
if ($p->boucles[$p->id_boucle]->hash)
$p->code = "url_var_recherche(" . $p->code . ")";
$p->type = 'html';
return $p;
}
function balise_URL_MOT_dist($p) {
$p->code = "generer_url_mot(" .
champ_sql('id_mot',$p) .
")";
$p->code = "url_var_recherche(" . $p->code . ")";
$p->type = 'html';
return $p;
}
function balise_URL_FORUM_dist($p) {
$p->code = "generer_url_forum(" .
champ_sql('id_forum',$p) .")";
$p->type = 'html';
return $p;
}
function balise_URL_DOCUMENT_dist($p) {
$p->code = "generer_url_document(" .
champ_sql('id_document',$p) . ")";
$p->type = 'html';
return $p;
}
function balise_URL_AUTEUR_dist($p) {
$p->code = "generer_url_auteur(" .
champ_sql('id_auteur',$p) .")";
if ($p->boucles[$p->id_boucle]->hash)
$p->code = "url_var_recherche(" . $p->code . ")";
$p->type = 'html';
return $p;
}
function balise_NOTES_dist($p) {
// Recuperer les notes
$p->code = '$GLOBALS["les_notes"]';
// Vider ensuite les globales des notes recuperees
// avec une formule qui renvoit toujours ""
$p->code .= '. ($GLOBALS["les_notes"] = $GLOBALS["compt_note"] = '
. '($GLOBALS["marqueur_notes"]++)?"":"")';
$p->type = 'html';
return $p;
}
function balise_RECHERCHE_dist($p) {
$p->code = 'htmlspecialchars($GLOBALS["recherche"])';
$p->type = 'php';
return $p;
}
function balise_COMPTEUR_BOUCLE_dist($p) {
$p->code = '$compteur_boucle';
$p->type = 'php';
return $p;
}
function balise_TOTAL_BOUCLE_dist($p) {
if ($p->id_mere === '') {
include_local("inc-admin.php3");
erreur_squelette(_L("Champ #TOTAL_BOUCLE hors boucle"), '', $p->id_boucle);
}
$p->code = "\$Numrows['$p->id_mere']";
$p->boucles[$p->id_mere]->numrows = true;
$p->type = 'php';
return $p;
}
function balise_POINTS_dist($p) {
$n = 0;
$b = $p->id_boucle;
$p->code = '';
while ($b != '') {
if ($s = $p->boucles[$b]->param) {
foreach($s as $v) {
if (strpos($v,'recherche') !== false) {
$p->code = '$Pile[$SP' . (($n==0) ? "" : "-$n") .
'][points]';
$b = '';
break;
}
}
}
$n++;
$b = $p->boucles[$b]->id_parent;
}
if (!$p->code) {
include_local("inc-admin.php3");
erreur_squelette(_L("Champ #POINTS hors d'une recherche"), '', $p->id_boucle);
}
$p->type = 'php';
return $p;
}
function balise_POPULARITE_ABSOLUE_dist($p) {
$p->code = 'ceil(' .
champ_sql('popularite', $p) .
')';
$p->type = 'php';
return $p;
}
function balise_POPULARITE_SITE_dist($p) {
$p->code = 'ceil(lire_meta(\'popularite_total\'))';
$p->type = 'php';
return $p;
}
function balise_POPULARITE_MAX_dist($p) {
$p->code = 'ceil(lire_meta(\'popularite_max\'))';
$p->type = 'php';
return $p;
}
function balise_EXPOSER_dist($p) {
global $table_primary;
$on = 'on';
$off= '';
if ($p->fonctions) {
// Gerer la notation [(#EXPOSER|on,off)]
reset($p->fonctions);
list(, $onoff) = each($p->fonctions);
ereg("([^,]*)(,(.*))?", $onoff, $regs);
$on = addslashes($regs[1]);
$off = addslashes($regs[3]);
// autres filtres
$filtres=Array();
while (list(, $nom) = each($p->fonctions))
$filtres[] = $nom;
$p->fonctions = $filtres;
}
$type_boucle = $p->type_requete;
$primary_key = $table_primary[$type_boucle];
$p->code = '(calcul_exposer('
.champ_sql($primary_key, $p)
.', "'.$primary_key.'", $Pile[0]) ?'." '$on': '$off')";
$p->type = 'php';
return $p;
}
//
// Inserer directement un document dans le squelette
//
function balise_EMBED_DOCUMENT_dist($p) {
$_id_document = champ_sql('id_document',$p);
$p->code = "embed_document($_id_document, '" .
texte_script($p->fonctions ? join($p->fonctions, "|") : "") .
"', false)";
unset ($p->fonctions);
$p->type = 'html';
return $p;
}
// Debut et fin de surlignage auto des mots de la recherche
// on insere une balise Span avec une classe sans spec:
// c'est transparent s'il n'y a pas de recherche,
// sinon elles seront remplacees par les fontions de inc_surligne
// flag_pcre est juste une flag signalant que preg_match est dispo.
function balise_DEBUT_SURLIGNE_dist($p) {
global $flag_pcre;
$p->code = ($flag_pcre ? ('\'<span class="spip_surligneconditionnel">\'') : "''");
return $p;
}
function balise_FIN_SURLIGNE_dist($p) {
global $flag_pcre;
$p->code = ($flag_pcre ? ('\'</span class="spip_surligneconditionnel">\'') : "''");
return $p;
}
// Formulaire de changement de langue
function balise_MENU_LANG_dist($p) {
$p->code = '"<"."?php
include_ecrire(\"inc_lang.php3\");
echo menu_langues(\"var_lang\", \$menu_lang);
?".">"';
$p->type = 'php';
return $p;
}
// Formulaire de changement de langue / page de login
function balise_MENU_LANG_ECRIRE_dist($p) {
$p->code = '"<"."?php
include_ecrire(\"inc_lang.php3\");
echo menu_langues(\"var_lang_ecrire\", \$menu_lang);
?".">"';
$p->type = 'php';
return $p;
}
//
// Formulaires de login
//
function balise_LOGIN_PRIVE_dist($p) {
$p->code = '"<"."?php include(\'inc-login.php3\'); login(\'\', \'prive\'); ?".">"';
$p->type = 'php';
return $p;
}
function balise_LOGIN_PUBLIC_dist($p) {
if ($nom = $p->fonctions[0])
$lacible = "new Link('".$nom."')";
else
$lacible = '\$GLOBALS[\'clean_link\']';
$p->code = '"<"."?php include(\'inc-login.php3\'); login(' . $lacible . ', false); ?".">"';
$p->fonctions = array();
$p->type = 'php';
return $p;
}
function balise_URL_LOGOUT_dist($p) {
if ($p->fonctions) {
$url = "&url=".$p->fonctions[0];
$p->fonctions = array();
} else {
$url = '&url=\'.urlencode(\$clean_link->getUrl()).\'';
}
$p->code = '"<"."?php if (\$GLOBALS[\'auteur_session\'][\'login\'])
{ echo \'spip_cookie.php3?logout_public=\'.\$GLOBALS[\'auteur_session\'][\'login\'].\'' . $url . '\'; } ?".">"';
$p->type = 'php';
return $p;
}
function balise_INTRODUCTION_dist ($p) {
$_type = $p->type_requete;
$_texte = champ_sql('texte', $p);
$_chapo = champ_sql('chapo', $p);
$_descriptif = champ_sql('descriptif', $p);
$p->code = "calcul_introduction('$_type', $_texte, $_chapo, $_descriptif)";
$p->type = 'html';
return $p;
}
// #LANG
// non documente ?
function balise_LANG_dist ($p) {
$_lang = champ_sql('lang', $p);
$p->code = "($_lang ? $_lang : \$GLOBALS['spip_lang'])";
$p->type = 'php';
return $p;
}
// #LESAUTEURS
// les auteurs d'un article (ou d'un article syndique)
// http://www.spip.net/fr_article902.html
// http://www.spip.net/fr_article911.html
function balise_LESAUTEURS_dist ($p) {
// Cherche le champ 'lesauteurs' dans la pile
$_lesauteurs = champ_sql('lesauteurs', $p);
// Si le champ n'existe pas (cas de spip_articles), on donne la
// construction speciale sql_auteurs(id_article) ;
// dans le cas contraire on prend le champ 'les_auteurs' (cas de
// spip_syndic_articles)
if ($_lesauteurs AND $_lesauteurs != '$Pile[0][lesauteurs]') {
$p->code = $_lesauteurs;
} else {
$_id_article = champ_sql('id_article', $p);
# On pourrait mieux faire qu'utiliser cette fonction assistante ?
$p->code = "sql_auteurs($_id_article)";
}
$p->type = 'html';
return $p;
}
// #PETITION
// Champ testant la presence d'une petition
// non documente ???
function balise_PETITION_dist ($p) {
$_id_article = champ_sql('id_article', $p);
$p->code = 'sql_petitions($_id_article)';
$p->type = 'php';
return $p;
}
// #POPULARITE
// http://www.spip.net/fr_article1846.html
function balise_POPULARITE_dist ($p) {
$_popularite = champ_sql('popularite', $p);
$p->code = "ceil(min(100, 100 * $_popularite
/ max(1 , 0 + lire_meta('popularite_max'))))";
$p->type = 'php';
return $p;
}
//
// Fonction commune aux balises #LOGO_XXXX
// (les balises portant ce type de nom sont traitees en bloc ici)
//
function calcul_balise_logo ($p) {
// analyser la balise LOGO_xxx
eregi("^LOGO_(([A-Z]+)(_.*)?)", $p->nom_champ, $regs);
$type_logo = $regs[1]; // ARTICLE_RUBRIQUE
$type_objet = $regs[2]; // ARTICLE
$suite_logo = $regs[3]; // _RUBRIQUE
$_id_objet = champ_sql("id_$type_objet", $p);
// analyser les filtres
$flag_fichier = 'false';
$filtres = '';
if (is_array($p->fonctions)) {
foreach($p->fonctions as $nom) {
if (ereg('^(left|right|center|top|bottom)$', $nom))
$align = $nom;
else if ($nom == 'lien') {
$flag_lien_auto = 'oui';
$flag_stop = true;
}
else if ($nom == 'fichier') {
$flag_fichier = 'true';
$flag_stop = true;
}
// double || signifie "on passe aux filtres"
else if ($nom == '')
$flag_stop = true;
else if (!$flag_stop) {
$lien = $nom;
$flag_stop = true;
}
// apres un URL ou || ou |fichier ce sont
// des filtres (sauf left...lien...fichier)
else
$filtres[] = $nom;
}
// recuperer les autres filtres s'il y en a
$p->fonctions = $filtres;
}
//
// Preparer le code du lien
//
// 1. filtre |lien
if ($flag_lien_auto AND !$lien)
$code_lien = '($lien = generer_url_'.$type_objet.'('.$_id_objet.')) ? $lien : ""';
// 2. lien indique en clair (avec des balises : imprimer#ID_ARTICLE.html)
else if ($lien) {
$code_lien = "'".texte_script(trim($lien))."'";
while (ereg("^([^#]*)#([A-Za-z_]+)(.*)$", $code_lien, $match)) {
$c = calculer_champ(array(), $match[2], $p->id_boucle, $p->boucles, $p->id_mere);
$code_lien = str_replace('#'.$match[2], "'.".$c.".'", $code_lien);
}
// supprimer les '' disgracieux
$code_lien = ereg_replace("^''\.|\.''$", "", $code_lien);
}
if (!$code_lien)
$code_lien = "''";
switch ($suite_logo) {
case '_NORMAL':
$onoff = 'true, false';
break;
case '_SURVOL':
$onoff = 'false, true';
break;
case '':
default:
$onoff = 'true, true';
break;
}
// cas des documents
if ($type_objet == 'DOCUMENT')
$code_logo =
"array(integre_image($_id_objet,'','fichier_vignette'), '')";
else
$code_logo = "cherche_logo_objet('$type_objet',
$_id_objet, $onoff)";
// cas des logo #BREVE_RUBRIQUE et #ARTICLE_RUBRIQUE
if ($suite_logo == '_RUBRIQUE') {
$_id_rubrique = champ_sql("id_rubrique", $p);
$code_logo = "(\$logo = $code_logo) ? \$logo : ".
"cherche_logo_objet('RUBRIQUE', $_id_rubrique, $onoff)";
}
$p->code = "affiche_logos($code_logo, $code_lien, '$align', $flag_fichier)";
$p->type = 'php';
return $p;
}
// #EXTRA [(#EXTRA|isbn)]
// Champs extra
// Non documentes, en voie d'obsolescence, cf. ecrire/inc_extra.php3
function balise_EXTRA_dist ($p) {
$_extra = champ_sql('extra', $p);
$p->code = $_extra;
// Gerer la notation [(#EXTRA|isbn)]
if ($p->fonctions) {
include_ecrire("inc_extra.php3");
list ($key, $champ_extra) = each($p->fonctions); // le premier filtre
$type_extra = $p->type_requete;
// ci-dessus est sans doute un peu buggue : si on invoque #EXTRA
// depuis un sous-objet sans champ extra d'un objet a champ extra,
// on aura le type_extra du sous-objet (!)
if (extra_champ_valide($type_extra, $champ_extra)) {
unset($p->fonctions[$key]);
$p->code = "extra($p->code, '".addslashes($champ_extra)."')";
// Appliquer les filtres definis par le webmestre
$filtres = extra_filtres($type_extra, $champ_extra);
if ($filtres) foreach ($filtres as $f)
$p->code = "$f($p->code)";
}
}
$p->type = 'html';
return $p;
}
//
// Traduction des champs "formulaire"
//
//
// Note : les balises de gestion de forums (FORMULAIRE_FORUM et
// PARAMETRES_FORUM) sont definies dans le fichier inc-forum.php3
// qui centralise toute la gestion des forums
//
//
// Formulaire de recherche
//
function balise_FORMULAIRE_RECHERCHE_dist($p) {
if ($p->fonctions) {
list(, $lien) = each($p->fonctions); // le premier est un url
while (list(, $filtre) = each($p->fonctions))
$filtres[] = $filtre; // les suivants sont des filtres
$p->fonctions = $filtres;
}
if (!$lien) $lien = 'recherche.php3';
$formulaire_recherche = "\"<form action='$lien' method='get' class='formrecherche'><input type='text' id='formulaire_recherche' size='20' class='formrecherche' name='recherche' value='\" . _T('info_rechercher') . \"' /></form>\"";
$p->code = "((lire_meta('activer_moteur') != 'oui') ? '' :
$formulaire_recherche)";
$p->type = 'html';
return $p;
}
//
// Formulaire d'inscription comme redacteur (dans inc-formulaires.php3)
//
function balise_FORMULAIRE_INSCRIPTION_dist($p) {
$p->code = '(lire_meta("accepter_inscriptions") != "oui") ? "" :
("<"."?php include(\'inc-formulaires.php3\'); lang_select(\"$spip_lang\"); formulaire_inscription(\"redac\"); lang_dselect(); ?".">")';
$p->type = 'php';
return $p;
}
//
// Formulaire ecrire auteur
//
function balise_FORMULAIRE_ECRIRE_AUTEUR_dist($p) {
$_id_auteur = champ_sql('id_auteur', $p);
$_mail_auteur = champ_sql('email', $p);
$p->code = '!email_valide('.$_mail_auteur.') ? "" :
("<'.'?php include(\'inc-formulaires.php3\');
lang_select(\'$spip_lang\');
formulaire_ecrire_auteur(".'.$_id_auteur.'.", \'".texte_script('.$_mail_auteur.')."\');
lang_dselect(); ?'.'>")';
$p->type = 'php';
return $p;
}
//
// Formulaire signature de petition
//
function balise_FORMULAIRE_SIGNATURE_dist($p) {
$_id_article = champ_sql('id_article', $p);
$p->code = '!($petition = sql_petitions('.$_id_article.')) ? "" :
("<"."?php include(\'inc-formulaires.php3\');
lang_select(\'$spip_lang\');
echo formulaire_signature(".'.$_id_article.'.",
\'".texte_script(serialize($petition))."\');
lang_dselect(); ?".">")';
$p->type = 'php';
return $p;
}
// Formulaire d'inscription de site dans l'annuaire
function balise_FORMULAIRE_SITE_dist($p) {
$_id_rubrique = champ_sql('id_rubrique', $p);
$p->code = '(lire_meta("proposer_sites") != 2) ? "":
"<"."?php include(\'inc-formulaires.php3\');
lang_select(\'".$GLOBALS[\'spip_lang\']."\');
formulaire_site(".'.$_id_rubrique.'.");
lang_dselect(); ?".">"';
$p->type = 'php';
return $p;
}
//
// Boutons d'administration:
//
function balise_FORMULAIRE_ADMIN_dist($p) {
$p->code = "'<!-- @@formulaire_admin@@45609871@@ -->'";
$p->type = "php";
return $p;
}
?>
--- inc-form-squel.php3 DELETED ---
--- NEW FILE: inc-compilo-debug.php3 ---
<?php
//
// Outils pour debugguer le compilateur (pas inclus)
//
//
// Ce fichier ne sera execute qu'une fois
if (defined("_INC_COMPILO_DEBUG")) return;
define("_INC_COMPILO_DEBUG", "1");
//
// Fonctions debug
//
function affval($val) {
echo "“" . entites_html($val) . "”";
}
function afftable($table) {
if (!$table) return;
reset($table);
echo "<UL>";
while (list($key, $val) = each($table)) {
echo "<LI>";
affobject($val);
echo "</LI>";
}
echo "</UL>\n";
}
function affobject($val)
{
if (!is_object($val))
affval($val);
else
switch ($val->type) {
case 'boucle':
echo "<font color='red'><b>Boucle".$val->id_boucle."</b>";
echo "<br><i><small>".affval($val->requete)."</small></i></font>";
break;
case 'texte':
echo affval($val->texte);
break;
case 'include':
echo affval($val->fichier);
afftable($params);
break;
case 'champ':
echo "<font color='blue'><i>#".$val->nom_champ;
if ($val->fonctions) echo " <small>(".join(',', $val->fonctions).")</small>";
echo "</i></font>";
echo "<ul><li>";
echo afftable($val->cond_avant);
echo "</li><li>";
echo afftable($val->cond_apres);
echo "</li></ul>";
break;
}
}
function affboucle($val) {
echo "<hr><ul>";
foreach(get_object_vars($val) as $k => $v)
{
echo "<li><b>$k : </b>";
if (is_array($v))
if (!$v) echo "<i>Tableau vide</i>"; else afftable($v);
elseif (is_object($v))
echo afftable($v);
else affval($v);
echo "</li>"; }
echo "</ul>\n";
}
function affboucles($boucles) {
while (list($key, $val) = each($boucles)) affboucle($val);
}
?>