Esempio n. 1
0
/**
 * Composer le code d'inclusion PHP
 *
 * @param string $fichier
 * @param Object $p
 * @return string
 */
function sandbox_composer_inclure_php($fichier, &$p)
{
    $compil = texte_script(memoriser_contexte_compil($p));
    // si inexistant, on essaiera a l'execution
    if ($path = find_in_path($fichier)) {
        $path = "\"{$path}\"";
    } else {
        $path = "find_in_path(\"{$fichier}\")";
    }
    return sprintf(CODE_INCLURE_SCRIPT, $path, $fichier, $compil);
}
Esempio n. 2
0
/**
 * 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;
}
Esempio n. 3
0
/**
 * Compile la balise `#MODELE` qui inclut un résultat de squelette de modèle
 *
 * `#MODELE{nom}` insère le résultat d’un squelette contenu dans le
 * répertoire `modeles/`. L’identifiant de la boucle parente est transmis
 * par défaut avec le paramètre `id` à cette inclusion.
 *
 * Des arguments supplémentaires peuvent être transmis :
 * `[(#MODELE{nom, argument=xx, argument})]`
 *
 * @balise
 * @see balise_INCLURE_dist()
 * @example
 *     ```
 *     #MODELE{article_traductions}
 *     ```
 *
 * @param Champ $p
 *     Pile au niveau de la balise
 * @return Champ
 *     Pile complétée par le code à générer
 **/
function balise_MODELE_dist($p)
{
    $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
    // erreur de syntaxe = fond absent
    // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
    if (!$_contexte) {
        $contexte = array();
    }
    if (!isset($_contexte[1])) {
        $msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
        erreur_squelette($msg, $p);
    } else {
        $nom = $_contexte[1];
        unset($_contexte[1]);
        if (preg_match("/^\\s*'[^']*'/s", $nom)) {
            $nom = "'modeles/" . substr($nom, 1);
        } else {
            $nom = "'modeles/' . {$nom}";
        }
        $flag_env = false;
        if (isset($_contexte['env'])) {
            $flag_env = true;
            unset($_contexte['env']);
        }
        // Incoherence dans la syntaxe du contexte. A revoir.
        // Reserver la cle primaire de la boucle courante si elle existe
        if (isset($p->boucles[$p->id_boucle]->primary)) {
            $primary = $p->boucles[$p->id_boucle]->primary;
            if (!strpos($primary, ',')) {
                $id = champ_sql($primary, $p);
                $_contexte[] = "'{$primary}'=>" . $id;
                $_contexte[] = "'id'=>" . $id;
            }
        }
        $_contexte[] = "'recurs'=>(++\$recurs)";
        $connect = '';
        if (isset($p->boucles[$p->id_boucle])) {
            $connect = $p->boucles[$p->id_boucle]->sql_serveur;
        }
        $_options = memoriser_contexte_compil($p);
        $_options = "'compil'=>array({$_options}), 'trim'=>true";
        if (isset($_contexte['ajax'])) {
            $_options .= ", " . preg_replace(",=>(.*)\$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
            unset($_contexte['ajax']);
        }
        $_l = 'array(' . join(",\n\t", $_contexte) . ')';
        if ($flag_env) {
            $_l = "array_merge(\$Pile[0],{$_l})";
        }
        $page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect));
        $p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t{$page})\n";
        $p->interdire_scripts = false;
        // securite assuree par le squelette
    }
    return $p;
}
Esempio n. 4
0
function calculer_balise_dynamique($p, $nom, $l, $supp=array()) {

	if (!balise_distante_interdite($p)) {
		$p->code = "''";
		return $p;
	}
	// compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
	// il faut recracher {...} quand ce n'est finalement pas des args
	if ($p->fonctions AND (!$p->fonctions[0][0]) AND $p->fonctions[0][1]) {
		$p->fonctions = null;
	}

	if ($p->param AND ($c = $p->param[0])) {
		// liste d'arguments commence toujours par la chaine vide
		array_shift($c);
		// construire la liste d'arguments comme pour un filtre
		$param = compose_filtres_args($p, $c, ',');
	} else	$param = "";
	$collecte = collecter_balise_dynamique($l, $p, $nom);

	$p->code = sprintf(CODE_EXECUTER_BALISE, $nom,
		join(',', $collecte),
		($collecte ? $param : substr($param,1)), # virer la virgule
		memoriser_contexte_compil($p),
		(!$supp ? '' : (', ' . join(',', $supp))));

	$p->interdire_scripts = false;
	return $p;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
function balise_MODELE_dist($p) {

	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);

	// erreur de syntaxe = fond absent
	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
	if (!$_contexte) $contexte = array();

	if (!isset($_contexte[1])) {
		$msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
		erreur_squelette($msg, $p);
	} else {
		$nom = $_contexte[1];
		unset($_contexte[1]);

		if (preg_match("/^\s*'[^']*'/s", $nom))
			$nom = "'modeles/" . substr($nom,1);
		else $nom = "'modeles/' . $nom";

		// Incoherence dans la syntaxe du contexte. A revoir.
		// Reserver la cle primaire de la boucle courante si elle existe
		if (isset($p->boucles[$p->id_boucle]->primary)) {
			$primary = $p->boucles[$p->id_boucle]->primary;
			if (!strpos($primary,',')) {
				$id = champ_sql($primary, $p);
				$_contexte[] = "'$primary'=>".$id;
				$_contexte[] = "'id'=>".$id;
			}
		}
		$_contexte[] = "'recurs'=>(++\$recurs)";
		$connect = '';
		if (isset($p->boucles[$p->id_boucle]))
			$connect = $p->boucles[$p->id_boucle]->sql_serveur;

		$_options = memoriser_contexte_compil($p);
		$_options = "'compil'=>array($_options), 'trim'=>true"
		  . (isset($_contexte['ajax'])?", 'ajax'=>true":'');

		$page = sprintf(CODE_RECUPERER_FOND, $nom, 'array(' . join(',', $_contexte) .')', $_options, _q($connect));

		$p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";

		$p->interdire_scripts = false; // securite assuree par le squelette
	}

	return $p;
}