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

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

declarer la variable IterateurSPHINX2->facet = array()

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