Rev 609 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/***************************************************************************\* SPIP, Systeme de publication pour l'internet ** ** Copyright (c) 2001-2005 ** Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James ** ** Ce programme est un logiciel libre distribue sous licence GNU/GPL. ** Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *\***************************************************************************///// Ce fichier ne sera execute qu'une foisif (defined("_ECRIRE_INC_INDEX")) return;define("_ECRIRE_INC_INDEX", "1");function separateurs_indexation($requete = false) {// Merci a Herve Lefebvre pour son apport sur cette fonction$liste = "],:;*\"!\r\n\t\\/)}{[|@<>$%";// pour autoriser les recherches en vietnamien,// ne pas eliminer les accents de translitterationif (!$requete)$liste .= "'`?\~.^+(-";// windowzeries iso-8859-1$charset = lire_meta('charset');if ($charset == 'iso-8859-1')$liste .= chr(187).chr(171).chr(133).chr(145).chr(146).chr(180).chr(147).chr(148);return $liste;}function nettoyer_chaine_indexation($texte) {global $translitteration_complexe;include_ecrire("inc_charsets.php3");// translitteration complexe (vietnamien, allemand)if ($translitteration_complexe) {$texte_c = translitteration_complexe ($texte);$texte_c = " ".strtr($texte_c, "'`?~.^+(-", "123456789");}$texte = translitteration($texte).$texte_c;return $texte;}function indexer_chaine($texte, $val = 1, $min_long = 3) {global $index, $mots, $translitteration_complexe;// Nettoyer les tags, entites HTML, signes diacritiques...$texte = ' '.ereg_replace("<[^>]*>"," ",$texte).' ';$texte = nettoyer_chaine_indexation($texte);// Nettoyer les caracteres non-alphanumeriques$regs = separateurs_indexation();$texte = strtr($texte, $regs, ereg_replace('.', ' ', $regs));// Cas particulier : sigles d'au moins deux lettres$texte = ereg_replace(" ([A-Z][0-9A-Z]{1,".($min_long - 1)."}) ", ' \\1___ ', $texte);$texte = strtolower($texte);// Separer les mots$table = preg_split("/ +/", $texte);while (list(, $mot) = each($table)) {if (strlen($mot) > $min_long) {$h = substr(md5($mot), 0, 16);$index[$h] += $val/(1+$translitteration_complexe);$mots .= ",(0x$h,'$mot')";}}}function deja_indexe($type, $id_objet) {$table_index = 'spip_index_'.table_objet($type);$col_id = 'id_'.$type;$query = "SELECT $col_id FROM $table_index WHERE $col_id=$id_objet LIMIT 0,1";$n = @spip_num_rows(@spip_query($query));return ($n > 0);}// Extracteur des documents 'txt'function extracteur_txt($fichier, &$charset) {lire_fichier($fichier, $contenu);// Reconnaitre le BOM utf-8 (0xEFBBBF)include_ecrire('inc_charsets.php3');if (bom_utf8($contenu))$charset = 'utf-8';return $contenu;}// Extracteur des documents 'html'function extracteur_html($fichier, &$charset) {lire_fichier($fichier, $contenu);// Importer dans le charset localinclude_ecrire('inc_charsets.php3');$contenu = transcoder_page($contenu);$charset = lire_meta('charset');return $contenu;}// Quels formats sait-on extraire ?$GLOBALS['extracteur'] = array ('txt' => 'extracteur_txt','pas' => 'extracteur_txt','c' => 'extracteur_txt','css' => 'extracteur_txt','html' => 'extracteur_html');// Indexer le contenu d'un documentfunction indexer_contenu_document ($row) {global $extracteur;if ($row['mode'] == 'vignette') return;list($extension) = spip_fetch_array(spip_query("SELECT extension FROM spip_types_documentsWHERE id_type = ".$row['id_type']));// Voir si on sait lire le contenu (eventuellement en chargeant le// fichier extract_pdf.php dans find_in_path() )if ($plugin = find_in_path('extract_'.$extension.'.php')) {include_local($plugin);}if (function_exists($lire = $extracteur[$extension])) {// Voir si on a deja une copie du doc distant// Note: si copie_locale() charge le doc, elle demande une reindexationif (!$fichier = copie_locale($row['fichier'], 'test')) {spip_log("pas de copie locale de '$fichier'");return;}// par defaut, on pense que l'extracteur va retourner ce charset$charset = 'iso-8859-1';// lire le contenu$contenu = $lire($fichier, $charset);if (!$contenu) {spip_log("Echec de l'extraction de '$fichier'");} else {// Ne retenir que les 50 premiers ko$contenu = substr($contenu, 0, 50000);// importer le charset$contenu = importer_charset($contenu, $charset);// Indexer le texteindexer_chaine($contenu, 1);}} else {spip_log("pas d'extracteur '$extension' fonctionnel");}}// Indexer les documents, auteurs, mots-cles associes a l'objetfunction indexer_elements_associes($objet, $id_objet, $associe, $valeur) {switch ($associe) {case 'document':$r = spip_query("SELECT doc.titre, doc.descriptifFROM spip_documents AS doc,spip_documents_".table_objet($objet)." AS lienWHERE lien.".id_table_objet($objet)."=$id_objetAND doc.id_document=lien.id_document");while ($row = spip_fetch_array($r)) {indexer_chaine($row['titre'],2 * $valeur);indexer_chaine($row['descriptif'],1 * $valeur);}break;case 'auteur':$r = spip_query("SELECT auteurs.nomFROM spip_auteurs AS auteurs,spip_auteurs_".table_objet($objet)." AS lienWHERE lien.".id_table_objet($objet)."=$id_objetAND auteurs.id_auteur=lien.id_auteur");while ($row = spip_fetch_array($r)) {indexer_chaine($row['nom'], 1 * $valeur, 2);}break;case 'mot':$r = spip_query("SELECT mots.titre, mots.descriptifFROM spip_mots AS mots,spip_mots_".table_objet($objet)." AS lienWHERE lien.".id_table_objet($objet)."=$id_objetAND mots.id_mot = lien.id_mot");while ($row = spip_fetch_array($r)) {indexer_chaine($row['titre'],4 * $valeur);indexer_chaine($row['descriptif'],1 * $valeur);}break;}}function indexer_objet($type, $id_objet, $forcer_reset = true) {global $index, $mots, $translitteration_complexe;$table = 'spip_'.table_objet($type);$table_index = 'spip_index_'.table_objet($type);$col_id = id_table_objet($type);if (!$id_objet) return;if (!$forcer_reset AND deja_indexe($type, $id_objet)) {spip_log ("$type $id_objet deja indexe");spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet");return;}// marquer "en cours d'indexation"spip_query("UPDATE $table SET idx='idx' WHERE $col_id=$id_objet");include_ecrire("inc_texte.php3");include_ecrire("inc_filtres.php3");spip_log("indexation $type $id_objet");$index = '';$mots = '';$query = "SELECT * FROM $table WHERE $col_id=$id_objet";$result = spip_query($query);$row = spip_fetch_array($result);if (!$row) return;// translitteration complexe ?if (!$lang = $row['lang']) $lang = lire_meta('langue_site');if ($lang == 'de' OR $lang=='vi') {$translitteration_complexe = 1;spip_log ('-> translitteration complexe');} else $translitteration_complexe = 0;switch($type) {case 'article':indexer_chaine($row['titre'], 8);indexer_chaine($row['soustitre'], 5);indexer_chaine($row['surtitre'], 5);indexer_chaine($row['descriptif'], 4);indexer_chaine($row['chapo'], 3);indexer_chaine($row['texte'], 1);indexer_chaine($row['ps'], 1);indexer_chaine($row['nom_site'], 1);indexer_chaine(@join(' ', unserialize($row['extra'])), 1);indexer_elements_associes('article', $id_objet, 'document', 1);indexer_elements_associes('article', $id_objet, 'auteur', 10);indexer_elements_associes('article', $id_objet, 'mot', 3);break;case 'breve':indexer_chaine($row['titre'], 8);indexer_chaine($row['texte'], 2);indexer_chaine(@join(' ', unserialize($row['extra'])), 1);indexer_elements_associes('breve', $id_objet, 'document', 1);indexer_elements_associes('breve', $id_objet, 'mot', 3);break;case 'rubrique':indexer_chaine($row['titre'], 8);indexer_chaine($row['descriptif'], 5);indexer_chaine($row['texte'], 1);indexer_chaine(@join(' ', unserialize($row['extra'])), 1);indexer_elements_associes('rubrique', $id_objet, 'document', 1);indexer_elements_associes('rubrique', $id_objet, 'mot', 3);break;case 'auteur':indexer_chaine($row['nom'], 5, 2);indexer_chaine($row['bio'], 1);indexer_chaine(@join(' ', unserialize($row['extra'])), 1);break;case 'mot':indexer_chaine($row['titre'], 8);indexer_chaine($row['descriptif'], 5);indexer_chaine($row['texte'], 1);indexer_chaine(@join(' ', unserialize($row['extra'])), 1);break;case 'signature':indexer_chaine($row['nom_email'], 2, 2);indexer_chaine($row['ad_email'], 2);indexer_chaine($row['nom_site'], 2);indexer_chaine($row['url_site'], 1);indexer_chaine($row['message'], 1);break;case 'syndic':indexer_chaine($row['nom_site'], 50);indexer_chaine($row['descriptif'], 30);indexer_elements_associes('syndic', $id_objet, 'document', 1);indexer_elements_associes('syndic', $id_objet, 'mot', 3);// Ajouter les titres des articles syndiques de ce site, le cas echeantif ($row['syndication'] = "oui") {$query_syndic = "SELECT titre FROM spip_syndic_articlesWHERE id_syndic=$id_objet AND statut='publie'ORDER BY date DESC LIMIT 0,100";$result_syndic = spip_query($query_syndic);while ($row_syndic = spip_fetch_array($result_syndic)) {indexer_chaine($row_syndic['titre'], 5);}}// Aller chercher la page d'accueilif (lire_meta("visiter_sites") == "oui") {include_ecrire ("inc_sites.php3");spip_log ("indexation contenu syndic ".$row['url_site']);indexer_chaine(supprimer_tags(recuperer_page($row['url_site'], true, false, 50000)), 1);}break;//// Cas tres particulier du forum :// on indexe le thread comme un toutcase 'forum':// 1. chercher la racine du thread$id_forum = $id_objet;while ($row['id_parent']) {$id_forum = $row['id_parent'];$s = spip_query("SELECT id_forum,id_parent FROM spip_forum WHERE id_forum=$id_forum");$row = spip_fetch_array($s);}// 2. chercher tous les forums du thread// (attention le forum de depart $id_objet n'appartient pas forcement// a son propre thread car il peut etre le fils d'un forum non 'publie')$thread="$id_forum";$fini = false;while (!$fini) {$s = spip_query("SELECT id_forum FROM spip_forum WHERE id_parent IN ($thread) AND id_forum NOT IN ($thread) AND statut='publie'");if (spip_num_rows($s) == 0) $fini = true;while ($t = spip_fetch_array($s))$thread.=','.$t['id_forum'];}// 3. marquer le thread comme "en cours d'indexation"spip_log("-> indexation thread $thread");spip_query("UPDATE spip_forum SET idx='idx'WHERE id_forum IN ($thread,$id_objet) AND idx!='non'");// 4. Indexer le thread$s = spip_query("SELECT * FROM spip_forumWHERE id_forum IN ($thread) AND idx!='non'");while ($row = spip_fetch_array($s)) {indexer_chaine($row['titre'], 3);indexer_chaine($row['texte'], 1);indexer_chaine($row['auteur'], 2, 2);indexer_chaine($row['email_auteur'], 2);indexer_chaine($row['nom_site'], 2);indexer_chaine($row['url_site'], 1);}// 5. marquer le thread comme "indexe"spip_query("UPDATE spip_forum SET idx='oui'WHERE id_forum IN ($thread,$id_objet) AND idx!='non'");// 6. Changer l'id_objet en id_forum de la racine du thread$id_objet = $id_forum;break;case 'document':// 1. Indexer le descriptifindexer_chaine($row['titre'], 20);indexer_chaine($row['descriptif'], 10);indexer_chaine(preg_replace(',^(IMG/|.*://),', '', $row['fichier']), 1);indexer_elements_associes('document', $id_objet, 'mot', 3);// 2. Indexer le contenu si on sait le lireindexer_contenu_document($row);break;} // switch$query = "DELETE FROM $table_index WHERE $col_id=$id_objet";$result = spip_query($query);if ($index) {if ($mots) {$mots = "INSERT IGNORE INTO spip_index_dico (hash, dico) VALUES ".substr($mots,1); // supprimer la virgule du debutspip_query($mots);}reset($index);unset($q);while (list($hash, $points) = each($index)) $q[] = "(0x$hash,".ceil($points).",$id_objet)";spip_query("INSERT INTO $table_index (hash, points, $col_id) VALUES ".join(',',$q));}// marquer "indexe"spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet");}/*Valeurs du champ 'idx' de la table spip_objet(s)'' ne sait pas'1' (re)indexer'oui' deja indexe'idx' en cours'non' ne jamais indexer*/// API pour l'espace privefunction marquer_indexer ($objet, $id_objet) {spip_log ("demande indexation $objet $id_objet");$table = 'spip_'.table_objet($objet);$id = id_table_objet($objet);spip_query ("UPDATE $table SET idx='1' WHERE $id=$id_objet AND idx!='non'");}// A garder pour compatibilite bouton memo...function indexer_article($id_article) {marquer_indexer('article', $id_article);}// n'indexer que les objets publiesfunction critere_indexation($type) {switch ($type) {case 'article':case 'breve':case 'rubrique':case 'syndic':case 'forum':case 'signature':$critere = "statut='publie'";break;case 'auteur':$critere = "statut IN ('0minirezo', '1comite')";break;case 'mot':case 'document':default:$critere = '1=1';break;}return $critere;}function effectuer_une_indexation($nombre_indexations = 1) {// chercher un objet a indexer dans chacune des tables d'objets$vu = array();$types = array('article','auteur','breve','mot','rubrique','signature','syndic','forum','document');while (list(,$type) = each($types)) {$table_objet = 'spip_'.table_objet($type);$table_index = 'spip_index_'.table_objet($type);$critere = critere_indexation($type);if ($type == 'syndic' OR $type == 'document')$limit = 1;else$limit = $nombre_indexations;$s = spip_query("SELECT id_$type, idx FROM $table_objet WHERE idx IN ('','1','idx') AND $critere ORDER BY idx='idx',idx='' LIMIT 0,$limit");while ($t = spip_fetch_array($s)) {$vu[$type] .= $t[0].", ";indexer_objet($type, $t[0], $t[1]);}}return $vu;}function executer_une_indexation_syndic() {$id_syndic = 0;if ($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 0,1"))) {$id_syndic = $row['id_syndic'];spip_query("UPDATE spip_syndic SET date_index=NOW() WHERE id_syndic=$id_syndic");marquer_indexer('syndic', $id_syndic);}return $id_syndic;}function creer_liste_indexation() {$types = array('article','auteur','breve','mot','rubrique','syndic','forum','signature','document');while (list(,$type) = each($types)) {$table = 'spip_'.table_objet($type);spip_query("UPDATE $table SET idx='1' WHERE idx!='non'");}}function purger_index() {spip_query("DELETE FROM spip_index_articles");spip_query("DELETE FROM spip_index_auteurs");spip_query("DELETE FROM spip_index_breves");spip_query("DELETE FROM spip_index_mots");spip_query("DELETE FROM spip_index_rubriques");spip_query("DELETE FROM spip_index_syndic");spip_query("DELETE FROM spip_index_forum");spip_query("DELETE FROM spip_index_signatures");spip_query("DELETE FROM spip_index_documents");spip_query("DELETE FROM spip_index_dico");}// cree la requete pour une recherche en txt integralfunction requete_txt_integral($objet, $hash_recherche) {$table = "spip_".table_objet($objet);$index_table = "spip_index_".table_objet($objet);$id_objet = "id_".$objet;return "SELECT objet.*, SUM(rec.points) AS pointsFROM $table AS objet, $index_table AS recWHERE objet.$id_objet = rec.$id_objetAND rec.hash IN ($hash_recherche)GROUP BY objet.$id_objetORDER BY points DESCLIMIT 0,10";}// rechercher un mot dans le dico// retourne deux methodes : lache puis strictfunction requete_dico($val) {$min_long = 3;// cas normalif (strlen($val) > $min_long) {return array("dico LIKE '".addslashes($val)."%'", "dico = '".addslashes($val)."'");} elsereturn array("dico = '".addslashes($val)."___'", "dico = '".addslashes($val)."___'");}// decode la chaine recherchee et la traduit en hashfunction requete_hash ($rech) {// recupere les mots de la recherche$translitteration_complexe = true;$rech = nettoyer_chaine_indexation($rech);$regs = separateurs_indexation(true)." ";$rech = strtr($rech, $regs, ereg_replace('.', ' ', $regs));$s = preg_split("/ +/", $rech);unset($dico);unset($h);// cherche les mots dans le dicowhile (list(, $val) = each($s)) {list($rq, $rq_strict) = requete_dico ($val);if ($rq)$dico[] = $rq;if ($rq_strict)$dico_strict[] = $rq_strict;}// Attention en MySQL 3.x il faut passer par HEX(hash)// alors qu'en MySQL 4.1 c'est interdit !$vers = spip_fetch_array(spip_query("SELECT VERSION()"));if (substr($vers[0], 0, 1) >= 4AND substr($vers[0], 2, 1) >= 1 ) {$hex_fmt = '';$select_hash = 'hash AS h';} else {$hex_fmt = '0x';$select_hash = 'HEX(hash) AS h';}// compose la recherche dans l'indexif ($dico_strict) {$query2 = "SELECT $select_hash FROM spip_index_dico WHERE ".join(" OR ", $dico_strict);$result2 = spip_query($query2);while ($row2 = spip_fetch_array($result2))$h_strict[] = $hex_fmt.$row2['h'];}if ($dico) {$query2 = "SELECT $select_hash FROM spip_index_dico WHERE ".join(" OR ", $dico);$result2 = spip_query($query2);while ($row2 = spip_fetch_array($result2))$h[] = $hex_fmt.$row2['h'];}if ($h_strict)$hash_recherche_strict = join(",", $h_strict);else$hash_recherche_strict = "0";if ($h)$hash_recherche = join(",", $h);else$hash_recherche = "0";return array($hash_recherche, $hash_recherche_strict);}function prepare_recherche($recherche, $type = 'id_article', $table='articles') {static $cache = array();if (!$cache[$type][$recherche]) {if (!$cache['hash'][$recherche])$cache['hash'][$recherche] = requete_hash($recherche);list($hash_recherche, $hash_recherche_strict)= $cache['hash'][$recherche];$strict = array();if ($hash_recherche_strict)foreach (split(',',$hash_recherche_strict) as $h)$strict[$h] = 99;$points = array();$s = spip_query ("SELECT hash,points,$type as idFROM spip_index_$tableWHERE hash IN ($hash_recherche)");while ($r = spip_fetch_array($s))$points[$r['id']]+= (1 + $strict[$r['hash']]) * $r['points'];spip_free_result($s);arsort($points, SORT_NUMERIC);# calculer le {id_article IN()} et le {... as points}if (!count($points)) {$cache[$type][$recherche] = array('', '');} else {$ids = array();$select = '0';foreach ($points as $id => $p)$listes_ids[$p] .= ','.$id;foreach ($listes_ids as $p => $liste_ids)$select .= "+$p*(".calcul_mysql_in("$table.$type", substr($liste_ids, 1)).") ";$cache[$type][$recherche] = array($select,'('.calcul_mysql_in("$table.$type", join(',',array_keys($points))).')');}}return $cache[$type][$recherche];}?>