source: spip-zone/_plugins_/polyhierarchie/branches/v2.0/polyhier_fonctions.php @ 107576

Last change on this file since 107576 was 107576, checked in by rastapopoulos@…, 3 years ago

coquille

File size: 12.2 KB
Line 
1<?php
2/*
3 * Plugin Polyhierarchie
4 * (c) 2009-2010 Cedric Morin
5 * Distribue sous licence GPL
6 *
7 */
8
9if (!defined("_ECRIRE_INC_VERSION")) return;
10
11/**
12 * {enfants} ou {enfants #ID_RUBRIQUE}
13 * renvoit tous les enfants d'une rubrique ou article
14 * directs (liens descendants) ou indirects (liens transverses)
15 *
16 * @global <type> $exceptions_des_tables
17 * @param <type> $idb
18 * @param <type> $boucles
19 * @param <type> $crit
20 * @param <type> $tous
21 */
22function critere_enfants($idb, &$boucles, $crit, $tous=true) {
23        global $exceptions_des_tables;
24        $boucle = &$boucles[$idb];
25
26        if (isset($crit->param[0])){
27                $arg = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
28        }
29        else
30                $arg = kwote(calculer_argument_precedent($idb, 'id_rubrique', $boucles));
31
32        if ($boucle->type_requete == 'rubriques' OR isset($exceptions_des_tables[$boucle->id_table]['id_parent'])) {
33                $id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ?
34                        $exceptions_des_tables[$boucle->id_table]['id_parent'] :
35                        'id_parent';
36                $mparent = $boucle->id_table . '.' . $id_parent;
37        }
38        else {
39                $mparent = $boucle->id_table . '.id_rubrique';
40        }
41
42        $where = array();
43
44        if ($tous!=='indirects')
45                $where[] = "is_array(\$r=$arg)?sql_in('$mparent',\$r):array('=', '$mparent', \$r)";
46
47        if ($tous!=='directs'
48          AND in_array(table_objet_sql($boucle->type_requete),array_keys(lister_tables_objets_sql()))){
49                $type = objet_type($boucle->type_requete);
50                $cond = "is_array(\$r=$arg)?sql_in('rl.id_parent',\$r):'rl.id_parent='.\$r";
51                $sous = "sql_get_select('rl.id_objet','spip_rubriques_liens as rl',$cond.' AND rl.objet=\'$type\'')";
52                $where[] = "array('IN', '".$boucle->id_table.".".$boucle->primary."', '(SELECT * FROM('.$sous.') AS subquery)')";
53        }
54        if (count($where)==2)
55                $where = array("'OR'",$where[0],$where[1]);
56        else
57                $where = reset($where);
58
59        $boucle->where[]= $where;
60}
61
62function critere_enfants_directs_dist($idb, &$boucles, $crit) {
63        critere_enfants($idb, $boucles, $crit, 'directs');
64}
65
66function critere_enfants_indirects_dist($idb, &$boucles, $crit) {
67        critere_enfants($idb, $boucles, $crit, 'indirects');
68}
69
70/**
71 * {parents}
72 * renvoit tous les parents d'une rubrique ou article
73 * {parents #ID_RUBRIQUE}
74 * renvoit tous les parents d'une rubrique
75 * directs (liens ascendants) ou indirects (liens transverses)
76 *
77 * @global <type> $exceptions_des_tables
78 * @param <type> $idb
79 * @param <type> $boucles
80 * @param <type> $crit
81 * @param <type> $tous
82 */
83function critere_parents($idb, &$boucles, $crit, $tous=true) {
84        global $exceptions_des_tables;
85        $boucle = &$boucles[$idb];
86        $boucle_parent = $boucles[$boucle->id_parent];
87
88        $primary = $boucle->id_table.".".$boucle->primary;
89
90        $where = array();
91
92        if ($tous!=='indirects'){
93                $argp = kwote(calculer_argument_precedent($idb, $boucle_parent->type_requete == 'rubriques' ? 'id_parent' : 'id_rubrique', $boucles));
94                $where[] = "is_array(\$r=$argp)?sql_in('$primary',\$r):array('=', '$primary', \$r)";
95        }
96
97        if ($tous!=='directs'
98          AND in_array(table_objet_sql($boucle_parent->type_requete),array_keys(lister_tables_objets_sql()))){
99                $arg = kwote(calculer_argument_precedent($idb, id_table_objet(objet_type($boucle_parent->type_requete)), $boucles));
100                $type = objet_type($boucle_parent->type_requete);
101                $sous = "sql_get_select('rl.id_parent','spip_rubriques_liens as rl','rl.id_objet='.$arg.' AND rl.objet=\'$type\'')";
102                $where[] = array("'IN'", "'$primary'", "'(SELECT * FROM('.$sous.') AS subquery)'");
103        }
104        if (count($where)==2)
105                $where = array("'OR'",$where[0],$where[1]);
106        else
107                $where = reset($where);
108
109        $boucle->where[]= $where;
110}
111
112function critere_parents_directs_dist($idb, &$boucles, $crit) {
113        critere_parents($idb, $boucles, $crit, 'directs');
114}
115function critere_parent($idb, &$boucles, $crit) {
116        critere_parents($idb, $boucles, $crit, 'directs');
117}
118
119function critere_parents_indirects_dist($idb, &$boucles, $crit) {
120        critere_parents($idb, $boucles, $crit, 'indirects');
121}
122
123
124/**
125 * Calcul d'une branche
126 * (liste des id_rubrique contenues dans une rubrique donnee)
127 * pour le critere {branche}
128 *
129 * @param <type> $id
130 * @return <type>
131 */
132function calcul_branche_polyhier_in($id, $tous=true) {
133
134        // normaliser $id qui a pu arriver comme un array, comme un entier, ou comme une chaine NN,NN,NN
135        if (!is_array($id)) $id = explode(',',$id);
136        $id = array_map('intval', $id);
137
138        // Notre branche commence par la rubrique de depart
139        $branche = $id;
140
141        // On ajoute une generation (les filles de la generation precedente)
142        // jusqu'a epuisement
143        while (
144                $id = array_merge(
145                $filles_directes = ($tous!=='indirects'?array_map('reset',sql_allfetsel('id_rubrique', 'spip_rubriques',sql_in('id_parent', $id))):array()),
146                $filles_indirectes = ($tous!=='directs'?array_map('reset',sql_allfetsel('id_objet', 'spip_rubriques_liens',"objet='rubrique' AND " . sql_in('id_parent', $id))):array())
147                )) {
148
149                // enlever les rubriques deja trouvee, sinon on risque de tourner en rond a l'infini en cas
150                // de polyhierarchie bouclee
151                $id = array_diff($id,$branche);
152                $branche = array_merge($branche,$id);
153        }
154
155        return implode(',',$branche);
156}
157
158
159
160/**
161 * {branche ?} ou {branche #ID_RUBRIQUE}
162 * {branche_directe ?} ou {branche_directe #ID_RUBRIQUE}
163 * {branche_principale ?} ou {branche_principale #ID_RUBRIQUE}
164 * {branche_complete ?} ou {branche_complete #ID_RUBRIQUE}
165 *
166 *
167 * @param <type> $idb
168 * @param <type> $boucles
169 * @param <type> $crit
170 */
171function critere_branche($idb, &$boucles, $crit, $tous='elargie') {
172
173        $not = $crit->not;
174        $boucle = &$boucles[$idb];
175        if (isset($crit->param[0])){
176                $arg = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
177        }
178        else
179                $arg = kwote(calculer_argument_precedent($idb, 'id_rubrique', $boucles));
180
181        $type = objet_type($boucle->type_requete);
182        $primary = $boucle->id_table.".".$boucle->primary;
183
184        //Trouver une jointure
185        $champ = "id_rubrique";
186        $desc = $boucle->show;
187        //Seulement si necessaire
188        if (!array_key_exists($champ, $desc['field'])){
189                $trouver_table = charger_fonction("trouver_table", "base");
190                $cle = "";
191                // peut-etre deja une jointure qui fournit id_rubrique ?
192                foreach($boucle->from as $k=>$t){
193                        $desc = $trouver_table($t);
194                        if (isset($desc['field']['id_rubrique'])){
195                                $cle = $k;
196                                break;
197                        }
198                }
199                if (!$cle){
200                        $cle = trouver_jointure_champ($champ, $boucle);
201                        $desc = $trouver_table($boucle->from[$cle]);
202                        if (count(trouver_champs_decomposes($champ, $desc))>1){
203                                $decompose = decompose_champ_id_objet($champ);
204                                $champ = array_shift($decompose);
205                                $boucle->where[] = array("'='", _q($cle.".".reset($decompose)), '"'.sql_quote(end($decompose)).'"');
206                        }
207                }
208                // si le champ id_rubrique est recupéré par jointure, c'est le type et la primary de la table jointe
209                // qu'il faut chercher dans la table spip_rubriques_liens (ie cas des evenements)
210                if ($cle AND $desc) {
211                        $type_jointure = objet_type($boucle->from[$cle]);
212                        $primary_jointure = $cle . "." . id_table_objet($boucle->from[$cle]);
213                }
214        }
215        else $cle = $boucle->id_table;
216
217
218        $c = "sql_in('$cle" . ".$champ', \$b = calcul_branche_polyhier_in($arg,".($tous===true?'true':"'directs'").")"
219          . ($not ? ", 'NOT'" : '') . ")";
220        $where[] = $c;
221       
222        if ($tous!=='directs'
223          AND in_array(table_objet_sql($boucle->type_requete),array_keys(lister_tables_objets_sql()))){
224                // S'il y a une jointure, on cherche toujours les liaisons avec celle-ci
225                if (isset($type_jointure)) {
226                        $sous_jointure = "sql_get_select('rl.id_objet','spip_rubriques_liens as rl',sql_in('rl.id_parent',\$in_rub" . ($not ? ", 'NOT'" : '') . ").' AND rl.objet=\'$type_jointure\'')";
227                        $where_jointure = "array('IN', '$primary_jointure', '(SELECT * FROM('.$sous_jointure.') AS subquery)')";
228                }
229               
230                // S'il n'y a pas de jointure (cas par défaut) ou que l'objet est explicitement configuré pour être classé avec polyhier
231                // on cherche les liaisons sur l'objet
232                if (
233                        !isset($type_jointure)
234                        or (include_spip('inc/config') and in_array(table_objet_sql($type), lire_config('polyhier/lier_objets', array())))
235                ) {
236                        $sous_objet = "sql_get_select('rl.id_objet','spip_rubriques_liens as rl',sql_in('rl.id_parent',\$in_rub" . ($not ? ", 'NOT'" : '') . ").' AND rl.objet=\'$type\'')";
237                        $where_objet = "array('IN', '$primary', '(SELECT * FROM('.$sous_objet.') AS subquery)')";
238                }
239               
240                // S'il y a les deux, on fait un OR
241                if (isset($where_jointure) and isset($where_objet)) {
242                        $where[] = "array('OR', $where_jointure, $where_objet)";
243                }
244                // Sinon s'il n'y a que jointure
245                elseif (isset($where_jointure)) {
246                        $where[] = $where_jointure;
247                }
248                // Sinon que sur l'objet
249                else {
250                        $where[] = $where_objet;
251                }
252        }
253
254        if (count($where)==2)
255                $where = "array('OR',".$where[0].",".$where[1].")";
256        else
257                $where = reset($where);
258
259        $boucle->where[]= !$crit->cond ? $where :
260          ("($arg ? $where : " . ($not ? "'0=1'" : "'1=1'") .')');
261}
262
263function critere_branche_principale_dist($idb, &$boucles, $crit) {
264        critere_branche($idb, $boucles, $crit, 'directs');
265}
266// un alias
267function critere_branche_directe_dist($idb, &$boucles, $crit) {
268        critere_branche($idb, $boucles, $crit, 'directs');
269}
270
271function critere_branche_complete_dist($idb, &$boucles, $crit) {
272        critere_branche($idb, $boucles, $crit, true);
273}
274
275/*
276 * Déclarer un fonction générique pour pouvoir chercher dans les champs des rubriques liées
277 *
278 */
279function inc_rechercher_joints_objet_rubrique_dist($table, $table_liee, $ids_trouves, $serveur){
280        $cle_depart = id_table_objet($table);
281        $s = sql_select(
282                "id_objet as $cle_depart, id_parent as id_rubrique",
283                'spip_rubriques_liens',
284                array("objet='$table'", sql_in('id_parent', $ids_trouves)),
285                '','','','',$serveur
286        );
287        return array($cle_depart, 'id_rubrique', $s);
288}
289
290
291
292/**
293 * Compile la balise `#URL_POLYHIER{#ID_RUBRIQUE,article,#ID_ARTICLE}`
294 * qui génère l'URL d'un article contextualisee a l'une de ses rubriques parentes
295 *
296 * Si la rubrique passee en argument n'est pas une rubrique parente elle est ignoree
297 * Si les URLs ne contiennent pas l'URL de la rubrique parente (URL arbo), la rubrique contextuelle est ajoutee en query string
298 *
299 * @balise
300 * @example
301 *     ```
302 *     #URL_POLYHIER{#ENV{id_rubrique,#ID_RUBRIQUE},article,#ID_ARTICLE}
303 *     ```
304 * @param Champ $p
305 *     Pile au niveau de la balise
306 * @return Champ
307 *     Pile complétée par le code à générer
308 */
309function balise_URL_POLYHIER_dist($p) {
310
311        $_id_rubrique = interprete_argument_balise(1, $p);
312        $_type = interprete_argument_balise(2, $p);
313        $_id = interprete_argument_balise(3, $p);
314
315        $code = "urlencode_1738(generer_url_polyhier_entite($_id, $_type, $_id_rubrique))";
316        $p->code = $code;
317        if (!$p->etoile) {
318                $p->code = "vider_url($code)";
319        }
320        $p->interdire_scripts = false;
321
322        return $p;
323}
324
325/**
326 * Generer l'URL polyhierarchique d'un objet relativement a une rubrique parente secondaire
327 * on cherche le parent secondaire qui est dans la branche de la rubrique fournie et on le passe en argument
328 * de l'URL. Si le module URL le gere (arbopoly) l'URL reposera sur l'URL de ce parent secondaire,
329 * sinon elle restera en argument
330 *
331 * a charge pour les squelettes de gerer la presence du id_rubrique=xxx dans le contexte de la page de l'objet concerne
332 *
333 * Ne fonctionne que si l'objet est lui même rattache en polyhierarchie,
334 * pas si il est enfant direct d'une rubrique enfant secondaire
335 *
336 * @param int $id_objet
337 * @param string $objet
338 * @param int $id_rubrique
339 * @param string $args
340 * @param string $ancre
341 * @return string
342 */
343function generer_url_polyhier_entite($id_objet, $objet, $id_rubrique=null, $args='', $ancre='') {
344
345        // si id_rubrique contextuel passe en argument et si c'est bien un parent polyhierarchique
346        $parents_poly = sql_allfetsel('id_parent','spip_rubriques_liens', 'objet='.sql_quote($objet). ' AND id_objet='.intval($id_objet));
347        $parents_poly = array_map('reset',$parents_poly);
348
349        $maxiter = 100;
350        $branche = $r = array($id_rubrique);
351        while (!($id_parent = array_intersect($parents_poly, $r))
352          and $maxiter--
353          and $filles = sql_allfetsel('id_rubrique','spip_rubriques',sql_in('id_parent', $r) . " AND " . sql_in('id_rubrique', $branche, 'NOT'))) {
354                $r = array_map('reset', $filles);
355                $branche = array_merge($branche, $r);
356        }
357
358        if ($id_parent = reset($id_parent)) {
359                // le vrai parent
360                $champ_parent = ($objet == 'rubrique' ? 'id_parent' : 'id_rubrique');
361                $args .= ($args?'&':'')."$champ_parent=$id_parent";
362        }
363        $url = generer_url_entite($id_objet, $objet, $args, $ancre, true);
364        return $url;
365}
Note: See TracBrowser for help on using the repository browser.