From 919326dce4f85b5a4552a6b2d998d719408be0d4 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Sat, 24 May 2025 01:21:50 +0200 Subject: [PATCH] search.php: (untested) refactor, using SearchService --- search.php | 188 +++++++++++++---------------------------------------- 1 file changed, 45 insertions(+), 143 deletions(-) diff --git a/search.php b/search.php index 0f577381..02edc242 100644 --- a/search.php +++ b/search.php @@ -1,6 +1,6 @@ get(SearchService::class); + +if (isset($_GET['search']) && !empty($_GET['search'])) { + $raw_search = $_GET['search']; + $ip = $_SERVER['REMOTE_ADDR']; + $fallback_board = (isset($_GET['board']) && !empty($_GET['board'])) ? $_GET['board'] : null; + + + if ($search_service->checkFlood($ip, $raw_search)) { + error(_('Wait a while before searching again, please.')); + } + + // Actually do the search. + $parse_res = $search_service->parse($raw_search); + $filters = $search_service->reduceAndWeight($parse_res); + $search_res = $search_service->search($ip, $raw_search, $filters, $fallback_board); + + + // Needed to set a global variable further down the stack, plus the template. + $actual_board = $filter->board ?? $fallback_board; -if (isset($_GET['search']) && !empty($_GET['search']) && isset($_GET['board']) && in_array($_GET['board'], $boards)) { $body = Element('search_form.html', [ - 'boards' => $boards, + 'boards' => $search_service->getSearchableBoards(), 'board' => $_GET['board'], 'search' => \str_replace('"', '"', utf8tohtml($_GET['search'])) ]); - $phrase = $_GET['search']; - $ip = $_SERVER['REMOTE_ADDR']; - $_body = ''; - - $ctx = Vichan\build_context($config); - $search_queries = $ctx->get(SearchQueries::class); - - if ($search_queries->checkFlood($ip, $phrase)) { - error(_('Wait a while before searching again, please.')); - } - - _syslog(LOG_NOTICE, 'Searched /' . $_GET['board'] . '/ for "' . $phrase . '"'); - - openBoard($_GET['board']); - - $filters = Array(); - - function search_filters($m) { - global $filters; - $name = $m[2]; - $value = isset($m[4]) ? $m[4] : $m[3]; - - if (!in_array($name, array('id', 'thread', 'subject', 'name'))) { - // unknown filter - return $m[0]; - } - - $filters[$name] = $value; - - return $m[1]; - } - - $phrase = trim(preg_replace_callback('/(^|\s)(\w+):("(.*)?"|[^\s]*)/', 'search_filters', $phrase)); - - if (!preg_match('/[^*^\s]/', $phrase) && empty($filters)) { - _syslog(LOG_WARNING, 'Query too broad.'); - $body .= '

(Query too broad.)

'; - echo Element('page.html', Array( - 'config'=>$config, - 'title'=>'Search', - 'body'=>$body, - )); - exit; - } - - // Escape escape character - $phrase = str_replace('!', '!!', $phrase); - - // Remove SQL wildcard - $phrase = str_replace('%', '!%', $phrase); - - // Use asterisk as wildcard to suit convention - $phrase = str_replace('*', '%', $phrase); - - // Remove `, it's used by table prefix magic - $phrase = str_replace('`', '!`', $phrase); - - $like = ''; - $match = Array(); - - // Find exact phrases - if (preg_match_all('/"(.+?)"/', $phrase, $m)) { - foreach($m[1] as &$quote) { - $phrase = str_replace("\"{$quote}\"", '', $phrase); - $match[] = $pdo->quote($quote); - } - } - - $words = explode(' ', $phrase); - foreach($words as &$word) { - if (empty($word)) { - continue; - } - $match[] = $pdo->quote($word); - } - - $like = ''; - foreach($match as &$phrase) { - if (!empty($like)) { - $like .= ' AND '; - } - $phrase = preg_replace('/^\'(.+)\'$/', '\'%$1%\'', $phrase); - $like .= '`body` LIKE ' . $phrase . ' ESCAPE \'!\''; - } - - foreach($filters as $name => $value) { - if (!empty($like)) { - $like .= ' AND '; - } - $like .= '`' . $name . '` = '. $pdo->quote($value); - } - - $like = str_replace('%', '%%', $like); - - $search_limit = $config['search']['search_limit']; - - $query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE " . $like . " ORDER BY `time` DESC LIMIT :limit", $board['uri'])); - $query->bindValue(':limit', $search_limit, PDO::PARAM_INT); - $query->execute() or error(db_error($query)); - - if ($query->rowCount() == $search_limit) { - _syslog(LOG_WARNING, 'Query too broad.'); - $body .= '

('._('Query too broad.').')

'; - echo Element('page.html', Array( - 'config'=>$config, - 'title'=>'Search', - 'body'=>$body, - )); - exit; - } - - $temp = ''; - while ($post = $query->fetch()) { - if (!$post['thread']) { - $po = new Thread($post); - } else { - $po = new Post($post); - } - $temp .= $po->build(true) . '
'; - } - - if (!empty($temp)) - $_body .= '
' . - sprintf(ngettext('%d result in', '%d results in', $query->rowCount()), - $query->rowCount()) . ' ' . - sprintf($config['board_abbreviation'], $board['uri']) . ' - ' . $board['title'] . - '' . $temp . '
'; - - $body .= '
'; - if (!empty($_body)) { - $body .= $_body; + if (empty($search_res)) { + $body .= '

(' . _('No results.') . ')

'; } else { - $body .= '

('._('No results.').')

'; + $body .= '
'; + + openBoard($actual_board); + + $posts_html = ''; + foreach ($search_res as $post) { + if (!$post['thread']) { + $po = new Thread($post); + } else { + $po = new Post($post); + } + $posts_html .= $po->build(true) . '
'; + } + + $body .= '
' . + sprintf(ngettext('%d result in', '%d results in', \count($search_res)), \count($search_res)) . ' ' . + sprintf($config['board_abbreviation'], $board['uri']) . ' - ' . $board['title'] . + '' . $posts_html . '
'; } } else { $body = Element('search_form.html', [ - 'boards' => $boards, + 'boards' => $search_service->getSearchableBoards(), 'board' => false, 'search' => false ]);