2 // PukiWiki - Yet another WikiWikiWeb clone.
4 // Copyright 2017 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
7 // Search2 plugin - Show detail result using JavaScript
9 define('PLUGIN_SEARCH2_MAX_LENGTH', 80);
10 define('PLUGIN_SEARCH2_MAX_BASE', 16); // #search(1,2,3,...,15,16)
12 // Show a search box on a page
13 function plugin_search2_convert()
15 $args = func_get_args();
16 return plugin_search_search_form('', '', $args);
19 function plugin_search2_action()
21 global $vars, $_title_search, $_title_result;
23 $action = isset($vars['action']) ? $vars['action'] : '';
24 $base = isset($vars['base']) ? $vars['base'] : '';
30 $q = isset($vars['q']) ? $vars['q'] : '';
32 return array('msg' => $_title_search,
33 'body' => plugin_search2_search_form($q, '', $bases));
35 $msg = str_replace('$1', htmlsc($q), $_title_result);
36 return array('msg' => $msg,
37 'body' => plugin_search2_search_form($q, '', $bases));
39 } else if ($action === 'query') {
40 $text = isset($vars['q']) ? $vars['q'] : '';
41 header('Content-Type: application/json; charset=UTF-8');
42 plugin_search2_do_search($text, $base);
47 function plugin_search2_do_search($query_text, $base)
49 global $whatsnew, $non_list, $search_non_list;
50 global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
55 $b_type_and = true; // AND:TRUE OR:FALSE
56 $key_candidates = preg_split('/\s+/', $query_text, -1, PREG_SPLIT_NO_EMPTY);
57 for ($i = count($key_candidates) - 1; $i >= 0; $i--) {
58 if ($key_candidates[$i] === 'OR') {
60 unset($key_candidates[$i]);
63 $key_candidates = array_merge($key_candidates);
64 $keys = get_search_words($key_candidates);
65 foreach ($keys as $key=>$value)
66 $keys[$key] = '/' . $value . '/S';
68 $pages = get_existpages();
72 $pages = preg_grep('/^' . preg_quote($base, '/') . '/S', $pages);
74 if (! $search_non_list) {
75 $pages = array_diff($pages, preg_grep('/' . $non_list . '/S', $pages));
78 $pages = array_flip($pages);
79 unset($pages[$whatsnew]);
80 $page_names = array_keys($pages);
82 $found_pages = array();
83 $readable_page_index = -1;
84 $scan_page_index = -1;
85 $last_read_page_name = null;
86 foreach ($page_names as $page) {
88 $pagename_only = false;
90 if (! is_page_readable($page)) {
92 // $search_auth - 1: User can know page names that contain search text if the page is readable
95 // $search_auth - 0: All users can know page names that conntain search text
96 $pagename_only = true;
98 $readable_page_index++;
99 // Search for page name and contents
100 $body = get_source($page, TRUE, TRUE, TRUE);
101 $target = $page . "\n" . remove_author_header($body);
102 foreach ($keys as $key) {
103 $b_match = preg_match($key, $target);
104 if ($b_type_and xor $b_match) break; // OR
109 $author_info = get_author_info($body);
110 if ($author_info === false || $pagename_only) {
111 $updated_at = get_date_atom(filemtime(get_filename($page)));
113 if ($pagename_only) {
114 // The user cannot read this page body
115 $found_pages[] = array('name' => (string)$page,
116 'url' => get_page_uri($page), 'updated_at' => $updated_at,
117 'body' => '', 'pagename_only' => 1);
119 $found_pages[] = array('name' => (string)$page,
120 'url' => get_page_uri($page), 'updated_at' => $updated_at,
121 'body' => (string)$body);
124 $last_read_page_name = $page;
126 $message = str_replace('$1', htmlsc($query_text), str_replace('$2', count($found_pages),
127 str_replace('$3', count($page_names), $b_type_and ? $_msg_andresult : $_msg_orresult)));
128 $search_done = (boolean)($scan_page_index + 1 === count($page_names));
130 'message' => $message,
132 'read_page_count' => $readable_page_index + 1,
133 'scan_page_count' => $scan_page_index + 1,
134 'page_count' => count($page_names),
135 'last_read_page_name' => $last_read_page_name,
136 'search_done' => $search_done,
137 'results' => $found_pages);
139 if (!defined('PKWK_UTF8_ENABLE')) {
140 if (SOURCE_ENCODING === 'EUC-JP') {
141 mb_convert_variables('UTF-8', 'CP51932', $obj);
143 mb_convert_variables('UTF-8', SOURCE_ENCODING, $obj);
146 print(json_encode($obj, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
149 function plugin_search2_search_form($s_word = '', $type = '', $bases = array())
152 global $_search_pages, $_search_all;
153 global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
154 global $_search_detail, $_search_searching;
155 global $_msg_unsupported_webbrowser, $_msg_use_alternative_link;
157 $script = get_base_uri();
158 $h_search_text = htmlsc($s_word);
161 if (!empty($bases)) {
165 foreach($bases as $base) {
167 if (PLUGIN_SEARCH2_MAX_BASE < $_num) break;
168 $s_base = htmlsc($base);
169 $base_str = '<strong>' . $s_base . '</strong>';
170 $base_label = str_replace('$1', $base_str, $_search_pages);
174 <input type="radio" name="base" value="$s_base" $check> $base_label
181 <label><input type="radio" name="base" value=""> $_search_all</label>
183 $base_option = '<div class="small">' . $base_msg . '</div>';
185 $_search2_result_notfound = htmlsc($_msg_notfoundresult);
186 $_search2_result_found = htmlsc($_msg_andresult);
187 $_search2_search_wait_milliseconds = PLUGIN_SEARCH2_SEARCH_WAIT_MILLISECONDS;
188 $result_page_panel =<<<EOD
189 <div id="_plugin_search2_search_status"></div>
190 <div id="_plugin_search2_message"></div>
191 <input type="checkbox" id="_plugin_search2_detail" checked><label for="_plugin_search2_detail">$_search_detail</label>
192 <input type="hidden" id="_plugin_search2_msg_searching" value="$_search_searching">
193 <input type="hidden" id="_plugin_search2_msg_result_notfound" value="$_search2_result_notfound">
194 <input type="hidden" id="_plugin_search2_msg_result_found" value="$_search2_result_found">
195 <input type="hidden" id="_search2_search_wait_milliseconds" value="$_search2_search_wait_milliseconds">
197 if ($h_search_text == '') {
198 $result_page_panel = '';
201 $plain_search_link = '<a href="' . $script . '?cmd=search' . '">' . htmlsc($_btn_search) . '</a>';
202 $alt_msg = str_replace('$1', $plain_search_link, $_msg_use_alternative_link);
205 <p>$_msg_unsupported_webbrowser $alt_msg</p>
207 <p class="_plugin_search2_nosupport_message" style="display:none;">
208 $_msg_unsupported_webbrowser $alt_msg
210 <form action="$script" method="GET" class="_plugin_search2_form">
212 <input type="hidden" name="cmd" value="search2">
213 <input type="search" name="q" value="$h_search_text" size="30">
214 <input type="submit" value="$_btn_search">
219 <ul id="result-list">