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

Last change on this file since 113280 was 113280, checked in by bystrano@…, 3 months ago

Surcharger le critère {logo} pour retourner aussi les docs avec des rôles logo_*

Pour éviter de mauvaises performances sur les sites avec beaucoup de logos, on
ne se sert pas de l'API pour trouver les logos, mais on fait directement des
jointures sur spip_documents_liens.

File size: 5.8 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        // Liste des rôles non attribués
78        $roles_attribuables = array_diff($roles_possibles, $roles_attribues);
79
80        // On filtre éventuellement les rôles principaux (=logos)
81        // Note : array_values pour remettre les bonnes clés
82        if (!is_null($principaux)
83                and !empty($infos_roles['roles']['principaux'])
84                and $roles_principaux = $infos_roles['roles']['principaux']
85        ){
86                $filtrer = ($principaux ? 'array_intersect' : 'array_diff');
87                $roles_possibles = array_values($filtrer($roles_possibles, $roles_principaux));
88                $roles_attribues = array_values($filtrer($roles_attribues, $roles_principaux));
89                $roles_attribuables = array_values($filtrer($roles_attribuables, $roles_principaux));
90        }
91
92        // On retourne le détail
93        $roles = array(
94                'possibles'    => $roles_possibles,
95                'attribues'    => $roles_attribues,
96                'attribuables' => $roles_attribuables,
97        );
98
99        return $done[$hash] = $roles;
100}
101
102/**
103 * Surcharge du critère `logo`
104 *
105 * Tout comme le critère {logo} par défaut, on permet de sélectionner tous les
106 * objets qui ont un logo, quel qu'il soit, au format historique ou au format
107 * document.
108 *
109 * Un unique paramètre optionnel permet de se restreindre à un rôle
110 * particulier. Par exemple, {logo accueil} permet de sélectionner les logos
111 * dont le rôle est 'logo_accueil'.
112 *
113 * {!logo} permet d'inverser la sélection, pour avoir les objets qui n'ont PAS
114 * de logo.
115 *
116 * @uses lister_objets_avec_logos()
117 *     Pour obtenir les éléments qui ont un logo enregistrés avec la méthode
118 *     "historique".
119 *
120 * @param string $idb Identifiant de la boucle
121 * @param array $boucles AST du squelette
122 * @param Critere $crit Paramètres du critère dans cette boucle
123 * @return void
124 */
125function critere_logo($idb, &$boucles, $crit) {
126
127        $boucle = &$boucles[$idb];
128
129        // On interprète le premier paramètre du critère, qui nous donne le type de
130        // logo
131        if (count($crit->param)) {
132                $type_logo = calculer_liste(
133                        array_shift($crit->param),
134                        array(),
135                        $boucles,
136                        $boucle->id_parent
137                );
138                $type_logo = trim($type_logo, "'");
139        }
140
141        // Pour ajouter la jointure qu'il nous faut à la boucle, on lui donne le
142        // premier alias L* qui n'est pas utilisé.
143        $i = 1;
144        while (isset($boucle->from["L$i"])) {
145                $i++;
146        }
147        $alias_jointure = "L$i";
148
149        $alias_table = $boucle->id_table;
150        $id_table_objet = $boucle->primary;
151
152        // On fait un LEFT JOIN avec les liens de documents qui correspondent au(x)
153        // rôle(s) cherchés. Cela permet de sélectionner aussi les objets qui n'ont
154        // pas de logo, dont le rôle sera alors NULL. C'est nécessaire pour pouvoir
155        // gérer les logos enregistrés avec l'ancienne méthode, et pour {!logo}.
156        $boucle->from[$alias_jointure] = 'spip_documents_liens';
157        $boucle->from_type[$alias_jointure] = 'LEFT';
158        $boucle->join[$alias_jointure] = array(
159                "'$alias_table'",
160                "'id_objet'",
161                "'$id_table_objet'",
162                "'$alias_jointure.objet='.sql_quote('" . objet_type($alias_table) . "')." .
163                "' AND $alias_jointure.role LIKE \'logo\_" . ($type_logo ?: '%') . "\''",
164        );
165        $boucle->group[] = "$alias_table.$id_table_objet";
166
167        // On calcule alors le where qui va bien.
168        if ($crit->not) {
169                $where = "$alias_jointure.role IS NULL";
170        } else {
171                $where = array(
172                        "'LIKE'",
173                        "'$alias_jointure.role'",
174                        "'\'logo\_" . ($type_logo ?: '%') . "\''",
175                );
176        }
177
178        // Rétro-compatibilité : Si l'on ne cherche pas un type de logo particulier,
179        // on retourne aussi les logos enregistrés avec la méthode "historique".
180        if (! $type_logo) {
181                $where_historique =
182                        'sql_in('
183                        . "'$alias_table.$id_table_objet', "
184                        . "lister_objets_avec_logos('$id_table_objet'), "
185                        . "'')";
186
187                if ($crit->not) {
188                        $where_historique = array("'NOT'", $where_historique);
189                }
190
191                $where = array(
192                        "'OR'",
193                        $where,
194                        $where_historique
195                );
196        }
197
198        // On ajoute le where à la boucle
199        $boucle->where[] = $where;
200}
Note: See TracBrowser for help on using the repository browser.