PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/spip/ecrire/inc/rechercher.php

https://github.com/eyeswebcrea/espace-couture-sittler.fr
PHP | 370 lines | 287 code | 44 blank | 39 comment | 43 complexity | 437601e4a37758c28d1d1da0fc85d7c0 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2011 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. if (!defined('_ECRIRE_INC_VERSION')) return;
  12. // Donne la liste des champs/tables ou l'on sait chercher/remplacer
  13. // avec un poids pour le score
  14. // http://doc.spip.org/@liste_des_champs
  15. function liste_des_champs() {
  16. return
  17. pipeline('rechercher_liste_des_champs',
  18. array(
  19. 'article' => array(
  20. 'surtitre' => 5, 'titre' => 8, 'soustitre' => 5, 'chapo' => 3,
  21. 'texte' => 1, 'ps' => 1, 'nom_site' => 1, 'url_site' => 1,
  22. 'descriptif' => 4
  23. ),
  24. 'breve' => array(
  25. 'titre' => 8, 'texte' => 2, 'lien_titre' => 1, 'lien_url' => 1
  26. ),
  27. 'rubrique' => array(
  28. 'titre' => 8, 'descriptif' => 5, 'texte' => 1
  29. ),
  30. 'site' => array(
  31. 'nom_site' => 5, 'url_site' => 1, 'descriptif' => 3
  32. ),
  33. 'mot' => array(
  34. 'titre' => 8, 'texte' => 1, 'descriptif' => 5
  35. ),
  36. 'auteur' => array(
  37. 'nom' => 5, 'bio' => 1, 'email' => 1, 'nom_site' => 1, 'url_site' => 1, 'login' => 1
  38. ),
  39. 'forum' => array(
  40. 'titre' => 3, 'texte' => 1, 'auteur' => 2, 'email_auteur' => 2, 'nom_site' => 1, 'url_site' => 1
  41. ),
  42. 'document' => array(
  43. 'titre' => 3, 'descriptif' => 1, 'fichier' => 1
  44. ),
  45. 'syndic_article' => array(
  46. 'titre' => 5, 'descriptif' => 1
  47. ),
  48. 'signature' => array(
  49. 'nom_email' => 2, 'ad_email' => 4,
  50. 'nom_site' => 2, 'url_site' => 4,
  51. 'message' => 1
  52. )
  53. )
  54. );
  55. }
  56. // Recherche des auteurs et mots-cles associes
  57. // en ne regardant que le titre ou le nom
  58. // http://doc.spip.org/@liste_des_jointures
  59. function liste_des_jointures() {
  60. return
  61. pipeline('rechercher_liste_des_jointures',
  62. array(
  63. 'article' => array(
  64. 'auteur' => array('nom' => 10),
  65. 'mot' => array('titre' => 3),
  66. 'document' => array('titre' => 2, 'descriptif' => 1)
  67. ),
  68. 'breve' => array(
  69. 'mot' => array('titre' => 3),
  70. 'document' => array('titre' => 2, 'descriptif' => 1)
  71. ),
  72. 'rubrique' => array(
  73. 'mot' => array('titre' => 3),
  74. 'document' => array('titre' => 2, 'descriptif' => 1)
  75. ),
  76. 'document' => array(
  77. 'mot' => array('titre' => 3)
  78. )
  79. )
  80. );
  81. }
  82. // Effectue une recherche sur toutes les tables de la base de donnees
  83. // options :
  84. // - toutvoir pour eviter autoriser(voir)
  85. // - flags pour eviter les flags regexp par defaut (UimsS)
  86. // - champs pour retourner les champs concernes
  87. // - score pour retourner un score
  88. // On peut passer les tables, ou une chaine listant les tables souhaitees
  89. // http://doc.spip.org/@recherche_en_base
  90. function recherche_en_base($recherche='', $tables=NULL, $options=array(), $serveur='') {
  91. include_spip('base/abstract_sql');
  92. if (!is_array($tables)) {
  93. $liste = liste_des_champs();
  94. if (is_string($tables)
  95. AND $tables != '') {
  96. $toutes = array();
  97. foreach(explode(',', $tables) as $t)
  98. if (isset($liste[$t]))
  99. $toutes[$t] = $liste[$t];
  100. $tables = $toutes;
  101. unset($toutes);
  102. } else
  103. $tables = $liste;
  104. }
  105. include_spip('inc/autoriser');
  106. // options par defaut
  107. $options = array_merge(array(
  108. 'preg_flags' => 'UimsS',
  109. 'toutvoir' => false,
  110. 'champs' => false,
  111. 'score' => false,
  112. 'matches' => false,
  113. 'jointures' => false
  114. ),
  115. $options
  116. );
  117. $results = array();
  118. if (!strlen($recherche) OR !count($tables))
  119. return array();
  120. include_spip('inc/charsets');
  121. $recherche = translitteration($recherche);
  122. $is_preg = false;
  123. if (substr($recherche,0,1)=='/' AND substr($recherche,-1,1)=='/'){
  124. // c'est une preg
  125. $preg = $recherche.$options['preg_flags'];
  126. $is_preg = true;
  127. }
  128. else
  129. $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
  130. // Si la chaine est inactive, on va utiliser LIKE pour aller plus vite
  131. // ou si l'expression reguliere est invalide
  132. if (!$is_preg
  133. OR (@preg_match($preg,'')===FALSE) ) {
  134. $methode = 'LIKE';
  135. $u = $GLOBALS['meta']['pcre_u'];
  136. // eviter les parentheses et autres caractères qui interferent avec pcre par la suite (dans le preg_match_all) s'il y a des reponses
  137. $recherche = str_replace(
  138. array('(',')','?','[', ']', '+', '*', '/'),
  139. array('\(','\)','[?]', '\[', '\]', '\+', '\*', '\/'),
  140. $recherche);
  141. $recherche_mod = $recherche;
  142. // echapper les % et _
  143. $q = str_replace(array('%','_'), array('\%', '\_'), trim($recherche));
  144. // les expressions entre " " sont un mot a chercher tel quel
  145. // -> on remplace les espaces par un _ et on enleve les guillemets
  146. if (preg_match(',["][^"]+["],Uims',$q,$matches)){
  147. foreach($matches as $match){
  148. // corriger le like dans le $q
  149. $word = preg_replace(",\s+,Uims","_",$match);
  150. $word = trim($word,'"');
  151. $q = str_replace($match,$word,$q);
  152. // corriger la regexp
  153. $word = preg_replace(",\s+,Uims","[\s]",$match);
  154. $word = trim($word,'"');
  155. $recherche_mod = str_replace($match,$word,$recherche_mod);
  156. }
  157. }
  158. $q = sql_quote(
  159. "%"
  160. . preg_replace(",\s+,".$u, "%", $q)
  161. . "%"
  162. );
  163. $preg = '/'.preg_replace(",\s+,".$u, ".+", trim($recherche_mod)).'/' . $options['preg_flags'];
  164. } else {
  165. $methode = 'REGEXP';
  166. $q = sql_quote(substr($recherche,1,-1));
  167. }
  168. $jointures = $options['jointures']
  169. ? liste_des_jointures()
  170. : array();
  171. foreach ($tables as $table => $champs) {
  172. $requete = array(
  173. "SELECT"=>array(),
  174. "FROM"=>array(),
  175. "WHERE"=>array(),
  176. "GROUPBY"=>array(),
  177. "ORDERBY"=>array(),
  178. "LIMIT"=>"",
  179. "HAVING"=>array()
  180. );
  181. $_id_table = id_table_objet($table);
  182. $requete['SELECT'][] = "t.".$_id_table;
  183. $a = array();
  184. // Recherche fulltext
  185. foreach ($champs as $champ => $poids) {
  186. if (is_array($champ)){
  187. spip_log("requetes imbriquees interdites");
  188. } else {
  189. if (strpos($champ,".")===FALSE)
  190. $champ = "t.$champ";
  191. $requete['SELECT'][] = $champ;
  192. $a[] = $champ.' '.$methode.' '.$q;
  193. }
  194. }
  195. if ($a) $requete['WHERE'][] = join(" OR ", $a);
  196. $requete['FROM'][] = table_objet_sql($table).' AS t';
  197. $s = sql_select(
  198. $requete['SELECT'], $requete['FROM'], $requete['WHERE'],
  199. implode(" ",$requete['GROUPBY']),
  200. $requete['ORDERBY'], $requete['LIMIT'],
  201. $requete['HAVING'], $serveur
  202. );
  203. while ($t = sql_fetch($s,$serveur)) {
  204. $id = intval($t[$_id_table]);
  205. if ($options['toutvoir']
  206. OR autoriser('voir', $table, $id)) {
  207. // indiquer les champs concernes
  208. $champs_vus = array();
  209. $score = 0;
  210. $matches = array();
  211. $vu = false;
  212. foreach ($champs as $champ => $poids) {
  213. $champ = explode('.',$champ);
  214. $champ = end($champ);
  215. if ($n =
  216. ($options['score'] || $options['matches'])
  217. ? preg_match_all($preg, translitteration_rapide($t[$champ]), $regs, PREG_SET_ORDER)
  218. : preg_match($preg, translitteration_rapide($t[$champ]))
  219. ) {
  220. $vu = true;
  221. if ($options['champs'])
  222. $champs_vus[$champ] = $t[$champ];
  223. if ($options['score'])
  224. $score += $n * $poids;
  225. if ($options['matches'])
  226. $matches[$champ] = $regs;
  227. if (!$options['champs']
  228. AND !$options['score']
  229. AND !$options['matches'])
  230. break;
  231. }
  232. }
  233. if ($vu) {
  234. if (!isset($results[$table]))
  235. $results[$table] = array();
  236. $results[$table][$id] = array();
  237. if ($champs_vus)
  238. $results[$table][$id]['champs'] = $champs_vus;
  239. if ($score)
  240. $results[$table][$id]['score'] = $score;
  241. if ($matches)
  242. $results[$table][$id]['matches'] = $matches;
  243. }
  244. }
  245. }
  246. // Gerer les donnees associees
  247. if (isset($jointures[$table])
  248. AND $joints = recherche_en_base(
  249. $recherche,
  250. $jointures[$table],
  251. array_merge($options, array('jointures' => false))
  252. )
  253. ) {
  254. foreach ($joints as $table_liee => $ids_trouves) {
  255. if (!$rechercher_joints = charger_fonction("rechercher_joints_${table}_${table_liee}","inc",true)){
  256. $cle_depart = id_table_objet($table);
  257. $cle_arrivee = id_table_objet($table_liee);
  258. $table_sql = preg_replace('/^spip_/', '', table_objet_sql($table));
  259. $table_liee_sql = preg_replace('/^spip_/', '', table_objet_sql($table_liee));
  260. if ($table_liee == 'document')
  261. $s = sql_select("id_objet as $cle_depart, $cle_arrivee", "spip_documents_liens", array("objet='$table'",sql_in('id_'.${table_liee}, array_keys($ids_trouves))), '','','','',$serveur);
  262. else
  263. $s = sql_select("$cle_depart,$cle_arrivee", "spip_${table_liee_sql}_${table_sql}", sql_in('id_'.${table_liee}, array_keys($ids_trouves)), '','','','',$serveur);
  264. }
  265. else
  266. list($cle_depart,$cle_arrivee,$s) = $rechercher_joints($table,$table_liee,array_keys($ids_trouves), $serveur);
  267. while ($t = is_array($s)?array_shift($s):sql_fetch($s)) {
  268. $id = $t[$cle_depart];
  269. $joint = $ids_trouves[$t[$cle_arrivee]];
  270. if (!isset($results[$table]))
  271. $results[$table] = array();
  272. if (!isset($results[$table][$id]))
  273. $results[$table][$id] = array();
  274. if ($joint['score'])
  275. $results[$table][$id]['score'] += $joint['score'];
  276. if ($joint['champs'])
  277. foreach($joint['champs'] as $c => $val)
  278. $results[$table][$id]['champs'][$table_liee.'.'.$c] = $val;
  279. if ($joint['matches'])
  280. foreach($joint['matches'] as $c => $val)
  281. $results[$table][$id]['matches'][$table_liee.'.'.$c] = $val;
  282. }
  283. }
  284. }
  285. }
  286. return $results;
  287. }
  288. // Effectue une recherche sur toutes les tables de la base de donnees
  289. // http://doc.spip.org/@remplace_en_base
  290. function remplace_en_base($recherche='', $remplace=NULL, $tables=NULL, $options=array()) {
  291. include_spip('inc/modifier');
  292. // options par defaut
  293. $options = array_merge(array(
  294. 'preg_flags' => 'UimsS',
  295. 'toutmodifier' => false
  296. ),
  297. $options
  298. );
  299. $options['champs'] = true;
  300. if (!is_array($tables))
  301. $tables = liste_des_champs();
  302. $results = recherche_en_base($recherche, $tables, $options);
  303. $preg = '/'.str_replace('/', '\\/', $recherche).'/' . $options['preg_flags'];
  304. foreach ($results as $table => $r) {
  305. $_id_table = id_table_objet($table);
  306. foreach ($r as $id => $x) {
  307. if ($options['toutmodifier']
  308. OR autoriser('modifier', $table, $id)) {
  309. $modifs = array();
  310. foreach ($x['champs'] as $key => $val) {
  311. if ($key == $_id_table) next;
  312. $repl = preg_replace($preg, $remplace, $val);
  313. if ($repl <> $val)
  314. $modifs[$key] = $repl;
  315. }
  316. if ($modifs)
  317. modifier_contenu($table, $id,
  318. array(
  319. 'champs' => array_keys($modifs),
  320. ),
  321. $modifs);
  322. }
  323. }
  324. }
  325. }
  326. ?>