[ Index ]
 

Code source de SPIP 1.9.2c

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/ecrire/inc/ -> indexation.php (source)

   1  <?php
   2  
   3  /***************************************************************************\
   4   *  SPIP, Systeme de publication pour l'internet                           *
   5   *                                                                         *
   6   *  Copyright (c) 2001-2007                                                *
   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  //
  15  if (!defined("_ECRIRE_INC_VERSION")) return;
  16  include_spip('base/create');
  17  include_spip('base/abstract_sql');
  18  include_spip('public/interfaces');
  19  
  20  // Quels formats sait-on extraire ?
  21  $GLOBALS['extracteur'] = array (
  22      'txt'   => 'extracteur_txt',
  23      'pas'   => 'extracteur_txt',
  24      'c'     => 'extracteur_txt',
  25      'css'   => 'extracteur_txt',
  26      'html'  => 'extracteur_html'
  27  );
  28  
  29  // tables que l'on ne doit pas indexer
  30  global $INDEX_tables_interdites;
  31  $INDEX_tables_interdites=array();
  32  
  33  // Indexation des elements de l'objet principal
  34  // 'champ'=>poids, ou 'champ'=>array(poids,min_long)
  35  $reindex = false;
  36  global $INDEX_elements_objet;
  37  $INDEX_elements_objet = FALSE;
  38  if (isset($GLOBALS['meta']['INDEX_elements_objet']))
  39      $INDEX_elements_objet = unserialize($GLOBALS['meta']['INDEX_elements_objet']);
  40  if (!$INDEX_elements_objet) {
  41      include_spip('inc/meta');
  42      $INDEX_elements_objet['spip_articles'] = array('titre'=>8,'soustitre'=>5,'surtitre'=>5,'descriptif'=>4,'chapo'=>3,'texte'=>1,'ps'=>1,'nom_site'=>1,'extra|unserialize_join'=>1);
  43      $INDEX_elements_objet['spip_breves'] = array('titre'=>8,'texte'=>2,'extra|unserialize_join'=>1);
  44      $INDEX_elements_objet['spip_rubriques'] = array('titre'=>8,'descriptif'=>5,'texte'=>1,'extra|unserialize_join'=>1);
  45      $INDEX_elements_objet['spip_auteurs'] = array('nom'=>array(5,2),'bio'=>1,'extra|unserialize_join'=>1);
  46      $INDEX_elements_objet['spip_mots'] = array('titre'=>8,'descriptif'=>5,'texte'=>1,'extra|unserialize_join'=>1);
  47      $INDEX_elements_objet['spip_signatures'] = array('nom_email'=>array(2,2),'ad_email'=>2,'nom_site'=>2,'url_site'=>1,'message'=>1);
  48      $INDEX_elements_objet['spip_syndic'] = array('nom_site'=>50,'descriptif'=>30,'url_site|contenu_page_accueil'=>1);
  49      $INDEX_elements_objet['spip_syndic_articles'] = array('titre'=>5);
  50      $INDEX_elements_objet['spip_forum'] = array('titre'=>3,'texte'=>2,'auteur'=>array(2,2),'email_auteur'=>2,'nom_site'=>2,'url_site'=>1);
  51      $INDEX_elements_objet['spip_documents'] = array('titre'=>20,'descriptif'=>10,'fichier|nettoie_nom_fichier'=>1);
  52      ecrire_meta('INDEX_elements_objet',serialize($INDEX_elements_objet));
  53      ecrire_metas();
  54      $reindex = true;
  55  }
  56  
  57  // Indexation des objets associes
  58  // 'objet'=>poids
  59  global $INDEX_objet_associes;
  60  $INDEX_objet_associes = FALSE;
  61  if (isset($GLOBALS['meta']['INDEX_objet_associes']))
  62      $INDEX_objet_associes = unserialize($GLOBALS['meta']['INDEX_objet_associes']);
  63  if (!$INDEX_objet_associes) {
  64      include_spip('inc/meta');
  65      $INDEX_objet_associes['spip_articles'] = array('spip_documents'=>1,'spip_auteurs'=>10,'spip_mots'=>3);
  66      $INDEX_objet_associes['spip_breves'] = array('spip_documents'=>1,'spip_mots'=>3);
  67      $INDEX_objet_associes['spip_rubriques'] = array('spip_documents'=>1,'spip_mots'=>3);
  68      $INDEX_objet_associes['spip_documents'] = array('spip_mots'=>3);
  69      ecrire_meta('INDEX_objet_associes',serialize($INDEX_objet_associes));
  70      ecrire_metas();
  71      $reindex = true;
  72  }
  73  
  74  // Indexation des elements des objets associes
  75  // 'champ'=>poids, ou 'champ'=>array(poids,min_long)
  76  global $INDEX_elements_associes;
  77  $INDEX_elements_associes = FALSE;
  78  if (isset($GLOBALS['meta']['INDEX_elements_associes']))
  79      $INDEX_elements_associes = unserialize($GLOBALS['meta']['INDEX_elements_associes']);
  80  if (!$INDEX_elements_associes){
  81      include_spip('inc/meta');
  82      $INDEX_elements_associes['spip_documents'] = array('titre'=>2,'descriptif'=>1);
  83      $INDEX_elements_associes['spip_auteurs'] = array('nom'=>1);
  84      $INDEX_elements_associes['spip_mots'] = array('titre'=>4,'descriptif'=>1);
  85      ecrire_meta('INDEX_elements_associes',serialize($INDEX_elements_associes));
  86      ecrire_metas();
  87      $reindex = true;
  88  }
  89  // Criteres d'indexation
  90  global $INDEX_critere_indexation;
  91  $INDEX_critere_indexation = FALSE;
  92  if (isset($GLOBALS['meta']['INDEX_critere_indexation']))
  93      $INDEX_critere_indexation = unserialize($GLOBALS['meta']['INDEX_critere_indexation']);
  94  if (!$INDEX_critere_indexation){
  95      include_spip('inc/meta');
  96      $INDEX_critere_indexation['spip_articles']="statut='publie'";
  97      $INDEX_critere_indexation['spip_breves']="statut='publie'";
  98      $INDEX_critere_indexation['spip_rubriques']="statut='publie'";
  99      $INDEX_critere_indexation['spip_syndic']="statut='publie'";
 100      $INDEX_critere_indexation['spip_forum']="statut='publie'";
 101      $INDEX_critere_indexation['spip_signatures']="statut='publie'";
 102      ecrire_meta('INDEX_critere_indexation',serialize($INDEX_critere_indexation));
 103      ecrire_metas();
 104      $reindex = true;
 105  }
 106  
 107  // Criteres de des-indexation (optimisation dans base/optimiser)
 108  global $INDEX_critere_optimisation;
 109  $INDEX_critere_optimisation = FALSE;
 110  if (isset($GLOBALS['meta']['INDEX_critere_optimisation']))
 111      $INDEX_critere_optimisation = unserialize($GLOBALS['meta']['INDEX_critere_optimisation']);
 112  if (!$INDEX_critere_optimisation) {
 113      include_spip('inc/meta');
 114      $INDEX_critere_optimisation['spip_articles']="statut<>'publie'";
 115      $INDEX_critere_optimisation['spip_breves']="statut<>'publie'";
 116      $INDEX_critere_optimisation['spip_rubriques']="statut<>'publie'";
 117      $INDEX_critere_optimisation['spip_syndic']="statut<>'publie'";
 118      $INDEX_critere_optimisation['spip_forum']="statut<>'publie'";
 119      $INDEX_critere_optimisation['spip_signatures']="statut<>'publie'";
 120      ecrire_meta('INDEX_critere_optimisation',serialize($INDEX_critere_optimisation));
 121      ecrire_metas();
 122      $reindex = true;
 123  }
 124  
 125  // Nombre d'elements maxi a indexer a chaque iteration
 126  global $INDEX_iteration_nb_maxi;
 127  $INDEX_iteration_nb_maxi = FALSE;
 128  if (isset($GLOBALS['meta']['INDEX_iteration_nb_maxi']))
 129      $INDEX_iteration_nb_maxi = unserialize($GLOBALS['meta']['INDEX_iteration_nb_maxi']);
 130  if (!$INDEX_iteration_nb_maxi) {
 131      include_spip('inc/meta');
 132      $INDEX_iteration_nb_maxi['spip_documents']=10;
 133      $INDEX_iteration_nb_maxi['spip_syndic']=1;
 134      ecrire_meta('INDEX_iteration_nb_maxi',serialize($INDEX_iteration_nb_maxi));
 135      ecrire_metas();
 136      $reindex = true;
 137  }
 138  if ($reindex) creer_liste_indexation();
 139  
 140  
 141  // Filtres d'indexation
 142  // http://doc.spip.org/@unserialize_join
 143  function unserialize_join($extra){
 144      return @join(' ', unserialize($extra));
 145  }
 146  // http://doc.spip.org/@contenu_page_accueil
 147  function contenu_page_accueil($url){
 148      $texte = '';
 149      if ($GLOBALS['meta']["visiter_sites"] == "oui") {
 150          include_spip('inc/distant');
 151          spip_log ("indexation contenu syndic $url");
 152          $texte = supprimer_tags(recuperer_page($url, true, false, 50000));
 153      }
 154      return $texte;
 155  }
 156  // http://doc.spip.org/@nettoie_nom_fichier
 157  function nettoie_nom_fichier($fichier){
 158      return preg_replace(',^(IMG/|.*://),', '', $fichier);
 159  }
 160  
 161  // Renvoie la liste des "mots" d'un texte (ou d'une requete adressee au moteur)
 162  // http://doc.spip.org/@mots_indexation
 163  function mots_indexation($texte, $min_long = 3) {
 164      include_spip('inc/charsets');
 165      include_spip('inc/texte');
 166  
 167      // Recuperer les parametres des modeles
 168      $texte = traiter_modeles($texte, true);
 169      
 170      // Supprimer les tags HTML
 171      $texte = preg_replace(',<.*>,Ums',' ',$texte);
 172  
 173      // Translitterer (supprimer les accents, recuperer les &eacute; etc)
 174      // la translitteration complexe (vietnamien, allemand) duplique
 175      // le texte, en mettant bout a bout une translitteration simple +
 176      // une translitteration riche
 177      if ($GLOBALS['translitteration_complexe'])
 178          $texte_c = ' '.translitteration_complexe ($texte, 'AUTO', true);
 179      else
 180          $texte_c = '';
 181      $texte = translitteration($texte);
 182      if($texte!=trim($texte_c)) $texte .= $texte_c;
 183      # NB. tous les caracteres non translitteres sont retournes en utf-8
 184  
 185      // OPTIONNEL //  Gestion du tiret '-' :
 186      // "vice-president" => "vice"+"president"+"vicepresident"
 187  #    $texte = preg_replace(',(\w+)-(\w+),', '\1 \2 \1\2', $texte);
 188  
 189      // Supprimer les caracteres de ponctuation, les guillemets...
 190      $e = "],:;*\"!\r\n\t\\/)}{[|@<>$%'`?\~.^(";
 191      $texte = strtr($texte, $e, ereg_replace('.', ' ', $e));
 192  
 193      //delete  +\- not at the beginning of a word
 194      $texte = preg_replace(",(?:\S)[\-+],"," ",$texte);
 195      // Cas particulier : sigles d'au moins deux lettres
 196      $texte = preg_replace("/ ([A-Z][0-9A-Z]{1,".($min_long - 1)."}) /",
 197          ' \\1___ ', $texte.' ');
 198  
 199      // Tout passer en bas de casse
 200      $texte = strtolower($texte);
 201  
 202      // Retourner sous forme de table
 203      return pipeline('mots_indexation',array('args'=>array('min_long'=>$min_long),'data'=>preg_split("/ +/", trim($texte))));
 204  }
 205  
 206  // http://doc.spip.org/@indexer_chaine
 207  function indexer_chaine($texte, $val = 1, $min_long = 3) {
 208      global $index, $mots;
 209      global $translitteration_complexe;
 210  
 211      // Point d'entree pour traiter le texte avant indexation 
 212      $texte = pipeline('pre_indexation', $texte);
 213  
 214      $table = mots_indexation($texte, $min_long);
 215  
 216      foreach ($table as $mot) {
 217          if (strlen($mot) > $min_long) {
 218              $h = substr(md5($mot), 0, 16);
 219              if (!isset($index[$h]))
 220                  $index[$h] = 0;
 221              $index[$h] += $val/(1+$translitteration_complexe);
 222              $mots .= ",(0x$h,'$mot')";
 223          }
 224      }
 225  }
 226  
 227  // id_table = 1...9 pour les tables spip, et ensuite 100, 101, 102...
 228  // pour les tables additionnelles, selon l'ordre dans lequel
 229  // elles sont reperees. On stocke le tableau de conversion table->id_table
 230  // dans spip_meta
 231  // http://doc.spip.org/@update_index_tables
 232  function update_index_tables(){
 233      global $tables_principales;
 234      global $INDEX_tables_interdites;
 235      
 236      $old_liste_tables = liste_index_tables();
 237      $rev_old_liste_tables = array_flip($old_liste_tables);
 238  
 239      $liste_tables = array();
 240      // les tables SPIP conventionnelles en priorite
 241      $liste_tables[1]='spip_articles';
 242      $liste_tables[2]='spip_auteurs';
 243      $liste_tables[3]='spip_breves';
 244      $liste_tables[4]='spip_documents';
 245      $liste_tables[5]='spip_forum';
 246      $liste_tables[6]='spip_mots';
 247      $liste_tables[7]='spip_rubriques';
 248      $liste_tables[8]='spip_signatures';
 249      $liste_tables[9]='spip_syndic';
 250  
 251      // detection des nouvelles tables
 252      $id_autres = 100;
 253      foreach(array_keys($tables_principales) as $new_table){
 254          if (    (!in_array($new_table,$INDEX_tables_interdites))
 255                  &&(!in_array($new_table,$liste_tables))
 256                  &&($id_autres<254) ){
 257              // on utilise abstract_showtable car cela permet d'activer l'indexation
 258              // en ajoutant simplement le champ idx, sans toucher au core
 259              $desc = spip_abstract_showtable($new_table, '', true);
 260              if (isset($desc['field']['idx'])){
 261                // la table a un champ idx pour gerer l'indexation
 262                if (     (isset($rev_old_liste_tables[$new_table]))
 263                          &&(!isset($liste_tables[$rev_old_liste_tables[$new_table]])) )
 264                        $liste_tables[$rev_old_liste_tables[$new_table]] = $new_table; // id conserve
 265                  else{
 266                      while (isset($liste_tables[$id_autres])&&($id_autres<254)) $id_autres++;
 267                      $liste_tables[$id_autres] = $new_table;
 268                  }
 269              }
 270          }
 271      }
 272  
 273      // Cas de l'ajout d'une nouvelle table a indexer :
 274      // mise en coherence de la table d'indexation avec les nouveaux id
 275      $rev_old_liste_tables = array_flip($old_liste_tables);
 276      foreach($liste_tables as $new_id=>$new_table){
 277          if (isset($rev_old_liste_tables[$new_table])){
 278            if (    ($old_id = ($rev_old_liste_tables[$new_table]))
 279                      &&($old_id!=$new_id)){
 280                  $temp_id = 254;
 281                  // liberer le nouvel id
 282                  spip_query("UPDATE spip_index SET id_table='$temp_id' WHERE id_table='$new_id'");
 283                  // deplacer les indexation de l'ancien id sous le nouvel id
 284                  spip_query("UPDATE spip_index SET id_table='$new_id' WHERE id_table='$old_id'");
 285                  // remettre les indexation deplacees sous l'id qui vient d'etre libere
 286                  spip_query("UPDATE spip_index SET id_table='$old_id' WHERE id_table='$temp_id'");
 287      
 288                  $old_liste_tables[$old_id] = $old_liste_tables[$new_id]; 
 289                  unset($old_liste_tables[$new_id]);
 290                  $rev_old_liste_tables = array_flip($old_liste_tables);
 291              }
 292          }
 293      } 
 294  
 295      ecrire_meta('index_table',serialize($liste_tables));
 296      ecrire_metas();
 297  }
 298  
 299  // http://doc.spip.org/@liste_index_tables
 300  function liste_index_tables() {
 301      $liste_tables = array();
 302      if (!isset($GLOBALS['meta']['index_table'])) {
 303          include_spip('inc/meta');
 304          lire_metas();
 305      }
 306      if (isset($GLOBALS['meta']['index_table']))
 307          $liste_tables = unserialize($GLOBALS['meta']['index_table']);
 308      return $liste_tables;
 309  }
 310  
 311  // http://doc.spip.org/@id_index_table
 312  function id_index_table($table){
 313      /*global $table_des_tables;
 314      $t = $table_des_tables[$table];
 315      // pour les tables non Spip
 316      if (!$t) $t = $table; else $t = "spip_$t";*/
 317      $t = $table;
 318      $id_table = 0;
 319      $l = liste_index_tables();
 320      $l = @array_flip($l);
 321      if (isset($l[$t]))
 322          $id_table=$l[$t];
 323      return $id_table;
 324  }
 325  
 326  // http://doc.spip.org/@primary_index_table
 327  function primary_index_table($table){
 328      global $tables_principales;
 329      /*global $table_des_tables;
 330      $t = $table_des_tables[$table];
 331      // pour les tables non Spip
 332      if (!$t) $t = $table; else $t = "spip_$t";*/
 333      $t = $table;
 334      $p = $tables_principales["$t"]['key']["PRIMARY KEY"];
 335      if (!$p){
 336          $p = preg_replace("{^spip_}","",$table);
 337          $p = "id_" . $p;
 338          if (substr($p,-1,1)=='s')
 339            $p = substr($p,0,strlen($p)-1);
 340      }
 341      return $p;
 342  }
 343  
 344  // http://doc.spip.org/@deja_indexe
 345  function deja_indexe($table, $id_objet) {
 346      $table_index = 'spip_index';
 347      $id_table = id_index_table($table);
 348      $n = @spip_num_rows(@spip_query("SELECT id_objet FROM $table_index WHERE id_objet=$id_objet AND id_table=$id_table LIMIT 1"));
 349      return ($n > 0);
 350  }
 351  
 352  // Extracteur des documents 'txt'
 353  // http://doc.spip.org/@extracteur_txt
 354  function extracteur_txt($fichier, &$charset) {
 355      lire_fichier($fichier, $contenu);
 356  
 357      // Reconnaitre le BOM utf-8 (0xEFBBBF)
 358      include_spip('inc/charsets');
 359      if (bom_utf8($contenu))
 360          $charset = 'utf-8';
 361  
 362      return $contenu;
 363  }
 364  
 365  // Extracteur des documents 'html'
 366  // http://doc.spip.org/@extracteur_html
 367  function extracteur_html($fichier, &$charset) {
 368      lire_fichier($fichier, $contenu);
 369  
 370      // Importer dans le charset local
 371      include_spip('inc/charsets');
 372      $contenu = transcoder_page($contenu);
 373      $charset = $GLOBALS['meta']['charset'];
 374  
 375      return $contenu;
 376  }
 377  
 378  
 379  
 380  // Indexer le contenu d'un document
 381  // http://doc.spip.org/@indexer_contenu_document
 382  function indexer_contenu_document ($row, $min_long=3) {
 383      global $extracteur;
 384  
 385      if ($row['mode'] == 'vignette') return;
 386      $extension = spip_fetch_array(spip_query("SELECT extension FROM spip_types_documents WHERE id_type = ".$row['id_type']));
 387      $extension = $extension['extension'];
 388  
 389      // Voir si on sait lire le contenu (eventuellement en chargeant le
 390      // fichier extract/pdf.php dans find_in_path() )
 391      include_spip('extract/'.$extension);
 392      if (function_exists($lire = $extracteur[$extension])) {
 393          // Voir si on a deja une copie du doc distant
 394          // Note: si copie_locale() charge le doc, elle demande une reindexation
 395          include_spip('inc/distant');
 396          if (!$fichier = copie_locale($row['fichier'], 'test')) {
 397              spip_log("pas de copie locale de '$fichier'");
 398              return;
 399          }
 400          // par defaut, on pense que l'extracteur va retourner ce charset
 401          $charset = 'iso-8859-1'; 
 402          // lire le contenu
 403          $contenu = $lire(_DIR_RACINE.$fichier, $charset);
 404          if (!$contenu) {
 405              spip_log("Echec de l'extraction de '$fichier'");
 406          } else {
 407              // Ne retenir que les 50 premiers ko
 408              $contenu = substr($contenu, 0, 50000);
 409              // importer le charset
 410              $contenu = importer_charset($contenu, $charset);
 411              // Indexer le texte
 412              indexer_chaine($contenu, 1, $min_long);
 413          }
 414      } else {
 415          spip_log("pas d'extracteur '$extension' fonctionnel");
 416      }
 417  }
 418  
 419  
 420  
 421  // http://doc.spip.org/@indexer_les_champs
 422  function indexer_les_champs(&$row,&$index_desc,$ponderation = 1, $min_long=3){
 423      reset($index_desc);
 424      while (list($quoi,$poids) = each($index_desc)){
 425          $pipe=array();
 426          if (strpos($quoi,"|")){
 427              $pipe = explode("|",$quoi);
 428              $quoi = array_shift($pipe);
 429          }
 430          if (isset($row[$quoi])){
 431              $texte = $row[$quoi];
 432              if (count($pipe)){
 433                  foreach ($pipe as $func){
 434                      $func = trim($func);
 435                      if (!function_exists($func)) {
 436                          spip_log("Erreur - $func n'est pas definie (indexation)");
 437                      }
 438                      else
 439                          // appliquer le filtre
 440                          $texte = $func($texte);
 441                  }
 442              }
 443              //spip_log(":$quoi:$poids:$texte");
 444              if (is_array($poids))
 445                  indexer_chaine($texte,array_shift($poids) * $ponderation,array_shift($poids));
 446              else
 447                  indexer_chaine($texte,$poids * $ponderation, $min_long);
 448          }
 449      }
 450  }
 451  
 452  // Indexer les documents, auteurs, mots-cles associes a l'objet
 453  // http://doc.spip.org/@indexer_elements_associes
 454  function indexer_elements_associes($table, $id_objet, $table_associe, $valeur, $min_long=3) {
 455      global $INDEX_elements_associes, $tables_jointures, $tables_auxiliaires, $tables_principales;
 456  
 457      if (isset($INDEX_elements_associes[$table_associe])){
 458          $table_abreg = preg_replace("{^spip_}","",$table);
 459          $col_id = primary_index_table($table);
 460          $col_id_as = primary_index_table($table_associe);
 461          if (is_array($rel = $tables_jointures[$table])) {
 462              foreach($rel as $joint) {
 463                  if (@in_array($col_id_as, @array_keys($tables_auxiliaires['spip_' . $joint]['field'])))
 464                      {$table_rel = $joint; break;}
 465                  if (@in_array($col_id_as, @array_keys($tables_principales['spip_' . $joint]['field'])))
 466                      {$table_rel = $joint; break;}
 467              }
 468              if (!$table_rel){
 469                  spip_log("Indexation de $table echouee : element associe $table_associe, jointure sur $col_id_as introuvable");
 470                  return;
 471              }
 472  
 473              $select="assoc.$col_id_as";
 474              foreach(array_keys($INDEX_elements_associes[$table_associe]) as $quoi)
 475                  $select.=',assoc.' . $quoi;
 476              $r = spip_query("SELECT $select FROM $table_associe AS assoc,    spip_$table_rel AS lien    WHERE lien.$col_id=$id_objet AND assoc.$col_id_as=lien.$col_id_as");
 477  
 478              while ($row = spip_fetch_array($r)) {
 479                  indexer_les_champs($row,$INDEX_elements_associes[$table_associe],$valeur);
 480              }
 481          }
 482       }
 483  }
 484  
 485  // http://doc.spip.org/@indexer_objet
 486  function indexer_objet($table, $id_objet, $forcer_reset = true) {
 487      global $index, $mots, $translitteration_complexe;
 488      global $INDEX_elements_objet;
 489      global $INDEX_objet_associes;
 490  
 491      $min_long = isset($GLOBALS['INDEX_mots_min_long'])?intval($GLOBALS['INDEX_mots_min_long']):3;
 492  
 493      $table_index = 'spip_index';
 494      $col_id = primary_index_table($table);
 495      $id_table = id_index_table($table);
 496  
 497      if (!$id_objet) return;
 498      if (!$forcer_reset AND deja_indexe($table, $id_objet)) {
 499          spip_log ("$table $id_objet deja indexe");
 500          spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet");
 501          return;
 502      }
 503      // marquer "en cours d'indexation"
 504      spip_query("UPDATE $table SET idx='idx' WHERE $col_id=$id_objet");
 505  
 506      include_spip('inc/texte');
 507  
 508      spip_log("indexation $table $id_objet");
 509      $index = '';
 510      $mots = '';
 511  
 512      $result = spip_query("SELECT * FROM $table WHERE $col_id=$id_objet");
 513  
 514      $row = spip_fetch_array($result);
 515  
 516      if (!$row) return;
 517  
 518      // translitteration complexe ?
 519      if (!$lang = $row['lang']) $lang = $GLOBALS['meta']['langue_site'];
 520      if ($lang == 'de' OR $lang=='vi') {
 521          $translitteration_complexe = 1;
 522          spip_log ('-> translitteration complexe');
 523      } else $translitteration_complexe = 0;
 524  
 525      if (isset($INDEX_elements_objet[$table])){
 526  
 527          // Cas tres particulier du forum :
 528          // on indexe le thread comme un tout
 529          if ($table=='spip_forum') {
 530  
 531              // 1. chercher la racine du thread
 532              $id_forum = $id_objet;
 533              while ($row['id_parent']) {
 534                  $id_forum = $row['id_parent'];
 535                  $s = spip_query("SELECT id_forum,id_parent FROM spip_forum WHERE id_forum=$id_forum");
 536                  $row = spip_fetch_array($s);
 537              }
 538  
 539              // 2. chercher tous les forums du thread
 540              // (attention le forum de depart $id_objet n'appartient pas forcement
 541              // a son propre thread car il peut etre le fils d'un forum non 'publie')
 542              $thread="$id_forum";
 543              $fini = false;
 544              while (!$fini) {
 545                  $s = spip_query("SELECT id_forum FROM spip_forum WHERE id_parent IN ($thread) AND id_forum NOT IN ($thread) AND statut='publie'");
 546                  if (spip_num_rows($s) == 0) $fini = true;
 547                  while ($t = spip_fetch_array($s))
 548                      $thread.=','.$t['id_forum'];
 549              }
 550  
 551              // 3. marquer le thread comme "en cours d'indexation"
 552              spip_log("-> indexation thread $thread");
 553              spip_query("UPDATE spip_forum SET idx='idx' WHERE id_forum IN ($thread,$id_objet) AND idx!='non'");
 554  
 555              // 4. Indexer le thread
 556              $s = spip_query("SELECT * FROM spip_forum WHERE id_forum IN ($thread) AND idx!='non'");
 557              while ($row = spip_fetch_array($s)) {
 558              indexer_les_champs($row,$INDEX_elements_objet[$table],1,$min_long);
 559              if (isset($INDEX_objet_associes[$table]))
 560                foreach($INDEX_objet_associes[$table] as $quoi=>$poids)
 561                          indexer_elements_associes($table, $id_objet, $quoi, $poids, $min_long);
 562                  break;
 563              }
 564  
 565              // 5. marquer le thread comme "indexe"
 566              spip_query("UPDATE spip_forum SET idx='oui' WHERE id_forum IN ($thread,$id_objet) AND idx!='non'");
 567  
 568              // 6. Changer l'id_objet en id_forum de la racine du thread
 569              $id_objet = $id_forum;
 570          } else {
 571              indexer_les_champs($row,$INDEX_elements_objet[$table],1,$min_long);
 572              if (isset($INDEX_objet_associes[$table]))
 573                  foreach($INDEX_objet_associes[$table] as $quoi=>$poids)
 574                      indexer_elements_associes($table, $id_objet, $quoi, $poids, $min_long);
 575  
 576              if ($table=='spip_syndic'){
 577                  // 2. Indexer les articles syndiques
 578                  if (($row['syndication'] = "oui")&&(isset($INDEX_elements_objet['syndic_articles']))) {
 579                      $result_syndic = spip_query("SELECT titre FROM spip_syndic_articles WHERE id_syndic=$id_objet AND statut='publie' ORDER BY date DESC LIMIT 100");
 580  
 581                      while ($row_syndic = spip_fetch_array($result_syndic)) {
 582                      indexer_les_champs($row,$INDEX_elements_objet['syndic_articles'],1,$min_long);
 583                      }
 584                  }
 585              }
 586              if ($table=='spip_documents'){
 587                  // 2. Indexer le contenu si on sait le lire
 588                  indexer_contenu_document($row,$min_long);
 589              }
 590           }
 591      } else
 592          spip_log("je ne sais pas indexer '$table'");
 593  
 594      $result = spip_query("DELETE FROM $table_index WHERE id_objet=$id_objet AND id_table=$id_table");
 595  
 596      if ($index) {
 597          if ($mots) {
 598      // supprimer la virgule du debut
 599              spip_query("INSERT IGNORE INTO spip_index_dico (hash, dico) VALUES ".substr($mots,1));
 600  
 601          }
 602          reset($index);
 603          while (list($hash, $points) = each($index)) {
 604            spip_query("INSERT INTO $table_index (hash, points, id_objet, id_table) VALUES (0x$hash,".ceil($points).",$id_objet,$id_table)");
 605          }
 606      }
 607  
 608      // marquer "indexe"
 609      spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet");
 610  }
 611  
 612  /*
 613      Valeurs du champ 'idx' de la table spip_objet(s)
 614      '' ne sait pas
 615      '1' ˆ (re)indexer
 616      'oui' deja indexe
 617      'idx' en cours
 618      'non' ne jamais indexer
 619  */
 620  
 621  // API pour l'espace prive pour marquer un objet d'une table a reindexer
 622  // http://doc.spip.org/@marquer_indexer
 623  function marquer_indexer ($table, $id_objet) {
 624      spip_log ("demande indexation $table id=$id_objet");
 625      $id = primary_index_table($table);
 626      spip_query("UPDATE $table SET idx='1' WHERE $id=$id_objet AND idx!='non'");
 627  }
 628  
 629  // A garder pour compatibilite bouton memo...
 630  // http://doc.spip.org/@indexer_article
 631  function indexer_article($id_article) {
 632      marquer_indexer('spip_articles', $id_article);
 633  }
 634  
 635  // n'indexer que les objets publies
 636  // http://doc.spip.org/@critere_indexation
 637  function critere_indexation($table) {
 638      global $INDEX_critere_indexation;
 639      if (isset($INDEX_critere_indexation[$table]))
 640        return $INDEX_critere_indexation[$table];
 641      else
 642        return '1=1'; // indexation par defaut
 643  }
 644  
 645  // ne desindexer que les objets non-publies
 646  // http://doc.spip.org/@critere_optimisation
 647  function critere_optimisation($table) {
 648      global $INDEX_critere_optimisation;
 649      if (isset($INDEX_critere_optimisation[$table]))
 650        return $INDEX_critere_optimisation[$table];
 651      else
 652        return '1=0';  // pas de indexation par defaut
 653  }
 654  
 655  
 656  // http://doc.spip.org/@effectuer_une_indexation
 657  function effectuer_une_indexation($nombre_indexations = 1) {
 658      global $INDEX_iteration_nb_maxi;
 659      $vu = array();
 660  
 661      // chercher un objet a indexer dans chacune des tables d'objets
 662      foreach (liste_index_tables() as $table) {
 663  
 664          $table_primary = primary_index_table($table);
 665          $critere = critere_indexation($table);
 666  
 667          $limit = $nombre_indexations;
 668          if (isset($INDEX_iteration_nb_maxi[$table]))
 669              $limit = min($limit,$INDEX_iteration_nb_maxi[$table]);
 670  
 671          // indexer en priorite les '1' (a reindexer), ensuite les ''
 672          // (statut d'indexation inconnu), enfin les 'idx' (ceux dont
 673          // l'indexation a precedemment echoue, p. ex. a cause d'un timeout)
 674          foreach (array('1', '', 'idx') as $mode) {
 675              $s = spip_query("SELECT $table_primary AS id FROM $table WHERE idx='$mode' AND $critere LIMIT $limit");
 676              while ($t = spip_fetch_array($s)) {
 677                  $vu[$table] .= $t['id'].", ";
 678                  indexer_objet($table, $t['id'], $mode);
 679              }
 680              if ($vu[$table]) break;
 681          }
 682      }
 683      return $vu;
 684  }
 685  
 686  // http://doc.spip.org/@executer_une_indexation_syndic
 687  function executer_une_indexation_syndic() {
 688      $id_syndic = 0;
 689      $row = spip_fetch_array(spip_query("SELECT id_syndic FROM spip_syndic WHERE statut='publie' AND date_index < DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY date_index LIMIT 1"));
 690      if ($row) {
 691          $id_syndic = $row['id_syndic'];
 692          spip_query("UPDATE spip_syndic SET date_index=NOW() WHERE id_syndic=$id_syndic");
 693          marquer_indexer('spip_syndic', $id_syndic);
 694      }
 695      return $id_syndic;
 696  }
 697  
 698  // http://doc.spip.org/@creer_liste_indexation
 699  function creer_liste_indexation() {
 700      foreach (liste_index_tables() as $table)
 701          spip_query("UPDATE $table SET idx='1' WHERE idx!='non'");
 702  }
 703  
 704  // http://doc.spip.org/@purger_index
 705  function purger_index() {
 706          spip_query("DELETE FROM spip_index");
 707          spip_query("DELETE FROM spip_index_dico");
 708  }
 709  
 710  // cree la requete pour une recherche en txt integral
 711  // http://doc.spip.org/@requete_txt_integral
 712  function requete_txt_integral($table, $hash_recherche) {
 713      $index_table = "spip_index";
 714      $id_objet = primary_index_table($table);
 715      $id_table = id_index_table($table);
 716      return array(
 717               'SELECT' => "objet.*, SUM(rec.points) AS points",
 718               'FROM' => "$table AS objet, $index_table AS rec",
 719               'WHERE' => "objet.$id_objet = rec.id_objet
 720  AND rec.hash IN ($hash_recherche)
 721  AND rec.id_table = $id_table",
 722               'GROUP BY' => "objet.$id_objet",
 723               'ORDER BY' => "points DESC",
 724               'LIMIT' => "10");
 725  }
 726  
 727  // rechercher un mot dans le dico
 728  // retourne deux methodes : lache puis strict
 729  // http://doc.spip.org/@requete_dico
 730  function requete_dico($val, $min_long = 3) {
 731      
 732      preg_match(",^([+\-]?)(.*),",$val,$mod);
 733      switch($mod[1]) {
 734          case '':
 735              $mode = "OR";
 736              break;
 737          case '+':
 738              $mode = "AND";
 739              break;
 740          case '-':
 741              $mode = "NOT";
 742              break;
 743      }
 744      //set logical operator between the various where parts
 745      $val = $mod[2];
 746      // cas normal
 747      $res = array();
 748      if (strlen($val) > $min_long)
 749        $res = array("dico LIKE "._q($val. "%"), "dico = " . _q($val),$mode);
 750      else
 751          $res = array("dico = "._q($val."___"), "dico = "._q($val."___"),$mode);
 752      return pipeline('requete_dico',array('args'=>array('val'=>$val,'min_long'=>$min_long),'data'=>$res));
 753  }
 754  
 755  
 756  // decode la chaine recherchee et la traduit en hash
 757  // http://doc.spip.org/@requete_hash
 758  function requete_hash ($rech) {
 759      $min_long = isset($GLOBALS['INDEX_mots_min_long'])?intval($GLOBALS['INDEX_mots_min_long']):3;
 760  
 761      // recupere les mots de la recherche
 762      $GLOBALS['translitteration_complexe'] = true;
 763      $s = mots_indexation($rech,$min_long);
 764      unset($dico);
 765      unset($h);
 766      
 767      // cherche les mots dans le dico
 768      while (list(, $val) = each($s)) {
 769          list($rq, $rq_strict,$mode) = requete_dico ($val,$min_long);
 770          if ($rq)
 771              $dico[$mode][$val] = $rq;
 772          if ($rq_strict)
 773              $dico_strict[$mode][$val] = $rq_strict;
 774      }
 775      
 776      // Attention en MySQL 3.x il faut passer par HEX(hash)
 777      // alors qu'en MySQL 4.1 c'est interdit !
 778      $vers = spip_query("SELECT VERSION() AS v");
 779      $vers = spip_fetch_array($vers);
 780      if (($vers['v']{0} == 4 AND $vers['v']{2} >= 1)
 781          OR $vers['v']{0} > 4) {
 782          $hex_fmt = '';
 783          $select_hash = 'hash AS h';
 784      } else {
 785          $hex_fmt = '0x';
 786          $select_hash = 'HEX(hash) AS h';
 787      }
 788  
 789      // compose la recherche dans l'index
 790      $cond = "";
 791      if ($dico_strict["OR"]) $cond = join(" OR ", $dico_strict["OR"]);
 792          
 793      if ($cond) {    
 794          $result2 = spip_query("SELECT $select_hash FROM spip_index_dico WHERE ".$cond);
 795  
 796          while ($row2 = spip_fetch_array($result2))
 797              $h_strict[] = $hex_fmt.$row2['h'];
 798      }
 799  
 800      $cond = "";
 801      if ($dico_strict["AND"])    $cond = join(" OR ", $dico_strict["AND"]);
 802      if ($cond) {    
 803          $result2 = spip_query("SELECT $select_hash FROM spip_index_dico WHERE ".$cond);
 804  
 805          while ($row2 = spip_fetch_array($result2))
 806              $h_strict_and[] = $hex_fmt.$row2['h'];
 807          
 808      }
 809  
 810      $cond = "";
 811      if ($dico["OR"]) $cond = join(" OR ", $dico["OR"]);
 812      if ($cond) {    
 813          $result2 = spip_query("SELECT $select_hash FROM spip_index_dico WHERE ".$cond);
 814  
 815          while ($row2 = spip_fetch_array($result2))
 816              $h[] = $hex_fmt.$row2['h'];
 817      }
 818      
 819      
 820      $cond = "";
 821      if ($dico["AND"])    $cond = join(" OR ", $dico["AND"]);
 822      if ($cond) {    
 823          $result2 = spip_query("SELECT $select_hash,dico FROM spip_index_dico WHERE ".$cond);
 824  
 825          while ($row2 = spip_fetch_array($result2)) {
 826              //store the condition that selected the hash (the word typed by the user)  
 827              foreach($dico["AND"] as $key=>$val) {
 828                  $mot_and = substr($key,1);
 829                  if(strpos($row2['dico'],$mot_and)===0) 
 830                      $h_and[$mot_and][] = $hex_fmt.$row2['h'];
 831              }
 832          }
 833          //store hash 0 for words without any hashes
 834          foreach($dico["AND"] as $key=>$val) {
 835              $mot_and = substr($key,1);
 836              if(!$h_and[$mot_and]) $h_and[$mot_and][] = 0;
 837          }
 838      }
 839          
 840      $cond = "";
 841      if ($dico["NOT"]) $cond = join(" OR ", $dico["NOT"]);
 842          
 843      if ($cond) {    
 844          $result2 = spip_query("SELECT $select_hash FROM spip_index_dico WHERE ".$cond);
 845  
 846          while ($row2 = spip_fetch_array($result2))
 847              $h_not[] = $hex_fmt.$row2['h'];
 848      }
 849      
 850      if ($h_strict)
 851          $hash_recherche_strict = join(",", $h_strict);
 852      else
 853          $hash_recherche_strict = "0";
 854          
 855      if ($h_strict_and)
 856          $hash_recherche_strict_and = join(",", $h_strict_and);
 857      else
 858          $hash_recherche_strict_and = "0";
 859  
 860      if ($h)
 861          $hash_recherche = join(",", $h);
 862      else
 863          $hash_recherche = "0";
 864  
 865      if ($h_and) { 
 866          foreach($h_and as $key=>$val)
 867              $hash_recherche_and[$key] = join(",", $h_and[$key]);
 868      } else
 869          $hash_recherche_and = "0";
 870  
 871      if ($h_not) 
 872          $hash_recherche_not = join(",", $h_not);
 873      else
 874          $hash_recherche_not = "0";
 875  
 876      return array($hash_recherche, $hash_recherche_strict, $hash_recherche_not, $hash_recherche_and, $hash_recherche_strict_and);
 877  }
 878  
 879  //
 880  // Preparer les elements pour le critere {recherche}
 881  // Note : si le critere est optionnel {recherche?}, ne pas s'activer
 882  // si la recherche est vide
 883  //
 884  // http://doc.spip.org/@prepare_recherche
 885  function prepare_recherche($recherche, $primary = 'id_article', $id_table='articles',$nom_table='spip_articles', $cond=false) {
 886      static $cache = array();
 887      static $fcache = array();
 888      // traiter le cas {recherche?}
 889      if ($cond AND !strlen($recherche))
 890          return array("''" /* as points */, /* where */ '1');
 891  
 892      // Premier passage : chercher eventuel un cache des donnees sur le disque
 893      if (!$cache[$recherche]['hash']) {
 894          $dircache = sous_repertoire(_DIR_CACHE,'rech');
 895          $fcache[$recherche] =
 896              $dircache . substr(md5($recherche),0,10).'.txt';
 897          if (lire_fichier($fcache[$recherche], $contenu))
 898              $cache[$recherche] = @unserialize($contenu);
 899      }
 900  
 901      // si on n'a pas encore traite les donnees dans une boucle precedente
 902      if (!$cache[$recherche][$primary]) {
 903          if (!$cache[$recherche]['hash'])
 904              $cache[$recherche]['hash'] = requete_hash($recherche);
 905          list($hash_recherche, $hash_recherche_strict, $hash_recherche_not, $hash_recherche_and, $hash_recherche_strict_and)
 906              = $cache[$recherche]['hash'];
 907  
 908          $strict = array();
 909          if ($hash_recherche_strict)
 910              foreach (split(',',$hash_recherche_strict) as $h)
 911                  $strict[$h] = 99;
 912          
 913          if ($hash_recherche_strict_and)
 914              foreach (split(',',$hash_recherche_strict_and) as $h)
 915                  $strict[$h] = 99;
 916  
 917          $index_id_table = id_index_table($nom_table);
 918          $points = array();
 919          
 920          $objet_and = array();
 921          $object_not = array();
 922          if($hash_recherche_and) {
 923              //$hash_recherche_and is an array of mots=>comma separated hashes
 924              $list_hashes = join(",",$hash_recherche_and);
 925              $pow = 1;
 926              foreach($hash_recherche_and as $key=>$val) {
 927                  $hash_groupes[] = "$pow*".calcul_mysql_in("hash",$val);
 928                  $pow *= 2; 
 929              }
 930              $count_groupes = join(" + ",$hash_groupes);
 931              
 932              $s = spip_query("SELECT id_objet as id,COUNT(DISTINCT $count_groupes) as count_groupes FROM spip_index WHERE id_table='$index_id_table' AND hash IN ($list_hashes) GROUP BY id HAVING count_groupes=".count($hash_recherche_and));
 933              //if no ids are found, pass at least id = 0 in order to exclude any result
 934              $objet_and[] = 0;
 935              while ($r = spip_fetch_array($s)) 
 936                  $objet_and[]=$r['id'];
 937          }
 938          if($hash_recherche_not) {
 939              $s = spip_query("SELECT DISTINCT id_objet as id FROM spip_index WHERE hash IN ($hash_recherche_not) AND id_table='$index_id_table'");
 940              while ($r = spip_fetch_array($s))
 941                  $objet_not[]=$r['id'];                                                        
 942          }
 943          if(count($objet_and))
 944              $list_and = " AND id_objet IN (".join(",",$objet_and).")";
 945          if(count($objet_not))
 946              $list_not = " AND id_objet NOT  IN (".join(",",$objet_not).")";
 947          if($hash_recherche) {
 948              $list_hash = " AND hash IN (".$hash_recherche.")";
 949          }
 950          
 951          if($list_hash || $list_and || $list_not) {
 952              $query = "SELECT hash,points,id_objet as id FROM spip_index WHERE id_table='$index_id_table'".$list_and.$list_not.$list_hash;  
 953              
 954              $s = spip_query($query);
 955                  
 956              while ($r = spip_fetch_array($s))
 957                  $points[$r['id']]
 958                  += (1 + $strict[$r['hash']]) * $r['points'];
 959              spip_free_result($s);
 960              arsort($points, SORT_NUMERIC);
 961          }
 962  
 963          # calculer le {id_article IN()} et le {... as points}
 964          if (!count($points)) {
 965              $cache[$recherche][$primary] = array("''", 0);
 966          } else {
 967              $ids = array();
 968              $select = '0';
 969              foreach ($points as $id => $p)
 970                  $listes_ids[$p] .= ','.$id;
 971              foreach ($listes_ids as $p => $liste_ids)
 972                  $select .= "+$p*(".
 973                      calcul_mysql_in("$id_table.$primary", substr($liste_ids, 1))
 974                      .") ";
 975  
 976              $cache[$recherche][$primary] = array($select,
 977                  '('.calcul_mysql_in("$id_table.$primary",
 978                      join(',',array_keys($points))).')'
 979                  );
 980          }
 981  
 982          // ecrire le cache de la recherche sur le disque
 983          ecrire_fichier($fcache[$recherche], serialize($cache[$recherche]));
 984          // purger le petit cache
 985          nettoyer_petit_cache('rech', 300);
 986      }
 987      return $cache[$recherche][$primary];
 988  }
 989  
 990  
 991  // http://doc.spip.org/@cron_indexation
 992  function cron_indexation($t) {
 993      $c = count(effectuer_une_indexation());
 994      // si des indexations ont ete effectuees, on passe la periode a 0 s
 995      ## note : (time() - 90) correspond en fait a :
 996      ## time() - $taches_generales['indexation']
 997      if ($c)
 998          return (0 - (time() - 90));
 999      else
1000          return 0;
1001  }
1002  
1003  
1004  // Si la liste des correspondances tables/id_table n'est pas la, la creer
1005  if ((isset($GLOBALS['meta']))&&(!isset($GLOBALS['meta']['index_table'])))
1006      update_index_tables();
1007  
1008  ?>


Généré le : Wed Nov 21 10:20:27 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics