コード例 #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
ファイル: 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);
}