| [ Index ] |
|
Code source de SPIP 1.9.2c |
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 é 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 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 10:20:27 2007 | par Balluche grâce à PHPXref 0.7 |
|