You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.1 KiB
181 lines
5.1 KiB
<?php |
|
/** |
|
* Plugin Spip-Bonux |
|
* Le plugin qui lave plus SPIP que SPIP |
|
* (c) 2008 Mathieu Marcillaud, Cedric Morin, Tetue |
|
* Licence GPL |
|
* |
|
*/ |
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
return; |
|
} |
|
|
|
/** |
|
* Permet de faire un comptage par table liee |
|
* |
|
* @syntaxe `{compteur table[, champ]}` |
|
* @link https://contrib.spip.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'; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* {compteur_left xxx} permet de faire la meme chose que {compteur xxx} |
|
* mais avec un LEFT JOIN pour ne pas ignorer ceux qui ont un compteur nul |
|
* @param <type> $idb |
|
* @param <type> $boucles |
|
* @param <type> $crit |
|
*/ |
|
function critere_compteur_left($idb, &$boucles, $crit) { |
|
critere_compteur($idb, $boucles, $crit, true); |
|
} |
|
|
|
/** Critere {somme champ} #SOMME{champ} */ |
|
function critere_somme($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array('SUM'=>'somme'), $idb, $boucles, $crit); |
|
} |
|
|
|
/** Critere {compte champ} #COMPTE{champ} */ |
|
function critere_compte($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array('COUNT'=>'compte'), $idb, $boucles, $crit); |
|
} |
|
|
|
/** Critere {moyenne champ} #MOYENNE{champ} */ |
|
function critere_moyenne($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array('AVG'=>'moyenne'), $idb, $boucles, $crit); |
|
} |
|
|
|
/** Critere {minimum champ} #MINIMUM{champ} */ |
|
function critere_minimum($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array('MIN'=>'minimum'), $idb, $boucles, $crit); |
|
} |
|
|
|
/** Critere {maximum champ} #MAXIMUM{champ} */ |
|
function critere_maximum($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array('MAX'=>'maximum'), $idb, $boucles, $crit); |
|
} |
|
|
|
/** Critere {stats champ} calcul la totale : somme, compte, minimum, moyenne, maximum */ |
|
function critere_stats($idb, &$boucles, $crit) { |
|
calcul_critere_fonctions(array( |
|
'SUM'=>'somme', |
|
'COUNT'=>'compte', |
|
'AVG'=>'moyenne', |
|
'MIN'=>'minimum', |
|
'MAX'=>'maximum', |
|
), $idb, $boucles, $crit); |
|
} |
|
|
|
/* $func : array(FUNC => balise) */ |
|
function calcul_critere_fonctions($func, $idb, &$boucles, $crit) { |
|
$boucle = &$boucles[$idb]; |
|
|
|
$params = $crit->param; |
|
$champ = reset($params); |
|
$champ = $champ[0]->texte; |
|
|
|
// option DISTINCT {compte DISTINCT(id_article) } |
|
$filter = ''; |
|
if (preg_match('/^([a-zA-Z]+)\(\s*([a-zA-Z_]+)\s*\)$/', trim($champ), $r)) { |
|
$filter = $r[1]; // DISTINCT |
|
$champ = $r[2]; // id_article |
|
} |
|
|
|
$sel = $filter ? "$filter($champ)" : $champ; |
|
foreach ($func as $f => $as) { |
|
$boucle->select[]= "$f($sel) AS $as" . "_$champ"; |
|
} |
|
} |
|
|
|
function critere_fusion_supprimer_dist($idb, &$boucles, $crit){ |
|
$boucles[$idb]->group = array(); |
|
}
|
|
|