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

Last change on this file since 71791 was 71791, checked in by marcimat@…, 7 years ago

Notices PHP en moins

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",$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.