source: spip-zone/_plugins_/indexer/trunk/iterateur/sphinx2.php @ 82643

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

la cle des facettes est leur alias

File size: 20.7 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) return;
4
5/**
6 * Gestion de l'itérateur SPHINX
7 *
8 * @package SPIP\Indexer\Iterateur\Sphinx
9**/
10
11include_spip('iterateur/data');
12
13/**
14 * Créer une boucle sur un itérateur SPHINX
15 *
16 * Annonce au compilateur les "champs" disponibles,
17 *
18 * @param Boucle $b
19 *     Description de la boucle
20 * @return Boucle
21 *     Description de la boucle complétée des champs
22 */
23function iterateur_SPHINX2_dist($b) {
24        $b->iterateur = 'SPHINX2'; # designe la classe d'iterateur
25        $b->show = array(
26                'field' => array(
27                        '*' => 'ALL' // Champ joker *
28                )
29        );
30        return $b;
31}
32
33
34/**
35 * Iterateur SPHINX pour itérer sur des données
36 *
37 * La boucle SPHINX n'a toujours qu'un seul élément.
38 */
39class IterateurSPHINX2 implements Iterator {
40
41        /**
42         * Type de l'iterateur
43         * @var string
44         */
45        protected $type = 'SPHINX2';
46
47        /**
48         * Commandes transmises à l'iterateur
49         * @var array
50         */
51        protected $command = array();
52
53        /**
54         * Infos de debug transmises à l'iterateur
55         * @var array
56         */
57        protected $info = array();
58
59        /**
60         * Instance de SphinxQL
61         * @var \Sphinx\SphinxQL\SphinxQL
62         */
63        protected $sphinxQL = null;
64
65        /**
66         * Instance de SphinxQL\QueryApi
67         * @var \Sphinx\SphinxQL\QueryAPi
68         */
69        protected $queryApi = null;
70
71        /**
72         * Résultats par la requête à Sphinx
73         * @var array
74         */
75        protected $result = array();
76
77        /**
78         * Données de la requête (hors documents récupérés)
79         *
80         * ArrayObject pour avoir 1 seul objet non dupliqué
81         *
82         * @var ArrayObject
83         */
84        protected $data = null;
85
86
87        /**
88         * Cle courante
89         * @var null
90         */
91        protected $cle = null;
92
93        /**
94         * Valeur courante
95         * @var null
96         */
97        protected $valeur = null;
98
99        /**
100         * Constructeur
101         *
102         * @param  $command
103         * @param array $info
104         */
105        public function __construct($command, $info=array()) {
106
107                $this->command = $command + array(
108                        'index'     => array(),
109                        'selection' => array(),
110                        'recherche' => array(),
111                        'orderby'   => array(),
112                        'group'     => array(),
113                        'snippet'   => array(),
114                        'facet'     => array(),
115                        'filter'    => array(),
116                );
117
118
119                $this->info = $info;
120
121                include_spip('inc/indexer');
122
123                $this->sphinxQL  = new \Sphinx\SphinxQL\SphinxQL(SPHINX_SERVER_HOST, SPHINX_SERVER_PORT);
124                $this->queryApi  = new \Sphinx\SphinxQL\QueryApi();
125
126                $this->setIndex($this->command['index']);
127                $this->setSelection($this->command['selection']);
128                $this->setRecherche($this->command['recherche']);
129                $this->setOrderBy($this->command['orderby']);
130                $this->setGroupBy($this->command['group']); // groupby interfère avec spip :/
131                $this->setFacet($this->command['facet']);
132
133                $this->setFilter($this->command['filter']);
134
135                $this->setSnippet($this->command);
136
137
138                $this->setPagination($this->command['pagination']);
139
140                $this->runQuery();
141        }
142
143
144        public function runQuery() {
145                $query  = $this->queryApi->get();
146                $result = $this->sphinxQL->allfetsel($query);
147                if (!$result) {
148                        return false;
149                }
150
151                // decaler les docs en fonction de la pagination demandee
152                if (is_array($result['query']['docs'])
153                        AND $pagination = $this->getPaginationLimit()) { 
154
155                        list($debut) = array_map('intval', $pagination); 
156
157                        $result['query']['docs'] = array_pad($result['query']['docs'], - count($result['query']['docs']) - $debut, null);
158                        $result['query']['docs'] = array_pad($result['query']['docs'], $result['query']['meta']['total'], null);
159                }
160
161                $this->result = $result['query'];
162                unset($result['query']['docs']);
163
164                // remettre les alias sur les facettes :
165                // {facet truc, FORMULE()} cree la facette 'truc'
166                $facets = array();
167                foreach ($this->facet as $f) {
168                        $facets[$f['alias']] = array_shift($result['query']['facets']);
169                }
170                $result['query']['facets'] = $facets;
171
172
173                $this->data = new ArrayObject($result['query']);
174
175                return true;
176        }
177
178
179        public function quote($m) {
180                return $this->queryApi->quote($m);
181        }
182
183
184        /**
185         * Définir la liste des index interrogés (FROM de la requête)
186         *
187         * Par défaut on utilise l'index déclaré dans la conf
188         *
189         * @param array $index Liste des index
190         * @return bool True si au moins un index est ajouté, false sinon
191        **/
192        public function setIndex($index) {
193                if (!is_array($index)) $index = array($index);
194                $index = array_filter($index);
195                if (!$index) {
196                        $index[] = SPHINX_DEFAULT_INDEX;
197                }
198                foreach ($index as $i) {
199                        $this->queryApi->from($i);
200                }
201                return true;
202        }
203
204
205
206        /**
207         * Définir la liste des champs récupérés (SELECT de la requête)
208         *
209         * Par défaut, en absence de précisions, on prend tous les champs
210         *
211         * @param array $select Liste des index
212         * @return bool True si au moins un index est ajouté, false sinon
213        **/
214        public function setSelection($select) {
215                if (!is_array($select)) $select = array($select);
216                $select = array_filter($select);
217                // si aucune selection demandée, on prend tout !
218                if (!$select) {
219                        $select[] = '*';
220                }
221                foreach ($select as $s) {
222                        $this->queryApi->select($s);
223                }
224                return true;
225        }
226
227
228
229        /**
230         * Définir la recherche fulltext
231         *
232         * @param array $index Liste des index
233         * @return bool True si au moins un index est ajouté, false sinon
234        **/
235        public function setRecherche($recherche) {
236                if (!is_array($recherche)) $recherche = array($recherche);
237                $recherche = array_filter($recherche);
238                if (!$recherche) {
239                        return false;
240                }
241                $match = implode(' ',$recherche);
242                $this->queryApi
243                        ->select('WEIGHT() AS score')
244                        ->where('MATCH(' . $this->quote( $recherche ) . ')');
245                return true;
246        }
247
248
249        public function setOrderby($orderby) {
250                if (!is_array($orderby)) $orderby = array($orderby);
251                $orderby = array_filter($orderby);
252                if (!$orderby) {
253                        return false;
254                }
255                foreach ($orderby as $order) {
256                        // juste ASC ou DESC sans le champ… passer le chemin…
257                        if (in_array(trim($order), array('ASC', 'DESC'))) {
258                                continue;
259                        }
260                        if (!preg_match('/(ASC|DESC)$/i', $order)) {
261                                $order .= ' ASC';
262                        }
263                        $this->queryApi->orderby($order);
264                }
265                return true;
266        }
267
268        public function setGroupby($groupby) {
269                if (!is_array($groupby)) $groupby = array($groupby);
270                $groupby = array_filter($groupby);
271                if (!$groupby) {
272                        return false;
273                }
274                foreach ($groupby as $group) {
275                        $this->queryApi->groupby($group);
276                }
277                return true;
278        }
279
280
281        /**
282        * Affecte une limite à la requête Sphinx (et sauve ses bornes)
283        *
284        * @param int Début
285        * @param int Nombre de résultats
286        **/ 
287        public function setPaginationLimit($debut, $nombre) { 
288                $this->pagination_limit = array($debut, $nombre); 
289                $this->queryApi->limit("$debut,$nombre"); 
290        } 
291
292        /**
293        * Retourne les limites de pagination précédemment sauvées
294        *
295        * @param int Début
296        * @param int Nombre de résultats
297        **/ 
298        public function getPaginationLimit() { 
299                return $this->pagination_limit; 
300                # return explode(',', $this->queryApi->getLimit());
301        }
302
303        /**
304         * Définir la pagination
305         *
306         * @param array $pagination
307         * @return bool True si une pagination est demandee
308        **/
309        public function setPagination($pagination) {
310                # {pagination 20}
311                if (is_array($pagination) and $pagination) {
312                        $debut = intval($pagination[0]);
313                        $nombre = 20;
314                        if (isset($pagination[1])) {
315                                $nombre = intval($pagination[1]);
316                        }
317                        $this->setPaginationLimit($debut, $nombre); 
318                        return true;
319                }
320        }
321
322        /**
323         * Définir le snippet
324         */
325        public function setSnippet($command) {
326                $snippet = array_filter($command['snippet']);
327                // si aucune selection demandée, on prend tout !
328                if (!$snippet) {
329                        return $this->setSnippetAuto($command);
330                } else {
331                        $ok = true;
332                        foreach ($snippet as $s) {
333                                if (!is_array($s)) continue;
334                                if (!$s['phrase']) {
335                                        $s['phrase'] = $this->getSnippetAutoPhrase($command);
336                                }
337                                $ok &= $this->setOneSnippet($s);
338                        }
339                }
340                return $ok;
341        }
342
343        /**
344         * Définir 1 snippet depuis sa description
345         *
346         * @param array $desc
347         * @return bool
348        **/
349        public function setOneSnippet($desc) {
350
351                $desc += array(
352                        'champ'  => 'content',
353                        'phrase' => '',
354                        'limit'  => 200,
355                        'as'     => 'snippet'
356                );
357                if (!$desc['phrase']) {
358                        return false;
359                }
360
361                $this->queryApi->addSnippetWords( $desc['phrase'] );
362                $desc['phrase'] = $this->queryApi->getSnippetWords();
363
364                if (!$desc['phrase'] OR !$desc['champ']) {
365                        return false;
366                }
367                $this->queryApi->select("SNIPPET($desc[champ], " . $this->quote($desc['phrase']) . ", 'limit=$desc[limit],html_strip_mode=strip') AS $desc[as]");
368                return true;
369        }
370
371        /**
372         * Définir automatiquement un snippet dans le champ 'snippet'
373         * à partir de la recherche et des filtres
374         */
375        public function setSnippetAuto($command) {
376                $phrase = $this->getSnippetAutoPhrase($command);
377                if (!$phrase) return false;
378                return $this->setOneSnippet(array('phrase' => $phrase));
379        }
380
381        /**
382         * Extrait de la commande de boucle les phrases pertinentes cherchées
383         *
384         * - Cherche la phrase de recherche
385         *
386         * @param array $command Commande de la boucle Sphinx
387         * @return string phrases séparées par espace.
388        **/
389        public function getSnippetAutoPhrase($command) {
390                $phrase = '';
391
392                // mots de la recherche
393                $recherche = $command['recherche'];
394                if (!is_array($recherche)) $recherche = array($recherche);
395                $recherche = array_filter($recherche);
396                $phrase .= implode(' ', $recherche);
397
398                return $phrase;
399        }
400
401
402        /**
403         * Définit les commandes FACET
404         *
405         * @param array $facets Tableau des facettes demandées
406         * @return bool
407        **/
408        public function setFacet($facets) {
409                $facets = array_filter($facets);
410                if (!$facets) {
411                        return false;
412                }
413                $ok = true;
414                foreach ($facets as $facet) {
415                        if (!isset($facet['alias']) OR !isset($facet['query'])) {
416                                $ok = false;
417                                continue;
418                        }
419                        $alias = trim($facet['alias']);
420                        $query = trim($facet['query']);
421                        if (!$alias OR !$query) {
422                                $ok =  false;
423                                continue;
424                        }
425                        $this->facet[] = array('alias' => $alias, 'query' => $query);
426                        $this->queryApi->facet($query);
427                }
428                return $ok;
429        }
430
431
432
433        /**
434         * Définit des filtres
435         *
436         * @param array $facets Tableau des filtres demandées
437         * @return bool
438        **/
439        public function setFilter($filters) {
440                // compter le nombre de filtres ajoutés à la requête.
441                static $nb = 0;
442
443                $facets = array_filter($filters);
444                if (!$filters) {
445                        return false;
446                }
447                foreach ($filters as $filter) {
448                        // ignorer toutes les données vides
449                        if (!is_array($filter) OR !isset($filter['valeur']) OR !$valeur = $filter['valeur']) {
450                                continue;
451                        }
452                        if (is_string($valeur)) {
453                                $valeur = trim($valeur);
454                                $valeurs = array($valeur);
455                        } else {
456                                $valeurs = $valeur;
457                                $valeur = 'Array !';
458                        }
459                        $valeurs = array_unique(array_filter($valeurs));
460                        if (!$valeurs) {
461                                continue;
462                        }
463
464                        $filter += array(
465                                'select_oui'  => '',
466                                'select_null' => '',
467                        );
468
469                        // préparer les données
470                        $aucun = ($valeur == '-'); // si aucun demandé
471                        $valeur = $this->quote($valeur);
472                        $valeurs = array_map(array($this, 'quote'), $valeurs);
473                        $valeurs = implode(', ', $valeurs);
474
475                        if (($aucun == '-') and $filter['select_null']) {
476                                $f = $filter['select_null'];
477                        } elseif ($filter['select_oui']) {
478                                $f = $filter['select_oui'];
479                        }
480
481                        // remplacer d'abord le pluriel !
482                        $f = str_replace(array('@valeurs', '@valeur'), array($valeurs, $valeur), $f);
483                        $this->queryApi->select("($f) AS f$nb");
484                        $this->queryApi->where("f$nb = 1");
485                        $nb++;
486                }
487        }
488
489
490
491        // pour #SPHINX_*, permet de récupérer tous les champs de metadata
492        public function getMetaData() {
493                return $this->data;
494        }
495
496
497        /**
498         * Revenir au depart
499         * @return void
500         */
501        public function rewind() {
502                if (!is_array($this->result['docs'])) return false;
503                reset($this->result['docs']);
504                list($this->cle, $this->valeur) = each($this->result['docs']);
505        }
506
507        /**
508         * L'iterateur est-il encore valide ?
509         * @return bool
510         */
511        public function valid(){
512                return !is_null($this->cle);
513        }
514
515        /**
516         * Retourner la valeur
517         * @return null
518         */
519        public function current() {
520                return $this->valeur;
521        }
522
523        /**
524         * Retourner la cle
525         * @return null
526         */
527        public function key() {
528                return $this->cle;
529        }
530
531        /**
532         * Passer a la valeur suivante
533         * @return void
534         */
535        public function next(){
536                if ($this->valid()) {
537                        list($this->cle, $this->valeur) = each($this->result['docs']);
538                        // on transmet, pour chaque ligne les metas données avec…
539                        // histoire d'être certain qu'on les verra dans $Pile[$SP]
540                        // (feinte de sioux)
541                        if (is_array($this->valeur)) {
542                                $this->valeur['_sphinx_data'] = $this->data;
543                        }
544                }
545        }
546
547        /**
548         * Compter le nombre total de resultats
549         * @return int
550         */
551        public function count() {
552                if (is_null($this->total))
553                        $this->total = count($this->result['docs']);
554          return $this->total;
555        }
556
557}
558
559
560/**
561 * Transmettre la source (l'index sphinx) désirée
562 * @param string $idb
563 * @param object $boucles
564 * @param object $crit
565 */
566function critere_SPHINX2_index_dist($idb, &$boucles, $crit) {
567        $boucle = &$boucles[$idb];
568        // critere unique
569        $boucle->hash .= "\n\t" . '$command[\'index\'] = array();';
570
571        foreach ($crit->param as $param){
572                $boucle->hash .= "\n\t" . '$command[\'index\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).';';
573        }
574}
575
576/**
577 * Transmettre la recherche (le match fulltext) désirée
578 * @param string $idb
579 * @param object $boucles
580 * @param object $crit
581 */
582function critere_SPHINX2_recherche_dist($idb, &$boucles, $crit) {
583        $boucle = &$boucles[$idb];
584        // critere unique
585        $boucle->hash .= "\n\t" . '$command[\'recherche\'] = array();';
586
587        foreach ($crit->param as $param){
588                $boucle->hash .= "\n\t" . '$command[\'recherche\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).';';
589        }
590}
591
592
593/**
594 * Indiquer les sélections de la requête
595 *
596 * @param string $idb
597 * @param object $boucles
598 * @param object $crit
599 */
600function critere_SPHINX2_select_dist($idb, &$boucles, $crit) {
601        $boucle = &$boucles[$idb];
602        // critere multiple
603        $boucle->hash .= "\n\tif (!isset(\$select_init)) { \$command['selection'] = array(); \$select_init = true; }\n";
604
605        foreach ($crit->param as $param){
606                $boucle->hash .= "\t\$command['selection'][] = "
607                                . calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent) . ";\n";
608        }
609}
610
611
612/**
613 * Indiquer les group by de la requête
614 *
615 * @param string $idb
616 * @param object $boucles
617 * @param object $crit
618 */
619function critere_SPHINX2_groupby_dist($idb, &$boucles, $crit) {
620        $boucle = &$boucles[$idb];
621        // critere multiple
622        $boucle->hash .= "\n\tif (!isset(\$group_init)) { \$command['group'] = array(); \$group_init = true; }\n";
623
624        foreach ($crit->param as $param){
625                $boucle->hash .= "\t\$command['group'][] = "
626                                . calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent) . ";\n";
627        }
628}
629
630
631/**
632 * Indiquer les snippets de la requête
633 *
634 * @param string $idb
635 * @param object $boucles
636 * @param object $crit
637 */
638function critere_SPHINX2_snippet_dist($idb, &$boucles, $crit) {
639        $boucle = &$boucles[$idb];
640        // critere multiple
641        $boucle->hash .= "\n\tif (!isset(\$snippet_init)) { \$command['snippet'] = array(); \$snippet_init = true; }\n";
642
643        $boucle->hash .= "\t\$command['snippet'][] = [\n"
644                . (isset($crit->param[0]) ? "\t\t'champ'  => ". calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
645                . (isset($crit->param[1]) ? "\t\t'phrase' => ". calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
646                . (isset($crit->param[2]) ? "\t\t'limit'  => ". calculer_liste($crit->param[2], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
647                . (isset($crit->param[3]) ? "\t\t'as'     => ". calculer_liste($crit->param[3], array(), $boucles, $boucles[$idb]->id_parent) . "\n"  : '')
648                . "\t];\n";
649}
650
651
652
653/**
654 * Indiquer les facets de la requête
655 *
656 * @param string $idb
657 * @param object $boucles
658 * @param object $crit
659 */
660function critere_SPHINX2_facet_dist($idb, &$boucles, $crit) {
661        $boucle = &$boucles[$idb];
662        // critere multiple
663        $boucle->hash .= "\n\tif (!isset(\$facet_init)) { \$command['facet'] = array(); \$facet_init = true; }\n";
664
665        $boucle->hash .= "\t\$command['facet'][] = array(\n"
666                . (isset($crit->param[0]) ? "\t\t'alias'  => ". calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
667                . (isset($crit->param[1]) ? "\t\t'query' => ". calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
668                . "\t);\n";
669}
670
671/**
672 * Indiquer les filtres de la requête
673 *
674 * @param string $idb
675 * @param object $boucles
676 * @param object $crit
677 */
678function critere_SPHINX2_filter_dist($idb, &$boucles, $crit) {
679        $boucle = &$boucles[$idb];
680        // critere multiple
681        $boucle->hash .= "\n\tif (!isset(\$sfilter_init)) { \$command['filter'] = array(); \$sfilter_init = true; }\n";
682
683        $boucle->hash .= "\t\$command['filter'][] = array(\n"
684                . (isset($crit->param[0]) ? "\t\t'valeur'      => ". calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
685                . (isset($crit->param[1]) ? "\t\t'select_oui'  => ". calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
686                . (isset($crit->param[2]) ? "\t\t'select_null' => ". calculer_liste($crit->param[2], array(), $boucles, $boucles[$idb]->id_parent) . ",\n" : '')
687                . "\t);\n";
688}
689
690
691
692/**
693 * Tris `{par x}`
694 *
695 * @param string $idb
696 * @param object $boucles
697 * @param object $crit
698 */
699function critere_SPHINX2_par_dist($idb, &$boucles, $crit) {
700        return critere_SPHINX2_parinverse($idb, $boucles, $crit);
701}
702
703/**
704 * Tris `{inverse}`
705 *
706 * @param string $idb
707 * @param object $boucles
708 * @param object $crit
709 */
710function critere_SPHINX2_inverse_dist($idb, &$boucles, $crit) {
711        $boucle = &$boucles[$idb];
712        if ($crit->not) {
713                critere_SPHINX2_parinverse($idb, $boucles, $crit);
714        } else {
715                // sinon idem parent.
716                critere_inverse_dist($idb, $boucles, $crit);
717        }
718}
719
720/**
721 * Gestion des critères `{par}` et `{inverse}`
722 *
723 * @note
724 *     Sphinx doit toujours avoir le sens de tri (ASC ou DESC).
725 *
726 *     Version simplifié du critère natif de SPIP, avec une permission
727 *     pour les champs de type json `properties.truc`
728 *
729 * @param string $idb
730 * @param object $boucles
731 * @param object $crit
732**/
733function critere_SPHINX2_parinverse($idb, $boucles, $crit, $sens = '') {
734        $boucle = &$boucles[$idb];
735        if ($crit->not) {
736                $sens = $sens ? "" : " . ' DESC'";
737        }
738
739        foreach ($crit->param as $tri){
740                $order = "";
741
742                // tris specifies dynamiquement
743                if ($tri[0]->type!='texte'){
744                        // calculer le order dynamique qui verifie les champs
745                        $order = calculer_critere_arg_dynamique($idb, $boucles, $tri, $sens);
746                } else {
747                        $par = array_shift($tri);
748                        $par = $par->texte;
749                        $order = "'$par'";
750                }
751
752
753                $t = $order.$sens;
754                $boucle->order[] = $t;
755        }
756}
757
758
759/**
760 * Récupère pour une balise `#SPHINX_QQC` la valeur de 'qqc'
761 * dans les meta données associées à la requête
762 *
763 * - `#SPHINX_QUERY`
764 * - `#SPHINX_META`
765 * - `#SPHINX_FACETS`
766 *
767 * @param Champ $p
768 * @return Champ
769**/
770function balise_SPHINX__dist($p){
771        $champ = $p->nom_champ;
772        if ($champ == 'SPHINX_') {
773                $msg = _T('zbug_balise_sans_argument', array('balise' => ' SPHINX_'));
774                erreur_squelette($msg, $p);
775                $p->interdire_scripts = true;
776                return $p;
777        };
778        $champ = substr($champ, 7);
779        return calculer_balise_SPHINX_CHAMP($p, $champ);
780}
781
782
783
784
785/**
786 * Récupère pour une balise `#SPHINX_QQC` la valeur de 'qqc'
787 * dans les meta données associées à la requête.
788 *
789 * On les puise soit directement dans l'iterateur si on l'a (partie centrale de boucle),
790 * soit dans une globale (conjointement à l'utilisation de `#SPHINX_SAVE_META`
791 *
792 * @param Champ $p
793 * @param string $champ
794 * @return Champ
795**/
796function calculer_balise_SPHINX_CHAMP($p, $champ) {
797        $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
798        if ($b === '' || !isset($p->boucles[$b])) {
799                $msg = array('zbug_champ_hors_boucle', array('champ' => '#SPHINX_' . $champ));
800                erreur_squelette($msg, $p);
801                $p->interdire_scripts = true;
802                return $p;
803        }
804
805        $champ = strtolower($champ);
806        $p->code =
807                // iterateur présent ?
808                "(isset(\$Iter) ? "
809                . "((\$d = \$Iter->getIterator()->getMetaData()) ? \$d['$champ'] : '') : "
810                // sinon sauvegarde de #SPHINX_SAVE_META
811                . "(isset(\$GLOBALS['SphinxSave']['$b']['$champ']) ? \$GLOBALS['SphinxSave']['$b']['$champ'] : '') )";
812        $p->interdire_scripts = false;
813        return $p;
814}
815
816/**
817 * Sauvegarde les meta données de requête Sphinx pour une
818 * utilisation ultérieure dans les parties alternatives de la boucle…
819 *
820 * - `#SPHINX_SAVE_META`
821 *
822 * Permet l'usage dans 'avant' ou 'apres' des boucles Sphinx des
823 * balises :
824 *
825 * - `#SPHINX_QUERY`
826 * - `#SPHINX_META`
827 * - `#SPHINX_FACETS`
828 *
829 * @param Champ $p
830 * @return Champ
831**/
832function balise_SPHINX_SAVE_META_dist($p){
833        $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
834        // doit être dans la partie centrale de la boucle
835        if ($b === '' || !isset($p->boucles[$b])) {
836                $msg = array('zbug_champ_hors_boucle', array('champ' => '#SPHINX_SAVE_META' ));
837                erreur_squelette($msg, $p);
838                $p->interdire_scripts = true;
839                return $p;
840        }
841
842        $p->code =
843                  "(!isset(\$GLOBALS['SphinxSave']) ? vide(\$GLOBALS['SphinxSave'] = array()) : '') . "
844                . "(!isset(\$GLOBALS['SphinxSave']['$b']) ? vide(\$GLOBALS['SphinxSave']['$b'] = \$iter->getInnerIterator()->getMetaData()) : '')"
845                #. " . ('<pre>' . print_r( \$GLOBALS['SphinxSave'] , true) . '</pre>')"
846                ;
847        $p->interdire_scripts = false;
848        return $p;
849}
Note: See TracBrowser for help on using the repository browser.