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

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

Attention : l'héritage était cassé après les grosses modifs réalisées pour l'héritage sur mots-clés => il ne marchait qu'à un niveau et non toute la branche pour les rubriques et les articles

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