[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / inc / prepare_recherche.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Gestion des préparatifs de recherches
15 *
16 * @package SPIP\Core\Recherche
17 **/
18
19 if (!defined('_ECRIRE_INC_VERSION')) {
20 return;
21 }
22
23 include_spip('inc/rechercher');
24 if (!defined('_DELAI_CACHE_resultats')) {
25 define('_DELAI_CACHE_resultats', 600);
26 }
27
28 /**
29 * Préparer les listes `id_article IN (...)` pour les parties WHERE
30 * et calcul des `points` pour la partie SELECT des requêtes du moteur de recherche
31 *
32 * Le paramètre $serveur est utilisé pour savoir sur quelle base on cherche
33 * mais l'index des résultats est toujours stocké sur le serveur principal
34 * car on ne sait pas si la base distante dispose d'une table spip_resultats
35 * ni meme si on aurait le droit d'ecrire dedans
36 *
37 * @param string $recherche
38 * chaine recherchee
39 * @param string $table
40 * table dans laquelle porte la recherche
41 * @param bool $cond
42 * critere conditionnel sur {recherche?}
43 * @param string $serveur
44 * serveur de base de donnees
45 * @param array $modificateurs
46 * modificateurs de boucle, ie liste des criteres presents
47 * @param string $primary
48 * cle primaire de la table de recherche
49 * @return array
50 */
51 function inc_prepare_recherche_dist(
52 $recherche,
53 $table = 'articles',
54 $cond = false,
55 $serveur = '',
56 $modificateurs = array(),
57 $primary = ''
58 ) {
59 static $cache = array();
60 $delai_fraicheur = min(_DELAI_CACHE_resultats,
61 time() - (isset($GLOBALS['meta']['derniere_modif']) ? $GLOBALS['meta']['derniere_modif'] : 0));
62
63 // si recherche n'est pas dans le contexte, on va prendre en globals
64 // ca permet de faire des inclure simple.
65 if (!isset($recherche) and isset($GLOBALS['recherche'])) {
66 $recherche = $GLOBALS['recherche'];
67 }
68
69 // traiter le cas {recherche?}
70 if ($cond and !strlen($recherche)) {
71 return array(
72 "0 as points" /* as points */, /* where */
73 ''
74 );
75 }
76
77
78 $rechercher = false;
79
80 if (!isset($cache[$serveur][$table][$recherche])) {
81 $hash_serv = ($serveur ? substr(md5($serveur), 0, 16) : '');
82 $hash = substr(md5($recherche . $table), 0, 16);
83 $where = "(resultats.recherche='$hash' AND resultats.table_objet=" . sql_quote($table) . " AND resultats.serveur='$hash_serv')";
84 $row = sql_fetsel('UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(resultats.maj) AS fraicheur', 'spip_resultats AS resultats',
85 $where, '', 'fraicheur DESC', '0,1');
86 if (!$row
87 or ($row['fraicheur'] > $delai_fraicheur)
88 or (defined('_VAR_MODE') and _VAR_MODE == 'recalcul')
89 ) {
90 $rechercher = true;
91 }
92 }
93
94 // si on n'a pas encore traite les donnees dans une boucle precedente
95 if ($rechercher) {
96 //$tables = liste_des_champs();
97 $x = objet_type($table);
98 $points = recherche_en_base($recherche,
99 $x,
100 array(
101 'score' => true,
102 'toutvoir' => true,
103 'jointures' => true
104 ),
105 $serveur);
106 // pas de résultat, pas de point
107 $points = isset($points[$x]) ? $points[$x] : array();
108
109 // permettre aux plugins de modifier le resultat
110 $points = pipeline('prepare_recherche', array(
111 'args' => array(
112 'type' => $x,
113 'recherche' => $recherche,
114 'serveur' => $serveur,
115 'modificateurs' => $modificateurs
116 ),
117 'data' => $points
118 ));
119
120 // supprimer les anciens resultats de cette recherche
121 // et les resultats trop vieux avec une marge
122 // pas de AS resultats dans un delete (mysql)
123 $whered = str_replace(array("resultats.recherche", "resultats.table_objet", "resultats.serveur"),
124 array("recherche", "table_objet", "serveur"), $where);
125 sql_delete('spip_resultats',
126 'NOT(' . sql_date_proche('maj', (0 - ($delai_fraicheur + 100)), " SECOND") . ") OR ($whered)");
127
128 // inserer les resultats dans la table de cache des resultats
129 if (count($points)) {
130 $tab_couples = array();
131 foreach ($points as $id => $p) {
132 $tab_couples[] = array(
133 'recherche' => $hash,
134 'id' => $id,
135 'points' => $p['score'],
136 'table_objet' => $table,
137 'serveur' => $hash_serv,
138 );
139 }
140 sql_insertq_multi('spip_resultats', $tab_couples, array());
141 }
142 }
143
144 if (!isset($cache[$serveur][$table][$recherche])) {
145 if (!$serveur) {
146 $cache[$serveur][$table][$recherche] = array("resultats.points AS points", $where);
147 } else {
148 if (sql_countsel('spip_resultats as resultats', $where)) {
149 $rows = sql_allfetsel('resultats.id,resultats.points', 'spip_resultats as resultats', $where);
150 }
151 $cache[$serveur][$table][$recherche] = generer_select_where_explicites($table, $primary, $rows, $serveur);
152 }
153 }
154
155 return $cache[$serveur][$table][$recherche];
156 }
157
158
159 /**
160 * Generer le select et where qui contiennent explicitement
161 * les id et points (ie comme dans SPIP 1.9.x)
162 * quand on fait une recherche sur une table externe
163 *
164 * @param string $table
165 * @param string $primary
166 * @param array $rows
167 * @param string $serveur
168 * @return array
169 */
170 function generer_select_where_explicites($table, $primary, $rows, $serveur) {
171 # calculer le {id_article IN()} et le {... as points}
172 if (!count($rows)) {
173 return array("''", "0=1");
174 } else {
175 $listes_ids = array();
176 $select = '0';
177 foreach ($rows as $r) {
178 $listes_ids[$r['points']][] = $r['id'];
179 }
180
181 foreach ($listes_ids as $p => $ids) {
182 $select .= "+$p*(" .
183 sql_in("$table.$primary", $ids, '', $serveur)
184 . ") ";
185 }
186
187 return array("$select AS points ", sql_in("$table.$primary", array_map('reset', $rows), '', $serveur));
188 }
189 }