PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/features/search/lib.php

https://gitlab.com/MotoSport/morgue
PHP | 132 lines | 91 code | 35 blank | 6 comment | 5 complexity | ba12edfd742a4fc8af596e8321e1b7ed MD5 | raw file
  1. <?php
  2. #require_once('Persistence.php');
  3. class Search {
  4. static private function split_terms($terms){
  5. $terms = preg_replace_callback("/\"(.*?)\"/", function($m) {return Search::transform_term($m[1]);}, $terms);
  6. $terms = preg_split("/\s+|,/", $terms);
  7. $out = array();
  8. foreach($terms as $term){
  9. $term = preg_replace_callback("/\{WHITESPACE-([0-9]+)\}/", function($m) {return chr($m[1]);}, $term);
  10. $term = preg_replace("/\{COMMA\}/", ",", $term);
  11. $out[] = $term;
  12. }
  13. return $out;
  14. }
  15. static function transform_term($term){
  16. $term = preg_replace_callback("/(\s)/", function($m) {return '{WHITESPACE-'.ord($m[1]).'}';}, $term);
  17. $term = preg_replace("/,/", "{COMMA}", $term);
  18. return $term;
  19. }
  20. static private function escape_rlike($string){
  21. return preg_replace("/([.\[\]*^\$])/", '\\\$1', $string);
  22. }
  23. static private function db_escape_terms($terms){
  24. $out = array();
  25. foreach($terms as $term){
  26. $out[] = '[[:<:]]'.AddSlashes(Search::escape_rlike($term)).'[[:>:]]';
  27. }
  28. return $out;
  29. }
  30. static function perform($terms){
  31. $terms = Search::split_terms($terms);
  32. $terms_db = Search::db_escape_terms($terms);
  33. $terms_rx = Search::rx_escape_terms($terms);
  34. $parts = array();
  35. foreach($terms_db as $term_db){
  36. array_push($parts, "(summary RLIKE '$term_db' OR title RLIKE '$term_db')");
  37. }
  38. $parts = implode(' AND ', $parts);
  39. $conn = Persistence::get_database_object();
  40. $sql = "SELECT id, title, summary, created FROM postmortems WHERE $parts";
  41. $rows = array();
  42. $stmt = $conn->prepare($sql);
  43. $stmt->execute();
  44. $timezone = getUserTimezone();
  45. $tz = new DateTimeZone($timezone);
  46. while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
  47. $row['score'] = 0;
  48. $row['created'] = new DateTime("@$row[created]");
  49. $row['created']->setTimezone($tz);
  50. $row['created'] = $row['created']->format('m/d/Y G:ia');
  51. foreach($terms_rx as $term_rx){
  52. $row['score'] += preg_match_all("/$term_rx/i", $row['summary'], $null);
  53. $row['score'] += preg_match_all("/$term_rx/i", $row['title'], $null);
  54. }
  55. $rows[] = $row;
  56. }
  57. uasort($rows, 'Search::sort_results');
  58. $conn = null;
  59. return $rows;
  60. }
  61. static private function rx_escape_terms($terms){
  62. $out = array();
  63. foreach($terms as $term){
  64. $out[] = '\b'.preg_quote($term, '/').'\b';
  65. }
  66. return $out;
  67. }
  68. static function sort_results($a, $b){
  69. $ax = $a['score'];
  70. $bx = $b['score'];
  71. if ($ax == $bx){ return 0; }
  72. return ($ax > $bx) ? -1 : 1;
  73. }
  74. static private function html_escape_terms($terms){
  75. $out = array();
  76. foreach($terms as $term){
  77. if (preg_match("/\s|,/", $term)){
  78. $out[] = '"'.HtmlSpecialChars($term).'"';
  79. }else{
  80. $out[] = HtmlSpecialChars($term);
  81. }
  82. }
  83. return $out;
  84. }
  85. static private function pretty_terms($terms_html){
  86. if (count($terms_html) == 1){
  87. return array_pop($terms_html);
  88. }
  89. $last = array_pop($terms_html);
  90. return implode(', ', $terms_html)." and $last";
  91. }
  92. }
  93. #
  94. # do the search here...
  95. #
  96. # $results = search_perform($HTTP_GET_VARS[q]);
  97. # $term_list = search_pretty_terms(search_html_escape_terms(search_split_terms($HTTP_GET_VARS[q])));