Fixed pagination in query page (lines were too long, distorting table),
[moodle.git] / search / query.php
CommitLineData
682d4032 1<?php
2
a25a3912 3 /* The query page - accepts a user-entered query string and returns results.
4 *
5 * Queries are boolean-aware, e.g.:
6 *
7 * '+' term required
8 * '-' term must not be present
9 * '' (no modifier) term's presence increases rank, but isn't required
10 * 'field:' search this field
11 *
12 * Examples:
13 *
14 * 'earthquake +author:michael'
15 * Searches for documents written by 'michael' that contain 'earthquake'
16 *
17 * 'earthquake +doctype:wiki'
18 * Search all wiki pages for 'earthquake'
19 *
20 * '+author:helen +author:foster'
21 * All articles written by Helen Foster
22 *
23 * */
24
682d4032 25 require_once('../config.php');
91ad9557 26 require_once("$CFG->dirroot/search/lib.php");
682d4032 27
28 //check for php5, but don't die yet (see line 27)
29 if ($check = search_check_php5()) {
30 require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
682d4032 31
a25a3912 32 $query_string = optional_param('query_string', '', PARAM_CLEAN);
33 $page_number = optional_param('page', 1, PARAM_INT);
34
35 if ($page_number < 1) {
36 $page_number = 1;
37 } //if
38
682d4032 39 $index_path = "$CFG->dataroot/search";
40 $no_index = false; //optimism!
a25a3912 41 $results_per_page = 10;
682d4032 42
43 try {
44 $index = new Zend_Search_Lucene($index_path, false);
45 } catch(Exception $e) {
46 //print $e;
47 $no_index = true;
48 } //catch
91ad9557 49 } //if
50
51
52 //Result document class that contains all the display information we need
53 class ResultDocument {
54 public $url,
55 $title,
56 $score,
57 $doctype,
58 $author;
59 } //ResultDocument
60
61 //generates an HTML string of links to result pages
62 function page_numbers($query, $hits, $page=1, $results_per_page=20) {
63 //total result pages
64 $pages = ceil($hits/$results_per_page);
65
66 $ret = "<div align='center'>";
67
68 //Back is disabled if we're on page 1
69 if ($page > 1) {
70 $ret .= "<a href='query.php?query_string=$query&page=".($page-1)."'>< Back</a>&nbsp;";
71 } else {
72 $ret .= "< Back&nbsp;";
73 } //else
74
75 //don't <a href> the current page
76 for ($i = 1; $i <= $pages; $i++) {
77 if ($page == $i) {
78 $ret .= "[$i]&nbsp;";
79 } else {
80 $ret .= "<a href='query.php?query_string=$query&page=$i'>$i</a>&nbsp;";
81 } //else
82 } //for
83
84 //Next disabled if we're on the last page
85 if ($page < $pages) {
86 $ret .= "<a href='query.php?query_string=$query&page=".($page+1)."'>Next ></a>&nbsp;";
87 } else {
88 $ret .= "Next >&nbsp;";
89 } //else
90
91 $ret .= "</div>";
92
93 //shorten really long page lists, to stop table distorting width-ways
94 if (strlen($ret) > 70) {
95 $start = 4;
96 $end = $page - 5;
97 $ret = preg_replace("/<a\D+\d+\D+>$start<\/a>.*?<a\D+\d+\D+>$end<\/a>/", '...', $ret);
98
99 $start = $page + 5;
100 $end = $pages - 3;
101 $ret = preg_replace("/<a\D+\d+\D+>$start<\/a>.*?<a\D+\d+\D+>$end<\/a>/", '...', $ret);
102 } //if
103
104 return $ret;
105 } //page_numbers
106
107 //calculates whether a user is allowed to see this result
108 function can_display(&$user, $course_id, $group_id) {
109 return true;
110 } //can_display
111
112 //caches the results of the last query, deletes the previous one also
113 function cache($id=false, &$object=false) {
114 //see if there was a previous query
115 $last_term = (isset($_SESSION['search_last_term'])) ? $_SESSION['search_last_term'] : false;
116
117 //if this query is different from the last, clear out the last one
118 if ($id != false and $last_term != $id) {
119 unset($_SESSION[$last_term]);
120 session_unregister($last_term);
121 } //if
122
123 //store the new query if id and object are passed in
124 if ($object and $id) {
125 $_SESSION['search_last_term'] = $id;
126 $_SESSION[$id] = $object;
127 return true;
128 //otherwise return the stored results
129 } else if ($id and isset($_SESSION[$id])) {
130 return $_SESSION[$id];
131 } //else
132 } //cache
133
682d4032 134
135 if (!$site = get_site()) {
136 redirect("index.php");
137 } //if
a25a3912 138
682d4032 139 $strsearch = "Search"; //get_string();
140 $strquery = "Enter your search query"; //get_string();
141
142 print_header("$site->shortname: $strsearch: $strquery", "$site->fullname",
143 "<a href=\"index.php\">$strsearch</a> -> $strquery");
144
145 //keep things pretty, even if php5 isn't available
146 if (!$check) {
147 print_heading(search_check_php5(true));
148 print_footer();
149 exit(0);
150 } //if
151
152 print_simple_box_start('center', '100%', '', 20);
153 print_heading($strquery);
154
155 print_simple_box_start('center', '', '', 20);
abb4ea20 156
682d4032 157?>
158
159<form name="query" method="get" action="query.php">
a25a3912 160 <input type="text" name="query_string" length="50" value="<?php print stripslashes(htmlentities($query_string)) ?>"/>
682d4032 161 &nbsp;<input type="submit" value="Search"/>&nbsp;&nbsp;<a href="query.php?advanced=yes">Advanced search</a>
162 <a href="stats.php">Statistics</a>
163</form>
164
165<br>
166
167<div align="center">
168<?php
91ad9557 169 echo 'Searching: ';
170
171 if ($no_index) {
172 print "0";
173 } else {
174 print $index->count();
175 } //else
176
177 print ' documents.';
178
179 if ($no_index and isadmin()) {
180 print "<br><br>Admin: There appears to be no index, click <a href='indexersplash.php'>here</a> to create one.";
181 } //if
682d4032 182?>
183</div>
184
185<?php
186 print_simple_box_end();
187
188 if (!empty($query_string) and !$no_index) {
189 print_simple_box_start('center', '50%', 'white', 10);
190
191 search_stopwatch();
91ad9557 192
193 //if the cache is empty
194 if (!($hits = cache($query_string))) {
195 $resultdocs = array();
196 $resultdoc = new ResultDocument;
197
198 //generate a new result-set
199 $hits = $index->find(strtolower($query_string));
200
201 foreach ($hits as $hit) {
202 //check permissions on each result
203 if (can_display($USER, $hit->course_id, $hit->group_id)) {
204 $resultdoc->url = $hit->url;
205 $resultdoc->title = $hit->title;
206 $resultdoc->score = $hit->score;
207 $resultdoc->doctype = $hit->doctype;
208 $resultdoc->author = $hit->author;
209
210 //and store it if it passes the test
211 $resultdocs[] = clone($resultdoc);
212 } //if
213 } //foreach
214
215 //cache the results so we don't have to compute this on every page-load
216 cache($query_string, $resultdocs);
217
218 //print "Using new results.";
219 } else {
220 //There was something in the cache, so we're using that to save time
221 //print "Using cached results.";
222 } //else
223
224 $hit_count = count($hits);
682d4032 225
226 print "<br>";
227
a25a3912 228 print $hit_count." results returned for '".stripslashes($query_string)."'.";
229 print "<br>";
230
91ad9557 231 if ($hit_count > 0) {
a25a3912 232 if ($hit_count < $results_per_page) {
233 $page_number = 1;
234 } else if ($page_number > ceil($hit_count/$results_per_page)) {
235 $page_number = $hit_count/$results_per_page;
236 } //if
682d4032 237
a25a3912 238 $start = ($page_number - 1)*$results_per_page;
239 $end = $start + $results_per_page;
91ad9557 240
241 $page_links = page_numbers($query_string, $hit_count, $page_number, $results_per_page);
a25a3912 242
243 print "<ol>";
682d4032 244
a25a3912 245 for ($i = $start; $i < $end; $i++) {
246 if ($i >= $hit_count) {
247 break;
248 } //if
249
250 $listing = $hits[$i];
91ad9557 251
a25a3912 252 print "<li value='".($i+1)."'><a href='".$listing->url."'>$listing->title</a><br>\n"
253 ."<em>".search_shorten_url($listing->url, 70)."</em><br>\n"
254 ."Type: ".$listing->doctype.", score: ".round($listing->score, 3).", author: ".$listing->author."<br>\n"
255 ."<br></li>\n";
256 } //for
257
258 print "</ol>";
91ad9557 259 print $page_links;
260 } //if
682d4032 261
262 print_simple_box_end();
263 } //if
264
265 if (!empty($query_string) and !$no_index) {
266?>
267
268<div align="center">
269 It took <?php search_stopwatch(); ?> to fetch these results.
270</div>
271
272<?php
273 } //if
274
275 print_simple_box_end();
276 print_footer();
277?>