[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_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-2016 *
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 if (!defined('_ECRIRE_INC_VERSION')) return;
15
16 include_spip('inc/rechercher');
17 if (!defined('_DELAI_CACHE_resultats')) define('_DELAI_CACHE_resultats', 600);
18
19 /**
20 * Preparer les listes id_article IN (...) pour les parties WHERE
21 * et points = des requetes du moteur de recherche
22 * http://doc.spip.org/@inc_prepare_recherche_dist
23 *
24 * Le parametre $serveur est utilise pour savoir sur quelle base on cherche
25 * mais l'index des resultats est toujours stock� sur le serveur principal
26 * car on ne sait pas si la base distante dispose d'une table spip_resultats
27 * ni meme si on aurait le droit d'ecrire dedans
28 *
29 * @param string $recherche
30 * chaine recherchee
31 * @param string $table
32 * table dans laquelle porte la recherche
33 * @param bool $cond
34 * critere conditionnel sur {recherche?}
35 * @param string $serveur
36 * serveur de base de donnees
37 * @param array $modificateurs
38 * modificateurs de boucle, ie liste des criteres presents
39 * @param string $primary
40 * cle primaire de la table de recherche
41 * @return array
42 */
43 function inc_prepare_recherche_dist($recherche, $table='articles', $cond=false, $serveur='', $modificateurs = array(), $primary='') {
44 static $cache = array();
45 $delai_fraicheur = min(_DELAI_CACHE_resultats,time()-$GLOBALS['meta']['derniere_modif']);
46
47 // si recherche n'est pas dans le contexte, on va prendre en globals
48 // ca permet de faire des inclure simple.
49 if (!isset($recherche) AND isset($GLOBALS['recherche']))
50 $recherche = $GLOBALS['recherche'];
51
52 // traiter le cas {recherche?}
53 if ($cond AND !strlen($recherche))
54 return array("0 as points" /* as points */, /* where */ '');
55
56
57 $rechercher = false;
58
59 if (!isset($cache[$serveur][$table][$recherche])){
60 $hash_serv = ($serveur?substr(md5($serveur),0,16):'');
61 $hash = substr(md5($recherche . $table),0,16);
62 $where = "(resultats.recherche='$hash' AND resultats.table_objet=".sql_quote($table)." AND resultats.serveur='$hash_serv')";
63 $row = sql_fetsel('UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(resultats.maj) AS fraicheur','spip_resultats AS resultats',$where,'','fraicheur DESC','0,1');
64 if (!$row
65 OR ($row['fraicheur']>$delai_fraicheur)
66 OR (defined('_VAR_MODE') AND _VAR_MODE=='recalcul')){
67 $rechercher = true;
68 }
69 }
70
71 // si on n'a pas encore traite les donnees dans une boucle precedente
72 if ($rechercher) {
73 //$tables = liste_des_champs();
74 $x = objet_type($table);
75 $points = recherche_en_base($recherche,
76 $x,
77 array(
78 'score' => true,
79 'toutvoir' => true,
80 'jointures' => true
81 ),
82 $serveur);
83 // pas de résultat, pas de point
84 $points = isset($points[$x]) ? $points[$x] : array();
85
86 // permettre aux plugins de modifier le resultat
87 $points = pipeline('prepare_recherche',array(
88 'args'=>array('type'=>$x,'recherche'=>$recherche,'serveur'=>$serveur,'modificateurs'=>$modificateurs),
89 'data'=>$points
90 ));
91
92 // supprimer les anciens resultats de cette recherche
93 // et les resultats trop vieux avec une marge
94 // pas de AS resultats dans un delete (mysql)
95 $whered = str_replace(array("resultats.recherche","resultats.table_objet","resultats.serveur"),array("recherche","table_objet","serveur"),$where);
96 sql_delete('spip_resultats', 'NOT(' .sql_date_proche('maj', (0-($delai_fraicheur+100)), " SECOND") . ") OR ($whered)");
97
98 // inserer les resultats dans la table de cache des resultats
99 if (count($points)){
100 $tab_couples = array();
101 foreach ($points as $id => $p){
102 $tab_couples[] = array(
103 'recherche' => $hash,
104 'id' => $id,
105 'points' => $p['score'],
106 'table_objet' => $table,
107 'serveur' => $hash_serv,
108 );
109 }
110 sql_insertq_multi('spip_resultats',$tab_couples,array());
111 }
112 }
113
114 if (!isset($cache[$serveur][$table][$recherche])){
115 if (!$serveur)
116 $cache[$serveur][$table][$recherche] = array("resultats.points AS points",$where);
117 else {
118 if (sql_countsel('spip_resultats as resultats',$where))
119 $rows = sql_allfetsel('resultats.id,resultats.points','spip_resultats as resultats',$where);
120 $cache[$serveur][$table][$recherche] = generer_select_where_explicites($table, $primary, $rows, $serveur);
121 }
122 }
123
124 return $cache[$serveur][$table][$recherche];
125 }
126
127
128 /**
129 * Generer le select et where qui contiennent explicitement
130 * les id et points (ie comme dans SPIP 1.9.x)
131 * quand on fait une recherche sur une table externe
132 *
133 * @param string $table
134 * @param string $primary
135 * @param array $rows
136 * @param string $serveur
137 * @return array
138 */
139 function generer_select_where_explicites($table, $primary, $rows, $serveur){
140 # calculer le {id_article IN()} et le {... as points}
141 if (!count($rows)){
142 return array("''", "0=1");
143 }
144 else {
145 $listes_ids = array();
146 $select = '0';
147 foreach ($rows as $r)
148 $listes_ids[$r['points']][] = $r['id'];
149
150 foreach ($listes_ids as $p => $ids)
151 $select .= "+$p*(".
152 sql_in("$table.$primary", $ids,'',$serveur)
153 .") ";
154
155 return array("$select AS points ",calcul_mysql_in("$table.$primary",array_map('reset',$rows),'',$serveur));
156 }
157 }
158
159
160 ?>