示例#1
0
文件: compiler.php 项目: JLuc/SPIP
/**
 * Compilation d'une boucle (non recursive). 
 *
 * @param string $id_boucle
 * 		Identifiant de la boucle
 * @param array $boucles
 * 		AST du squelette
 * @param string $trace
 * 		Code PHP (en mode debug uniquement) servant à conserver une
 * 		trace des premières valeurs de la boucle afin de pouvoir
 * 		les afficher dans le débugueur ultérieurement
 * @return string
 * 		Code PHP compilé de la boucle récursive
**/
function calculer_boucle_nonrec($id_boucle, &$boucles, $trace)
{
    $boucle =& $boucles[$id_boucle];
    $return = $boucle->return;
    $type_boucle = $boucle->type_requete;
    $primary = $boucle->primary;
    $constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
    $flag_cpt = $boucle->mode_partie || $boucle->cptrows;
    $corps = '';
    // faudrait expanser le foreach a la compil, car y en a souvent qu'un
    // et puis faire un [] plutot qu'un "','."
    if ($boucle->doublons) {
        $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' . index_pile($id_boucle, $primary, $boucles) . "; // doublons\n";
    }
    // La boucle doit-elle selectionner la langue ?
    // - par defaut, les boucles suivantes le font
    //    (sauf si forcer_lang==true ou si le titre contient <multi>).
    // - a moins d'une demande explicite via {!lang_select}
    if (!$constant && $boucle->lang_select != 'non' && ($boucle->lang_select == 'oui' || in_array($type_boucle, array('articles', 'rubriques', 'hierarchie', 'breves')))) {
        // Memoriser la langue avant la boucle et la restituer apres
        // afin que le corps de boucle affecte la globale directement
        $init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
        $fin_lang = "lang_select();\n\t";
        $fin_lang_select_public = "\n\t\tlang_select();";
        $corps .= "\n\t\tlang_select_public(" . index_pile($id_boucle, 'lang', $boucles) . ", '" . $boucle->lang_select . "'" . (in_array($type_boucle, array('articles', 'rubriques', 'hierarchie', 'breves')) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '') . ');';
    } else {
        $init_lang = '';
        $fin_lang = '';
        $fin_lang_select_public = '';
        // sortir les appels au traducteur (invariants de boucle)
        if (strpos($return, '?php') === false and preg_match_all("/\\W(_T[(]'[^']*'[)])/", $return, $r)) {
            $i = 1;
            foreach ($r[1] as $t) {
                $init_lang .= "\n\t\$l{$i} = {$t};";
                $return = str_replace($t, "\$l{$i}", $return);
                $i++;
            }
        }
    }
    // gestion optimale des separateurs et des boucles constantes
    if (count($boucle->separateur)) {
        $code_sep = "'" . str_replace("'", "\\'", join('', $boucle->separateur)) . "'";
    }
    $corps .= !$boucle->separateur ? $constant && !$corps && !$flag_cpt ? $return : ($return === "''" ? '' : "\n\t\t" . '$t0 .= ' . $return . ";") : "\n\t\t\$t1 " . (strpos($return, '$t1.') === 0 ? ".=" . substr($return, 4) : '= ' . $return) . ";\n\t\t" . '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;";
    // Calculer les invalideurs si c'est une boucle non constante et si on
    // souhaite invalider ces elements
    if (!$constant and $primary) {
        include_spip('inc/invalideur');
        if (function_exists($i = 'calcul_invalideurs')) {
            $corps = $i($corps, $primary, $boucles, $id_boucle);
        }
    }
    // gerer le compteur de boucle
    // avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
    if ($boucle->partie or $boucle->cptrows) {
        $corps = "\n\t\t\$Numrows['{$id_boucle}']['compteur_boucle']++;" . $boucle->partie . $corps;
    }
    // depiler la lang de la boucle si besoin
    $corps .= $fin_lang_select_public;
    // si le corps est une constante, ne pas appeler le serveur N fois!
    if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
        if (!isset($r[2]) or !$r[2]) {
            if (!$boucle->numrows) {
                return "\n\t\$t0 = '';";
            } else {
                $corps = "";
            }
        } else {
            $boucle->numrows = true;
            $corps = "\n\t\$t0 = str_repeat({$corps}, \$Numrows['{$id_boucle}']['total']);";
        }
    } else {
        $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n{$corps}\n\t}";
    }
    $count = '';
    if (!$boucle->select) {
        if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
            $count = '1';
        } else {
            $count = 'count(*)';
        }
        $boucles[$id_boucle]->select[] = $count;
    }
    if ($flag_cpt) {
        $nums = "\n\t// COMPTEUR\n\t" . "\$Numrows['{$id_boucle}']['compteur_boucle'] = 0;\n\t";
    } else {
        $nums = '';
    }
    if ($boucle->numrows or $boucle->mode_partie) {
        $nums .= "\$Numrows['{$id_boucle}']['total'] = @intval(\$iter->count());" . $boucle->mode_partie . "\n\t";
    }
    // Ne calculer la requete que maintenant
    // car ce qui precede appelle index_pile qui influe dessus
    $init = (($init = $boucles[$id_boucle]->doublons) ? "\n\t{$init} = array();" : '') . calculer_requete_sql($boucles[$id_boucle]);
    $contexte = memoriser_contexte_compil($boucle);
    $a = sprintf(CODE_CORPS_BOUCLE, $init, $boucle->iterateur, "\$command", $contexte, $nums, $init_lang, $corps, $fin_lang, $trace, 'BOUCLE' . $id_boucle . ' @ ' . $boucle->descr['sourcefile']);
    #	var_dump($a);exit;
    return $a;
}
示例#2
0
/**
 * Compile la balise `#TRI` permettant d'afficher un lien de changement d'ordre de tri
 * d'une colonne de la boucle
 *
 * La balise `#TRI{champ[,libelle]}` champ prend `>` ou `<` pour afficher
 * le lien de changement de sens croissant ou decroissant (`>` `<` indiquent
 * un sens par une flèche)
 *
 * @balise
 * @example
 *     ```
 *     <th>[(#TRI{titre,<:info_titre:>,ajax})]</th>
 *     ```
 *
 * @param Champ $p
 *     Pile au niveau de la balise
 * @param string $liste
 *     Inutilisé
 * @return Champ
 *     Pile complétée par le code à générer
 */
function balise_TRI_dist($p, $liste = 'true')
{
    $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
    // s'il n'y a pas de nom de boucle, on ne peut pas trier
    if ($b === '') {
        erreur_squelette(_T('zbug_champ_hors_boucle', array('champ' => '#TRI')), $p->id_boucle);
        $p->code = "''";
        return $p;
    }
    $boucle = $p->boucles[$b];
    // s'il n'y a pas de tri_champ, c'est qu'on se trouve
    // dans un boucle recursive ou qu'on a oublie le critere {tri}
    if (!isset($boucle->modificateur['tri_champ'])) {
        erreur_squelette(_T('zbug_tri_sans_critere', array('champ' => '#TRI')), $p->id_boucle);
        $p->code = "''";
        return $p;
    }
    $_champ = interprete_argument_balise(1, $p);
    // si pas de champ, renvoyer le critere de tri utilise
    if (!$_champ) {
        $p->code = $boucle->modificateur['tri_champ'];
        return $p;
    }
    // forcer la jointure si besoin, et si le champ est statique
    if (preg_match(",^'([\\w.]+)'\$,i", $_champ, $m)) {
        index_pile($b, $m[1], $p->boucles, '', null, true, false);
    }
    $_libelle = interprete_argument_balise(2, $p);
    $_libelle = $_libelle ? $_libelle : $_champ;
    $_class = interprete_argument_balise(3, $p);
    // si champ = ">" c'est un lien vers le tri croissant : de gauche a droite ==> 1
    // si champ = "<" c'est un lien vers le tri decroissant : (sens inverse) == -1
    $_issens = "in_array({$_champ},array('>','<'))";
    $_sens = "(strpos('< >',{$_champ})-1)";
    $_variable = "((\$s={$_issens})?'sens':'tri')." . $boucle->modificateur['tri_nom'];
    $_url = "parametre_url(self(),{$_variable},\$s?{$_sens}:{$_champ})";
    $_url = "parametre_url({$_url},'var_memotri',strncmp(" . $boucle->modificateur['tri_nom'] . ",'session',7)==0?{$_variable}:'')";
    $_on = "\$s?(" . $boucle->modificateur['tri_sens'] . "=={$_sens}" . '):(' . $boucle->modificateur['tri_champ'] . "=={$_champ})";
    $p->code = "lien_ou_expose({$_url},{$_libelle},{$_on}" . ($_class ? ",{$_class}" : "") . ")";
    //$p->code = "''";
    $p->interdire_scripts = false;
    return $p;
}
示例#3
0
function calculer_argument_precedent($idb, $nom_champ, &$boucles) {

	// si recursif, forcer l'extraction du champ SQL mais ignorer le code
	if ($boucles[$idb]->externe) {
		index_pile ($idb, $nom_champ, $boucles); 
		$zero = '$SP';
	} else $zero = '0';
	// retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
	$prec = $boucles[$idb]->id_parent;
	return (($prec === '')
		? ('$Pile[' . $zero . "]['$nom_champ']") 
		: index_pile($prec, $nom_champ, $boucles));
}
示例#4
0
文件: compiler.php 项目: rhertzog/lcs
function calculer_boucle_nonrec($id_boucle, &$boucles, $trace){

	$boucle = &$boucles[$id_boucle];
	$return = $boucle->return;
	$type_boucle = $boucle->type_requete;
	$primary = $boucle->primary;
	$constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
	$flag_cpt = $boucle->mode_partie || $boucle->cptrows;
	$corps = '';

	// faudrait expanser le foreach a la compil, car y en a souvent qu'un 
	// et puis faire un [] plutot qu'un "','."
	if ($boucle->doublons)
		$corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
			index_pile($id_boucle, $primary, $boucles)
			. "; // doublons\n";

	// La boucle doit-elle selectionner la langue ?
	// -. par defaut, les boucles suivantes le font
	//    (sauf si forcer_lang==true ou si le titre contient <multi>).
	// - . a moins d'une demande explicite via {!lang_select}
	if (!$constant && $boucle->lang_select!='non' &&
		(($boucle->lang_select=='oui') ||
			in_array($type_boucle, array(
				'articles', 'rubriques', 'hierarchie', 'breves'
			)))
	){
		// Memoriser la langue avant la boucle et la restituer apres
		// afin que le corps de boucle affecte la globale directement
		$init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
		$fin_lang = "lang_select();\n\t";

		$corps .=
			"\n\t\tlang_select_public("
				. index_pile($id_boucle, 'lang', $boucles)
				. ", '" . $boucle->lang_select . "'"
				. (in_array($type_boucle, array(
				'articles', 'rubriques', 'hierarchie', 'breves'
			)) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
				. ');';
	}
	else {
		$init_lang = '';
		$fin_lang = '';
		// sortir les appels au traducteur (invariants de boucle)
		if (strpos($return, '?php')===false
			AND preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
		){
			$i = 1;
			foreach ($r[1] as $t){
				$init_lang .= "\n\t\$l$i = $t;";
				$return = str_replace($t, "\$l$i", $return);
				$i++;
			}
		}
	}

	// gestion optimale des separateurs et des boucles constantes
	if (count($boucle->separateur))
		$code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");

	$corps .=
		((!$boucle->separateur) ?
			(($constant && !$corps && !$flag_cpt) ? $return :
				(($return==="''") ? '' :
					("\n\t\t" . '$t0 .= ' . $return . ";"))) :
			("\n\t\t\$t1 " .
				((strpos($return, '$t1.')===0) ?
					(".=" . substr($return, 4)) :
					('= ' . $return)) .
				";\n\t\t" .
				'$t0 .= (($t1 && $t0) ? ' . $code_sep . " : '') . \$t1;"));

	// Calculer les invalideurs si c'est une boucle non constante et si on
	// souhaite invalider ces elements
	if (!$constant AND $primary){
		include_spip('inc/invalideur');
		if (function_exists($i = 'calcul_invalideurs'))
			$corps = $i($corps, $primary, $boucles, $id_boucle);
	}

	// gerer le compteur de boucle 
	// avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...

	if ($boucle->partie OR $boucle->cptrows)
		$corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
			. $boucle->partie
			. $corps;

	$serveur = !$boucle->sql_serveur ? ''
		: (', ' . _q($boucle->sql_serveur));

	// si le corps est une constante, ne pas appeler le serveur N fois!

	if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)){
		if (!isset($r[2]) OR (!$r[2])){
			if (!$boucle->numrows)
				return "\n\t\$t0 = '';";
			else
				$corps = "";
		} else {
			$boucle->numrows = true;
			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
		}
	} else $corps = "while (\$Pile[\$SP] = @sql_fetch(\$result$serveur)) {\n$corps\n	}";

	$count = '';
	if (!$boucle->select){
		if (!$boucle->numrows OR $boucle->limit OR $boucle_mode_partie OR $boucle->group)
			$count = '1';
		else $count = 'count(*)';
		$boucles[$id_boucle]->select[] = $count;
	}

	if ($flag_cpt)
		$nums = "\n\t// COMPTEUR\n\t"
			. "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
	else $nums = '';

	if ($boucle->numrows OR $boucle->mode_partie){
		if ($count=='count(*)')
			$count = "(\$cc=sql_fetch(\$result$serveur))?array_shift(\$cc):0";
		else
			$count = "sql_count(\$result$serveur)";
		$nums .= "\$Numrows['$id_boucle']['total'] = @intval($count);"
			. $boucle->mode_partie
			. "\n\t";
	}

	// Ne calculer la requete que maintenant
	// car ce qui precede appelle index_pile qui influe dessus

	$init = (($init = $boucles[$id_boucle]->doublons)
		? ("\n\t$init = array();") : '')
		. calculer_requete_sql($boucles[$id_boucle]);

	$contexte = memoriser_contexte_compil($boucle);

	return sprintf(CODE_CORPS_BOUCLE, $init, $contexte, $nums, $init_lang, $corps, $fin_lang, $serveur, $trace);
}
示例#5
0
文件: references.php 项目: JLuc/SPIP
/**
 * Réserve les champs necessaires à la comparaison avec le contexte donné par
 * la boucle parente.
 *
 * Attention en recursif il faut les réserver chez soi-même ET chez sa maman
 *
 * @param string $idb          Identifiant de la boucle
 * @param string $nom_champ    
 * @param array $boucles       AST du squelette
 * @param null|string $defaut  
 * @return 
**/
function calculer_argument_precedent($idb, $nom_champ, &$boucles, $defaut = null)
{
    // si recursif, forcer l'extraction du champ SQL mais ignorer le code
    if ($boucles[$idb]->externe) {
        index_pile($idb, $nom_champ, $boucles, '', $defaut);
        // retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
        // on ignore le defaut fourni dans ce cas
        $defaut = "@\$Pile[\$SP]['{$nom_champ}']";
    }
    return index_pile($boucles[$idb]->id_parent, $nom_champ, $boucles, '', $defaut);
}
示例#6
0
文件: balises.php 项目: rhertzog/lcs
function calculer_balise_expose($p, $on, $off)
{
	$b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
	$key = $p->boucles[$b]->primary;
	$type = $p->boucles[$p->id_boucle]->primary;
	$desc = $p->boucles[$b]->show;
	$connect = sql_quote($p->boucles[$b]->sql_serveur);

	if (!$key) {
		$msg = array('zbug_champ_hors_boucle', array('champ' => '#EXPOSER'));
		erreur_squelette($msg, $p);
	}

	// Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
	$c = index_pile($p->id_boucle, $type, $p->boucles);

	if (isset($desc['field']['id_parent'])) {
		$parent = 0; // pour if (!$parent) dans calculer_expose
	} elseif (isset($desc['field']['id_rubrique'])) {
		$parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
	} elseif  (isset($desc['field']['id_groupe'])) {
		$parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
	} else $parent = "''";

	$p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";

	$p->interdire_scripts = false;
	return $p;
}