source: spip-zone/_plugins_/fabrique/trunk/fabrique_fonctions.php @ 92926

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

Échapper quelques # dans le phpdoc.

File size: 34.3 KB
Line 
1<?php
2
3/**
4 * Fonctions utiles pour les squelettes de la fabrique
5 *
6 * @package SPIP\Fabrique\Fonctions
7**/
8
9if (!defined("_ECRIRE_INC_VERSION")) return;
10
11
12/**
13 * Déterminer le répertoire de travail
14 * de la Fabrique.
15 *
16 * Dans :
17 * - plugins/fabrique_auto si possible, sinon dans
18 * - tmp/cache/fabrique
19 *
20 * @return string
21 *     Le chemin de destination depuis la racine de SPIP.
22**/
23function fabrique_destination() {
24        static $destination = null;
25        if (is_null($destination)) {
26                if (is_writable(_DIR_PLUGINS . rtrim(FABRIQUE_DESTINATION_PLUGINS, '/'))) {
27                        $destination = _DIR_PLUGINS . FABRIQUE_DESTINATION_PLUGINS;
28                } else {
29                        sous_repertoire(_DIR_CACHE, rtrim(FABRIQUE_DESTINATION_CACHE, '/'));
30                        $destination = _DIR_CACHE . FABRIQUE_DESTINATION_CACHE;
31                }
32        }
33        return $destination;
34}
35
36
37/**
38 * Crée l'arborescence manquante
39 *
40 * Crée tous les répertoires manquants dans une arborescence donnée.
41 * Les répertoires sont séparés par des '/'
42 *
43 * @example
44 *     sous_repertoire_complet('a/b/c/d');
45 *     appelle sous_repertoire() autant de fois que nécéssaire.
46 *
47 * @param string $arbo
48 *     Arborescence, tel que 'prive/squelettes/contenu'
49 * @return void
50**/
51function sous_repertoire_complet($arbo) {
52        $a = explode('/', $arbo);
53        if ($a[0] == '.' OR $a[0] == '..') {
54                $base = $a[0] . '/' . $a[1];
55                array_shift($a);
56                array_shift($a);
57        } else {
58                $base = $a[0];
59                array_shift($a);
60        }
61
62        foreach ($a as $dir) {
63                $base .= '/' . $dir;
64                sous_repertoire($base);
65        }
66}
67
68
69/**
70 * Concatène en utilisant implode, un tableau, de maniere récursive
71 *
72 * @param array $tableau
73 *     Tableau à transformer
74 * @param string $glue
75 *     Chaine insérée entre les valeurs
76 * @return string|bool
77 *     - False si pas un tableau
78 *     - Chaine concaténée sinon
79**/
80function fabrique_implode_recursif($tableau, $glue='') {
81        if (!is_array($tableau)) {
82                return false;
83        }
84
85        foreach ($tableau as $c =>$valeur) {
86                if (is_array($valeur)) {
87                        $tableau[$c] = fabrique_implode_recursif($valeur, $glue);
88                }
89        }
90
91        return implode($glue, $tableau);
92}
93
94
95/**
96 * Écrit une ouverture de code PHP
97 *
98 * Fait écrire '<?php' sans que ce php soit executé par SPIP !
99 *
100 * @param Champ $p
101 *     Pile au niveau de la balise
102 * @return Champ
103 *     Pile complétée du code à produire
104**/
105function balise_PHP_dist($p) {
106        $p->code = "'<?php echo \'<?php\n\'; ?>'";
107        $p->interdire_scripts = false;
108        return $p;
109}
110
111/**
112 * Convertie une chaîne pour en faire une chaîne de langue
113 *
114 * Permet d'insérer un texte comme valeur d'une clé de langue, lorsqu'on
115 * crée un fichier de langue avec la fabrique.
116 *
117 * Transforme les caractères &# et échappe les apostrophes :
118 * - &#xxx => le bon caractère
119 * - ' => \'
120 *
121 * @example
122 *     '#ENV{prefixe}_description' => '[(#ENV{paquet/description}|chaine_de_langue)]',
123 *
124 * @link http://www.php.net/manual/fr/function.html-entity-decode.php#104617
125 * @param string $texte
126 *     Le texte à écrire dans la chaîne de langue
127 * @return string
128 *     Le texte transformé
129**/
130function chaine_de_langue($texte) {
131        $texte = html_entity_decode($texte, ENT_QUOTES, 'UTF-8');
132        # egalement
133        # http://www.php.net/manual/fr/function.html-entity-decode.php#104617
134
135        return addslashes($texte);
136}
137
138/**
139 * Modifie le nom de la clé de langue pour
140 * utiliser le vrai nom de l'objet
141 *
142 * Remplace 'objets' par le nom de l'objet, et 'objet' par le type d'objet,
143 * mais ne touche pas à '\objets' ou '\objet'.
144 *
145 * @note
146 *     Cette fonction ne sert pas uniquement à définir des clés pour
147 *     les fichiers de chaînes de langue, et pourrait être renommée
148 *
149 * @example
150 *     ```
151 *     cle_de_langue('titre_objets') => titre_chats
152 *     cle_de_langue('icone_creer_objet') => icone_creer_chat
153 *     cle_de_langue('prive/\objets/infos/objet.html') => prive/objets/infos/chat.html
154 *     ```
155 * @param string $cle
156 *     La clé à transformer
157 * @param array $desc_objet
158 *     Couples d'information sur l'objet en cours, avec les index
159 *     'objet' et 'type' définis
160 * @return string
161 *     La clé transformée
162**/
163function cle_de_langue($cle, $desc_objet) {
164        // on permet d'echapper \objets pour trouver 'objets' au bout du compte
165        // sans qu'il soit transforme dans le nom reel de l'objet
166        // cas : 'prive/\objets/infos/objet.html' => 'prive/objets/infos/nom.html'
167        $cle = str_replace("\o", "\1o\\", $cle);
168        $cle =  str_replace(
169                array('objets', 'objet'),
170                array($desc_objet['objet'], $desc_objet['type']), $cle);
171        return str_replace("\1o\\", "o", $cle);
172}
173
174/**
175 * Identique à |cle_de_langue sur toutes les valeurs d'un tableau
176 *
177 * @see cle_de_langue()
178 * @param array $tableau
179 *     Tableau dont on veut transformer les valeurs
180 * @param array $desc_objet
181 *     Couples d'information sur l'objet en cours, avec les index
182 *     'objet' et 'type' définis
183 * @return array
184 *     Tableau avec les valeurs transformées
185**/
186function tab_cle_de_langue($tableau, $desc_objet) {
187        foreach($tableau as $c => $v) {
188                $tableau[$c] = cle_de_langue($v, $desc_objet);
189        }
190        return $tableau;
191}
192
193/**
194 * Cherche s'il existe une chaîne de langue pour les clés de tableaux
195 * et ajoute alors la traduction dans la valeur de ce tableau
196 *
197 * @param array $tableau
198 *     Couples (clé => texte)
199 * @param string $prefixe_cle
200 *     Préfixe ajouté aux clés pour chercher les trads
201 * @param string $sep
202 *     Séparateur entre l'ancienne valeur et la concaténation de traduction
203 * @return array
204 *     Couples (clé => texte complété de la traduction si elle existe)
205**/
206function tab_cle_traduite_ajoute_dans_valeur($tableau, $prefixe_cle="", $sep = "&nbsp;: ") {
207        foreach($tableau as $c => $v) {
208                $trad = _T("fabrique:". $prefixe_cle . $c, array(), array('force' => false));
209                if ($trad) {
210                        $tableau[$c] = $v . $sep . $trad;
211                } else {
212                        $tableau[$c] = $v;
213                }
214        }
215        return $tableau;
216}
217
218/**
219 * Équivalent de wrap() sur les valeurs du tableau
220 *
221 * @param array $tableau
222 *     Tableau cle => texte
223 * @param string $balise
224 *     Balise qui encapsule
225 * @return array $tableau
226 *     Tableau clé => <balise>texte</balise>
227**/
228function tab_wrap($tableau, $balise) {
229        foreach ($tableau as $c => $v) {
230                $tableau[$c] = wrap($v, $balise);
231        }
232        return $tableau;
233}
234
235
236/**
237 * Fabrique un tableau de chaînes de langues
238 * avec des clés d'origines passées dans la fonctions
239 * cle_de_langue, et trie.
240 *
241 * @param array $objet
242 *     Description de l'objet dans la fabrique
243 * @return array
244 *     Couples (clé de langue => Texte)
245**/
246function fabriquer_tableau_chaines($objet) {
247        $chaines = array();
248        if (!is_array($objet)) { return $chaines; }
249        if (!$table = $objet['table'] OR !isset($objet['chaines']) OR !is_array($objet['chaines'])) {
250                return $chaines;
251        }
252        // les chaines definies pour l'objet
253        foreach ($objet['chaines'] as $cle => $chaine) {
254                $chaines[ cle_de_langue($cle, $objet) ] = $chaine;
255        }
256        // les chaines definies pour chaque champ de l'objet
257        if (is_array($objet['champs'])) {
258                foreach ($objet['champs'] as $info) {
259                        $chaines[ cle_de_langue('champ_' . $info['champ'] . '_label', $objet) ] = $info['nom'];
260                        if ($info['explication']) {
261                                $chaines[ cle_de_langue('champ_' . $info['champ'] . '_explication', $objet) ] = $info['explication'];
262                        }
263                }
264        }
265        // les rôles définis
266        if ($roles = fabrique_description_roles($objet)) {
267                foreach ($roles['roles_trads'] as $cle => $texte) {
268                        $chaines[ $cle ] = $texte;
269                }
270        }
271
272        ksort($chaines);
273        return $chaines;
274}
275
276/**
277 * Retourne la description des rôles pour un objet
278 *
279 * @param array $objet
280 *     Descrption de l'objet
281 * @return array
282 *     Description des rôles. 4 index :
283 *     - roles_colonne : la colonne utilisée, toujours 'role'
284 *     - roles_titre   : couples clé du role, clé de langue du role
285 *     - roles_objets  : tableau objet => liste des clés de roles
286 *     - roles_trads   : couples clé de langue => Texte
287 *     - roles_defaut  : la clé du role par défaut
288 */
289function fabrique_description_roles($objet) {
290        $desc = array();
291        // les rôles définis
292        if (!options_presentes($objet, array('table_liens', 'roles'))
293        OR !($roles = trim($objet['roles']))) {
294                return $desc;
295        }
296        $desc['roles_colonne'] = 'role';
297        $desc['roles_titres'] = array(); # cle => cle_langue
298        $desc['roles_objets'] = array();
299        $desc['roles_trads']  = array(); # cle_langue => Texte
300        $desc['roles_defaut']  = '';
301
302        $roles = explode("\n", $roles);
303        foreach ($roles as $i=>$r) {
304                list($cle, $texte) = explode(',', $r, 2);
305                $cle = trim($cle);
306                if (!$i) $desc['roles_defaut'] = $cle; # la valeur par défaut est la première indiquée
307                $cle_langue = 'role_' . $cle;
308                $desc['roles_titres'][$cle] = $objet['type'] . ':' . $cle_langue;
309                $desc['roles_trads'][$cle_langue] = trim($texte);
310        }
311        $liens = array_map('table_objet', $objet['vue_liens']);
312        foreach ($liens as $l) {
313                $desc['roles_objets'][$l] = array_keys($desc['roles_titres']);
314        }
315        return $desc;
316}
317
318
319/**
320 * Indique si le champ est présent dans l'objet
321 *
322 * Champ, au sens de colonne SQL
323 *
324 * @param array $objet
325 *     Descrption de l'objet
326 * @param string $champ
327 *     Nom du champ SQL à tester
328 * @return string
329 *     Même retour que le filtre |oui :
330 *     - Un espace si le champ SQL exsitera dans l'objet
331 *     - Chaîne vide sinon
332**/
333function champ_present($objet, $champ) {
334        if (is_array($objet['champs'])) {
335                foreach ($objet['champs'] as $info) {
336                        if ($info['champ'] == $champ) {
337                                return " "; // true
338                        }
339                }
340        }
341        // id_rubrique, id_secteur
342        if (isset($objet['rubriques']) AND is_array($objet['rubriques'])) {
343                if (in_array($champ, $objet['rubriques'])) {
344                        return " "; // true
345                }
346        }
347        // lang, langue_choisie, id_trad
348        if (isset($objet['langues']) AND is_array($objet['langues'])) {
349                if (in_array($champ, $objet['langues'])) {
350                        return " "; // true
351                }
352                if (isset($objet['langues']['lang'])
353                        and ($objet['langues']['lang'])
354                        and ($champ == 'langue_choisie')) {
355                                return " "; // true
356                }
357        }
358        // date
359        if ($objet['champ_date']) {
360                if ($champ == $objet['champ_date']) {
361                        return " "; // true
362                }
363        }
364        // statut
365        if ($objet['statut']) {
366                if ($champ == 'statut') {
367                        return " "; // true
368                }
369        }
370
371        return ""; // false
372}
373
374
375/**
376 * Indique si toutes les options sont présentes dans l'objet
377 *
378 * Option au sens de clé de configuration, pas un nom de champ SQL
379 *
380 * @param array $objet
381 *     Descrption de l'objet
382 * @param array $champs
383 *     Liste de nom d'options à tester
384 * @return string
385 *     Même retour que le filtre |oui :
386 *     - Un espace si toutes les options sont présentes dans l'objet
387 *     - Chaîne vide sinon
388**/
389function options_presentes($objet, $champs) {
390        if (!$champs) return false;
391        if (!is_array($champs)) $champs = array($champs);
392        foreach ($champs as $champ) {
393                if (!option_presente($objet, $champ)) {
394                        return ""; // false
395                }
396        }
397        return " "; // true
398
399}
400
401/**
402 * Indique si une option est présente dans l'objet
403 *
404 * Option au sens de clé de configuration, pas un nom de champ SQL
405 *
406 * @param array $objet
407 *     Descrption de l'objet
408 * @param array $champ
409 *     Nom de l'option à tester
410 * @return string
411 *     Même retour que le filtre |oui :
412 *     - Un espace si l'option est présente dans l'objet
413 *     - Chaîne vide sinon
414**/
415function option_presente($objet, $champ) {
416        // a la racine
417        if (isset($objet[$champ]) and $objet[$champ]) {
418                return " "; // true
419        }
420
421        // id_rubrique, vue_rubrique, plan
422        if (isset($objet['rubriques']) AND is_array($objet['rubriques'])) {
423                if (in_array($champ, $objet['rubriques'])) {
424                        return " "; // true
425                }
426        }
427
428        // lang, id_trad
429        if (isset($objet['langues']) AND is_array($objet['langues'])) {
430                if (in_array($champ, $objet['langues'])) {
431                        return " "; // true
432                }
433        }
434       
435        // menu_edition, outils_rapides
436        if (isset($objet['boutons']) AND is_array($objet['boutons'])) {
437                if (in_array($champ, $objet['boutons'])) {
438                        return " "; // true
439                }
440        }
441
442        return ""; // false
443}
444
445
446/**
447 * Indique si une saisie est présente dans l'objet
448 *
449 * @param array $objet
450 *     Descrption de l'objet
451 * @param array $saisie
452 *     Nom de la saisie à tester
453 * @return string
454 *     Même retour que le filtre |oui :
455 *     - Un espace si l'option est présente dans l'objet
456 *     - Chaîne vide sinon
457**/
458function saisie_presente($objet, $saisie) {
459        if (isset($objet['champs']) and is_array($objet['champs'])) {
460                foreach ($objet['champs'] as $champ) {
461                        if (isset($champ['saisie']) and $champ['saisie'] == $saisie) {
462                                return " "; // true
463                        }
464                }
465        }
466        return ""; // false
467}
468
469
470/**
471 * Indique si une option donnée est presente dans la définition d'un champ
472 * de la fabrique
473 *
474 * @param array $champ
475 *     Description d'un champ SQL d'un objet créé avec la fabrique
476 * @param string $option
477 *     Option testée
478 * @return string
479 *     Même retour que le filtre |oui :
480 *     - Un espace si l'option est présente dans le champ de l'objet
481 *     - Chaîne vide sinon
482 */
483function champ_option_presente($champ, $option) {
484        if (isset($champ[$option]) and $champ[$option]) {
485                return " "; // true
486        }
487
488        // editable, versionne, obligatoire
489        if (isset($champ['caracteristiques']) and is_array($champ['caracteristiques'])) {
490                if (in_array($option, $champ['caracteristiques'])) {
491                        return " "; // true
492                }
493        }
494
495        return false;
496}
497
498
499/**
500 * Indique si une saisie donnée est presente dans la définition d'un champ
501 * de la fabrique
502 *
503 * @param array $champ
504 *     Description d'un champ SQL d'un objet créé avec la fabrique
505 * @param string $saisie
506 *     Saisie testée
507 * @return string
508 *     Même retour que le filtre |oui :
509 *     - Un espace si l'option est présente dans le champ de l'objet
510 *     - Chaîne vide sinon
511 */
512function champ_saisie_presente($champ, $saisie) {
513        if (isset($champ['saisie']) and $champ['saisie'] == $saisie) {
514                return " "; // true
515        }
516        return false;
517}
518
519
520/**
521 * Retourne les objets possédant un certain champ SQL
522 *
523 * Cela simplifie des boucles DATA
524 *
525 * @example
526 *     - `#OBJETS|objets_champ_present{id_rubrique}`
527 *     - On peut ne retourner qu'une liste de type de valeur (objet, type, id_objet)
528 *       `#OBJETS|objets_champ_present{id_rubrique, objet}` // chats,souris
529 *
530 * @param array $objets
531 *     Liste des descriptions d'objets créés avec la fabrique
532 * @param string $champ
533 *     Type de champ sélectionné
534 * @param string $type
535 *     Information de retour désiré :
536 *     - vide pour toute la description de l'objet
537 *     - clé dans la description de l'objet pour obtenir uniquement ces descriptions
538 * @return array
539 *     - tableau de description des objets sélectionnés (si type non défini)
540 *     - tableau les valeurs du type demandé dans les objets sélectionnés (si type défini)
541**/
542function objets_champ_present($objets, $champ, $type='') {
543        return _tableau_option_presente('champ_present', $objets, $champ, $type);
544}
545
546
547/**
548 * Retourne les objets possédant une certaine option
549 *
550 * Option au sens des clés du formulaire de configuration de l'objet
551 *
552 * @example
553 *     - `#OBJETS|objets_option_presente{vue_rubrique}`
554 *     - `#OBJETS|objets_option_presente{auteurs_liens}`
555 *     - On peut ne retourner qu'une liste de type de valeur (objet, type, id_objet)
556 *       `#OBJETS|objets_option_presente{auteurs_liens, objet}` // chats,souris
557 *
558 * @param array $objets
559 *     Liste des descriptions d'objets créés avec la fabrique
560 * @param string $option
561 *     Type d'option sélectionnée
562 * @param string $type
563 *     Information de retour désiré :
564 *     - vide pour toute la description de l'objet
565 *     - clé dans la description de l'objet pour obtenir uniquement ces descriptions
566 * @return array
567 *     - tableau de description des objets sélectionnés (si type non défini)
568 *     - tableau les valeurs du type demandé dans les objets sélectionnés (si type défini)
569**/
570function objets_option_presente($objets, $option, $type='') {
571        return _tableau_option_presente('option_presente', $objets, $option, $type);
572}
573
574
575/**
576 * Retourne les objets possédant une certaine saisie
577 *
578 * @example
579 *     - `#OBJETS|objets_saisie_presente{date}`
580 *     - On peut ne retourner qu'une liste de type de valeur (objet, type, id_objet)
581 *       `#OBJETS|objets_saisie_presente{date, objet}` // chats,souris
582 *
583 * @param array $objets
584 *     Liste des descriptions d'objets créés avec la fabrique
585 * @param string $saisie
586 *     Type de saisie sélectionnée
587 * @param string $type
588 *     Information de retour désiré :
589 *     - vide pour toute la description de l'objet
590 *     - clé dans la description de l'objet pour obtenir uniquement ces descriptions
591 * @return array
592 *     - tableau de description des objets sélectionnés (si type non défini)
593 *     - tableau les valeurs du type demandé dans les objets sélectionnés (si type défini)
594**/
595function objets_saisie_presente($objets, $saisie, $type='') {
596        return _tableau_option_presente('saisie_presente', $objets, $saisie, $type);
597}
598
599
600/**
601 * Retourne les objets possédant plusieurs options
602 *
603 * Option au sens des clés du formulaire de configuration de l'objet
604 *
605 * @example
606 *     - `#OBJETS|objets_options_presentes{#LISTE{table_liens,vue_liens}}`
607 *     - On peut ne retourner qu'une liste de type de valeur (objet, type, id_objet)
608 *       `#OBJETS|objets_options_presentes{#LISTE{table_liens,vue_liens}, objet}` // chats,souris
609 *
610 * @param array $objets
611 *     Liste des descriptions d'objets créés avec la fabrique
612 * @param array $options
613 *     Liste de type d'option à sélectionner
614 * @param string $type
615 *     Information de retour désiré :
616 *     - vide pour toute la description de l'objet
617 *     - clé dans la description de l'objet pour obtenir uniquement ces descriptions
618 * @return array
619 *     - tableau de description des objets sélectionnés (si type non défini)
620 *     - tableau les valeurs du type demandé dans les objets sélectionnés (si type défini)
621**/
622function objets_options_presentes($objets, $options, $type='') {
623        return _tableau_options_presentes('option_presente', $objets, $options, $type);
624}
625
626/**
627 * Retourne des champs en fonction d'une option trouvée
628 *
629 * @example
630 *     - `#CHAMPS|champs_option_presente{editable}`
631 *     - `#CHAMPS|champs_option_presente{versionne}`
632 *
633 * @param array $champs
634 *     Liste des descriptions de champs d'un objet créé avec la fabrique
635 * @param string $option
636 *     Type d'option sélectionnée
637 * @param string $type
638 *     Information de retour désiré :
639 *     - vide pour toute la description du champ
640 *     - clé dans la description du champ pour obtenir uniquement ces descriptions
641 * @return array
642 *     - tableau de description des champs sélectionnés (si type non défini)
643 *     - tableau les valeurs du type demandé dans les champs sélectionnés (si type défini)
644**/
645function champs_option_presente($champs, $option, $type='') {
646        return _tableau_option_presente('champ_option_presente', $champs, $option, $type);
647}
648
649/**
650 * Retourne des champs en fonction des options trouvées
651 *
652 * @example
653 *     `#CHAMPS|champs_options_presentes{#LISTE{obligatoire,saisie}}`
654 *
655 * @param array $champs
656 *     Liste des descriptions de champs d'un objet créé avec la fabrique
657 * @param array $options
658 *     Liste de type d'options à sélectionner
659 * @param string $type
660 *     Information de retour désiré :
661 *     - vide pour toute la description du champ
662 *     - clé dans la description du champ pour obtenir uniquement ces descriptions
663 * @return array
664 *     - tableau de description des champs sélectionnés (si type non défini)
665 *     - tableau les valeurs du type demandé dans les champs sélectionnés (si type défini)
666**/
667function champs_options_presentes($champs, $options, $type='') {
668        return _tableau_options_presentes('champ_option_presente', $champs, $options, $type);
669}
670
671/**
672 * Retourne des champs en fonction d'une option trouvée
673 *
674 * @example
675 *     `#CHAMPS|champs_saisie_presente{date}`
676 *
677 * @param array $champs
678 *     Liste des descriptions de champs d'un objet créé avec la fabrique
679 * @param string $saisie
680 *     Type de saisie sélectionnée
681 * @param string $type
682 *     Information de retour désiré :
683 *     - vide pour toute la description du champ
684 *     - clé dans la description du champ pour obtenir uniquement ces descriptions
685 * @return array
686 *     - tableau de description des champs sélectionnés (si type non défini)
687 *     - tableau les valeurs du type demandé dans les champs sélectionnés (si type défini)
688**/
689function champs_saisie_presente($champs, $saisie, $type='') {
690        return _tableau_option_presente('champ_saisie_presente', $champs, $saisie, $type);
691}
692
693/**
694 * Fonction générique pour retourner une liste de choses dans un tableau
695 *
696 * @param string $func
697 *     Nom de la fonction à appeler, tel que
698 *     - champ_option_presente
699 *     - option_presente
700 *     - ...
701 * @param array $tableau
702 *     Tableau de descriptions (descriptions d'objet ou descriptions de champ d'objet)
703 * @param string $option
704 *     Nom de l'option dont on teste la présence
705 * @param string $type
706 *     Information de retour désiré :
707 *     - vide pour toute la description
708 *     - clé dans la description pour obtenir uniquement ces descriptions
709 * @return array
710 *     Liste des descriptions correspondant à l'option demandée
711 */
712function _tableau_option_presente($func, $tableau, $option, $type='') {
713        $o = array();
714
715        if (!is_array($tableau) OR !$func) {
716                return $o;
717        }
718        // tableau est un tableau complexe de donnee
719        foreach ($tableau as $objet) {
720                // on cherche la donnee 'option' dans le tableau
721                // en utilisant une fonction specifique de recherche (option_presente, champ_present, ...)
722                if ($func($objet, $option)) {
723                        // si on a trouve notre option :
724                        // type permet de recuperer une cle specifique dans la liste des cles parcourues.
725                        // sinon, retourne tout le sous tableau.
726                        if ($type and isset($objet[$type])) {
727                                $o[] = $objet[$type];
728                        } elseif (!$type) {
729                                $o[] = $objet;
730                        }
731                }
732        }
733        return $o;
734}
735
736/**
737 * Fonction générique pour retourner une liste de choses multiples dans un tableau
738 *
739 * @param string $func
740 *     Nom de la fonction à appeler, tel que
741 *     - champ_option_presente
742 *     - option_presente
743 *     - ...
744 * @param array $tableau
745 *     Tableau de descriptions (descriptions d'objet ou descriptions de champ d'objet)
746 * @param array $options
747 *     Nom des l'options dont on teste leur présence
748 * @param string $type
749 *     Information de retour désiré :
750 *     - vide pour toute la description
751 *     - clé dans la description pour obtenir uniquement ces descriptions
752 * @return array
753 *     Liste des descriptions correspondant aux options demandées
754 */
755function _tableau_options_presentes($func, $tableau, $options, $type='') {
756        if (!$options) return array();
757
758        if (!is_array($options)) {
759                $options = array($options);
760        }
761
762        $first = false;
763        foreach ($options as $option) {
764                $r = _tableau_option_presente($func, $tableau, $option, $type);
765                if (!$first) {
766                        $res = $r;
767                        $first = true;
768                } else {
769                        #$res = array_intersect($res, $r);
770                        // array_intersect() ne prend pas en compte les sous tableaux
771                        foreach ($res as $i => $v) {
772                                if (false === array_search($v, $r)) {
773                                        unset($res[$i]);
774                                }
775                        }
776                        $res = array_values($res);
777                }
778        }
779
780        return $res;
781}
782
783
784/**
785 * Retourne une ecriture de criteres `{id_xxx}`
786 *
787 * Tous les champs déclarés commençant par `id_x` sont retournés
788 * sous forme d'une écriture de critère, tel que `{id_parent?}{id_documentation?}`
789 *
790 * Cela ne concerne pas les champs speciaux (id_rubrique, id_secteur, id_trad)
791 * qui ne seront pas inclus.
792 *
793 * @param array $objet
794 *     Description de l'objet dans la fabrique
795 * @return string
796 *     L'écriture des critères de boucle
797**/
798function criteres_champs_id($objet) {
799        $ids = array();
800        if (is_array($objet['champs'])) {
801                foreach ($objet['champs'] as $info) {
802                        if (substr($info['champ'], 0, 3) == 'id_') {
803                                $ids[] = $info['champ'];
804                        }
805                }
806        }
807        if (!$ids) {
808                return "";
809        }
810        return "{" . implode("?}{", $ids) . "?}";
811}
812
813/**
814 * Retourne un tableau de toutes les tables SQL
815 * pour tous les objets.
816 *
817 * @param array $objets
818 *     Liste des descriptions d'objets créés avec la fabrique
819 * @param string $quoi
820 *     Choix du retour désiré :
821 *     - 'tout'   => toutes les tables (par défaut)
822 *     - 'objets' => les tables d'objet (spip_xx, spip_yy)
823 *     - 'liens'  => les tables de liens (spip_xx_liens, spip_yy_liens)
824 * @return array
825 *     Liste des tables
826**/
827function fabrique_lister_tables($objets, $quoi='tout') {
828        static $tables = array();
829
830        if (!$objets) return array();
831
832        $hash = md5(serialize($objets));
833       
834        if (!isset($tables[$hash])) {
835                $tables[$hash] = array(
836                        'tout' => array(),
837                        'objets' => array(),
838                        'liens' => array(),
839                );
840                foreach ($objets as $o) {
841                        // tables principales
842                        if (isset($o['table']) and $o['table']) {
843                                $tables[$hash]['objets'][] = $o['table'];
844                                $tables[$hash]['tout'][] = $o['table'];
845                                // tables de liens
846                                if ($o['table_liens']) {
847                                        $tables[$hash]['liens'][] = $o['nom_table_liens'];
848                                        $tables[$hash]['tout'][]  = $o['nom_table_liens'];
849                                }
850                        }
851                }
852        }
853       
854        return $tables[$hash][$quoi];
855}
856
857
858/**
859 * Indique si un des objets a besoin du pipeline demandé
860 *
861 * @param array $objets
862 *     Liste des descriptions d'objets créés avec la fabrique
863 * @param string $pipeline
864 *     Nom du pipeline
865 * @return array
866 *     Liste des objets (descriptions) utilisant le pipeline
867 */
868function fabrique_necessite_pipeline($objets, $pipeline) {
869
870        if (!$objets) return false;
871
872        switch ($pipeline) {
873                case "autoriser":
874                case "declarer_tables_objets_sql":
875                case "declarer_tables_interfaces":
876                        return (bool)fabrique_lister_tables($objets, 'objets');
877                        break;
878
879                case "declarer_tables_auxiliaires":
880                        return (bool)fabrique_lister_tables($objets, 'liens');
881                        break;
882
883                case "affiche_enfants":
884                        if (objets_option_presente($objets, 'vue_rubrique')) {
885                                return true;
886                        }
887                        break;
888
889                case "affiche_milieu":
890                        if (objets_option_presente($objets, 'auteurs_liens')
891                        OR  objets_options_presentes($objets, array('table_liens', 'vue_liens'))) {
892                                return true;
893                        }
894                        break;
895
896                case "affiche_auteurs_interventions":
897                        if (objets_option_presente($objets, 'vue_auteurs_liens')) {
898                                return true;
899                        }
900                        break;
901
902                case "afficher_contenu_objet":
903                        return false;
904                        break;
905
906                case "objet_compte_enfants":
907                        if (objets_options_presentes($objets, array('id_rubrique', 'statut_rubrique'))) {
908                                return true;
909                        }
910                        break;
911
912                case "optimiser_base_disparus":
913                        # nettoie depuis spip_{objet}_liens
914                        # mais aussi les liaisions vers spip_{objet} (uniquement si une table de liens existe)
915                        return (bool)fabrique_lister_tables($objets, 'liens');
916                        #return (bool)fabrique_lister_tables($objets, 'objets');
917                        break;
918        }
919        return false;
920}
921
922
923/**
924 * Crée le code PHP de création d'un tableau
925 *
926 * Fonction un peu équivalente à var_export()
927 *
928 * @param array $tableau
929 *     Le tableau dont on veut obtenir le code de création array( ... )
930 * @param bool $quote
931 *     Appliquer sql_quote() sur chaque valeur (dans le code retourne)
932 * @param string $defaut
933 *     Si $tableau est vide ou n'est pas une chaîne, la fonction retourne cette valeur
934 * @return string
935 *     - Le code de création du tableau, avec éventuellement le code pour appliquer sql_quote.
936 *     - $defaut si le tableau est vide
937**/
938function ecrire_tableau($tableau, $quote = false, $defaut = "array()") {
939        // pas de tableau ?
940        if (!is_array($tableau) OR !count($tableau)) {
941                return $defaut;
942        }
943
944        $res = "array('" . implode("', '", array_map('addslashes', $tableau)) . "')";
945
946        if ($quote) {
947                $res = "array_map('sql_quote', $res)";
948        }
949        return $res;
950}
951
952/**
953 * Crée le code PHP de création d'un tableau sauf s'il est vide
954 *
955 * Identique à ecrire_tableau() mais ne retourne rien si le tableau est vide
956 * @see ecrire_tableau()
957 *
958 * @param array $tableau
959 *     Le tableau dont on veut obtenir le code de création array( ... )
960 * @param bool $quote
961 *     Appliquer sql_quote() sur chaque valeur (dans le code retourne)
962 * @return string
963 *     - Le code de création du tableau, avec éventuellement le code pour appliquer sql_quote.
964 *     - Chaîne vide si le tableau est vide
965**/
966function ecrire_tableau_sinon_rien($tableau, $quote = false) {
967        return ecrire_tableau($tableau, $quote, "");
968}
969
970/**
971 * Ajoute autant des espaces à la fin d'une chaîne jusqu'à la taille indiquée
972 *
973 * Fonction un peu equivalente à str_pad() mais avec une valeur par défaut
974 * définie par la constante `_FABRIQUE_ESPACER`
975 *
976 * @param string $texte
977 *     Texte à compléter
978 * @param int $taille
979 *     Taille spécifique, utilisée à la place de la constante si renseignée
980 * @return
981 *     Texte complété des espaces de fin
982 */
983function espacer($texte, $taille = 0) {
984        if (!$taille) $taille = _FABRIQUE_ESPACER;
985        return str_pad($texte, $taille);
986}
987
988
989/**
990 * Tabule à gauche chaque ligne du nombre de tabulations indiquées
991 * + on enleve les espaces sur les lignes vides
992 *
993 * @param string $texte
994 *     Un texte, qui peut avoir plusieurs lignes
995 * @param int $nb_tabulations
996 *     Nombre de tabulations à appliquer à gauche de chaque ligne
997 * @return string
998 *     Texte indenté du nombre de tabulations indiqué
999 */
1000function fabrique_tabulations($texte, $nb_tabulations) {
1001        $tab = "";
1002        if ($nb_tabulations) {
1003                $tab = str_pad("\t", $nb_tabulations);
1004        }
1005        $texte = explode("\n", $texte);
1006        foreach ($texte as $c => $ligne) {
1007                $l = ltrim(ltrim($ligne), "\t");
1008                if (!$l) {
1009                        $texte[$c] = "";
1010                } else {
1011                        $texte[$c] = $tab . $ligne;
1012                }
1013        }
1014        return implode("\n", $texte);
1015}
1016
1017
1018
1019
1020/**
1021 * Passer en majuscule en utilisant mb de préférence
1022 * s'il est disponible.
1023 *
1024 * @param string $str
1025 *     La chaine à passer en majuscule
1026 * @return string
1027 *     La chaine en majuscule
1028**/
1029function fabrique_mb_strtoupper($str) {
1030        if (function_exists('mb_strtoupper')) {
1031                return mb_strtoupper($str);
1032        } else {
1033                return strtoupper($str);
1034        }
1035}
1036
1037/**
1038 * Passer en minuscule en utilisant mb de préférence
1039 * s'il est disponible.
1040 *
1041 * @param string $str
1042 *              La chaine à passer en minuscule
1043 * @return string
1044 *              La chaine en minuscule
1045**/
1046function fabrique_mb_strtolower($str) {
1047        if (function_exists('mb_strtolower')) {
1048                return mb_strtolower($str);
1049        } else {
1050                return strtolower($str);
1051        }
1052}
1053
1054
1055/**
1056 * Crée une balise HTML <img> à partir d'un fichier,
1057 * réactualisée à chaque calcul, selon une réduction donnée.
1058 *
1059 * Cela évite un |array_shift qui ne passe pas en PHP 5.4
1060 *
1061 * Attention à bien rafraîchir l'image réduite lorsqu'on change de logo.
1062 *
1063 * @example
1064 *     `#URL_IMAGE|fabrique_miniature_image{128}`
1065 *     Applique l'équivalent de :
1066 *     ```
1067 *     #URL_IMAGE
1068 *         |image_reduire{128}|extraire_attribut{src}
1069 *         |explode{?}|array_shift|timestamp|balise_img
1070 *     ```
1071 *
1072 * @param string $fichier
1073 *     Chemin du fichier
1074 * @param int $taille
1075 *     Taille de réduction de l'image
1076 * @return string
1077 *     Balise HTML IMG de l'image réduite et à jour
1078 */
1079function filtre_fabrique_miniature_image($fichier, $taille=256) {
1080        $im = filtrer('image_reduire', $fichier, $taille);
1081        $im = extraire_attribut($im, 'src');
1082        $im = explode('?', $im);
1083        $im = array_shift($im);
1084        $im = timestamp($im);
1085        $im = filtrer('balise_img', $im);
1086        return $im;
1087}
1088
1089
1090
1091/**
1092 * Retourne un tableau table_sql=>Nom des objets de SPIP
1093 * complété des objets declares dans la fabrique ainsi
1094 * que de tables indiquees même si elles ne font pas parties
1095 * de declarations connues.
1096 *
1097 * @param array $objets_fabrique
1098 *              Déclaration d'objets de la fabrique
1099 * @param array $inclus
1100 *              Liste de tables SQL que l'on veut forcement presentes
1101 *              meme si l'objet n'est pas declare
1102 * @param array $exclus
1103 *              Liste de tables SQL que l'on veut forcement exclues
1104 *              meme si l'objet n'est pas declare
1105 * @return array
1106 *              Tableau table_sql => Nom
1107**/
1108function filtre_fabrique_lister_objets_editoriaux($objets_fabrique, $inclus=array(), $exclus=array()) {
1109
1110        // les objets existants
1111        $objets = lister_tables_objets_sql();
1112        foreach ($objets as $sql => $o) {
1113                if ($o['editable']) {
1114                        $liste[$sql] = _T($o['texte_objets']);
1115                }
1116        }
1117        unset($objets);
1118
1119        // les objets de la fabrique
1120        foreach ($objets_fabrique as $o) {
1121                if (isset($o['table']) and !isset($liste[$o['table']])) {
1122                        $liste[ $o['table'] ] = $o['nom'];
1123                }
1124        }
1125
1126        // des objets qui n'existent pas mais qui sont actuellement coches dans la saisie
1127        foreach ($inclus as $sql) {
1128                if (!isset($liste[$sql])) {
1129                        $liste[$sql] = $sql; // on ne connait pas le nom
1130                }
1131        }
1132
1133        // tables forcement exclues
1134        foreach ($exclus as $sql) {
1135                unset($liste[$sql]);
1136        }
1137        // enlever un eventuel element vide
1138        unset($liste['']);
1139
1140        asort($liste);
1141
1142        return $liste;
1143}
1144
1145
1146/**
1147 * Retourne le code pour tester un type d'autorisation
1148 *
1149 * @param string $type
1150 *              Quelle type d'autorisation est voulue
1151 * @return string
1152 *              Code de test de l'autorisation
1153**/
1154function fabrique_code_autorisation($type) {
1155        switch($type) {
1156
1157                case "jamais":
1158                        return "false";
1159                        break;
1160
1161                case "toujours":
1162                        return "true";
1163                        break;
1164
1165                case "redacteur":
1166                        return "in_array(\$qui['statut'], array('0minirezo', '1comite'))";
1167                        break;
1168
1169                case "administrateur_restreint":
1170                        return "\$qui['statut'] == '0minirezo'";
1171                        break;
1172
1173                case "administrateur":
1174                        return "\$qui['statut'] == '0minirezo' AND !\$qui['restreint']";
1175                        break;
1176
1177                case "webmestre":
1178                        return "autoriser('webmestre', '', '', \$qui)";
1179                        break;
1180
1181        }
1182
1183        return "";
1184}
1185
1186/**
1187 * Retourne la valeur de type d'autorisation
1188 * qui s'applique par defaut pour une autorisation donnee
1189 *
1190 * @param string $autorisation
1191 *              Nom de l'autorisation (objet et objets remplacent le veritable type et nom d'objet)
1192 * @return string
1193 *              Type d'autorisation par defaut (jamais, toujours, redacteur, ...)
1194**/
1195function fabrique_autorisation_defaut($autorisation) {
1196        switch($autorisation) {
1197                case 'objet_voir':
1198                        return "toujours";
1199                        break;
1200
1201                case 'objet_creer':
1202                case 'objet_modifier':
1203                        return "redacteur";
1204                        break;
1205
1206                case 'objet_supprimer':
1207                case 'associerobjet':
1208                        return "administrateur";
1209                        break;
1210        }
1211}
1212
1213/**
1214 * Retourne le code d'autorisation indique
1215 * sinon celui par defaut pour une fonction d'autorisation
1216 *
1217 * @param array $autorisations
1218 *              Les autorisations renseignees par l'interface pour un objet
1219 * @param string $autorisation
1220 *              Le nom de l'autorisation souhaitee
1221 * @return string
1222 *              Code de l'autorisation
1223**/
1224function fabrique_code_autorisation_defaut($autorisations, $autorisation) {
1225        if (!$autorisation) return "";
1226
1227        // trouver le type d'autorisation souhaitee, soit indiquee, soit par defaut
1228        if (!isset($autorisations[$autorisation]) OR !$type = $autorisations[$autorisation]) {
1229                $type = fabrique_autorisation_defaut($autorisation);
1230        }
1231
1232        // retourner le code PHP correspondant
1233        return fabrique_code_autorisation($type);
1234}
1235
1236/**
1237 * Retourne le type pour le nom d'une fonction d'autorisation
1238 * 'article' => 'article'
1239 * 'truc_muche' => 'trucmuche'
1240 *
1241 * @param string $type
1242 *              Type ou objet
1243 * @return string
1244 *              Type pour le nom d'autorisation
1245**/
1246function fabrique_type_autorisation($type) {
1247        return str_replace('_', '', $type);
1248}
Note: See TracBrowser for help on using the repository browser.