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 define('PLUGIN_SEARCH2_RESULT_RECORD_LIMIT', 500);
13 define('PLUGIN_SEARCH2_RESULT_RECORD_LIMIT_START', 100);
15 // Show a search box on a page
16 function plugin_search2_convert()
18 $args = func_get_args();
19 return plugin_search_search_form('', '', $args);
22 function plugin_search2_action()
24 global $vars, $_title_search, $_title_result;
26 $action = isset($vars['action']) ? $vars['action'] : '';
27 $base = isset($vars['base']) ? $vars['base'] : '';
28 $start_s = isset($vars['start']) ? $vars['start'] : '';
29 $start_index = pkwk_ctype_digit($start_s) ? intval($start_s) : 0;
35 $q = isset($vars['q']) ? $vars['q'] : '';
37 return array('msg' => $_title_search,
38 'body' => plugin_search2_search_form($q, '', $bases));
40 $msg = str_replace('$1', htmlsc($q), $_title_result);
41 return array('msg' => $msg,
42 'body' => plugin_search2_search_form($q, '', $bases));
44 } else if ($action === 'query') {
45 $text = isset($vars['q']) ? $vars['q'] : '';
46 plugin_search2_do_search($text, $base, $start_index);
51 function plugin_search2_do_search($query_text, $base, $start_index)
53 global $whatsnew, $non_list, $search_non_list;
54 global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
57 $result_record_limit = $start_index === 0 ?
58 PLUGIN_SEARCH2_RESULT_RECORD_LIMIT_START : PLUGIN_SEARCH2_RESULT_RECORD_LIMIT;
63 $b_type_and = ($type == 'AND'); // AND:TRUE OR:FALSE
64 $keys = get_search_words(preg_split('/\s+/', $word, -1, PREG_SPLIT_NO_EMPTY));
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 $saved_scan_start_index = -1;
86 $last_read_page_name = null;
87 foreach ($page_names as $page) {
89 $pagename_only = false;
91 if (! is_page_readable($page)) {
93 // $search_auth - 1: User can know page names that contain search text if the page is readable
96 // $search_auth - 0: All users can know page names that conntain search text
97 $pagename_only = true;
99 $readable_page_index++;
100 if ($readable_page_index < $start_index) {
101 // Skip: It's not time to read
104 if ($saved_scan_start_index === -1) {
105 $saved_scan_start_index = $scan_page_index;
107 // Search for page name and contents
108 $raw_lines = get_source($page, TRUE, FALSE);
109 $lines = remove_author_lines($raw_lines);
110 $body = join('', $raw_lines);
111 $target = $page . '\n' . join('', $lines);
112 foreach ($keys as $key) {
113 $b_match = preg_match($key, $target);
114 if ($b_type_and xor $b_match) break; // OR
118 if ($pagename_only) {
119 // The user cannot read this page body
120 $found_pages[] = array('name' => (string)$page,
121 'url' => get_page_uri($page), 'body' => '',
122 'pagename_only' => 1);
124 $found_pages[] = array('name' => (string)$page,
125 'url' => get_page_uri($page), 'body' => (string)$body);
128 $last_read_page_name = $page;
129 if ($start_index + $result_record_limit <= $readable_page_index + 1) {
134 $s_word = htmlsc($word);
136 if (empty($found_pages)) {
137 $message = str_replace('$1', $s_word, $_msg_notfoundresult);
138 $result_obj = array('message' => $message, 'results' => array());
139 print(json_encode($result_obj, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
143 $message = str_replace('$1', $s_word, str_replace('$2', count($found_pages),
144 str_replace('$3', count($page_names), $b_type_and ? $_msg_andresult : $_msg_orresult)));
145 $search_done = (boolean)($scan_page_index + 1 === count($page_names));
147 'message' => $message,
149 'start_index' => $start_index,
150 'limit' => $result_record_limit,
151 'read_page_count' => $readable_page_index - $start_index + 1,
152 'scan_page_count' => $scan_page_index - $saved_scan_start_index + 1,
153 'page_count' => count($page_names),
154 'last_read_page_name' => $last_read_page_name,
155 'next_start_index' => $readable_page_index + 1,
156 'search_done' => $search_done,
157 'results' => $found_pages);
158 print(json_encode($result_obj, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
161 function plugin_search2_search_form($s_word = '', $type = '', $bases = array())
164 global $_search_pages, $_search_all;
165 global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
166 global $_search_detail, $_search_searching;
168 $script = get_base_uri();
169 $h_search_text = htmlsc($s_word);
172 if (!empty($bases)) {
175 $check = ' checked="checked"';
176 foreach($bases as $base) {
178 if (PLUGIN_SEARCH_MAX_BASE < $_num) break;
179 $label_id = '_p_search_base_id_' . $_num;
180 $s_base = htmlsc($base);
181 $base_str = '<strong>' . $s_base . '</strong>';
182 $base_label = str_replace('$1', $base_str, $_search_pages);
185 <input type="radio" name="base" id="$label_id" value="$s_base" $check />
186 <label for="$label_id">$base_label</label>
192 <input type="radio" name="base" id="_p_search_base_id_all" value="" />
193 <label for="_p_search_base_id_all">$_search_all</label>
195 $base_option = '<div class="small">' . $base_msg . '</div>';
197 $_search2_result_notfound = htmlsc($_msg_notfoundresult);
198 $_search2_result_found = htmlsc($_msg_andresult);
199 $result_page_panel =<<<EOD
200 <div id="_plugin_search2_search_status"></div>
201 <div id="_plugin_search2_message"></div>
202 <input type="checkbox" id="_plugin_search2_detail" checked><label for="_plugin_search2_detail">$_search_detail</label>
203 <input type="hidden" id="_plugin_search2_msg_searching" value="$_search_searching">
204 <input type="hidden" id="_plugin_search2_msg_result_notfound" value="$_search2_result_notfound">
205 <input type="hidden" id="_plugin_search2_msg_result_found" value="$_search2_result_found">
207 if ($h_search_text == '') {
208 $result_page_panel = '';
212 <form action="$script" method="GET">
214 <input type="hidden" name="cmd" value="search2">
215 <input type="search" name="q" id="_plugin_search2_searchtext" value="$h_search_text" size="30">
216 <input type="submit" value="$_btn_search">
221 <ul id="result-list">