source: spip-zone/_plugins_/roles_documents/trunk/roles_documents_fonctions.php @ 113289

Last change on this file since 113289 was 113289, checked in by root, 3 months ago

Le formulaire d'édition de logos affiche toujours les logos dans le même ordre

Sinon, quand on crée un logo de survol avant le logo tout court, il s'affiche
toujours en premier. C'est confusant, puisqu'alors l'ordre d'affichage des logos
change selon l'objet qu'on regarde.

File size: 6.2 KB
Line 
1<?php
2/**
3 * Fonctions utiles au plugin Rôles de documents
4 *
5 * @plugin     Rôles de documents
6 * @copyright  2015-2018
7 * @author     tcharlss
8 * @licence    GNU/GPL
9 * @package    SPIP\Roles_documents\Fonctions
10 */
11
12// Sécurité
13if (!defined('_ECRIRE_INC_VERSION')) {
14        return;
15}
16
17
18/**
19 * Lister les rôles de documents pour un objet : ceux possibles, ceux attribués et non attribués.
20 *
21 * - Soit les rôles uniques des documents pour un type d'objet (si $id_document == 0)
22 * - Soit tous les rôles entre un document et un objet (si $id_document)
23 *
24 * @note
25 * Vaguement basé sur la fonction roles_presents_sur_id() de l'API.
26 *
27 * @see
28 * roles_presents_sur_id()
29 * roles_presents_liaisons()
30 *
31 * @param string $objet
32 *     Type d'objet lié
33 * @param integer $id_objet
34 *     Identifiant de l'objet lié
35 * @param integer $id_document
36 *     Identifiant d'un document pour renvoyer les rôles de ce document précis
37 * @param bool|mixed $principaux
38 *     true : ne renvoyer que les rôles principaux (logos)
39 *     false : exclure les rôles principaux (logos)
40 * @return array
41 *     Tableau associatif avec 3 clés
42 *     - possibles : tous les rôles possibles
43 *     - attribués : ceux attribués
44 *     - attribuables : ceux non attribues
45 */
46function roles_documents_presents_sur_objet($objet, $id_objet, $id_document = 0, $principaux = null) {
47        static $done = array();
48
49        // Stocker le résultat
50        $hash = "$id_document-$objet-$id_objet-$principaux";
51        if (isset($done[$hash])) {
52                return $done[$hash];
53        }
54
55        // Liste de tous les rôles possibles
56        // Si aucun rôle sur cet objet, on sort
57        $infos_roles = roles_presents('document', $objet);
58        if (!$infos_roles) {
59                return $done['hash'] = false;
60        }
61        $roles_possibles = $infos_roles['roles']['choix'];
62
63        // Liste des rôles attribués
64        $select = 'distinct(role)';
65        $where = array(
66                'objet = ' . sql_quote($objet),
67                'id_objet = ' . intval($id_objet),
68                "role != ''",
69        );
70        if ($id_document) {
71                $select = 'role';
72                $where[] = 'id_document=' . intval($id_document);
73        }
74        $res = sql_allfetsel($select, 'spip_documents_liens', $where);
75        $roles_attribues = array_column($res, 'role');
76
77        // On trie les rôles attribués dans le même ordre que les rôles possibles,
78        // et non dans l'ordre de création des liens dans la base.
79        $roles_attribues_ordonnes = array();
80        foreach ($roles_possibles as $role) {
81                if (in_array($role, $roles_attribues)) {
82                        $roles_attribues_ordonnes[] = $role;
83                }
84        }
85        $roles_attribues = $roles_attribues_ordonnes;
86
87        // Liste des rôles non attribués
88        $roles_attribuables = array_diff($roles_possibles, $roles_attribues);
89
90        // On filtre éventuellement les rôles principaux (=logos)
91        // Note : array_values pour remettre les bonnes clés
92        if (!is_null($principaux)
93                and !empty($infos_roles['roles']['principaux'])
94                and $roles_principaux = $infos_roles['roles']['principaux']
95        ){
96                $filtrer = ($principaux ? 'array_intersect' : 'array_diff');
97                $roles_possibles = array_values($filtrer($roles_possibles, $roles_principaux));
98                $roles_attribues = array_values($filtrer($roles_attribues, $roles_principaux));
99                $roles_attribuables = array_values($filtrer($roles_attribuables, $roles_principaux));
100        }
101
102        // On retourne le détail
103        $roles = array(
104                'possibles'    => $roles_possibles,
105                'attribues'    => $roles_attribues,
106                'attribuables' => $roles_attribuables,
107        );
108
109        return $done[$hash] = $roles;
110}
111
112/**
113 * Surcharge du critère `logo`
114 *
115 * Tout comme le critère {logo} par défaut, on permet de sélectionner tous les
116 * objets qui ont un logo, quel qu'il soit, au format historique ou au format
117 * document.
118 *
119 * Un unique paramètre optionnel permet de se restreindre à un rôle
120 * particulier. Par exemple, {logo accueil} permet de sélectionner les logos
121 * dont le rôle est 'logo_accueil'.
122 *
123 * {!logo} permet d'inverser la sélection, pour avoir les objets qui n'ont PAS
124 * de logo.
125 *
126 * @uses lister_objets_avec_logos()
127 *     Pour obtenir les éléments qui ont un logo enregistrés avec la méthode
128 *     "historique".
129 *
130 * @param string $idb Identifiant de la boucle
131 * @param array $boucles AST du squelette
132 * @param Critere $crit Paramètres du critère dans cette boucle
133 * @return void
134 */
135function critere_logo($idb, &$boucles, $crit) {
136
137        $boucle = &$boucles[$idb];
138
139        // On interprète le premier paramètre du critère, qui nous donne le type de
140        // logo
141        if (count($crit->param)) {
142                $type_logo = calculer_liste(
143                        array_shift($crit->param),
144                        array(),
145                        $boucles,
146                        $boucle->id_parent
147                );
148                $type_logo = trim($type_logo, "'");
149        }
150
151        // Pour ajouter la jointure qu'il nous faut à la boucle, on lui donne le
152        // premier alias L* qui n'est pas utilisé.
153        $i = 1;
154        while (isset($boucle->from["L$i"])) {
155                $i++;
156        }
157        $alias_jointure = "L$i";
158
159        $alias_table = $boucle->id_table;
160        $id_table_objet = $boucle->primary;
161
162        // On fait un LEFT JOIN avec les liens de documents qui correspondent au(x)
163        // rôle(s) cherchés. Cela permet de sélectionner aussi les objets qui n'ont
164        // pas de logo, dont le rôle sera alors NULL. C'est nécessaire pour pouvoir
165        // gérer les logos enregistrés avec l'ancienne méthode, et pour {!logo}.
166        $boucle->from[$alias_jointure] = 'spip_documents_liens';
167        $boucle->from_type[$alias_jointure] = 'LEFT';
168        $boucle->join[$alias_jointure] = array(
169                "'$alias_table'",
170                "'id_objet'",
171                "'$id_table_objet'",
172                "'$alias_jointure.objet='.sql_quote('" . objet_type($alias_table) . "')." .
173                "' AND $alias_jointure.role LIKE \'logo\_" . ($type_logo ?: '%') . "\''",
174        );
175        $boucle->group[] = "$alias_table.$id_table_objet";
176
177        // On calcule alors le where qui va bien.
178        if ($crit->not) {
179                $where = "$alias_jointure.role IS NULL";
180        } else {
181                $where = array(
182                        "'LIKE'",
183                        "'$alias_jointure.role'",
184                        "'\'logo\_" . ($type_logo ?: '%') . "\''",
185                );
186        }
187
188        // Rétro-compatibilité : Si l'on ne cherche pas un type de logo particulier,
189        // on retourne aussi les logos enregistrés avec la méthode "historique".
190        if (! $type_logo) {
191                $where_historique =
192                        'sql_in('
193                        . "'$alias_table.$id_table_objet', "
194                        . "lister_objets_avec_logos('$id_table_objet'), "
195                        . "'')";
196
197                if ($crit->not) {
198                        $where_historique = array("'NOT'", $where_historique);
199                }
200
201                $where = array(
202                        "'OR'",
203                        $where,
204                        $where_historique
205                );
206        }
207
208        // On ajoute le where à la boucle
209        $boucle->where[] = $where;
210}
Note: See TracBrowser for help on using the repository browser.