Source for file lodelparser.php
Documentation is available at lodelparser.php
* LODEL - Logiciel d'Edition ELectronique.
* Copyright (c) 2001-2002, Ghislain Picard, Marin Dacos
* Copyright (c) 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
* Copyright (c) 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
* Copyright (c) 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* Copyright (c) 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* Copyright (c) 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
* Home page: http://www.lodel.org
* E-Mail: lodel@lodel.org
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* @author Ghislain Picard
* @author Sophie Malafosse
* @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
* @licence http://www.gnu.org/copyleft/gpl.html
// traitement particulier des attributs d'une loop
// l'essentiel des optimisations et aide a l'uitilisateur doivent
// en general etre ajouter ici
require_once "balises.php";
require_once "parser.php";
* Classe utilitaire pour parser le Lodelscript - Fille de la classe Parser
* @author Ghislain Picard
* @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
* @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
* @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
* @licence http://www.gnu.org/copyleft/gpl.html
* @since Classe ajoutée depuis la version 0.8
* Tableau associatif concernant le status des textes
var $textstatus = array ('-1' => ' traduire', '1' => ' revoir', '2' => 'traduit');
* Tableau associatif concernant le status associé à la couleur
var $colorstatus = array ('-1' => 'red', '1' => 'orange', 2 => 'green');
* Liste des langues de la traduction
$this->commands[] = 'TEXT'; // catch the text
$this->codepieces['sqlquery'] = "mysql_query(lq(%s))";
} else { // call the ADODB driver
die("DBDRIVER not supported currently for the parser");
$this->codepieces['sqlerror'] = "or die($GLOBALS[db]->errormsg())";
$this->codepieces['sqlquery'] = "$GLOBALS[db]->execute(%s)";
function parse_loop_extra(& $tables, & $tablesinselect, & $extrainselect, & $selectparts)
global $site, $home, $db;
static $tablefields; // charge qu'une seule fois
require ('tablefields.php');
// split the SQL parts into quoted/non-quoted par
foreach ($selectparts as $k => $v) {
$where = & $selectparts['where'];
// convertion des codes specifiques dans le where
// ce bout de code depend du parenthesage et du trim fait dans parse_loop.
# $where=preg_replace (array(
# '".($GLOBALS[lodeluser][admin] ? "1" : "(usergroup IN ($GLOBALS[lodeluser][groups]))")."'
if ($tablefields[lq("#_TP_classes")]) {
$classes = $dao->findMany("status > 0");
foreach ($classes as $class) {
// manage the linked tables...
// do we have the table class in $tables ?
if ($ind === FALSE || $ind === NULL) {
$alias = "alias_". $class->classtype. "_". $class->class;
$aliastype = "aliastype_". $class->classtype. "_". $class->class;
$aliasbyclasstype[$class->classtype] = $alias;
$classbyclasstype[$class->classtype] = $class->class;
switch ($class->classtype) {
protect($selectparts, $alias, "id|idtype|identifier|usergroup|iduser|rank|status|idparent|creationdate|modificationdate|g_title");
$typetable = "entrytypes";
protect($selectparts, $alias, "id|idtype|g_name|sortkey|rank|status|idparent");
$typetable = "persontypes";
protect($selectparts, $alias, "id|idtype|g_familyname|g_firstname|status");
die("ERROR: internal error in lodelparser");
array_push($tables, $class->classtype. " AS ". $alias, typestable($class->classtype). " AS ". $aliastype);
// put entites just after the class table
$where[count($where) - 1] .= " AND ". $class->class. ".". $longid. "=". $alias. ".id AND ". $alias. ".idtype=". $aliastype. ".id AND ". $aliastype. ".class=";
$where[] = "'". $class->class. "'"; // quoted part
$extrainselect .= ", ". $aliastype. ".type , ". $aliastype. ".class";
($class->classtype == "entities" || $class->classtype == "entries")) {
array_push($tables, $class->classtype. " AS ". $alias. "_parent");
$fullid = $class->classtype == "entries" ? "g_name" : "identifier";
$where[count($where) - 1] .= " AND ". $alias. "_parent.id=". $alias. ".idparent";
protect($selectparts, "entities", "id|status|rank");
$jointypesentitiesadded = 1;
$where[count($where) - 1] .= " AND entities.idtype=types.id";
array_push($tables, "entities as entities_parent");
protect($selectparts, "entities", "id|idtype|identifier|usergroup|iduser|rank|status|idparent|creationdate|modificationdate|g_title");
$where[count($where) - 1] .= " AND entities_parent.id=entities.idparent";
if (in_array("types", $tables)) { // compatibilite avec avant... et puis c est pratique quand meme.
$extrainselect .= ", types.type , types.class";
if (!preg_match_sql("/\bstatus\b/i", $where)) { // test que l'element n'est pas a la poubelle
foreach ($tables as $table) {
list ($table, $alias) = preg_split("/\s+AS\s+/i", $table);
if (!$tablefields[$realtable] || !in_array("status", $tablefields[$realtable])) {
if ($table == "session") {
if ($table == "entities") {
$lowstatus = '"-64".($GLOBALS[lodeluser][admin] ? "" : "*('. $alias. '.usergroup IN (".$GLOBALS[lodeluser][groups]."))")';
$where[count($where) - 1] .= " AND (". $alias. ".status>\".(\$GLOBALS[lodeluser][visitor] ? $lowstatus : \"0\").\")";
# echo "where 2:",htmlentities($where),"<br>";
///////// CODE SPECIFIQUE -- gere les tables croisees
// les regexp ci-dessous sont insuffisantes, il faudrait tester que ce n'est pas dans une zone quotee de la clause where !!!!
foreach (array ("persons" => "persontypes", "entries" => "entrytypes") as $table => $typetable) {
protect($selectparts, $table, "id|status|rank");
$where[count($where) - 1] .= " AND ". $table. ".idtype=". $typetable. ".id";
if (in_array($table, $tables) || $aliasbyclasstype[$table]) {
if ($aliasbyclasstype[$table]) {
$class = $classbyclasstype[$table];
$table = $aliasbyclasstype[$table];
// on a besoin de la table croisee entities_persons
$alias = "relation_entities_". $table; // use alias for security
array_push($tables, "relations as ". $alias); ###,"entities_persons");
$where[count($where) - 1] .= " AND $alias.id2=$table.id";
if ($class && $typetable == "persontypes") { // related table for persons only
$relatedtable = "entities_". $class;
if (!in_array($relatedtable, $tables)) {
$where[count($where) - 1] .= " AND ". $relatedtable. ".idrelation=". $alias. ".idrelation";
$extrainselect .= ", ". $relatedtable. ".* ";
if ($aliasbyclasstype['entities'] || in_array("entities", $tables)) {
foreach (array ("persons" => "idperson", "entries" => "identry") as $table => $regexp) {
// on a besoin de la table croise relation
$alias = "relation2_". $table; // use alias for security
$where[count($where) - 1] .= " AND ". $alias. ".id1=". ($aliasbyclasstype['entities'] ? $aliasbyclasstype['entities'] : "entities"). ".id";
if ($table == "persons" && $classbyclasstype['persons']) { // related table for persons only
$relatedtable = "entities_". $classbyclasstype['persons'];
if (!in_array($relatedtable, $tables)) {
$where[count($where) - 1] .= " AND ". $relatedtable. ".idrelation=". $alias. ".idrelation";
$extrainselect .= ", ". $relatedtable. ".* ";
// on a besoin de la table croise users_groupes
$where[count($where) - 1] .= " AND idgroup=usergroups.id";
$where[count($where) - 1] .= " AND iduser=users.id";
foreach ($selectparts as $k => $v) {
$selectparts[$k] = join("", $v);
$selectparts['where'] = lq($selectparts['where']);
if (preg_match("/\b(count|min|max|avg|bit_and|bit_or|bit_xor|group_concat|std|stddev|stddev_pop|stddev_samp|sum|var_pop|var_samp|variance)\s*\(/i", $selectparts['select']))
$extrainselect = ""; // group by function
$extrainselect = lq($extrainselect);
$tables = array_map(array (& $this, "prefixTableName"), $tables);
$tablesinselect = array_map(array (& $this, "prefixTableName"), $tablesinselect);
// Traitement special des variables
if ($varname == "GROUPRIGHT") {
return '($GLOBALS[lodeluser][admin] || in_array($context[usergroup],explode(\',\',$GLOBALS[lodeluser][groups])))';
if (preg_match("/^OPTION[_.]/", $varname)) { // options
$dotpos = strpos($varname, ".");
$name = substr($varname, $dotpos + 1);
$group = substr($varname, 0, $dotpos);
return $this->maketext($name, $group, "@");
// fonction qui gere les decodage du contenu des differentes parties
// fonction speciale pour lodel
$havepublications = in_array("publications", $tables);
$havedocuments = in_array("documents", $tables);
// est-ce qu'on veut le prev et next publication ?
// if ($havepublications && preg_match("/\[\(?#(PREV|NEXT)PUBLICATION\b/",$content[$balise])) {
// $content["PRE_".$balise]='include_once("$GLOBALS[home]/func.php"); export_prevnextpublication($context);';
// les filtrages automatiques
if ($havedocuments || $havepublications) {
$options['sqlfetchassoc'] = 'filtered_mysql_fetch_assoc($context,%s)';
$this->fct_txt .= 'if (!(@include_once("CACHE/filterfunc.php"))) require_once("filterfunc.php");';
$this->errmsg("ERROR: The TEXT tag has no NAME attribute");
if ($GLOBALS['righteditor']) { // cherche si le texte existe
require_once TOINCLUDE. "connect.php";
$textexists = $db->getOne("SELECT 1 FROM ". $prefix. "texts WHERE name='$name' |