source: spip-zone/_plugins_/compositions/trunk/compositions_fonctions.php @ 74051

Last change on this file since 74051 was 74051, checked in by kent1@…, 6 years ago

Correction de compositions_lister_disponibles()

On applique la regexp sur le fichier et non son chemin complet

Dans le cas où le répertoire avait un trait d'union dans son répertoire, le découpage utilisait la première partie du répertoire (cas de spipr-dist par exemple) et cassait les héritages.

File size: 14.9 KB
Line 
1<?php
2/**
3 * Plugin Compositions
4 * (c) 2007-2013 Cedric Morin
5 * Distribue sous licence GPL
6 *
7 * @package SPIP\Compositions\Fonctions
8 */
9
10if (!defined("_ECRIRE_INC_VERSION")) return;
11
12define('_COMPOSITIONS_MATCH','-([^0-9][^.]*)');
13
14/**
15 * Lister les objets actives par configuration
16 *
17 * @return array
18 */
19function compositions_objets_actives(){
20        static $config=null;
21        if (is_null($config)){
22                // lister les objets dont on a active la composition dans la configuration
23                $config = isset($GLOBALS['meta']['compositions']) ? unserialize($GLOBALS['meta']['compositions']) : array();
24                $config = (isset($config['objets'])?$config['objets']:array('spip_articles','spip_rubriques'));
25                $config = array_map('objet_type',$config);
26        }
27        return $config;
28}
29
30/**
31 * Retrouver le nom du dossier ou sont stockees les compositions
32 * reglage par defaut, ou valeur personalisee via cfg
33 *
34 * @return string
35 */
36function compositions_chemin(){
37        $config_chemin = 'compositions/';
38        if (defined('_DIR_PLUGIN_Z') OR defined('_DIR_PLUGIN_ZCORE'))
39                $config_chemin = (isset($GLOBALS['z_blocs'])?reset($GLOBALS['z_blocs']):'contenu').'/';
40
41        elseif (isset($GLOBALS['meta']['compositions'])){
42                $config = unserialize($GLOBALS['meta']['compositions']);
43                if (isset ($config['chemin_compositions'])){
44                        $config_chemin = rtrim($config['chemin_compositions'],'/').'/';
45                }
46        }
47       
48        return $config_chemin;
49}
50
51/**
52 * Tester si la stylisation auto est activee
53 * @return string
54 */
55function compositions_styliser_auto(){
56        $config_styliser = true;
57        if (defined('_DIR_PLUGIN_Z') OR defined('_DIR_PLUGIN_ZCORE')){
58                $config_styliser = false; // Z s'occupe de styliser les compositions
59        }
60        elseif (isset($GLOBALS['meta']['compositions'])){
61                $config = unserialize($GLOBALS['meta']['compositions']);
62                $config_styliser = $config['styliser_auto'] != 'non';
63        }
64        return $config_styliser?' ':'';
65}
66
67/**
68 * Lister les compositions disponibles : toutes ou pour un type donne
69 * Si informer est a false, on ne charge pas les infos du xml
70 *
71 * @param string $type
72 * @param bool $informer
73 * @return array
74 */
75function compositions_lister_disponibles($type, $informer=true){
76        include_spip('inc/compositions');
77        $type_match = "";
78        if (strlen($type)){
79                $type = objet_type($type); // securite
80                $type_match = $type;
81        }
82        else {
83                $type_match = "[a-z0-9]+";
84        }
85
86        // rechercher les skel du type article-truc.html
87        // truc ne doit pas commencer par un chiffre pour eviter de confondre avec article-12.html
88        $match = "($type_match)("._COMPOSITIONS_MATCH.")?[.]html$";
89
90        // lister les compositions disponibles
91        $liste = find_all_in_path(compositions_chemin(),$match);
92        $res = array();
93        if (count($liste)){
94                foreach($liste as $s) {
95                        $base = preg_replace(',[.]html$,i','',$s);
96                        if (preg_match(",$match,ims",basename($s),$regs)
97                          AND ($composition = !$informer
98                                OR $composition = compositions_charger_infos($base)))
99                                $res[$regs[1]][$regs[3]] = $composition;
100                        // retenir les skels qui ont un xml associe
101                }
102        }
103        // Pipeline compositions_lister_disponibles
104        $res = pipeline('compositions_lister_disponibles',array(
105                'args'=>array('type' => $type,'informer' => $informer), 
106                'data'=> $res
107                )
108        );
109        return $res;
110}
111
112/**
113 * Liste les id d'un type donne utilisant une composition donnee
114 *
115 * @param string $type
116 * @param string $composition
117 * @return array
118 */
119function compositions_lister_utilisations($type,$composition){
120        $table_sql = table_objet_sql($type);
121        if (!in_array($table_sql, sql_alltable())) return;
122        $_id_table_objet = id_table_objet($type);
123        return sql_allfetsel("$_id_table_objet as id,titre", $table_sql, "composition=".sql_quote($composition));
124}
125
126/**
127 * Selectionner le fond en fonction du type et de la composition
128 * en prenant en compte la configuration pour le chemin
129 * et le fait que la composition a pu etre supprimee
130 *
131 * @param string $composition
132 * @param string $type
133 * @param string $defaut
134 * @param string $ext
135 * @param bool $fullpath
136 * @param string $vide
137 * @return string
138 */
139function compositions_selectionner($composition,$type,$defaut="",$ext="html",$fullpath = false, $vide="composition-vide"){
140        if ($type=='syndic') $type='site'; //grml
141        $fond = compositions_chemin() . $type;
142
143        // regarder si compositions/article-xxx est disponible
144        if (strlen($composition)
145                AND $f = find_in_path("$fond-$composition.$ext"))
146                return $fullpath ? $f : $fond . "-$composition";
147        else
148                // sinon regarder si compositions/article-defaut est disponible
149                if (strlen($defaut)
150                        AND $f = find_in_path("$fond-$defaut.$ext"))
151                        return $fullpath ? $f : $fond . "-$defaut";
152
153        // se rabattre sur compositions/article si disponible
154        if ($f = find_in_path("$fond.$ext"))
155                return $fullpath ? $f : $fond;
156
157        // sinon une composition vide pour ne pas generer d'erreur
158        if ($vide AND $f = find_in_path("$vide.$ext"))
159                return $fullpath ? $f : $vide;
160
161        // rien mais ca fera une erreur dans le squelette si appele en filtre
162        return '';
163}
164
165/**
166 * Decrire une composition pour un objet
167 * @param string $type
168 * @param string $composition
169 * @return array|bool|string
170 */
171function compositions_decrire($type, $composition){
172        static $compositions = array();
173        if (!function_exists('compositions_charger_infos'))
174                include_spip('inc/compositions');
175        if ($type=='syndic') $type='site'; //grml
176        if (isset($compositions[$type][$composition]))
177                return $compositions[$type][$composition];
178        $ext = "html";
179        $fond = compositions_chemin() . $type;
180        if (strlen($composition)
181                AND $f = find_in_path("$fond-$composition.$ext")
182                AND $desc = compositions_charger_infos($f))
183                return $compositions[$type][$composition] = $desc;
184        return $compositions[$type][$composition] = false;
185}
186
187/**
188 * Un filtre a utiliser sur [(#COMPOSITION|composition_class{#ENV{type}})]
189 * pour poser des classes generiques sur le <body>
190 * si une balise <class>toto</class> est definie dans la composition c'est elle qui est appliquee
191 * sinon on pose simplement le nom de la composition
192 *
193 * @param string $composition
194 * @param string $type
195 * @return string
196 */
197function composition_class($composition,$type){
198        if ($desc = compositions_decrire($type, $composition)
199                AND isset($desc['class'])
200                AND strlen($desc['class']))
201                return $desc['class'];
202        return $composition;
203}
204
205/**
206 * Liste les types d'objets qui ont une composition ET sont autorises par la configuration
207 * utilise la valeur en cache meta sauf si demande de recalcul
208 * ou pas encore definie
209 *
210 * @staticvar array $liste
211 * @return array
212 */
213function compositions_types(){
214        static $liste = null;
215        if (is_null($liste)) {
216                if (_VAR_MODE OR !isset($GLOBALS['meta']['compositions_types'])){
217                        include_spip('inc/compositions');
218                        compositions_cacher();
219                }
220                $liste = explode(',',$GLOBALS['meta']['compositions_types']);
221        }
222        return $liste;
223}
224
225/**
226 * Renvoie les parametres necessaires pour utiliser l'heritage de composition de façon generique
227 * recupere les donnes du pipeline compositions_declarer_heritage.
228 * Si $type n'est pas precise, on renvoie simplement le tableau des objets pouvant heriter.
229 *
230 * @param string $type
231 * @staticvar array $heritages
232 * @return array
233 */
234function compositions_recuperer_heritage($type=NULL){
235        static $heritages = NULL;
236        if (is_null($heritages)) // recuperer les heritages declares via le pipeline compositions_declarer_heritage
237                $heritages = pipeline('compositions_declarer_heritage', array());
238       
239        if (is_null($type))
240                return $heritages;
241
242        if (array_key_exists($type, $heritages)) {
243                $type_parent = $heritages[$type];
244                $table_parent =  table_objet_sql($type_parent);
245                $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
246                $nom_id_table_parent = id_table_objet($type_parent); // Nom de l'identifiant du parent dans la table parent
247               
248                // verifier que table et champs existent...
249                $trouver_table = charger_fonction('trouver_table', 'base');
250                if (!$type_parent
251                        OR !$desc = $trouver_table($table_parent)
252                        OR !isset($desc['field']['composition'])
253                        OR !isset($desc['field'][$nom_id_parent]))
254                        return '';
255
256                return array(
257                        'type_parent' => $type_parent,
258                        'table_parent' => $table_parent,
259                        'nom_id_parent' => $nom_id_parent,
260                        'nom_id_table_parent' => $nom_id_table_parent
261                );
262        }
263        return array();
264}
265
266/**
267 * Renvoie la composition qui s'applique a un objet
268 * en tenant compte, le cas echeant, de la composition heritee
269 * si etoile=true on renvoi directment le champ sql
270 *
271 * @param string $type
272 * @param integer $id
273 * @param string $serveur
274 * @param bool $etoile
275 * @return string
276 */
277function compositions_determiner($type, $id, $serveur='', $etoile = false){
278        static $composition = array();
279        $id = intval($id);
280       
281        if (isset($composition[$etoile][$serveur][$type][$id]))
282                return $composition[$etoile][$serveur][$type][$id];
283
284        include_spip('base/abstract_sql');
285        $table = table_objet($type);
286        $table_sql = table_objet_sql($type);
287        $_id_table = id_table_objet($type);
288
289        $retour = '';
290
291        $trouver_table = charger_fonction('trouver_table', 'base');
292        $desc = $trouver_table($table,$serveur);
293        if (isset($desc['field']['composition']) AND $id){
294                $select = "composition";
295
296        $heritage = compositions_recuperer_heritage($type);
297        if (isset($desc['field'][$heritage['nom_id_parent']]))
298                $select .= ', '.$heritage['nom_id_parent'].' as id_parent';
299
300        $row = sql_fetsel($select, $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
301        if ($row['composition'] != '')
302                $retour = $row['composition'];
303        elseif (!$etoile
304          AND isset($row['id_parent'])
305          AND $row['id_parent'])
306                $retour = compositions_heriter($type, $id, $row['id_parent'], $serveur);
307        }
308        return $composition[$etoile][$serveur][$type][$id] = (($retour == '-') ? '' : $retour);
309}
310
311/**
312 * Renvoie la composition heritee par un objet selon son identifiant.
313 * Optionnellement, on peut lui transmettre directement l'id du parent s'il a ate calcule.
314 *
315 * @param string $type
316 * @param integer $id
317 * @param integer $id_parent
318 * @param string $serveur
319 * @return string
320 */
321function compositions_heriter($type, $id, $id_parent=NULL, $serveur=''){
322        if ($type=='syndic') $type='site'; //grml
323        if (intval($id) < 1) return '';
324        static $infos = null;
325        $compo_parent = '';
326       
327        $heritage = compositions_recuperer_heritage($type);
328        $type_parent = $heritage['type_parent'];
329        $table_parent = $heritage['table_parent'];
330        $nom_id_parent = $heritage['nom_id_parent'];
331        $nom_id_table_parent = $heritage['nom_id_table_parent'];
332       
333        if (is_null($id_parent))
334                $id_parent = sql_getfetsel($nom_id_parent, table_objet_sql($type), id_table_objet($type).'='.intval($id));
335       
336        $heritages = compositions_recuperer_heritage();
337       
338        do {
339                $select = 'composition';
340                if ($heritages[$type_parent]==$type_parent) // S'il y a recursivite sur le parent
341                        $select .= ', id_parent';
342                $row = sql_fetsel($select, $table_parent, $nom_id_table_parent.'='.intval($id_parent),'','','','',$serveur);
343                if (strlen($row['composition']) AND $row['composition']!='-')
344                        $compo_parent = $row['composition'];
345                elseif (strlen($row['composition'])==0 AND isset($heritages[$type_parent])) // Si le parent peut heriter, il faut verifier s'il y a heritage
346                        $compo_parent = compositions_determiner($type_parent, $id_parent, $serveur='');
347               
348                if (strlen($compo_parent) AND is_null($infos))
349                        $infos = compositions_lister_disponibles('');
350                       
351        }
352        while ($id_parent = $row['id_parent']
353                AND
354                (!strlen($compo_parent) OR !isset($infos[$type_parent][$compo_parent]['branche'][$type])));
355
356        if (strlen($compo_parent) AND isset($infos[$type_parent][$compo_parent]['branche'][$type]))
357                return $infos[$type_parent][$compo_parent]['branche'][$type];
358
359        return '';
360}
361
362/**
363 * #COMPOSITION
364 * Renvoie la composition s'appliquant a un objet
365 * en tenant compte, le cas echeant, de l'heritage.
366 *
367 * Sans precision, l'objet et son identifiant sont pris
368 * dans la boucle en cours, mais l'on peut specifier notre recherche
369 * en passant objet et id_objet en argument de la balise :
370 * #COMPOSITION{article, 8}
371 *
372 * #COMPOSITION* renvoie toujours le champs brut, sans tenir compte de l'heritage
373 *
374 * @param array $p      AST au niveau de la balise
375 * @return array        AST->code modifie pour calculer le nom de la composition
376 */
377function balise_COMPOSITION_dist($p) {
378        $_composition = "";
379        if ($_objet = interprete_argument_balise(1, $p)) {
380                $_id_objet = interprete_argument_balise(2, $p);
381        } else {
382                $_composition = champ_sql('composition',$p);
383                $_id_objet = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
384                $_objet = "objet_type('" . $p->boucles[$p->id_boucle]->id_table . "')";
385        }
386        // si on veut le champ brut, et qu'on l'a sous la main, inutile d'invoquer toute la machinerie
387        if ($_composition AND $p->etoile)
388                $p->code = $_composition;
389        else {
390                $connect = $p->boucles[$p->id_boucle]->sql_serveur;
391                $p->code = "compositions_determiner($_objet, $_id_objet, '$connect', ".($p->etoile?'true':'false').")";
392                // ne declencher l'usine a gaz que si composition est vide ...
393                if ($_composition)
394                        $p->code = "((\$zc=$_composition)?(\$zc=='-'?'':\$zc):".$p->code.")";
395        }
396        return $p;
397}
398
399/**
400 * Indique si la composition d'un objet est verrouillee ou non,
401 * auquel cas, seul le webmaster peut la modifier
402 *
403 * @param string $type
404 * @param integer $id
405 * @param string $serveur
406 * @return string
407 */
408function compositions_verrouiller($type, $id, $serveur=''){
409        $config = unserialize($GLOBALS['meta']['compositions']);
410        if (isset($config['tout_verrouiller']) AND $config['tout_verrouiller'] == 'oui')
411                return true;
412       
413        include_spip('base/abstract_sql');
414        $table = table_objet($type);
415        $table_sql = table_objet_sql($type);
416        $_id_table = id_table_objet($type);
417
418        $trouver_table = charger_fonction('trouver_table', 'base');
419        $desc = $trouver_table($table,$serveur);
420        if (isset($desc['field']['composition_lock']) AND $id){
421                $lock = sql_getfetsel('composition_lock', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
422                if ($lock)
423                        return true;
424                elseif (isset($desc['field']['id_rubrique'])) {
425                        $id_rubrique = sql_getfetsel('id_rubrique', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur);
426                        return compositions_verrou_branche($id_rubrique, $serveur);
427                }
428                else
429                        return false;
430        }
431        else return false;
432}
433
434/**
435 * Indique si les objets d'une branche sont verrouilles
436 * @param integer $id_rubrique
437 * @param string $serveur
438 * @return string
439 */
440function compositions_verrou_branche($id_rubrique, $serveur=''){
441       
442        if (intval($id_rubrique) < 1) return false;
443        if($infos_rubrique = sql_fetsel(array('id_parent','composition_branche_lock'),'spip_rubriques','id_rubrique='.intval($id_rubrique),'','','','',$serveur)) {
444                if ($infos_rubrique['composition_branche_lock'])
445                        return true;
446                else
447                        return compositions_verrou_branche($infos_rubrique['id_parent'],$serveur);
448        }
449        return '';
450}
451?>
Note: See TracBrowser for help on using the repository browser.