| [ Index ] |
|
Code source de SPIP 1.9.2c |
1 <?php 2 3 /***************************************************************************\ 4 * SPIP, Systeme de publication pour l'internet * 5 * * 6 * Copyright (c) 2001-2007 * 7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * 8 * * 9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * 10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * 11 \***************************************************************************/ 12 13 14 // 15 // Fichier principal du compilateur de squelettes 16 // 17 18 if (!defined("_ECRIRE_INC_VERSION")) return; 19 20 // reperer un code ne calculant rien, meme avec commentaire 21 define('CODE_MONOTONE', ",^(\n//[^\n]*\n)?\(?'([^'])*'\)?$,"); 22 23 // Definition de la structure $p, et fonctions de recherche et de reservation 24 // dans l'arborescence des boucles 25 include_spip('public/references'); 26 27 // definition des boucles 28 include_spip('public/boucles'); 29 30 // definition des criteres 31 include_spip('public/criteres'); 32 33 // definition des balises 34 include_spip('public/balises'); 35 36 // definition de l'API 37 include_spip('public/interfaces'); 38 39 # definition des tables 40 include_spip('base/serial'); 41 42 // http://doc.spip.org/@argumenter_inclure 43 function argumenter_inclure($struct, $descr, &$boucles, $id_boucle, $echap=true){ 44 $l = array(); 45 $lang = ''; 46 foreach($struct->param as $val) { 47 $var = array_shift($val); 48 if ($var == 'lang') 49 $lang = $val; 50 else 51 $l[$var] = ($echap?"\'$var\' => ' . argumenter_squelette(":"'$var' => ") . 52 ($val 53 ? calculer_liste($val[0], $descr, $boucles, $id_boucle) 54 : index_pile($id_boucle, $var, $boucles) 55 ) . ($echap?") . '":" "); 56 } 57 // Cas particulier de la langue : si {lang=xx} est definie, on 58 // la passe, sinon on passe la langue courante au moment du calcul 59 $l['lang'] = ($echap?"\'lang\' => ' . argumenter_squelette(":"'lang' => ") . 60 ($lang 61 ? calculer_liste($lang[0], $descr, $boucles, $id_boucle) 62 : '$GLOBALS["spip_lang"]' 63 ) . ($echap?") . '":" "); 64 return $l; 65 } 66 67 // 68 // Calculer un <INCLURE()> 69 // 70 // http://doc.spip.org/@calculer_inclure 71 function calculer_inclure($struct, $descr, &$boucles, $id_boucle) { 72 73 # Si pas raccourci <INCLURE{fond=xxx}> 74 # chercher le fichier, eventuellement en changeant.php3 => .php 75 # et en gardant la compatibilite <INCLURE(page.php3)> 76 if ($fichier = $struct->texte) { 77 if (preg_match(',^(.*[.]php)3?$,', $fichier, $r)) { 78 $fichier = $r[1]; 79 } 80 if ($fichier == 'page.php') { 81 $fichier = ''; 82 } else { 83 if (!$path = find_in_path($fichier)) 84 $path = find_in_path($fichier.'3'); 85 if (!$path) { 86 spip_log("ERREUR: <INCLURE($fichier)> impossible"); 87 erreur_squelette(_T('zbug_info_erreur_squelette'), 88 "<INCLURE($fichier)> - " 89 ._T('fichier_introuvable', array('fichier' => $fichier))); 90 return "'<!-- Erreur INCLURE(".texte_script($fichier).") -->'"; 91 } 92 } 93 } 94 95 return "\n'<". 96 "?php\n\t\$contexte_inclus = array(" . 97 join(",\n\t", argumenter_inclure($struct, $descr, $boucles, $id_boucle)) . 98 ");" . 99 "\n\tinclude(" . 100 ($fichier ? "\\'$path\\'" : ('_DIR_RESTREINT . "public.php"')). 101 ");" . 102 "\n?'." . "'>'"; 103 } 104 105 // 106 // calculer_boucle() produit le corps PHP d'une boucle Spip. 107 // ce corps remplit une variable $t0 retournee en valeur. 108 // Ici on distingue boucles recursives et boucle a requete SQL 109 // et on insere le code d'envoi au debusqueur du resultat de la fonction. 110 111 // http://doc.spip.org/@calculer_boucle 112 function calculer_boucle($id_boucle, &$boucles) { 113 114 if ($boucles[$id_boucle]->type_requete == 'boucle') { 115 $corps = calculer_boucle_rec($id_boucle, $boucles); 116 $req = ""; 117 } else { 118 $corps = calculer_boucle_nonrec($id_boucle, $boucles); 119 // attention, ne calculer la requete que maintenant 120 // car la fonction precedente appelle index_pile qui influe dessus 121 $req = (($init = $boucles[$id_boucle]->doublons) ? 122 ("\n\t$init = array();") : '') . 123 calculer_requete_sql($boucles[$id_boucle]); 124 } 125 $notrace = isset($GLOBALS['var_mode_affiche']) ? ($GLOBALS['var_mode_affiche'] != 'resultat') : true; 126 return $req . $corps 127 . ($notrace ? "" : " 128 boucle_debug_resultat('$id_boucle', 'resultat', \$t0);") 129 . "\n return \$t0;"; 130 } 131 132 // compil d'une boucle recursive. 133 // il suffit (ET IL FAUT) sauvegarder les valeurs des arguments passes par 134 // reference, car par definition un tel passage ne les sauvegarde pas 135 136 // http://doc.spip.org/@calculer_boucle_rec 137 function calculer_boucle_rec($id_boucle, &$boucles) { 138 $nom = $boucles[$id_boucle]->param[0]; 139 return "\n\t\$save_numrows = (\$Numrows['$nom']);" 140 . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";" 141 . "\n\t\$Numrows['$nom'] = (\$save_numrows);"; 142 } 143 144 // compil d'une boucle non recursive. 145 // c'est un "while (fetch_sql)" dans le cas général, 146 // qu'on essaye d'optimiser un max. 147 148 // http://doc.spip.org/@calculer_boucle_nonrec 149 function calculer_boucle_nonrec($id_boucle, &$boucles) { 150 151 $boucle = &$boucles[$id_boucle]; 152 $return = $boucle->return; 153 $type_boucle = $boucle->type_requete; 154 $primary = $boucle->primary; 155 $constant = preg_match(CODE_MONOTONE,$return); 156 157 // Cas {1/3} {1,4} {n-2,1}... 158 159 $flag_cpt = $boucle->mode_partie ||$boucle->cptrows; 160 161 // 162 // Creer le debut du corps de la boucle : 163 // 164 $corps = !$flag_cpt ? '' : "\n \$Numrows['$id_boucle']['compteur_boucle']++;"; 165 166 if ($boucle->mode_partie) 167 $corps .= " 168 if (\$Numrows['$id_boucle']['compteur_boucle']-1 >= \$debut_boucle) { 169 if (\$Numrows['$id_boucle']['compteur_boucle']-1 > \$fin_boucle) break;\n"; 170 171 // Calculer les invalideurs si c'est une boucle non constante et si on 172 // souhaite invalider ces elements 173 if (!$constant AND $primary) { 174 include_spip('inc/invalideur'); 175 if (function_exists($i = 'calcul_invalideurs')) 176 $corps = $i($corps, $primary, $boucles, $id_boucle); 177 } 178 179 // faudrait expanser le foreach a la compil, car y en a souvent qu'un 180 // et puis faire un [] plutot qu'un "','." 181 if ($boucle->doublons) 182 $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' . 183 index_pile($id_boucle, $primary, $boucles) 184 . "; // doublons\n"; 185 186 187 if (count($boucle->separateur)) 188 $code_sep = ("'" . str_replace("'","\'",join('',$boucle->separateur)) . "'"); 189 190 // La boucle doit-elle selectionner la langue ? 191 // -. par defaut, les boucles suivantes le font 192 // "peut-etre", c'est-a-dire si forcer_lang == false. 193 // - . a moins d'une demande explicite 194 if (!$constant && $boucle->lang_select != 'non' && 195 (($boucle->lang_select == 'oui') || 196 ( 197 $type_boucle == 'articles' 198 OR $type_boucle == 'rubriques' 199 OR $type_boucle == 'hierarchie' 200 OR $type_boucle == 'breves' 201 ))) 202 { 203 $corps .= 204 (($boucle->lang_select != 'oui') ? 205 "\t\tif (!\$GLOBALS['forcer_lang'])\n\t " : '') 206 . "\t\t\$GLOBALS['spip_lang'] = (\$x = " 207 . index_pile($id_boucle, 'lang', $boucles) 208 . ') ? $x : $old_lang;'; 209 // Memoriser la langue avant la boucle pour la restituer apres 210 $init = "\n \$old_lang = \$GLOBALS['spip_lang'];"; 211 $fin = "\n \$GLOBALS['spip_lang'] = \$old_lang;"; 212 213 } 214 else { 215 $init = ''; 216 $fin = ''; 217 } 218 219 // gestion optimale des separateurs et des boucles constantes 220 $corps .= 221 ((!$boucle->separateur) ? 222 (($constant && !$corps) ? $return : 223 ("\n\t\t" . '$t0 .= ' . $return . ";")) : 224 ("\n\t\t\$t1 " . 225 ((strpos($return, '$t1.') === 0) ? 226 (".=" . substr($return,4)) : 227 ('= ' . $return)) . 228 ";\n\t\t" . 229 '$t0 .= (($t1 && $t0) ? ' . $code_sep . " : '') . \$t1;")); 230 231 // Fin de parties 232 if ($boucle->mode_partie) $corps .= "\n }\n"; 233 234 235 // si le corps est une constante, ne pas appeler le serveur N fois! 236 if (preg_match(CODE_MONOTONE,$corps, $r)) { 237 if (!$r[2]) { 238 if (!$boucle->numrows) 239 return 'return "";'; 240 else 241 $corps = ""; 242 } else { 243 $boucle->numrows = true; 244 $corps = "\n ".'for($x=$Numrows["'.$id_boucle.'"]["total"];$x>0;$x--) 245 $t0 .= ' . $corps .';'; 246 } 247 } else { 248 249 $corps = $init . ' 250 251 // RESULTATS 252 while ($Pile[$SP] = @spip_abstract_fetch($result,"' . 253 $boucle->sql_serveur . 254 '")) {' . 255 "\n$corps\n }\n" . 256 $fin ; 257 } 258 259 return ($boucle->mode_partie ? 260 calculer_parties($boucles, $id_boucle) : 261 (!$boucle->numrows ? '' : 262 ( "\n \$Numrows['" . 263 $id_boucle . 264 "']['total'] = @spip_abstract_count(\$result,'" . 265 $boucle->sql_serveur . 266 "');"))) . 267 (!$flag_cpt ? "" : 268 "\n \$Numrows['$id_boucle']['compteur_boucle'] = 0;") 269 . ' 270 $t0 = ""; 271 $SP++;' 272 . 273 $corps . 274 "\n @spip_abstract_free(\$result,'" . 275 $boucle->sql_serveur . "');"; 276 } 277 278 279 // http://doc.spip.org/@calculer_requete_sql 280 function calculer_requete_sql(&$boucle) 281 { 282 if (!$order = $boucle->order 283 AND !$order = $boucle->default_order) 284 $order = array(); 285 286 return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '') 287 . $boucle->in 288 . $boucle->hash . 289 "\n\n // REQUETE 290 \$result = spip_optim_select(\n\t\tarray(\"" . 291 # En absence de champ c'est un decompte : 292 # prendre une constante pour avoir qqch 293 (!$boucle->select ? 1 : 294 join("\",\n\t\t\"", $boucle->select)) . 295 '"), # SELECT 296 ' . calculer_from($boucle) . 297 ', # FROM 298 ' . calculer_dump_array($boucle->where) . 299 ', # WHERE 300 ' . calculer_dump_join($boucle->join) 301 . ', # WHERE pour jointure 302 ' . (!$boucle->group ? "''" : 303 ('"' . join(", ", $boucle->group)) . '"') . 304 ', # GROUP 305 array(' . 306 join(', ', $order) . 307 "), # ORDER 308 " . (strpos($boucle->limit, 'intval') === false ? 309 "'".$boucle->limit."'" : 310 $boucle->limit). ", # LIMIT 311 '".$boucle->sous_requete. "', # sous 312 " . calculer_dump_array($boucle->having) . ", # HAVING 313 '".$boucle->id_table."', # table 314 '".$boucle->id_boucle."', # boucle 315 '".$boucle->sql_serveur."'); # serveur"; 316 } 317 318 319 // http://doc.spip.org/@calculer_dump_array 320 function calculer_dump_array($a) 321 { 322 if (!is_array($a)) return $a ; 323 $res = ""; 324 if ($a AND $a[0] == "'?'") 325 return ("(" . calculer_dump_array($a[1]) . 326 " ? " . calculer_dump_array($a[2]) . 327 " : " . calculer_dump_array($a[3]) . 328 ")"); 329 else { 330 foreach($a as $k => $v) $res .= ", " . calculer_dump_array($v); 331 return "\n\t\t\tarray(" . substr($res,2) . ')'; 332 } 333 } 334 335 // http://doc.spip.org/@calculer_dump_join 336 function calculer_dump_join($a) 337 { 338 $res = ""; 339 foreach($a as $k => $v) $res .= ", $k => array('$v[0]', '$v[1]')"; 340 return 'array(' . substr($res,2) . ')'; 341 } 342 343 // http://doc.spip.org/@calculer_from 344 function calculer_from(&$boucle) 345 { 346 $res = ""; 347 foreach($boucle->from as $k => $v) $res .= ",'$k' => '$v'"; 348 return 'array(' . substr($res,1) . ')'; 349 } 350 351 // 352 // fonction traitant les criteres {1,n} (analyses dans inc-criteres) 353 // 354 ## a deplacer dans inc-criteres ?? 355 // http://doc.spip.org/@calculer_parties 356 function calculer_parties($boucles, $id_boucle) { 357 358 $boucle = &$boucles[$id_boucle]; 359 $partie = $boucle->partie; 360 $mode_partie = $boucle->mode_partie; 361 $total_parties = $boucle->total_parties; 362 363 // Notes : 364 // $debut_boucle et $fin_boucle sont les indices SQL du premier 365 // et du dernier demandes dans la boucle : 0 pour le premier, 366 // n-1 pour le dernier ; donc total_boucle = 1 + debut - fin 367 368 // nombre total avant partition 369 $retour = "\n\n // Partition\n " . 370 '$nombre_boucle = @spip_abstract_count($result,"' . 371 $boucle->sql_serveur . 372 '");'; 373 374 preg_match(",([+-/p])([+-/])?,", $mode_partie, $regs); 375 list(,$op1,$op2) = $regs; 376 377 // {1/3} 378 if ($op1 == '/') { 379 $pmoins1 = is_numeric($partie) ? ($partie-1) : "($partie-1)"; 380 $totpos = is_numeric($total_parties) ? ($total_parties) : 381 "($total_parties ? $total_parties : 1)"; 382 $retour .= "\n " 383 .'$debut_boucle = ceil(($nombre_boucle * ' 384 . $pmoins1 . ')/' . $totpos . ");"; 385 $fin = 'ceil (($nombre_boucle * ' 386 . $partie . ')/' . $totpos . ") - 1"; 387 } 388 389 // {1,x} 390 elseif ($op1 == '+') { 391 $retour .= "\n " 392 . '$debut_boucle = ' . $partie . ';'; 393 } 394 // {n-1,x} 395 elseif ($op1 == '-') { 396 $retour .= "\n " 397 . '$debut_boucle = $nombre_boucle - ' . $partie . ';'; 398 } 399 // {pagination} 400 elseif ($op1 == 'p') { 401 $retour .= "\n " 402 . '$debut_boucle = ' . $partie . ';'; 403 } 404 405 // {x,1} 406 if ($op2 == '+') { 407 $fin = '$debut_boucle' 408 . (is_numeric($total_parties) ? 409 (($total_parties==1) ? "" :(' + ' . ($total_parties-1))): 410 ('+' . $total_parties . ' - 1')); 411 } 412 // {x,n-1} 413 elseif ($op2 == '-') { 414 $fin = '$debut_boucle + $nombre_boucle - ' 415 . (is_numeric($total_parties) ? ($total_parties+1) : 416 ($total_parties . ' - 1')); 417 } 418 419 // Rabattre $fin_boucle sur le maximum 420 $retour .= "\n " 421 .'$fin_boucle = min(' . $fin . ', $nombre_boucle - 1);'; 422 423 // calcul du total boucle final 424 $retour .= "\n " 425 .'$Numrows[\''.$id_boucle.'\']["grand_total"] = $nombre_boucle;' 426 . "\n " 427 .'$Numrows[\''.$id_boucle.'\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);'; 428 429 return $retour; 430 } 431 432 // Production du code PHP a partir de la sequence livree par le phraseur 433 // $boucles est passe par reference pour affectation par index_pile. 434 // Retourne une expression PHP, 435 // (qui sera argument d'un Return ou la partie droite d'une affectation). 436 437 // http://doc.spip.org/@calculer_liste 438 function calculer_liste($tableau, $descr, &$boucles, $id_boucle='') { 439 if (!$tableau) return "''"; 440 if (!isset($descr['niv'])) $descr['niv'] = 0; 441 $codes = compile_cas($tableau, $descr, $boucles, $id_boucle); 442 $n = count($codes); 443 if (!$n) return "''"; 444 $tab = str_repeat("\t", $descr['niv']); 445 if (!isset($GLOBALS['var_mode_affiche']) 446 OR $GLOBALS['var_mode_affiche'] != 'validation') 447 return 448 (($n==1) ? $codes[0] : 449 "(" . join (" .\n$tab", $codes) . ")"); 450 else return "@debug_sequence('$id_boucle', '" . 451 ($descr['nom']) . 452 "', " . 453 $descr['niv'] . 454 ", array(" . 455 join(" ,\n$tab", $codes) . "))"; 456 } 457 458 // http://doc.spip.org/@compile_cas 459 function compile_cas($tableau, $descr, &$boucles, $id_boucle) { 460 $codes = array(); 461 // cas de la boucle recursive 462 if (is_array($id_boucle)) 463 $id_boucle = $id_boucle[0]; 464 $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete; 465 $tab = str_repeat("\t", ++$descr['niv']); 466 $mode = isset($GLOBALS['var_mode_affiche']) ? $GLOBALS['var_mode_affiche'] : ''; 467 // chaque commentaire introduit dans le code doit commencer 468 // par un caractere distinguant le cas, pour exploitation par debug. 469 foreach ($tableau as $p) { 470 471 switch($p->type) { 472 // texte seul 473 case 'texte': 474 $code = "'".str_replace(array("\\","'"),array("\\\\","\\'"), $p->texte)."'"; 475 476 $commentaire= strlen($p->texte) . " signes"; 477 $avant=''; 478 $apres=''; 479 $altern = "''"; 480 break; 481 482 case 'polyglotte': 483 $code = ""; 484 foreach($p->traductions as $k => $v) { 485 $code .= ",'" . 486 str_replace(array("\\","'"),array("\\\\","\\'"), $k) . 487 "' => '" . 488 str_replace(array("\\","'"),array("\\\\","\\'"), $v) . 489 "'"; 490 } 491 $code = "multi_trad(array(" . 492 substr($code,1) . 493 "))"; 494 $commentaire= '&'; 495 $avant=''; 496 $apres=''; 497 $altern = "''"; 498 break; 499 500 // inclure 501 case 'include': 502 $code = calculer_inclure($p, $descr, $boucles, $id_boucle); 503 504 $commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>'; 505 $avant=''; 506 $apres=''; 507 $altern = "''"; 508 break; 509 510 // boucle 511 case 'boucle': 512 $nom = $p->id_boucle; 513 $newdescr = $descr; 514 $newdescr['id_mere'] = $nom; 515 $newdescr['niv']++; 516 $code = 'BOUCLE' . 517 str_replace("-","_", $nom) . $descr['nom'] . 518 '($Cache, $Pile, $doublons, $Numrows, $SP)'; 519 $commentaire= "?$nom"; 520 $avant = calculer_liste($p->avant, 521 $newdescr, $boucles, $id_boucle); 522 $apres = calculer_liste($p->apres, 523 $newdescr, $boucles, $id_boucle); 524 $newdescr['niv']--; 525 $altern = calculer_liste($p->altern, 526 $newdescr, $boucles, $id_boucle); 527 break; 528 529 case 'idiome': 530 $code = "_T('" . $p->module . ":" .$p->nom_champ . "')"; 531 if ($p->param) { 532 $p->id_boucle = $id_boucle; 533 $p->boucles = &$boucles; 534 $code = compose_filtres($p, $code); 535 } 536 $commentaire = ":"; 537 $avant=''; 538 $apres=''; 539 $altern = "''"; 540 break; 541 542 case 'champ': 543 544 // cette structure pourrait etre completee des le phrase' (a faire) 545 $p->id_boucle = $id_boucle; 546 $p->boucles = &$boucles; 547 $p->descr = $descr; 548 #$p->interdire_scripts = true; 549 $p->type_requete = $type; 550 551 $code = calculer_champ($p); 552 $commentaire = '#' . $p->nom_champ . $p->etoile; 553 $avant = calculer_liste($p->avant, 554 $descr, $boucles, $id_boucle); 555 $apres = calculer_liste($p->apres, 556 $descr, $boucles, $id_boucle); 557 $altern = "''"; 558 break; 559 560 default: 561 erreur_squelette(_T('zbug_info_erreur_squelette')); 562 } // switch 563 564 if ($code != "''") { 565 if ($avant == "''") 566 $avant = ''; 567 if ($apres == "''") 568 $apres = ''; 569 if ($avant||$apres||($altern!="''")) { 570 $t = '$t' . $descr['niv']; 571 $res = (!$avant ? "" : "$avant . ") . 572 $t . 573 (!$apres ? "" : " . $apres"); 574 $code = "((strval($t = $code)!='')" 575 ." ?\n\t$tab($res) :\n\t$tab($altern))"; 576 } 577 578 // gestion d'une boucle-fragment (ahah) 579 if (isset($p->modificateur['fragment'])) { 580 static $nombre_fragments = array(); 581 $fragment = $p->modificateur['fragment']; 582 $fragment .= $nombre_fragments[$p->modificateur['fragment']]++; 583 $code = "\n((\$f = ($code))? 584 '<div id=\"$fragment\" class=\"fragment\">'.\$f.'<!-- /$fragment --></div><"."?php stop_inclure(\"$fragment\"); ?".">':'')\n"; 585 } 586 587 } 588 if ($code != "''") 589 $codes[]= (($mode == 'validation') ? 590 "array(" . $p->ligne . ", '$commentaire', $code)" 591 : (($mode == 'code') ? 592 "\n// $commentaire\n$code" : 593 $code)); 594 } // foreach 595 return $codes; 596 } 597 598 // affichage du code produit 599 600 // http://doc.spip.org/@code_boucle 601 function code_boucle(&$boucles, $id, $nom) 602 { 603 $boucle = &$boucles[$id]; 604 605 // Indiquer la boucle en commentaire 606 $pretty = ''; 607 608 if ($boucle->type_requete != 'boucle') 609 { 610 // Resynthetiser les criteres 611 foreach ($boucle->param as $param) { 612 $s = ""; 613 $sep = ""; 614 foreach ($param as $t) { 615 if (is_array($t)) { // toujours vrai normalement 616 $s .= $sep; 617 $c = $t[0]; 618 if ($c->apres) 619 $s .= ($c->apres . $c->texte . $c->apres); 620 else { 621 // faudrait decompiler aussi les balises... 622 foreach ($t as $c) 623 $s .= ($c->type == 'texte') ? $c->texte : '#...'; 624 } 625 $sep = ", "; 626 } 627 } 628 $pretty .= ' {' . $s . '}'; 629 } 630 } 631 632 $pretty = "BOUCLE$id(".strtoupper($boucle->type_requete) . ")" . 633 strtr($pretty,"\r\n", " "); 634 635 return $pretty; 636 } 637 638 639 // Prend en argument le texte d'un squelette (et son fichier d'origine) 640 // sa grammaire et un nom. 641 // Retourne une fonction PHP/SQL portant ce nom et calculant une page. 642 // Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment: 643 // - 1er: element 'cache' => nom (du fichier ou` mettre la page) 644 // - 2e: element 0 contenant un environnement ('id_article => $id_article, etc) 645 // Elle retourne alors un tableau de 5 e'le'ments: 646 // - 'texte' => page HTML, application du squelette a` l'environnement; 647 // - 'squelette' => le nom du squelette 648 // - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique 649 // - 'invalideurs' => de'pendances de cette page, pour invalider son cache. 650 // - 'entetes' => tableau des entetes http 651 // En cas d'erreur, elle retourne un tableau des 2 premiers elements seulement 652 653 // http://doc.spip.org/@public_compiler_dist 654 function public_compiler_dist($squelette, $nom, $gram, $sourcefile) { 655 global $table_des_tables, $tables_des_serveurs_sql, $tables_principales, 656 $tables_jointures; 657 658 // Pre-traitement : reperer le charset du squelette, et le convertir 659 // Bonus : supprime le BOM 660 include_spip('inc/charsets'); 661 $squelette = transcoder_page($squelette); 662 663 // Hacke un eventuel tag xml "<?xml" pour qu'il ne soit pas traite comme php 664 $squelette = str_replace('<'.'?xml', "#HTTP_HEADER{X-Xml-Hack: ok}<\1?xml", $squelette); 665 666 // Phraser le squelette, selon sa grammaire 667 // pour le moment: "html" seul connu (HTML+balises BOUCLE) 668 $boucles = array(); 669 spip_timer('calcul_skel'); 670 671 $f = charger_fonction('phraser_'.$gram, 'public'); 672 673 $racine = $f($squelette, '',$boucles, $nom); 674 675 // tableau des informations sur le squelette 676 $descr = array('nom' => $nom, 'sourcefile' => $sourcefile); 677 678 // une boucle documents est conditionnee par tout le reste! 679 foreach($boucles as $id => $boucle) { 680 $type = $boucle->type_requete; 681 if ($type != 'boucle') { 682 $boucles[$id]->descr = &$descr; 683 if ($x = $table_des_tables[$type]) { 684 $boucles[$id]->id_table = $x; 685 $boucles[$id]->primary = $tables_principales["spip_$x"]['key']["PRIMARY KEY"]; 686 if ((!$boucles[$id]->jointures) 687 AND (is_array($x = $tables_jointures['spip_' . $x]))) 688 $boucles[$id]->jointures = $x; 689 } else { 690 // table non Spip. 691 $boucles[$id]->id_table = $type; 692 $serveur = $boucle->sql_serveur; 693 $x = $tables_des_serveurs_sql[$serveur ? $serveur : 'localhost'][$type]['key']; 694 $boucles[$id]->primary = ($x["PRIMARY KEY"] ? $x["PRIMARY KEY"] : $x["KEY"]); 695 } 696 } 697 if (($boucle->type_requete == 'documents') && $boucle->doublons) 698 { $descr['documents'] = true; } 699 } 700 // Commencer par reperer les boucles appelees explicitement 701 // car elles indexent les arguments de maniere derogatoire 702 foreach($boucles as $id => $boucle) { 703 if ($boucle->type_requete == 'boucle') { 704 $boucles[$id]->descr = &$descr; 705 $rec = &$boucles[$boucle->param[0]]; 706 if (!$rec) { 707 return array(_T('zbug_info_erreur_squelette'), 708 ($boucle->param[0] 709 . ' '. _T('zbug_boucle_recursive_undef'))); 710 } else { 711 $rec->externe = $id; 712 $descr['id_mere'] = $id; 713 $boucles[$id]->return = 714 calculer_liste(array($rec), 715 $descr, 716 $boucles, 717 $boucle->param); 718 } 719 } 720 } 721 foreach($boucles as $id => $boucle) { 722 $type = $boucle->type_requete; 723 if ($type != 'boucle') { 724 if ($boucle->param) { 725 $res = calculer_criteres($id, $boucles); 726 if (is_array($res)) return $res; # erreur 727 } 728 $descr['id_mere'] = $id; 729 $boucles[$id]->return = 730 calculer_liste($boucle->milieu, 731 $descr, 732 $boucles, 733 $id); 734 } 735 } 736 737 // idem pour la racine 738 $descr['id_mere'] = ''; 739 $corps = calculer_liste($racine, $descr, $boucles); 740 741 // Calcul du corps de toutes les fonctions PHP, 742 // en particulier les requetes SQL et TOTAL_BOUCLE 743 // de'terminables seulement maintenant 744 745 foreach($boucles as $id => $boucle) { 746 // appeler la fonction de definition de la boucle 747 $f = 'boucle_'.strtoupper($boucle->type_requete); 748 // si pas de definition perso, definition spip 749 if (!function_exists($f)) $f = $f.'_dist'; 750 // laquelle a une definition par defaut 751 if (!function_exists($f)) $f = 'boucle_DEFAUT'; 752 if (!function_exists($f)) $f = 'boucle_DEFAUT_dist'; 753 $boucles[$id]->return = 754 "function BOUCLE" . strtr($id,"-","_") . $nom . 755 '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' . 756 $f($id, $boucles) . 757 "\n}\n\n"; 758 if ($GLOBALS['var_mode'] == 'debug') 759 boucle_debug_compile ($id, $nom, $boucles[$id]->return); 760 761 } 762 763 $code = ""; 764 foreach($boucles as $id => $boucle) { 765 $code .= "\n//\n// <BOUCLE " . 766 # code_boucle($boucles, $id, $nom). # pas au point 767 $boucle->type_requete . 768 ">\n//\n" . 769 $boucle->return; 770 } 771 772 $secondes = spip_timer('calcul_skel'); 773 spip_log("COMPIL ($secondes) [" 774 .preg_replace(',\.html$,', '', $sourcefile) 775 ."] $nom.php"); 776 777 $code = "<"."?php 778 /* 779 * Squelette : $sourcefile 780 * Date : ".gmdate("D, d M Y H:i:s", @filemtime($sourcefile))." GMT 781 * Compile : ".gmdate("D, d M Y H:i:s", time())." GMT ($secondes) 782 * " . (!$boucles ? "Pas de boucle" : 783 ("Boucles : " . join (', ', array_keys($boucles)))) ." 784 */ " . 785 $code . ' 786 787 // 788 // Fonction principale du squelette ' . $sourcefile ." 789 // 790 function " . $nom . '($Cache, $Pile, $doublons=array(), $Numrows=array(), $SP=0) { 791 $page = ' . 792 // ATTENTION, le calcul du l'expression $corps affectera $Cache 793 // c'est pourquoi on l'affecte a cette variable auxiliaire 794 // avant de referencer $Cache 795 $corps . "; 796 797 return analyse_resultat_skel('$nom', \$Cache, \$page); 798 } 799 800 ?".">"; 801 802 if ($GLOBALS['var_mode'] == 'debug') 803 squelette_debug_compile($nom, $sourcefile, $code, $squelette); 804 return $code; 805 806 } 807 808 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 10:20:27 2007 | par Balluche grâce à PHPXref 0.7 |
|