array('type' => $type,'informer' => $informer),
'data'=> $res
));
return $res;
}
/**
* Liste les id d'un type donne utilisant une composition donnee
*
* @param string $type
* @param string $composition
* @return array
*/
function compositions_lister_utilisations($type, $composition) {
$table_sql = table_objet_sql($type);
if (!in_array($table_sql, sql_alltable())) {
return;
}
$trouver_table = charger_fonction('trouver_table', 'base');
$desc = $trouver_table($table_sql);
$_id_table_objet = id_table_objet($type);
$titre = isset($desc['titre']) ? $desc['titre'] : "'' AS titre";
return sql_allfetsel("$_id_table_objet as id, $titre", $table_sql, 'composition='.sql_quote($composition));
}
/**
* Selectionner le fond en fonction du type et de la composition
* en prenant en compte la configuration pour le chemin
* et le fait que la composition a pu etre supprimee
*
* @param string $composition
* @param string $type
* @param string $defaut
* @param string $ext
* @param bool $fullpath
* @param string $vide
* @return string
*/
function compositions_selectionner($composition, $type, $defaut = '', $ext = 'html', $fullpath = false, $vide = 'composition-vide') {
if ($type=='syndic') {
$type='site'; //grml
}
$fond = compositions_chemin() . $type;
// regarder si compositions/article-xxx est disponible
if (strlen($composition)
and $f = find_in_path("$fond-$composition.$ext")) {
return $fullpath ? $f : $fond . "-$composition";
} elseif (strlen($defaut)
and $f = find_in_path("$fond-$defaut.$ext")) {
// sinon regarder si compositions/article-defaut est disponible
return $fullpath ? $f : $fond . "-$defaut";
}
// se rabattre sur compositions/article si disponible
if ($f = find_in_path("$fond.$ext")) {
return $fullpath ? $f : $fond;
}
// sinon une composition vide pour ne pas generer d'erreur
if ($vide and $f = find_in_path("$vide.$ext")) {
return $fullpath ? $f : $vide;
}
// rien mais ca fera une erreur dans le squelette si appele en filtre
return '';
}
/**
* Decrire une composition pour un objet
* @param string $type
* @param string $composition
* @return array|bool|string
*/
function compositions_decrire($type, $composition) {
static $compositions = array();
if (!function_exists('compositions_charger_infos')) {
include_spip('inc/compositions');
}
if ($type=='syndic') {
$type='site'; //grml
}
if (isset($compositions[$type][$composition])) {
return $compositions[$type][$composition];
}
$ext = 'html';
$fond = compositions_chemin() . $type;
if (strlen($composition)
and $f = find_in_path("$fond-$composition.$ext")
and $desc = compositions_charger_infos($f)) {
return $compositions[$type][$composition] = $desc;
}
return $compositions[$type][$composition] = false;
}
/**
* Un filtre a utiliser sur [(#COMPOSITION|composition_class{#ENV{type}})]
* pour poser des classes generiques sur le
* si une balise toto est definie dans la composition c'est elle qui est appliquee
* sinon on pose simplement le nom de la composition
*
* @param string $composition
* @param string $type
* @return string
*/
function composition_class($composition, $type) {
if ($desc = compositions_decrire($type, $composition)
and isset($desc['class'])
and strlen($desc['class'])) {
return $desc['class'];
}
return $composition;
}
/**
* Liste les types d'objets qui ont une composition ET sont autorises par la configuration
* utilise la valeur en cache meta sauf si demande de recalcul
* ou pas encore definie
*
* @staticvar array $liste
* @return array
*/
function compositions_types() {
static $liste = null;
if (is_null($liste)) {
if (_VAR_MODE or !isset($GLOBALS['meta']['compositions_types'])) {
include_spip('inc/compositions');
compositions_cacher();
}
$liste = explode(',', $GLOBALS['meta']['compositions_types']);
}
return $liste;
}
/**
* Renvoie les parametres necessaires pour utiliser l'heritage de composition de façon generique
* recupere les donnes du pipeline compositions_declarer_heritage.
* Si $type n'est pas precise, on renvoie simplement le tableau des objets pouvant heriter.
*
* @param string $type
* @staticvar array $heritages
* @return array
*/
function compositions_recuperer_heritage($type = null) {
static $heritages = null;
if (is_null($heritages)) {
// recuperer les heritages declares via le pipeline compositions_declarer_heritage
$heritages = pipeline('compositions_declarer_heritage', array());
}
if (is_null($type)) {
return $heritages;
}
if (array_key_exists($type, $heritages)) {
$type_parent = $heritages[$type];
$table_parent = table_objet_sql($type_parent);
$nom_id_parent = ($type==$type_parent) ? 'id_parent' : id_table_objet($type_parent); // Recursivite pour les rubriques, nom de l'identifiant du parent dans la table enfant
$nom_id_table_parent = id_table_objet($type_parent); // Nom de l'identifiant du parent dans la table parent
// verifier que table et champs existent...
$trouver_table = charger_fonction('trouver_table', 'base');
if (!$type_parent
or !$desc = $trouver_table($table_parent)
or !isset($desc['field']['composition'])
or !isset($desc['field'][$nom_id_parent])) {
return '';
}
return array(
'type_parent' => $type_parent,
'table_parent' => $table_parent,
'nom_id_parent' => $nom_id_parent,
'nom_id_table_parent' => $nom_id_table_parent
);
}
return array();
}
/**
* Renvoie la composition qui s'applique a un objet
* en tenant compte, le cas echeant, de la composition heritee
* si etoile=true on renvoi directment le champ sql
*
* @param string $type
* @param integer $id
* @param string $serveur
* @param bool $etoile
* @return string
*/
function compositions_determiner($type, $id, $serveur = '', $etoile = false) {
// le compilateur produi(sait) des occurences de compositions_determiner('',...)
// qui provoquent un appel a $trouver_table('')
// qui vide le cache des descriptions SQL
// evitons ce cas
if (!$type) return '';
static $composition = array();
$id = intval($id);
if (isset($composition[$etoile][$serveur][$type][$id])) {
return $composition[$etoile][$serveur][$type][$id];
}
include_spip('base/abstract_sql');
$table = table_objet($type);
$table_sql = table_objet_sql($type);
$_id_table = id_table_objet($type);
$retour = '';
$trouver_table = charger_fonction('trouver_table', 'base');
$desc = $trouver_table($table,$serveur);
if (isset($desc['field']['composition']) and $id) {
$select = 'composition';
$heritage = compositions_recuperer_heritage($type);
if ($heritage and isset($desc['field'][$heritage['nom_id_parent']])) {
$select .= ', '.$heritage['nom_id_parent'].' as id_parent';
}
$row = sql_fetsel($select, $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
if ($row['composition'] != '') {
$retour = $row['composition'];
} elseif (!$etoile
and isset($row['id_parent'])
and $row['id_parent']) {
$retour = compositions_heriter($type, $id, $row['id_parent'], $serveur);
}
}
return $composition[$etoile][$serveur][$type][$id] = (($retour == '-') ? '' : $retour);
}
/**
* Renvoie la composition heritee par un objet selon son identifiant.
* Optionnellement, on peut lui transmettre directement l'id du parent s'il a ate calcule.
*
* @param string $type
* @param integer $id
* @param integer $id_parent
* @param string $serveur
* @return string
*/
function compositions_heriter($type, $id, $id_parent = null, $serveur = '') {
if ($type=='syndic') {
$type='site'; //grml
}
if (intval($id) < 1) {
return '';
}
static $infos = null;
$compo_parent = '';
$heritage = compositions_recuperer_heritage($type);
/* Si aucun héritage n'a été défini pour le type d'objet, ce
* n'est pas la peine d'aller plus loin. */
if (count($heritage) == 0) {
return '';
}
$type_parent = $heritage['type_parent'];
$table_parent = $heritage['table_parent'];
$nom_id_parent = $heritage['nom_id_parent'];
$nom_id_table_parent = $heritage['nom_id_table_parent'];
if (is_null($id_parent)) {
$id_parent = sql_getfetsel($nom_id_parent, table_objet_sql($type), id_table_objet($type).'='.intval($id));
}
$heritages = compositions_recuperer_heritage();
do {
$select = 'composition';
if ($heritages[$type_parent]==$type_parent) {
// S'il y a recursivite sur le parent
$select .= ', id_parent';
}
$row = sql_fetsel($select, $table_parent, $nom_id_table_parent.'='.intval($id_parent), '', '', '', '', $serveur);
if (strlen($row['composition']) and $row['composition']!='-') {
$compo_parent = $row['composition'];
} elseif (strlen($row['composition'])==0 and isset($heritages[$type_parent])) {
// Si le parent peut heriter, il faut verifier s'il y a heritage
$compo_parent = compositions_determiner($type_parent, $id_parent, $serveur = '');
}
if (strlen($compo_parent) and is_null($infos)) {
$infos = compositions_lister_disponibles('');
}
} while (
isset($row['id_parent'])
and $id_parent = $row['id_parent']
and
(!strlen($compo_parent) or !isset($infos[$type_parent][$compo_parent]['branche'][$type]))
);
if (strlen($compo_parent) and isset($infos[$type_parent][$compo_parent]['branche'][$type])) {
return $infos[$type_parent][$compo_parent]['branche'][$type];
}
return '';
}
/**
* #COMPOSITION
* Renvoie la composition s'appliquant a un objet
* en tenant compte, le cas echeant, de l'heritage.
*
* Sans precision, l'objet et son identifiant sont pris
* dans la boucle en cours, mais l'on peut specifier notre recherche
* en passant objet et id_objet en argument de la balise :
* #COMPOSITION{article, 8}
*
* #COMPOSITION* renvoie toujours le champs brut, sans tenir compte de l'heritage
*
* @param array $p AST au niveau de la balise
* @return array AST->code modifie pour calculer le nom de la composition
*/
function balise_COMPOSITION_dist($p) {
$_composition = '';
$_objet = '';
if ($_objet = interprete_argument_balise(1, $p)) {
$_id_objet = interprete_argument_balise(2, $p);
} else {
$_composition = champ_sql('composition', $p);
if($p->id_boucle) {
$_id_objet = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
$_objet = "objet_type('" . $p->boucles[$p->id_boucle]->id_table . "')";
}
}
// si on veut le champ brut, et qu'on l'a sous la main, inutile d'invoquer toute la machinerie
if ($_composition and (!$_objet or $p->etoile)) {
$p->code = $_composition;
} else {
$connect = $p->boucles[$p->id_boucle]->sql_serveur;
$p->code = "compositions_determiner($_objet, $_id_objet, '$connect', ".($p->etoile?'true':'false').")";
// ne declencher l'usine a gaz que si composition est vide ...
if ($_composition) {
$p->code = "((\$zc=$_composition)?(\$zc=='-'?'':\$zc):".$p->code.")";
}
}
return $p;
}
/**
* Indique si la composition d'un objet est verrouillee ou non,
* auquel cas, seul le webmaster peut la modifier
*
* @param string $type
* @param integer $id
* @param string $serveur
* @return string
*/
function compositions_verrouiller($type, $id, $serveur = '') {
$config = (isset($GLOBALS['meta']['compositions']) ? unserialize($GLOBALS['meta']['compositions']) : array());
if (isset($config['tout_verrouiller']) and $config['tout_verrouiller'] == 'oui') {
return true;
}
include_spip('base/abstract_sql');
$table = table_objet($type);
$table_sql = table_objet_sql($type);
$_id_table = id_table_objet($type);
$trouver_table = charger_fonction('trouver_table', 'base');
$desc = $trouver_table($table,$serveur);
if (isset($desc['field']['composition_lock']) and $id) {
$lock = sql_getfetsel('composition_lock', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
if ($lock) {
return true;
} elseif (isset($desc['field']['id_rubrique'])) {
$id_rubrique = sql_getfetsel('id_rubrique', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
return compositions_verrou_branche($id_rubrique, $serveur);
} else {
return false;
}
} else {
return false;
}
}
/**
* Indique si les objets d'une branche sont verrouilles
* @param integer $id_rubrique
* @param string $serveur
* @return string
*/
function compositions_verrou_branche($id_rubrique, $serveur = '') {
if (intval($id_rubrique) < 1) {
return false;
}
if ($infos_rubrique = sql_fetsel(array('id_parent', 'composition_branche_lock'), 'spip_rubriques', 'id_rubrique='.intval($id_rubrique), '', '', '', '', $serveur)) {
if ($infos_rubrique['composition_branche_lock']) {
return true;
} else {
return compositions_verrou_branche($infos_rubrique['id_parent'], $serveur);
}
}
return '';
}