source: spip-zone/_plugins_/fabrique/branches/v1/fabrique_fonctions.php @ 79328

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

Si une saisie date est présente, on crée le code de normalisation adéquat…
il faudrait mettre la dépendance au plugin verifier (si c'est pas déjà fait).

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