r336: Smart query caching is done
[bugdar.git] / search.php
1 <?php
2 /*=====================================================================*\
3 || ################################################################### ||
4 || # BugStrike [#]version[#]
5 || # --------------------------------------------------------------- # ||
6 || # Copyright ©2002-[#]year[#] by Iris Studios, Inc. All Rights Reserved. # ||
7 || # This file may not be reproduced in any way without permission. # ||
8 || # --------------------------------------------------------------- # ||
9 || # User License Agreement at http://www.iris-studios.com/license/ # ||
10 || ################################################################### ||
11 \*=====================================================================*/
12
13 $fetchtemplates = array(
14 'search',
15 'pcv_select_row',
16 'search_results'
17 );
18
19 define('SVN', '$Id$');
20
21 $focus['search'] = 'focus';
22
23 require_once('./global.php');
24
25 if (!can_perform('cansearch'))
26 {
27 $message->error_permission();
28 }
29
30 define('MODE', intval($bugsys->in['mode']));
31 define('MODE_ANY', ((MODE == 1) ? 1 : 0));
32 define('MODE_ALL', ((MODE == 2) ? 1 : 0));
33 define('MODE_RAW', ((MODE == 3) ? 1 : 0));
34
35 define('SEARCH_WORD_MIN', 3);
36
37 $show['search'] = true;
38
39 // ###################################################################
40
41 if (empty($_REQUEST['do']))
42 {
43 $_REQUEST['do'] = 'search';
44 }
45
46 // ###################################################################
47
48 if ($_REQUEST['do'] == 'process')
49 {
50 // -------------------------------------------------------------------
51 // parse out our product/component/version
52 $pcv = parse_pcv_select($bugsys->in['pcv_select']);
53
54 // -------------------------------------------------------------------
55 // handle keywords
56 if ($bugsys->in['summary'])
57 {
58 $keywords = preg_split('#\s+#', $bugsys->in['summary']);
59
60 // #*# need to have some str to bool conversions
61
62 foreach ($keywords AS $word)
63 {
64 if (strlen($word) < SEARCH_WORD_MIN)
65 {
66 continue;
67 }
68
69 if (MODE_ALL)
70 {
71 $querybuild['text'] .= " +$word";
72 }
73 else
74 {
75 $querybuild['text'] .= " $word";
76 }
77
78 if (!preg_match('#-(.+?)#', trim($word)))
79 {
80 $hilight .= " $word";
81 }
82 }
83
84 $hilight = preg_replace('#[^0-9a-zA-Z_ ]#', '', $hilight);
85 $hilight = trim($hilight);
86 $hilight = preg_replace('#\s#', '+', $hilight);
87
88 $temp = trim($querybuild['text']);
89
90 if (MODE_ALL OR MODE_RAW)
91 {
92 $bool_flag = ' IN BOOLEAN MODE';
93 }
94
95 $querybuild['text'] = "AND\n\t\t\t(\n\t\t\t\tMATCH (bug.summary) AGAINST ('$temp'$bool_flag)\n\t\t\t\tOR MATCH (comment.comment) AGAINST ('$temp'$bool_flag)\n\t\t\t)";
96 }
97
98 // -------------------------------------------------------------------
99 // reporter
100 if ($bugsys->in['reporter'])
101 {
102 // force email or name?? make a distinction?
103 // more elegant way to do this? probably
104 $user = $db->query_first("SELECT * FROM user WHERE email = '" . $bugsys->in['reporter'] . "' OR MATCH (displayname) AGAINST ('" . $bugsys->in['reporter'] . "')");
105 if ($user['userid'])
106 {
107 $querybuild['reporter'] = "AND bug.userid = $user[userid] OR comment.userid = $user[userid]";
108 }
109 }
110
111 // -------------------------------------------------------------------
112 // product/component/version stuff
113 if (is_array($bugsys->in['pcv']))
114 {
115 $querybuild['pcv'] = "AND bug.productid = $pcv[product] AND bug.componentid = $pcv[component] AND bug.versionid = $pcv[version]";
116 }
117
118 // -------------------------------------------------------------------
119 // severity, priority, status, resolution, assignedto
120
121 // severity
122 if ($bugsys->in['severity'])
123 {
124 $querybuild['severity'] = "AND bug.severity = " . intval($bugsys->in['severity']);
125 }
126
127 // priority
128 if ($bugsys->in['priority'])
129 {
130 $querybuild['priority'] = "AND bug.priority = " . intval($bugsys->in['priority']);
131 }
132
133 // status
134 if ($bugsys->in['status'])
135 {
136 $querybuild['status'] = "AND bug.status = " . intval($bugsys->in['status']);
137 }
138
139 // resolution
140 if ($bugsys->in['resolution'])
141 {
142 $querybuild['resolution'] = "AND bug.resolution = " . intval($bugsys->in['resolution']);
143 }
144
145 // assignment
146 if ($bugsys->in['assignedto'])
147 {
148 $querybuild['assignedto'] = "AND bug.assignedto = " . intval($bugsys->in['assignedto']);
149 }
150
151 // -------------------------------------------------------------------
152 // date
153 if ($bugsys->in['date'])
154 {
155 // now - (seconds/day * number of days)
156 $dateline = time() - (intval($bugsys->in['date']) * 3600);
157 $querybuild['date'] = "AND bug.dateline >= $dateline";
158 }
159
160 // -------------------------------------------------------------------
161 // favourites
162 if ($bugsys->in['favourite'] AND $bugsys->userinfo['userid'])
163 {
164 $favourites = $db->query("SELECT * FROM " . TABLE_PREFIX . "favourite WHERE userid = " . $bugsys->userinfo['userid']);
165 while ($favourite = $db->fetch_array($favourites))
166 {
167 $ids[] = $favourite['bugid'];
168 }
169 $querybuild['favourites'] = "AND bug.bugid IN (" . implode(', ', $ids) . ")";
170 }
171
172 // -------------------------------------------------------------------
173 // sort by
174 $sortby = array('bugid', 'severity', 'priority', 'status', 'resolution', 'dateline');
175 $orderby = array('ASC', 'DESC');
176 $bugsys->in['orderby'] = strtoupper($bugsys->in['orderby']);
177 if (in_array($bugsys->in['sortby'], $sortby) AND in_array($bugsys->in['orderby'], $orderby))
178 {
179 $sortclause = "ORDER BY " . $bugsys->in['sortby'] . ' ' . $bugsys->in['orderby'];
180 }
181 else if ($bugsys->in['sortby'] == 'relevance')
182 {
183 $sortclause = '';
184 }
185 else
186 {
187 $sortclause = '';
188 }
189
190 // -------------------------------------------------------------------
191 // custom fields
192 $fields_fetch = $bugsys->db->query("
193 SELECT bugfield.*
194 FROM " . TABLE_PREFIX . "bugfield AS bugfield
195 LEFT JOIN " . TABLE_PREFIX . "bugfieldpermission AS permission
196 ON (bugfield.fieldid = permission.fieldid)
197 WHERE permission.mask <> 0
198 AND permission.usergroupid = {$bugsys->userinfo['usergroupid']}
199 AND bugfield.cansearch = 1"
200 );
201 while ($field = $bugsys->db->fetch_array($fields_fetch))
202 {
203 if (!empty($bugsys->in['custom']["$field[fieldid]"]) OR ($field['type'] == 'select_single' AND isset($bugsys->in['custom']["$field[fieldid]"])))
204 {
205 if ($field['type'] == 'input_checkbox')
206 {
207 $querybuild[] = "AND bugfieldvalue.field$field[fieldid] = " . (($bugsys->in['custom']["$field[fieldid]"] == 1) ? 0 : 1);
208 }
209 else if ($field['type'] == 'input_text')
210 {
211 $querybuild[] = "AND bugfieldvalue.field$field[fieldid] LIKE '%" . $bugsys->in['custom']["$field[fieldid]"] . "%'";
212 }
213 else if ($field['type'] == 'select_single' AND $bugsys->in['custom']["$field[fieldid]"] != -1)
214 {
215 $temp = unserialize($field['selects']);
216 $querybuild[] = "AND bugfieldvalue.field$field[fieldid] = '" . trim($temp[ intval($bugsys->in['custom']["$field[fieldid]"]) ]) . "'";
217 }
218 }
219 }
220
221 // -------------------------------------------------------------------
222 // have to search something
223 if (count($querybuild) < 1)
224 {
225 $message->error('you need to search for something!');
226 }
227
228 // -------------------------------------------------------------------
229 // do the search
230 $query = "
231 SELECT bug.*, comment.commentid,
232 user1.displayname AS firstreport,
233 user2.displayname AS lastpost
234 FROM " . TABLE_PREFIX . "bug AS bug
235 LEFT JOIN " . TABLE_PREFIX . "comment AS comment
236 ON (bug.bugid = comment.bugid)
237 LEFT JOIN " . TABLE_PREFIX . "user AS user1
238 ON (bug.userid = user1.userid)
239 LEFT JOIN " . TABLE_PREFIX . "user AS user2
240 ON (bug.lastpostby = user2.userid)
241 LEFT JOIN " . TABLE_PREFIX . "bugvaluefill AS bugfieldvalue
242 ON (bug.bugid = bugfieldvalue.bugid)
243 WHERE bug.bugid <> 0
244 " . implode("\n\t\t", $querybuild) . ((!can_perform('canviewhidden')) ? "
245 AND !bug.hidden
246 AND !comment.hidden" : "") . "
247 GROUP BY bug.bugid
248 $sortclause";
249
250 $search = $db->query($query);
251
252 $numrows = $db->num_rows($search);
253
254 if ($numrows < 1)
255 {
256 $message->error('no results found');
257 }
258
259 while ($result = $db->fetch_array($search))
260 {
261 $ids[] = $result['bugid'];
262 $results[] = $result;
263 }
264
265 if ($bugsys->userinfo['userid'])
266 {
267 $db->query("
268 REPLACE INTO " . TABLE_PREFIX . "search
269 (userid, dateline, query, ids, orderby, hilight)
270 VALUES
271 (" . $bugsys->userinfo['userid'] . ",
272 " . TIMENOW . ", '" . $bugsys->escape($query) . "',
273 '" . implode(',', $ids) . "', '" . $bugsys->escape($sortclause) . "',
274 '" . $bugsys->escape($hilight) . "'
275 )"
276 );
277 }
278
279 $justprocess = true;
280
281 $_REQUEST['do'] = 'results';
282 }
283
284 // ###################################################################
285
286 if ($_REQUEST['do'] == 'search')
287 {
288 if ($bugsys->userinfo['userid'] AND !$bugsys->in['new'])
289 {
290 if ($cachedsearch = $db->query_first("SELECT * FROM " . TABLE_PREFIX . "search WHERE userid = " . $bugsys->userinfo['userid']))
291 {
292 $_REQUEST['do'] = 'results';
293 }
294 else
295 {
296 $newsearch = true;
297 }
298 }
299 else
300 {
301 $newsearch = true;
302 }
303
304 if ($newsearch)
305 {
306 $pcv_select = construct_pcv_select('radio', '--');
307
308 // -------------------------------------------------------------------
309 // custom fields
310 $fields = construct_custom_fields($bug, true, true);
311
312 $bugsys->debug(count($fields) % 2);
313 $i = 1;
314 foreach ($fields AS $field)
315 {
316 $bugsys->debug("i = $i");
317 if ($i == 1)
318 {
319 $left = $field;
320 }
321 else if ($i == 2)
322 {
323 $right = $field;
324 eval('$customfields .= "' . $template->fetch('customfield_bit') . '";');
325 $i = 0;
326 }
327 $i++;
328 }
329
330 if ((count($fields) % 2) != 0)
331 {
332 $bugsys->debug('no modulo for you');
333 $right = '';
334 eval('$customfields .= "' . $template->fetch('customfield_bit') . '";');
335 }
336
337 // -------------------------------------------------------------------
338 // built-in fields
339 $select['severity'] = construct_datastore_select('severity', 'severity', 'severityid', 0, true);
340 $select['priority'] = construct_datastore_select('priority', 'priority', 'priorityid', 0, true);
341 $select['status'] = construct_datastore_select('status', 'status', 'statusid', 0, true);
342 $select['resolution'] = construct_datastore_select('resolution', 'resolution', 'resolutionid', 0, true);
343
344 $select['dev'] = '<option value="0" selected="selected"></option>';
345 foreach ($bugsys->datastore['assignto'] AS $dev)
346 {
347 $value = $dev['userid'];
348 $label = construct_user_display($dev, false);
349 eval('$select[dev] .= "' . $template->fetch('selectoption') . '";');
350 }
351
352 eval('$template->flush("' . $template->fetch('search') . '");');
353 }
354 }
355
356 // ###################################################################
357
358 if ($_REQUEST['do'] == 'results')
359 {
360 $show['cached'] = false;
361 if ($bugsys->userinfo['userid'] AND !$justprocess)
362 {
363 $search = $cachedsearch;
364 if ($search['dateline'] < TIMENOW - 900 OR $bugsys->in['rerun'])
365 {
366 $search = $db->query($search['query']);
367 while ($bug = $db->fetch_array($search))
368 {
369 $ids[] = $bug['bugid'];
370 $results[] = $bug;
371 }
372 $db->query("UPDATE " . TABLE_PREFIX . "search SET ids = '" . implode(',', $ids) . "', dateline = " . TIMENOW . " WHERE userid = " . $bugsys->userinfo['userid']);
373 }
374 else
375 {
376 $search = $db->query("
377 SELECT bug.*, user1.displayname AS firstreport,
378 user2.displayname AS lastpost
379 FROM " . TABLE_PREFIX . "bug AS bug
380 LEFT JOIN " . TABLE_PREFIX . "user AS user1
381 ON (bug.userid = user1.userid)
382 LEFT JOIN " . TABLE_PREFIX . "user AS user2
383 ON (bug.lastpostby = user2.userid)
384 WHERE bug.bugid IN ($search[ids])" . ($search['orderby'] ? "
385 ORDER BY $search[orderby]" : '')
386 );
387 while ($bug = $db->fetch_array($search))
388 {
389 $results[] = $bug;
390 }
391 }
392 $show['cached'] = true;
393 $hilight = $search['hilight'];
394 }
395
396 foreach ($results AS $bug)
397 {
398 $bug['bgcolour'] = $bugsys->datastore['status']["$bug[status]"]['color'];
399 $bug['product'] = $bugsys->datastore['product']["$bug[productid]"]['title'];
400 $bug['version'] = $bugsys->datastore['version']["$bug[versionid]"]['version'];
401 $bug['status'] = $bugsys->datastore['status']["$bug[status]"]['status'];
402 $bug['resolution'] = $bugsys->datastore['resolution']["$bug[resolution]"]['resolution'];
403 $bug['lastposttime'] = (($bug['hiddendisplay']) ? $bug['hiddenlastposttime'] : $bug['lastposttime']);
404 $bug['lastpost'] = (($bug['hiddendisplay']) ? $bug['hiddenlastpost'] : $bug['lastpost']);
405 $bug['lastposttime'] = $datef->format($bugsys->options['dateformat'], $bug['lastposttime']);
406 $bug['urladd'] = "&amp;hilight=$hilight";
407 eval('$bugs .= "' . $template->fetch('trackerhome_bits') . '";');
408 }
409
410 eval('$template->flush("' . $template->fetch('search_results') . '");');
411 }
412
413 /*=====================================================================*\
414 || ###################################################################
415 || # $HeadURL$
416 || # $Id$
417 || ###################################################################
418 \*=====================================================================*/
419 ?>