Changeset 108346 in spip-zone


Ignore:
Timestamp:
Jan 4, 2018, 9:18:38 AM (17 months ago)
Author:
cedric@…
Message:

Report des ameliorations du core + separation claire de ce qui est specifique au plugin et ce qui vient du core (a terme ce fichier pourrait etre supprime, la fonction fulltext_keys et le define etant deplaces dans le fichier options)

Location:
_plugins_/fulltext/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/fulltext/trunk/inc/rechercher.php

    r104327 r108346  
    44 *  SPIP, Systeme de publication pour l'internet                           *
    55 *                                                                         *
    6  *  Copyright (c) 2001-2014                                                *
     6 *  Copyright (c) 2001-2017                                                *
    77 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
    88 *                                                                         *
     
    1111\***************************************************************************/
    1212
     13/**
     14 * Gestion des recherches
     15 *
     16 * @package SPIP\Core\Recherche
     17 **/
    1318
    1419if (!defined('_ECRIRE_INC_VERSION')) {
    1520        return;
    16 }
    17 
    18 
    19 // Donne la liste des champs/tables ou l'on sait chercher/remplacer
    20 // avec un poids pour le score
    21 // https://code.spip.net/@liste_des_champs
    22 function liste_des_champs() {
    23         static $liste=null;
    24         if (is_null($liste)) {
    25                 $liste = array();
    26                 // recuperer les tables_objets_sql declarees
    27                 include_spip('base/objets');
    28                 $tables_objets = lister_tables_objets_sql();
    29                 foreach ($tables_objets as $t => $infos) {
    30                         if ($infos['rechercher_champs']) {
    31                                 $liste[$infos['type']] = $infos['rechercher_champs'];
    32                         }
    33                 }
    34                 // puis passer dans le pipeline
    35                 $liste = pipeline('rechercher_liste_des_champs', $liste);
    36         }
    37         return $liste;
    38 }
    39 
    40 
    41 // Recherche des auteurs et mots-cles associes
    42 // en ne regardant que le titre ou le nom
    43 // https://code.spip.net/@liste_des_jointures
    44 function liste_des_jointures() {
    45         static $liste=null;
    46         if (is_null($liste)) {
    47                 $liste = array();
    48                 // recuperer les tables_objets_sql declarees
    49                 include_spip('base/objets');
    50                 $tables_objets = lister_tables_objets_sql();
    51                 foreach ($tables_objets as $t => $infos) {
    52                         if ($infos['rechercher_jointures']) {
    53                                 $liste[$infos['type']] = $infos['rechercher_jointures'];
    54                         }
    55                 }
    56                 // puis passer dans le pipeline
    57                 $liste = pipeline('rechercher_liste_des_jointures', $liste);
    58         }
    59         return $liste;
    6021}
    6122
     
    7940}
    8041
     42/*
     43 * Le reste du fichier est identique au core SPIP 3
     44 */
     45
     46defined('_RECHERCHE_LOCK_KEY') || define('_RECHERCHE_LOCK_KEY', 'fulltext');
     47
     48/**
     49 * Donne la liste des champs/tables où l'on sait chercher / remplacer
     50 * avec un poids pour le score
     51 *
     52 * Utilise l'information `rechercher_champs` sur la déclaration
     53 * des objets éditoriaux.
     54 *
     55 * @pipeline_appel rechercher_liste_des_champs
     56 * @uses lister_tables_objets_sql()
     57 *
     58 * @return array Couples (type d'objet => Couples (champ => score))
     59 */
     60function liste_des_champs() {
     61        static $liste = null;
     62        if (is_null($liste)) {
     63                $liste = array();
     64                // recuperer les tables_objets_sql declarees
     65                include_spip('base/objets');
     66                $tables_objets = lister_tables_objets_sql();
     67                foreach ($tables_objets as $t => $infos) {
     68                        if ($infos['rechercher_champs']) {
     69                                $liste[$infos['type']] = $infos['rechercher_champs'];
     70                        }
     71                }
     72                // puis passer dans le pipeline
     73                $liste = pipeline('rechercher_liste_des_champs', $liste);
     74        }
     75
     76        return $liste;
     77}
     78
     79
     80// Recherche des auteurs et mots-cles associes
     81// en ne regardant que le titre ou le nom
     82// http://code.spip.net/@liste_des_jointures
     83function liste_des_jointures() {
     84        static $liste = null;
     85        if (is_null($liste)) {
     86                $liste = array();
     87                // recuperer les tables_objets_sql declarees
     88                include_spip('base/objets');
     89                $tables_objets = lister_tables_objets_sql();
     90                foreach ($tables_objets as $t => $infos) {
     91                        if ($infos['rechercher_jointures']) {
     92                                $liste[$infos['type']] = $infos['rechercher_jointures'];
     93                        }
     94                }
     95                // puis passer dans le pipeline
     96                $liste = pipeline('rechercher_liste_des_jointures', $liste);
     97        }
     98
     99        return $liste;
     100}
    81101
    82102function expression_recherche($recherche, $options) {
     
    101121
    102122        $is_preg = false;
    103         if (substr($recherche, 0, 1) == '/' and substr($recherche, -1, 1) == '/') {
     123        if (substr($recherche, 0, 1) == '/' and substr($recherche, -1, 1) == '/' and strlen($recherche) > 2) {
    104124                // c'est une preg
    105125                $recherche_trans = translitteration($recherche);
    106                 $preg = $recherche_trans.$options['preg_flags'];
     126                $preg = $recherche_trans . $options['preg_flags'];
    107127                $is_preg = true;
    108128        } else {
    109                 // s'il y a plusieurs mots il faut les chercher tous : oblige REGEXP
     129                // s'il y a plusieurs mots il faut les chercher tous : oblige REGEXP,
    110130                // sauf ceux de moins de 4 lettres (on supprime ainsi 'le', 'les', 'un',
    111131                // 'une', 'des' ...)
    112                 if (preg_match(',\s+,'. $u, $recherche)) {
     132
     133                // attention : plusieurs mots entre guillemets sont a rechercher tels quels
     134                $recherche_trans = $recherche_mod = $recherche;
     135
     136                // les expressions entre " " sont un mot a chercher tel quel
     137                // -> on remplace les espaces par un \x1 et on enleve les guillemets
     138                if (preg_match(',["][^"]+["],Uims', $recherche_mod, $matches)) {
     139                        foreach ($matches as $match) {
     140                                $word = preg_replace(",\s+,Uims", "\x1", $match);
     141                                $word = trim($word, '"');
     142                                $recherche_mod = str_replace($match, $word, $recherche_mod);
     143                        }
     144                }
     145
     146                if (preg_match(",\s+," . $u, $recherche_mod)) {
    113147                        $is_preg = true;
     148
    114149                        $recherche_inter = '|';
    115                         $recherche_mots = explode(' ', $recherche);
     150                        $recherche_mots = explode(' ', $recherche_mod);
    116151                        $min_long = defined('_RECHERCHE_MIN_CAR') ? _RECHERCHE_MIN_CAR : 4;
    117152                        foreach ($recherche_mots as $mot) {
    118153                                if (strlen($mot) >= $min_long) {
    119                                         $recherche_inter .= $mot.' ';
     154                                        // echapper les caracteres de regexp qui sont eventuellement dans la recherche
     155                                        $recherche_inter .= preg_quote($mot) . ' ';
    120156                                }
    121157                        }
    122                         // mais on cherche quand meme l'expression complete, meme si elle
     158                        $recherche_inter = str_replace("\x1", '\s', $recherche_inter);
     159
     160                        // mais on cherche quand même l'expression complète, même si elle
    123161                        // comporte des mots de moins de quatre lettres
    124                         $recherche = rtrim($recherche.preg_replace(',\s+,'.$u, '|', $recherche_inter), '|');
    125                 }
    126 
    127                 $recherche_trans = translitteration($recherche);
    128                 $preg = '/'.str_replace('/', '\\/', $recherche_trans).'/' . $options['preg_flags'];
     162                        $recherche = rtrim(preg_quote($recherche) . preg_replace(',\s+,' . $u, '|', $recherche_inter), '|');
     163                        $recherche_trans = translitteration($recherche);
     164                }
     165
     166                $preg = '/' . str_replace('/', '\\/', $recherche_trans) . '/' . $options['preg_flags'];
    129167        }
    130168
     
    132170        // ou si l'expression reguliere est invalide
    133171        if (!$is_preg
    134         or (@preg_match($preg, '') === false) ) {
     172                or (@preg_match($preg, '') === false)
     173        ) {
    135174                $methode = 'LIKE';
    136175                $u = $GLOBALS['meta']['pcre_u'];
    137                 // eviter les parentheses et autres caracteres qui interferent avec pcre
    138                 // par la suite (dans le preg_match_all) s'il y a des reponses
    139                 $recherche = str_replace(
    140                         array('(',')','?','[', ']', '+', '*', '/'),
    141                         array('\(','\)','[?]', '\[', '\]', '\+', '\*', '\/'),
    142                         $recherche
    143                 );
     176
     177                // echapper les % et _
     178                $q = str_replace(array('%', '_'), array('\%', '\_'), trim($recherche));
     179
     180                // 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
     181                $recherche = preg_quote($recherche, '/');
    144182                $recherche_trans = translitteration($recherche);
    145183                $recherche_mod = $recherche_trans;
    146184
    147                 // echapper les % et _
    148                 $q = str_replace(array('%','_'), array('\%', '\_'), trim($recherche));
    149185                // les expressions entre " " sont un mot a chercher tel quel
    150186                // -> on remplace les espaces par un _ et on enleve les guillemets
     187                // corriger le like dans le $q
    151188                if (preg_match(',["][^"]+["],Uims', $q, $matches)) {
    152189                        foreach ($matches as $match) {
    153                                 // corriger le like dans le $q
    154                                 $word = preg_replace(',\s+,Uims', '_', $match);
     190                                $word = preg_replace(",\s+,Uims", "_", $match);
    155191                                $word = trim($word, '"');
    156192                                $q = str_replace($match, $word, $q);
    157                                 // corriger la regexp
    158                                 $word = preg_replace(',\s+,Uims', '[\s]', $match);
     193                        }
     194                }
     195                // corriger la regexp
     196                if (preg_match(',["][^"]+["],Uims', $recherche_mod, $matches)) {
     197                        foreach ($matches as $match) {
     198                                $word = preg_replace(",\s+,Uims", "[\s]", $match);
    159199                                $word = trim($word, '"');
    160200                                $recherche_mod = str_replace($match, $word, $recherche_mod);
     
    162202                }
    163203                $q = sql_quote(
    164                         '%'
    165                         . preg_replace(',\s+,' . $u, '%', $q)
    166                         . '%'
     204                        "%"
     205                        . preg_replace(",\s+," . $u, "%", $q)
     206                        . "%"
    167207                );
    168208
    169                 $preg = '/'.preg_replace(',\s+,' . $u, '.+', trim($recherche_mod)).'/' . $options['preg_flags'];
     209                $preg = '/' . preg_replace(",\s+," . $u, ".+", trim($recherche_mod)) . '/' . $options['preg_flags'];
     210
    170211        } else {
    171212                $methode = 'REGEXP';
     
    180221                if (!is_ascii($char)
    181222                        and $char_t = translitteration($char)
    182                         and $char_t !== $char) {
    183                         $q_t = str_replace($char, $is_preg ? '.' : '_', $q_t);
     223                        and $char_t !== $char
     224                ) {
     225                        $q_t = str_replace($char, $is_preg ? "." : "_", $q_t);
    184226                }
    185227        }
     
    191233        // (oui c'est tres dicustable...)
    192234        if (isset($GLOBALS['connexions'][$options['serveur'] ? $options['serveur'] : 0]['type'])
    193                 and strncmp($GLOBALS['connexions'][$options['serveur'] ? $options['serveur'] : 0]['type'], 'sqlite', 6) == 0) {
    194                 $q_t = strtr($q, 'aeuioc', $is_preg ? '......' : '______');
     235                and strncmp($GLOBALS['connexions'][$options['serveur'] ? $options['serveur'] : 0]['type'], 'sqlite', 6) == 0
     236        ) {
     237                $q_t = strtr($q, "aeuioc", $is_preg ? "......" : "______");
    195238                // si il reste au moins un char significatif...
    196239                if (preg_match(",[^'%_.],", $q_t)) {
     
    203246
    204247
    205 // Effectue une recherche sur toutes les tables de la base de donnees
    206 // options :
    207 // - toutvoir pour eviter autoriser(voir)
    208 // - flags pour eviter les flags regexp par defaut (UimsS)
    209 // - champs pour retourner les champs concernes
    210 // - score pour retourner un score
    211 // On peut passer les tables, ou une chaine listant les tables souhaitees
    212 // https://code.spip.net/@recherche_en_base
     248
     249/**
     250 * Effectue une recherche sur toutes les tables de la base de données
     251 *
     252 * @uses liste_des_champs()
     253 * @uses inc_recherche_to_array_dist()
     254 *
     255 * @param string $recherche
     256 *     Le terme de recherche
     257 * @param null|array|string $tables
     258 *     - null : toutes les tables acceptant des recherches
     259 *     - array : liste des tables souhaitées
     260 *     - string : une chaîne listant les tables souhaitées, séparées par des virgules (préférer array cependant)
     261 * @param array $options {
     262 *     @var $toutvoir pour éviter autoriser(voir)
     263 *     @var $flags pour éviter les flags regexp par défaut (UimsS)
     264 *     @var $champs pour retourner les champs concernés
     265 *     @var $score pour retourner un score
     266 * }
     267 * @param string $serveur
     268 * @return array
     269 */
    213270function recherche_en_base($recherche = '', $tables = null, $options = array(), $serveur = '') {
    214271        include_spip('base/abstract_sql');
     
    218275
    219276                if (is_string($tables)
    220                         and $tables != '') {
     277                        and $tables != ''
     278                ) {
    221279                        $toutes = array();
    222280                        foreach (explode(',', $tables) as $t) {
     
    240298
    241299        // options par defaut
    242         $options = array_merge(
    243                 array(
    244                         'preg_flags' => 'UimsS',
    245                         'toutvoir' => false,
    246                         'champs' => false,
    247                         'score' => false,
    248                         'matches' => false,
    249                         'jointures' => false,
    250                         'serveur' => $serveur
    251                 ),
     300        $options = array_merge(array(
     301                'preg_flags' => 'UimsS',
     302                'toutvoir' => false,
     303                'champs' => false,
     304                'score' => false,
     305                'matches' => false,
     306                'jointures' => false,
     307                'serveur' => $serveur
     308        ),
    252309                $options
    253310        );
     
    262319        // }
    263320
    264         include_spip('inc/memoization');
    265321        include_spip('inc/recherche_to_array');
    266322
     
    268324                # lock via memoization, si dispo
    269325                if (function_exists('cache_lock')) {
    270                         cache_lock($lock = 'fulltext '.$table.' '.$recherche);
     326                        cache_lock($lock = _RECHERCHE_LOCK_KEY . ' ' . $table . ' ' . $recherche);
    271327                }
    272328
     
    281337
    282338
    283                 spip_log("recherche $table ($recherche) : " . count($results[$table]) . ' resultats ' . spip_timer('rech'), 'recherche');
     339                spip_log("recherche $table ($recherche) : " . count($results[$table]) . " resultats " . spip_timer('rech'),
     340                        'recherche');
    284341
    285342                if (isset($lock)) {
     
    293350
    294351// Effectue une recherche sur toutes les tables de la base de donnees
    295 // https://code.spip.net/@remplace_en_base
     352// http://code.spip.net/@remplace_en_base
    296353function remplace_en_base($recherche = '', $remplace = null, $tables = null, $options = array()) {
    297354        include_spip('inc/modifier');
    298355
    299356        // options par defaut
    300         $options = array_merge(
    301                 array(
    302                         'preg_flags' => 'UimsS',
    303                         'toutmodifier' => false
    304                 ),
     357        $options = array_merge(array(
     358                'preg_flags' => 'UimsS',
     359                'toutmodifier' => false
     360        ),
    305361                $options
    306362        );
     
    314370        $results = recherche_en_base($recherche, $tables, $options);
    315371
    316         $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
     372        $preg = '/' . str_replace('/', '\\/', $recherche) . '/' . $options['preg_flags'];
    317373
    318374        foreach ($results as $table => $r) {
     
    320376                foreach ($r as $id => $x) {
    321377                        if ($options['toutmodifier']
    322                         or autoriser('modifier', $table, $id)) {
     378                                or autoriser('modifier', $table, $id)
     379                        ) {
    323380                                $modifs = array();
    324381                                foreach ($x['champs'] as $key => $val) {
    325382                                        if ($key == $_id_table) {
    326                                                 next;
     383                                                continue;
    327384                                        }
    328385                                        $repl = preg_replace($preg, $remplace, $val);
     
    332389                                }
    333390                                if ($modifs) {
    334                                         objet_modifier_champs(
    335                                                 $table,
    336                                                 $id,
     391                                        objet_modifier_champs($table, $id,
    337392                                                array(
    338393                                                        'champs' => array_keys($modifs),
    339394                                                ),
    340                                                 $modifs
    341                                         );
     395                                                $modifs);
    342396                                }
    343397                        }
  • _plugins_/fulltext/trunk/paquet.xml

    r106544 r108346  
    22        prefix="fulltext"
    33        categorie="navigation"
    4         version="1.1.20"
     4        version="1.1.21"
    55        etat="test"
    66        compatibilite="[3.0.1;3.2.*]"
Note: See TracChangeset for help on using the changeset viewer.