[SPIP] v3.0.22-->v3.0.24
[lhc/web/www.git] / www / ecrire / inc / rechercher.php
index 858137f..f5ecc4b 100644 (file)
@@ -3,7 +3,7 @@
 /***************************************************************************\
  *  SPIP, Systeme de publication pour l'internet                           *
  *                                                                         *
- *  Copyright (c) 2001-2012                                                *
+ *  Copyright (c) 2001-2016                                                *
  *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
  *                                                                         *
  *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
@@ -58,24 +58,47 @@ function liste_des_jointures() {
 }
 
 function expression_recherche($recherche, $options) {
+       // ne calculer qu'une seule fois l'expression par hit
+       // (meme si utilisee dans plusieurs boucles)
+       static $expression = array();
+       $key = serialize(array($recherche, $options['preg_flags']));
+       if (isset($expression[$key]))
+               return $expression[$key];
+
        $u = $GLOBALS['meta']['pcre_u'];
+       if ($u AND strpos($options['preg_flags'],$u)===false)
+               $options['preg_flags'] .= $u;
        include_spip('inc/charsets');
-       $recherche = trim(translitteration($recherche));
+       $recherche = trim($recherche);
 
        $is_preg = false;
-       if (substr($recherche,0,1)=='/' AND substr($recherche,-1,1)=='/'){
+       if (substr($recherche, 0, 1) == '/' and substr($recherche, -1, 1) == '/' and strlen($recherche) > 2) {
                // c'est une preg
-               $preg = $recherche.$options['preg_flags'];
+               $recherche_trans = translitteration($recherche);
+               $preg = $recherche_trans.$options['preg_flags'];
                $is_preg = true;
        }
        else{
                // s'il y a plusieurs mots il faut les chercher tous : oblige REGEXP
+               // sauf ceux de moins de 4 lettres (on supprime ainsi 'le', 'les', 'un',
+               // 'une', 'des' ...)
                if (preg_match(",\s+,".$u, $recherche)){
                        $is_preg = true;
-                       $recherche = preg_replace(',\s+,'.$u, '|', $recherche);
+                       $recherche_inter = '|';
+                       $recherche_mots = explode(' ', $recherche);
+                       $min_long = defined('_RECHERCHE_MIN_CAR') ? _RECHERCHE_MIN_CAR : 4;
+                       foreach ($recherche_mots as $mot) {
+                               if (strlen($mot) >= $min_long) {
+                                       $recherche_inter .= $mot.' ';
+                               }
+                       }
+                       // mais on cherche quand même l'expression complète, même si elle
+                       // comporte des mots de moins de quatre lettres
+                       $recherche = rtrim($recherche.preg_replace(',\s+,'.$u, '|', $recherche_inter), '|');
+                       $recherche_trans = translitteration($recherche);
                }
 
-               $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
+               $preg = '/'.str_replace('/', '\\/', $recherche_trans).'/' . $options['preg_flags'];
        }
 
        // Si la chaine est inactive, on va utiliser LIKE pour aller plus vite
@@ -89,7 +112,8 @@ function expression_recherche($recherche, $options) {
                        array('(',')','?','[', ']', '+', '*', '/'),
                        array('\(','\)','[?]', '\[', '\]', '\+', '\*', '\/'),
                        $recherche);
-               $recherche_mod = $recherche;
+               $recherche_trans = translitteration($recherche);
+               $recherche_mod = $recherche_trans;
 
                // echapper les % et _
                $q = str_replace(array('%','_'), array('\%', '\_'), trim($recherche));
@@ -120,7 +144,32 @@ function expression_recherche($recherche, $options) {
                $q = sql_quote(trim($recherche, '/'));
        }
 
-       return array($methode, $q, $preg);
+       // tous les caracteres transliterables de $q sont remplaces par un joker
+       // permet de matcher en SQL meme si on est sensible aux accents (SQLite)
+       $q_t = $q;
+       for($i = 0;$i<spip_strlen($q);$i++){
+               $char = spip_substr($q,$i,1);
+               if (!is_ascii($char)
+                 AND $char_t = translitteration($char)
+                 AND $char_t !== $char){
+                       $q_t = str_replace($char,$is_preg?".":"_", $q_t);
+               }
+       }
+
+       $q = $q_t;
+
+       // fix : SQLite 3 est sensible aux accents, on jokerise les caracteres
+       // les plus frequents qui peuvent etre accentues
+       // (oui c'est tres dicustable...)
+       if (isset($GLOBALS['connexions'][$options['serveur']?$options['serveur']:0]['type'])
+         AND strncmp($GLOBALS['connexions'][$options['serveur']?$options['serveur']:0]['type'],'sqlite',6)==0){
+               $q_t = strtr($q,"aeuioc",$is_preg?"......":"______");
+               // si il reste au moins un char significatif...
+               if (preg_match(",[^'%_.],",$q_t))
+                       $q = $q_t;
+       }
+
+       return $expression[$key] = array($methode, $q, $preg);
 }