3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2011 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
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 \***************************************************************************/
14 if (!defined('_ECRIRE_INC_VERSION')) return;
17 // Donne la liste des champs/tables ou l'on sait chercher/remplacer
18 // avec un poids pour le score
19 // http://doc.spip.org/@liste_des_champs
20 function liste_des_champs() {
22 pipeline('rechercher_liste_des_champs',
25 'surtitre' => 5, 'titre' => 8, 'soustitre' => 5, 'chapo' => 3,
26 'texte' => 1, 'ps' => 1, 'nom_site' => 1, 'url_site' => 1,
30 'titre' => 8, 'texte' => 2, 'lien_titre' => 1, 'lien_url' => 1
33 'titre' => 8, 'descriptif' => 5, 'texte' => 1
36 'nom_site' => 5, 'url_site' => 1, 'descriptif' => 3
39 'titre' => 8, 'texte' => 1, 'descriptif' => 5
42 'nom' => 5, 'bio' => 1, 'email' => 1, 'nom_site' => 1, 'url_site' => 1, 'login' => 1
45 'titre' => 3, 'texte' => 1, 'auteur' => 2, 'email_auteur' => 2, 'nom_site' => 1, 'url_site' => 1
48 'titre' => 3, 'descriptif' => 1, 'fichier' => 1
50 'syndic_article' => array(
51 'titre' => 5, 'descriptif' => 1
54 'nom_email' => 2, 'ad_email' => 4,
55 'nom_site' => 2, 'url_site' => 4,
64 // Recherche des auteurs et mots-cles associes
65 // en ne regardant que le titre ou le nom
66 // http://doc.spip.org/@liste_des_jointures
67 function liste_des_jointures() {
69 pipeline('rechercher_liste_des_jointures',
72 'auteur' => array('nom' => 10),
73 'mot' => array('titre' => 3),
74 'document' => array('titre' => 2, 'descriptif' => 1)
77 'mot' => array('titre' => 3),
78 'document' => array('titre' => 2, 'descriptif' => 1)
81 'mot' => array('titre' => 3),
82 'document' => array('titre' => 2, 'descriptif' => 1)
85 'mot' => array('titre' => 3)
94 // Effectue une recherche sur toutes les tables de la base de donnees
96 // - toutvoir pour eviter autoriser(voir)
97 // - flags pour eviter les flags regexp par defaut (UimsS)
98 // - champs pour retourner les champs concernes
99 // - score pour retourner un score
100 // On peut passer les tables, ou une chaine listant les tables souhaitees
101 // http://doc.spip.org/@recherche_en_base
102 function recherche_en_base($recherche='', $tables=NULL, $options=array(), $serveur='') {
103 include_spip('base/abstract_sql');
105 if (!is_array($tables)) {
106 $liste = liste_des_champs();
108 if (is_string($tables)
111 foreach(explode(',', $tables) as $t)
112 if (isset($liste[$t]))
113 $toutes[$t] = $liste[$t];
120 include_spip('inc/autoriser');
122 // options par defaut
123 $options = array_merge(array(
124 'preg_flags' => 'UimsS',
136 if (!strlen($recherche) OR !count($tables))
138 include_spip('inc/charsets');
139 $recherche = translitteration($recherche);
142 if (substr($recherche,0,1)=='/' AND substr($recherche,-1,1)=='/'){
144 $preg = $recherche.$options['preg_flags'];
148 $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
149 // Si la chaine est inactive, on va utiliser LIKE pour aller plus vite
150 // ou si l'expression reguliere est invalide
152 OR (@preg_match
($preg,'')===FALSE) ) {
154 $u = $GLOBALS['meta']['pcre_u'];
155 // eviter les parentheses et autres caractères qui interferent avec pcre par la suite (dans le preg_match_all) s'il y a des reponses
156 $recherche = str_replace(
157 array('(',')','?','[', ']', '+', '*', '/'),
158 array('\(','\)','[?]', '\[', '\]', '\+', '\*', '\/'),
160 $recherche_mod = $recherche;
162 // echapper les % et _
163 $q = str_replace(array('%','_'), array('\%', '\_'), trim($recherche));
164 // les expressions entre " " sont un mot a chercher tel quel
165 // -> on remplace les espaces par un _ et on enleve les guillemets
166 if (preg_match(',["][^"]+["],Uims',$q,$matches)){
167 foreach($matches as $match){
168 // corriger le like dans le $q
169 $word = preg_replace(",\s+,Uims","_",$match);
170 $word = trim($word,'"');
171 $q = str_replace($match,$word,$q);
172 // corriger la regexp
173 $word = preg_replace(",\s+,Uims","[\s]",$match);
174 $word = trim($word,'"');
175 $recherche_mod = str_replace($match,$word,$recherche_mod);
180 . preg_replace(",\s+,".$u, "%", $q)
184 $preg = '/'.preg_replace(",\s+,".$u, ".+", trim($recherche_mod)).'/' . $options['preg_flags'];
188 $q = sql_quote(substr($recherche,1,-1));
191 $jointures = $options['jointures']
192 ?
liste_des_jointures()
195 foreach ($tables as $table => $champs) {
206 $_id_table = id_table_objet($table);
207 $requete['SELECT'][] = "t.".$_id_table;
209 // Recherche fulltext
210 foreach ($champs as $champ => $poids) {
211 if (is_array($champ)){
212 spip_log("requetes imbriquees interdites");
214 if (strpos($champ,".")===FALSE)
216 $requete['SELECT'][] = $champ;
217 $a[] = $champ.' '.$methode.' '.$q;
220 if ($a) $requete['WHERE'][] = join(" OR ", $a);
221 $requete['FROM'][] = table_objet_sql($table).' AS t';
224 $requete['SELECT'], $requete['FROM'], $requete['WHERE'],
225 implode(" ",$requete['GROUPBY']),
226 $requete['ORDERBY'], $requete['LIMIT'],
227 $requete['HAVING'], $serveur
230 while ($t = sql_fetch($s,$serveur)) {
231 $id = intval($t[$_id_table]);
232 if ($options['toutvoir']
233 OR autoriser('voir', $table, $id)) {
234 // indiquer les champs concernes
235 $champs_vus = array();
240 foreach ($champs as $champ => $poids) {
241 $champ = explode('.',$champ);
242 $champ = end($champ);
244 ($options['score'] ||
$options['matches'])
245 ?
preg_match_all($preg, translitteration_rapide($t[$champ]), $regs, PREG_SET_ORDER
)
246 : preg_match($preg, translitteration_rapide($t[$champ]))
250 if ($options['champs'])
251 $champs_vus[$champ] = $t[$champ];
252 if ($options['score'])
253 $score +
= $n * $poids;
254 if ($options['matches'])
255 $matches[$champ] = $regs;
257 if (!$options['champs']
258 AND !$options['score']
259 AND !$options['matches'])
265 if (!isset($results[$table]))
266 $results[$table] = array();
267 $results[$table][$id] = array();
269 $results[$table][$id]['champs'] = $champs_vus;
271 $results[$table][$id]['score'] = $score;
273 $results[$table][$id]['matches'] = $matches;
279 // Gerer les donnees associees
280 if (isset($jointures[$table])
281 AND $joints = recherche_en_base(
284 array_merge($options, array('jointures' => false))
287 foreach ($joints as $table_liee => $ids_trouves) {
288 if (!$rechercher_joints = charger_fonction("rechercher_joints_${table}_${table_liee}","inc",true)){
289 $cle_depart = id_table_objet($table);
290 $cle_arrivee = id_table_objet($table_liee);
291 $table_sql = preg_replace('/^spip_/', '', table_objet_sql($table));
292 $table_liee_sql = preg_replace('/^spip_/', '', table_objet_sql($table_liee));
293 if ($table_liee == 'document')
294 $s = sql_select("id_objet as $cle_depart, $cle_arrivee", "spip_documents_liens", array("objet='$table'",sql_in('id_'.$
{table_liee
}, array_keys($ids_trouves))), '','','','',$serveur);
296 $s = sql_select("$cle_depart,$cle_arrivee", "spip_${table_liee_sql}_${table_sql}", sql_in('id_'.$
{table_liee
}, array_keys($ids_trouves)), '','','','',$serveur);
299 list($cle_depart,$cle_arrivee,$s) = $rechercher_joints($table,$table_liee,array_keys($ids_trouves), $serveur);
301 while ($t = is_array($s)?
array_shift($s):sql_fetch($s)) {
302 $id = $t[$cle_depart];
303 $joint = $ids_trouves[$t[$cle_arrivee]];
304 if (!isset($results[$table]))
305 $results[$table] = array();
306 if (!isset($results[$table][$id]))
307 $results[$table][$id] = array();
309 $results[$table][$id]['score'] +
= $joint['score'];
310 if ($joint['champs'])
311 foreach($joint['champs'] as $c => $val)
312 $results[$table][$id]['champs'][$table_liee.'.'.$c] = $val;
313 if ($joint['matches'])
314 foreach($joint['matches'] as $c => $val)
315 $results[$table][$id]['matches'][$table_liee.'.'.$c] = $val;
325 // Effectue une recherche sur toutes les tables de la base de donnees
326 // http://doc.spip.org/@remplace_en_base
327 function remplace_en_base($recherche='', $remplace=NULL, $tables=NULL, $options=array()) {
328 include_spip('inc/modifier');
330 // options par defaut
331 $options = array_merge(array(
332 'preg_flags' => 'UimsS',
333 'toutmodifier' => false
337 $options['champs'] = true;
340 if (!is_array($tables))
341 $tables = liste_des_champs();
343 $results = recherche_en_base($recherche, $tables, $options);
345 $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
347 foreach ($results as $table => $r) {
348 $_id_table = id_table_objet($table);
349 foreach ($r as $id => $x) {
350 if ($options['toutmodifier']
351 OR autoriser('modifier', $table, $id)) {
353 foreach ($x['champs'] as $key => $val) {
354 if ($key == $_id_table) next
;
355 $repl = preg_replace($preg, $remplace, $val);
357 $modifs[$key] = $repl;
360 modifier_contenu($table, $id,
362 'champs' => array_keys($modifs),