final move of files
[web.mtrack] / search.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3 include '../inc/common.php';
4
5 $q = $_GET['q'];
6
7 if (preg_match('/^#([a-zA-Z0-9]+)$/', $q, $M)) {
8   /* ticket */
9   header("Location: {$ABSWEB}ticket.php/$M[1]");
10   exit;
11 }
12 if (preg_match('/^r([a-zA-Z]*\d+)$/', $q, $M)) {
13   /* changeset */
14   $url = mtrack_changeset_url($M[1]);
15   header("Location: $url");
16   exit;
17 }
18 if (preg_match('/^\[([a-zA-Z]*\d+)\]$/', $q, $M)) {
19   /* changeset */
20   $url = mtrack_changeset_url($M[1]);
21   header("Location: $url");
22   exit;
23 }
24 if (preg_match('/^\{(\d+)\}$/', $q, $M)) {
25   /* report */
26   header("Location: {$ABSWEB}report.php/$M[1]");
27   exit;
28 }
29 mtrack_head("Search results for \"$q\"");
30
31 ?>
32 <h1>Search results</h1>
33
34 <form action="<?php echo $ABSWEB; ?>search.php">
35   <input type="text" name="q"
36     size="50"
37     value="<?php echo htmlentities($q, ENT_QUOTES, 'utf-8'); ?>">
38   <button type="submit">Search</button>
39   Read more about <a href="<?php echo $ABSWEB ; ?>help.php/Searching">Searching</a>.
40   <button id='togglesummary' type='button'>Show Fields</button>
41 <script>
42 $(document).ready(function () {
43   $('#togglesummary').click(function () {
44     $('#fieldsummary').toggle();
45   });
46 });
47 </script>
48 <div id='fieldsummary' style='display:none'>
49   <p>The following fields are available for targeted searching:</p>
50   <table>
51     <tr>
52       <th>Item</th>
53       <th>Field</th>
54       <th>Description</th>
55     </tr>
56     <tr>
57       <td>Ticket</td>
58       <td>summary</td>
59       <td>The one-line ticket summary</td>
60     </tr>
61     <tr>
62       <td>Ticket</td>
63       <td>description</td>
64       <td>The ticket description</td>
65     </tr>
66     <tr>
67       <td>Ticket</td>
68       <td>changelog</td>
69       <td>The changelog field</td>
70     </tr>
71     <tr>
72       <td>Ticket</td>
73       <td>keyword</td>
74       <td>The keyword field</td>
75     </tr>
76     <tr>
77       <td>Ticket</td>
78       <td>date</td>
79       <td>The last-changed date</td>
80     </tr>
81     <tr>
82       <td>Ticket</td>
83       <td>who</td>
84       <td>who last changed the ticket</td>
85     </tr>
86     <tr>
87       <td>Ticket</td>
88       <td>creator</td>
89       <td>who opened the ticket</td>
90     </tr>
91     <tr>
92       <td>Ticket</td>
93       <td>created</td>
94       <td>The date that the ticket was created</td>
95     </tr>
96     <tr>
97       <td>Ticket</td>
98       <td>owner</td>
99       <td>who is responsible for the ticket</td>
100     </tr>
101     <tr>
102       <td>Comment</td>
103       <td>description</td>
104       <td>The comment text</td>
105     </tr>
106     <tr>
107       <td>Comment</td>
108       <td>date</td>
109       <td>Date the comment was made</td>
110     </tr>
111     <tr>
112       <td>Comment</td>
113       <td>who</td>
114       <td>who made that comment</td>
115     </tr>
116     <tr>
117       <td>Wiki</td>
118       <td>wiki</td>
119       <td>The content from the wiki page</td>
120     </tr>
121     <tr>
122       <td>Wiki</td>
123       <td>who</td>
124       <td>Who last changed that wiki page</td>
125     </tr>
126     <tr>
127       <td>Wiki</td>
128       <td>date</td>
129       <td>Date the wiki page was last changed</td>
130     </tr>
131 <?php
132 $CF = MTrackTicket_CustomFields::getInstance();
133 foreach ($CF->fields as $f) {
134   echo "<tr><td>Ticket</td><td>$f->name</td><td>",
135     htmlentities($f->label, ENT_QUOTES, 'utf-8'),
136     "</td></tr>\n";
137 }
138 ?>
139   </table>
140
141 </div>
142 </form>
143
144 <?php
145
146 if (strlen($q)) {
147   $start = microtime(true);
148   $hits = MTrackSearchDB::search($q);
149   $end = microtime(true);
150   $elapsed = sprintf("%.2f seconds", $end - $start);
151 } else {
152   $hits = array();
153   $elapsed = '';
154 }
155 ?>
156
157
158 <p>Searching for <i>
159
160 <?php
161 echo htmlentities($q, ENT_QUOTES, 'utf-8'), "</i>:</p><br>\n";
162
163 $hits_by_object = array();
164 $objects = array();
165 /* aggregate results by canonical object; since
166  * we index comments separately from the top level
167  * item, we need to adjust for that here */
168 foreach ($hits as $hit) {
169   /* get canonical object */
170   list($item, $id) = explode(':', $hit->objectid, 3);
171
172   $object = "$item:$id";
173   if (isset($hits_by_object[$object])) {
174     if ($hit->score > $hits_by_object[$object]) {
175       $hits_by_object[$object] = $hit->score;
176       $objects[$object] = $hit;
177     }
178   } else {
179     $hits_by_object[$object] = $hit->score;
180     $objects[$object] = $hit;
181   }
182 }
183 arsort($hits_by_object);
184 ?>
185 <table class='searchresults'>
186 <?php
187
188
189
190 $denied = 0;
191 foreach ($hits_by_object as $object => $score) {
192   list($item, $id) = explode(':', $object, 2);
193   $obj = $objects[$object];
194   $score = (int)($score * 100);
195
196   $html = "<tr><td valign='right'>$score%</td><td>";
197
198   switch ($item) {
199     case 'ticket':
200       $tkt = MTrackIssue::loadByNSIdent($id);
201       if ($tkt === null) {
202         $tkt = MTrackIssue::loadById($id);
203       }
204       $aclid = "ticket:" . $tkt->tid;
205       $html .= mtrack_ticket($tkt);
206       if ($tkt->nsident) {
207         $url = "{$ABSWEB}ticket.php/$tkt->nsident";
208       } else {
209         $url = "{$ABSWEB}ticket.php/$id";
210       }
211       $html .= " <a href='$url'>";
212       $html .= htmlentities($tkt->summary, ENT_QUOTES, 'utf-8');
213       $html .= "</a>";
214       $html .= $obj->getExcerpt($tkt->description);
215
216       break;
217     case 'wiki':
218       $wiki = MTrackWikiItem::loadByPageName($id);
219       $aclid = "wiki:$id";
220       $url = "{$ABSWEB}wiki.php/$id";
221       $html .= "<a href='$url'>".
222         htmlentities($id, ENT_QUOTES, 'utf-8').
223         "</a>";
224       $html .= $obj->getExcerpt($wiki->content);
225       break;
226     default:
227       $aclid = $object;
228       $html .= $object;
229   }
230
231   if (!MTrackACL::hasAnyRights($aclid, 'read')) {
232     $denied++;
233     continue;
234   }
235
236   $html .= "</td></tr>\n";
237   echo $html;
238 }
239 echo "</table>\n";
240
241 if (!count($hits_by_object)) {
242   echo "<em>No matches</em>";
243 } else {
244   echo "<em>" . count($hits_by_object) . " results in $elapsed</em>\n";
245 }
246 if ($denied) {
247   echo "<br>Denied access to $denied items<br>\n";
248 }
249
250 mtrack_foot();