コード例 #1
0
/**
 * Permet de faire un comptage par table liee
 *
 * @syntaxe `{compteur table[, champ]}`
 * @link http://www.spip-contrib.net/Classer-les-articles-par-nombre-de#forum409210
 * 
 * @example
 *     Pour avoir les auteurs classes par articles et
 *     le nombre d'article de chacun :
 * 
 *     ```
 *     <BOUCLE1(AUTEURS){compteur articles}{par compteur_articles}>
 *     #ID_AUTEUR : #COMPTEUR{articles}
 *     </BOUCLE1>
 *     ```
 *
 * @note
 *     Avec un seul argument {compteur autre_table} le groupby est fait
 *     implicitement sur la cle primaire de la boucle en cours.
 *     Avec un second argument {compteur autre_table,champ_fusion}
 *     le groupby est fait sur le champ_fusion"
 * 
 * @param string $idb
 *     Identifiant de la boucle
 * @param Boucle[] $boucles
 *     AST du squelette
 * @param Critere $crit
 *     Paramètres du critère dans cette boucle
 * @param bool $left
 *     true pour utiliser un left join plutôt qu'un inner join.      
 * @return void
 */
function critere_compteur($idb, &$boucles, $crit, $left = false)
{
    $boucle =& $boucles[$idb];
    if (isset($crit->param[1])) {
        $_fusion = calculer_liste($crit->param[1], array(), $boucles, $boucle->id_parent);
    } else {
        $_fusion = "''";
    }
    $params = $crit->param;
    $table = reset($params);
    $table = $table[0]->texte;
    $op = false;
    if (preg_match(',^(\\w+)([<>=])([0-9]+)$,', $table, $r)) {
        $table = $r[1];
        if (count($r) >= 3) {
            $op = $r[2];
        }
        if (count($r) >= 4) {
            $op_val = $r[3];
        }
    }
    $type = objet_type($table);
    $type_id = id_table_objet($type);
    /**
     * Si la clé primaire est une clé multiple, on prend la première partie
     * Utile pour compter les versions de spip_versions par exemple
     */
    if (count($types = explode(',', $type_id)) > 1) {
        $type_id = $types[0];
    }
    $table_sql = table_objet_sql($type);
    $trouver_table = charger_fonction('trouver_table', 'base');
    $arrivee = array($table, $trouver_table($table, $boucle->sql_serveur));
    $depart = array($boucle->id_table, $trouver_table($boucle->id_table, $boucle->sql_serveur));
    // noter les jointures deja installees
    $joins = array_keys($boucle->from);
    if ($compt = calculer_jointure($boucle, $depart, $arrivee)) {
        if ($_fusion != "''") {
            // en cas de jointure, on ne veut pas du group_by sur la cle primaire !
            // cela casse le compteur !
            foreach ($boucle->group as $k => $group) {
                if ($group == $boucle->id_table . '.' . $boucle->primary) {
                    unset($boucle->group[$k]);
                }
            }
            $boucle->group[] = '".($gb=' . $_fusion . ')."';
        }
        $boucle->select[] = "COUNT({$compt}.{$type_id}) AS compteur_{$table}";
        if ($op) {
            $boucle->having[] = array("'" . $op . "'", "'compteur_" . $table . "'", $op_val);
        }
        if ($left) {
            foreach ($boucle->from as $k => $val) {
                if (!in_array($k, $joins)) {
                    $boucle->from_type[$k] = 'left';
                }
            }
        }
    }
}
コード例 #2
0
ファイル: spip_bonux_criteres.php プロジェクト: rhertzog/lcs
/**
 * http://www.spip-contrib.net/Classer-les-articles-par-nombre-de#forum409210
 * Permet de faire un comptage par table liee
 * exemple
 * <BOUCLE1(AUTEURS){compteur articles}{par compteur_articles}>
 * #ID_AUTEUR : #COMPTEUR{articles}
 * </BOUCLE1>
 * pour avoir les auteurs classes par articles et le nombre d'article de chacun
 *
 * @param unknown_type $idb
 * @param unknown_type $boucles
 * @param unknown_type $crit
 */
function critere_compteur($idb, &$boucles, $crit, $left=false){
	$boucle = &$boucles[$idb];

	$_fusion = calculer_liste($crit->param[1], array(), $boucles, $boucle->id_parent);
	$params = $crit->param;
	$table = reset($params);
	$table = $table[0]->texte;
	$op = false;
	if(preg_match(',^(\w+)([<>=])([0-9]+)$,',$table,$r)){
		$table=$r[1];
		if (count($r)>=3) $op=$r[2];
		if (count($r)>=4) $op_val=$r[3];
	}
	$type = objet_type($table);
	$type_id = id_table_objet($type);
	$table_sql = table_objet_sql($type);
	
	
	$trouver_table = charger_fonction('trouver_table','base');
	$arrivee = array($table, $trouver_table($table, $boucle->sql_serveur));
	$depart = array($boucle->id_table,$trouver_table($boucle->id_table, $boucle->sql_serveur));

	// noter les jointures deja installees
	$joins = array_keys($boucle->from);
	if ($compt = calculer_jointure($boucle,$depart,$arrivee)){
		if ($_fusion!="''"){
			// en cas de jointure, on ne veut pas du group_by sur la cle primaire !
			// cela casse le compteur !
			foreach($boucle->group as $k=>$group)
				if ($group == $boucle->id_table.'.'.$boucle->primary)
					unset($boucle->group[$k]);
			$boucle->group[] = '".($gb='.$_fusion.')."';
		}

		$boucle->select[]= "COUNT($compt.$type_id) AS compteur_$table";	
		if ($op)
			$boucle->having[]= array("'".$op."'", "'compteur_".$table."'",$op_val);
		if ($left){
			foreach($boucle->from as $k=>$val){
				if (!in_array($k, $joins)){
					$boucle->from_type[$k] = 'left';
				}
			}
		}
	}
}
コード例 #3
0
ファイル: jointures.php プロジェクト: rhertzog/lcs
function trouver_jointure_champ($champ, &$boucle)
{
	$cle = trouver_champ_exterieur($champ, $boucle->jointures, $boucle);
	if ($cle) {
		$desc = $boucle->show;
		$cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $cle, false);
	}
	if ($cle) return $cle;
	spip_log("trouver_jointure_champ: $champ inconnu");
	return '';
}
コード例 #4
0
ファイル: criteres.php プロジェクト: phenix-factory/SPIP
/**
 * Champ hors table, ça ne peut être qu'une jointure.
 *
 * On cherche la table du champ et on regarde si elle est déjà jointe
 * Si oui et qu'on y cherche un champ nouveau, pas de jointure supplementaire
 * Exemple: criteres {titre_mot=...}{type_mot=...}
 * Dans les 2 autres cas ==> jointure
 * (Exemple: criteres {type_mot=...}{type_mot=...} donne 2 jointures
 * pour selectioner ce qui a exactement ces 2 mots-cles.
 *
 * @param Boucle $boucle
 *     Description de la boucle
 * @param array $joints
 *     Liste de jointures possibles (ex: $boucle->jointures ou $boucle->jointures_explicites)
 * @param string $col
 *     Colonne cible de la jointure
 * @param array $desc
 *     Description de la table
 * @param bool $cond
 *     Flag pour savoir si le critère est conditionnel ou non
 * @param bool|string $checkarrivee
 *     string : nom de la table jointe où on veut trouver le champ.
 *     n'a normalement pas d'appel sans $checkarrivee.
 * @return string
 *     Alias de la table de jointure (Lx)
 *     Vide sinon.
 */
function calculer_critere_externe_init(&$boucle, $joints, $col, $desc, $cond, $checkarrivee = false)
{
    // si on demande un truc du genre spip_mots
    // avec aussi spip_mots_liens dans les jointures dispo
    // et qu'on est la
    // il faut privilegier la jointure directe en 2 etapes spip_mots_liens, spip_mots
    if ($checkarrivee and is_string($checkarrivee) and $a = table_objet($checkarrivee) and in_array($a . '_liens', $joints)) {
        if ($res = calculer_lien_externe_init($boucle, $joints, $col, $desc, $cond, $checkarrivee)) {
            return $res;
        }
    }
    foreach ($joints as $joint) {
        if ($arrivee = trouver_champ_exterieur($col, array($joint), $boucle, $checkarrivee)) {
            // alias de table dans le from
            $t = array_search($arrivee[0], $boucle->from);
            // recuperer la cle id_xx eventuellement decomposee en (id_objet,objet)
            $cols = $arrivee[2];
            // mais on ignore la 3eme cle si presente qui correspond alors au point de depart
            if (count($cols) > 2) {
                array_pop($cols);
            }
            if ($t) {
                // la table est déjà dans le FROM, on vérifie si le champ est utilisé.
                $joindre = false;
                foreach ($cols as $col) {
                    $c = '/\\b' . $t . ".{$col}" . '\\b/';
                    if (trouver_champ($c, $boucle->where)) {
                        $joindre = true;
                    } else {
                        // mais ca peut etre dans le FIELD pour le Having
                        $c = "/FIELD.{$t}" . ".{$col},/";
                        if (trouver_champ($c, $boucle->select)) {
                            $joindre = true;
                        }
                    }
                }
                if (!$joindre) {
                    return $t;
                }
            }
            array_pop($arrivee);
            if ($res = calculer_jointure($boucle, array($boucle->id_table, $desc), $arrivee, $cols, $cond, 1)) {
                return $res;
            }
        }
    }
    return '';
}
コード例 #5
0
ファイル: criteres.php プロジェクト: rhertzog/lcs
function calculer_critere_externe_init(&$boucle, $joints, $col, $desc, $eg, $checkarrivee = false)
{
	$cle = trouver_champ_exterieur($col, $joints, $boucle, $checkarrivee);
	if (!$cle) return '';
	$t = array_search($cle[0], $boucle->from);
	// transformer eventuellement id_xx en (id_objet,objet)
	$cols = trouver_champs_decomposes($col,$cle[1]); 
	if ($t) {
			$joindre = false;
			foreach($cols as $col){
			  $c = '/\b' . $t  . ".$col" . '\b/';
			  if (trouver_champ($c, $boucle->where)) $joindre = true;
			  else {
			    // mais ca peut etre dans le FIELD pour le Having
			    $c = "/FIELD.$t" .".$col,/";
			    if (trouver_champ($c, $boucle->select)) $joindre = true;
			  }
			}
		  if (!$joindre) return $t;
	}
	return calculer_jointure($boucle, array($boucle->id_table, $desc), $cle, $cols, $eg);

}
コード例 #6
0
ファイル: criteres.php プロジェクト: loorenzooo/aslfc
/**
 * Champ hors table, ca ne peut etre qu'une jointure.
 * On cherche la table du champ et on regarde si elle est deja jointe
 * Si oui et qu'on y cherche un champ nouveau, pas de jointure supplementaire
 * Exemple: criteres {titre_mot=...}{type_mot=...}
 * Dans les 2 autres cas ==> jointure
 * (Exemple: criteres {type_mot=...}{type_mot=...} donne 2 jointures
 * pour selectioner ce qui a exactement ces 2 mots-cles.
 *
 * http://doc.spip.org/@calculer_critere_externe_init
 *
 * @param  $boucle
 * @param  $joints
 * @param  $col
 * @param  $desc
 * @param  $cond
 * @param bool|string $checkarrivee
 * @return mixed|string
 */
function calculer_critere_externe_init(&$boucle, $joints, $col, $desc, $cond, $checkarrivee = false)
{
    // si on demande un truc du genre spip_mots
    // avec aussi spip_mots_liens dans les jointures dispo
    // et qu'on est la
    // il faut privilegier la jointure directe en 2 etapes spip_mots_liens, spip_mots
    if ($checkarrivee and is_string($checkarrivee) and $a = table_objet($checkarrivee) and in_array($a . '_liens', $joints)) {
        if ($res = calculer_lien_externe_init($boucle, $joints, $col, $desc, $cond, $checkarrivee)) {
            return $res;
        }
    }
    foreach ($joints as $joint) {
        if ($arrivee = trouver_champ_exterieur($col, array($joint), $boucle, $checkarrivee)) {
            $t = array_search($arrivee[0], $boucle->from);
            // transformer eventuellement id_xx en (id_objet,objet)
            $cols = trouver_champs_decomposes($col, $arrivee[1]);
            if ($t) {
                $joindre = false;
                foreach ($cols as $col) {
                    $c = '/\\b' . $t . ".{$col}" . '\\b/';
                    if (trouver_champ($c, $boucle->where)) {
                        $joindre = true;
                    } else {
                        // mais ca peut etre dans le FIELD pour le Having
                        $c = "/FIELD.{$t}" . ".{$col},/";
                        if (trouver_champ($c, $boucle->select)) {
                            $joindre = true;
                        }
                    }
                }
                if (!$joindre) {
                    return $t;
                }
            }
            if ($res = calculer_jointure($boucle, array($boucle->id_table, $desc), $arrivee, $cols, $cond, 1)) {
                return $res;
            }
        }
    }
    return '';
}
コード例 #7
0
ファイル: jointures.php プロジェクト: nursit/SPIP
/**
 * Cherche a ajouter la possibilite d'interroger un champ sql
 * dans une boucle. Cela construira les jointures necessaires
 * si une possibilite est trouve et retournera le nom de
 * l'alias de la table contenant ce champ
 * (L2 par exemple pour 'spip_mots AS L2' dans le FROM),
 *
 * 
 * @param string $champ
 * 		Nom du champ cherche (exemple id_article)
 * @param object $boucle
 * 		Informations connues de la boucle
 * @param array $jointures
 * 		Liste des tables parcourues (articles, mots) pour retrouver le champ sql
 * 		et calculer la jointure correspondante.
 * 		En son absence et par defaut, on utilise la liste des jointures connues
 * 		par SPIP pour la table en question ($boucle->jointures)
 * @param bool $cond
 *     flag pour savoir si le critere est conditionnel ou non
 * 
 * @return string
 */
function trouver_jointure_champ($champ, &$boucle, $jointures = false, $cond = false)
{
    if ($jointures === false) {
        $jointures = $boucle->jointures;
    }
    $cle = trouver_champ_exterieur($champ, $jointures, $boucle);
    if ($cle) {
        $desc = $boucle->show;
        $cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $cle, '', $cond);
    }
    if ($cle) {
        return $cle;
    }
    spip_log("trouver_jointure_champ: {$champ} inconnu");
    return '';
}
コード例 #8
0
/**
 * Cherche a ajouter la possibilite d'interroger un champ sql
 * dans une boucle. Cela construira les jointures necessaires
 * si une possibilite est trouve et retournera le nom de
 * l'alias de la table contenant ce champ
 * (L2 par exemple pour 'spip_mots AS L2' dans le FROM),
 *
 *
 * @param string $champ
 *    Nom du champ cherche (exemple id_article)
 * @param object $boucle
 *    Informations connues de la boucle
 * @param array $jointures
 *    Liste des tables parcourues (articles, mots) pour retrouver le champ sql
 *    et calculer la jointure correspondante.
 *    En son absence et par defaut, on utilise la liste des jointures connues
 *    par SPIP pour la table en question ($boucle->jointures)
 * @param bool $cond
 *     flag pour savoir si le critere est conditionnel ou non
 *
 * @return string
 */
function trouver_jointure_champ($champ, &$boucle, $jointures = false, $cond = false)
{
    if ($jointures === false) {
        $jointures = $boucle->jointures;
    }
    // TODO : aberration, on utilise $jointures pour trouver le champ
    // mais pas poour construire la jointure ensuite
    $arrivee = trouver_champ_exterieur($champ, $jointures, $boucle);
    if ($arrivee) {
        $desc = $boucle->show;
        array_pop($arrivee);
        // enlever la cle en 3eme argument
        $cle = calculer_jointure($boucle, array($desc['id_table'], $desc), $arrivee, '', $cond);
        if ($cle) {
            return $cle;
        }
    }
    spip_log("trouver_jointure_champ: {$champ} inconnu");
    return '';
}