OSDN Git Service

648398839ce98b246dbd3b79475e2b2f9de7f0d4
[pukiwiki/pukiwiki.git] / plugin / search2.inc.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone.
3 // search2.inc.php
4 // Copyright 2017 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Search2 plugin - Show detail result using JavaScript
8
9 define('PLUGIN_SEARCH2_MAX_LENGTH', 80);
10 define('PLUGIN_SEARCH2_MAX_BASE',   16); // #search(1,2,3,...,15,16)
11
12 define('PLUGIN_SEARCH2_RESULT_RECORD_LIMIT', 500);
13 define('PLUGIN_SEARCH2_RESULT_RECORD_LIMIT_START', 100);
14
15 // Show a search box on a page
16 function plugin_search2_convert()
17 {
18         $args = func_get_args();
19         return plugin_search_search_form('', '', $args);
20 }
21
22 function plugin_search2_action()
23 {
24         global $vars, $_title_search, $_title_result;
25
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;
30         $bases = array();
31         if ($base !== '') {
32                 $bases[] = $base;
33         }
34         if ($action === '') {
35                 $q = isset($vars['q']) ? $vars['q'] : '';
36                 if ($q === '') {
37                         return array('msg' => $_title_search,
38                                 'body' => plugin_search2_search_form($q, '', $bases));
39                 } else {
40                         $msg  = str_replace('$1', htmlsc($q), $_title_result);
41                         return array('msg' => $msg,
42                                         'body' => plugin_search2_search_form($q, '', $bases));
43                 }
44         } else if ($action === 'query') {
45                 $text = isset($vars['q']) ? $vars['q'] : '';
46                 plugin_search2_do_search($text, $base, $start_index);
47                 exit;
48         }
49 }
50
51 function plugin_search2_do_search($query_text, $base, $start_index)
52 {
53         global $whatsnew, $non_list, $search_non_list;
54         global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
55         global $search_auth;
56
57         $result_record_limit = $start_index === 0 ?
58                 PLUGIN_SEARCH2_RESULT_RECORD_LIMIT_START : PLUGIN_SEARCH2_RESULT_RECORD_LIMIT;
59         $type = 'AND';
60         $word = $query_text;
61         $retval = array();
62
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';
67
68         $pages = get_existpages();
69
70         // Avoid
71         if ($base != '') {
72                 $pages = preg_grep('/^' . preg_quote($base, '/') . '/S', $pages);
73         }
74         if (! $search_non_list) {
75                 $pages = array_diff($pages, preg_grep('/' . $non_list . '/S', $pages));
76         }
77         natsort($pages);
78         $pages = array_flip($pages);
79         unset($pages[$whatsnew]);
80         $page_names = array_keys($pages);
81
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) {
88                 $b_match = FALSE;
89                 $pagename_only = false;
90                 $scan_page_index++;
91                 if (! is_page_readable($page)) {
92                         if ($search_auth) {
93                                 // $search_auth - 1: User can know page names that contain search text if the page is readable
94                                 continue;
95                         }
96                         // $search_auth - 0: All users can know page names that conntain search text
97                         $pagename_only = true;
98                 }
99                 $readable_page_index++;
100                 if ($readable_page_index < $start_index) {
101                         // Skip: It's not time to read
102                         continue;
103                 }
104                 if ($saved_scan_start_index === -1) {
105                         $saved_scan_start_index = $scan_page_index;
106                 }
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
115                 }
116                 if ($b_match) {
117                         // Found!
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);
123                         } else {
124                                 $found_pages[] = array('name' => (string)$page,
125                                 'url' => get_page_uri($page), 'body' => (string)$body);
126                         }
127                 }
128                 $last_read_page_name = $page;
129                 if ($start_index + $result_record_limit <= $readable_page_index + 1) {
130                         // Read page limit
131                         break;
132                 }
133         }
134         $s_word = htmlsc($word);
135         /*
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));
140                 return;
141         }
142         */
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));
146         $result_obj = array(
147                 'message' => $message,
148                 'q' => $word,
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));
159 }
160
161 function plugin_search2_search_form($s_word = '', $type = '', $bases = array())
162 {
163         global $_btn_search;
164         global $_search_pages, $_search_all;
165         global $_msg_andresult, $_msg_orresult, $_msg_notfoundresult;
166         global $_search_detail, $_search_searching;
167
168         $script = get_base_uri();
169         $h_search_text = htmlsc($s_word);
170
171         $base_option = '';
172         if (!empty($bases)) {
173                 $base_msg = '';
174                 $_num = 0;
175                 $check = ' checked="checked"';
176                 foreach($bases as $base) {
177                         ++$_num;
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);
183                         $base_msg  .=<<<EOD
184  <div>
185   <input type="radio" name="base" id="$label_id" value="$s_base" $check />
186   <label for="$label_id">$base_label</label>
187  </div>
188 EOD;
189                         $check = '';
190                 }
191                 $base_msg .=<<<EOD
192   <input type="radio" name="base" id="_p_search_base_id_all" value="" />
193   <label for="_p_search_base_id_all">$_search_all</label>
194 EOD;
195                 $base_option = '<div class="small">' . $base_msg . '</div>';
196         }
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">
206 EOD;
207         if ($h_search_text == '') {
208                 $result_page_panel = '';
209         }
210
211         return <<<EOD
212 <form action="$script" method="GET">
213  <div>
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">
217  </div>
218 $base_option
219 </form>
220 $result_page_panel
221 <ul id="result-list">
222 </ul>
223 EOD;
224 }