MDL-11719 increased size of idnumber in user table - needed for some enrolment plugin...
[moodle.git] / search / query.php
1 <?php
2     /**
3     * Global Search Engine for Moodle
4     *
5     * @package search
6     * @category core
7     * @subpackage search_engine
8     * @author Michael Champanis (mchampan) [cynnical@gmail.com], Valery Fremaux [valery.fremaux@club-internet.fr] > 1.8
9     * @date 2008/03/31
10     * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
11     *
12     * The query page - accepts a user-entered query string and returns results.
13     *
14     * Queries are boolean-aware, e.g.:
15     *
16     * '+'      term required
17     * '-'      term must not be present
18     * ''       (no modifier) term's presence increases rank, but isn't required
19     * 'field:' search this field
20     *
21     * Examples:
22     *
23     * 'earthquake +author:michael'
24     *   Searches for documents written by 'michael' that contain 'earthquake'
25     *
26     * 'earthquake +doctype:wiki'
27     *   Search all wiki pages for 'earthquake'
28     *
29     * '+author:helen +author:foster'
30     *   All articles written by Helen Foster
31     *
32     */
33     
34     /**
35     * includes and requires
36     */
37     require_once('../config.php');
38     require_once("$CFG->dirroot/search/lib.php");
41     if ($CFG->forcelogin) {
42         require_login();
43     }
44     
45     if (empty($CFG->enableglobalsearch)) {
46         error(get_string('globalsearchdisabled', 'search'));
47     }
48     
49     $adv = new Object();
50     
51 /// check for php5, but don't die yet (see line 52)
53     require_once("{$CFG->dirroot}/search/querylib.php");
55     $page_number  = optional_param('page', -1, PARAM_INT);
56     $pages        = ($page_number == -1) ? false : true;
57     $advanced     = (optional_param('a', '0', PARAM_INT) == '1') ? true : false;
58     $query_string = optional_param('query_string', '', PARAM_CLEAN);
60     if ($pages && isset($_SESSION['search_advanced_query'])) {
61         // if both are set, then we are busy browsing through the result pages of an advanced query
62         $adv = unserialize($_SESSION['search_advanced_query']);
63     } else if ($advanced) {
64         // otherwise we are dealing with a new advanced query
65         unset($_SESSION['search_advanced_query']);
66         session_unregister('search_advanced_query');
67         
68         // chars to strip from strings (whitespace)
69         $chars = " \t\n\r\0\x0B,-+";
70         
71         // retrieve advanced query variables
72         $adv->mustappear  = trim(optional_param('mustappear', '', PARAM_CLEAN), $chars);
73         $adv->notappear   = trim(optional_param('notappear', '', PARAM_CLEAN), $chars);
74         $adv->canappear   = trim(optional_param('canappear', '', PARAM_CLEAN), $chars);
75         $adv->module      = optional_param('module', '', PARAM_CLEAN);
76         $adv->title       = trim(optional_param('title', '', PARAM_CLEAN), $chars);
77         $adv->author      = trim(optional_param('author', '', PARAM_CLEAN), $chars);
78     } 
80     if ($advanced) {
81         //parse the advanced variables into a query string
82         //TODO: move out to external query class (QueryParse?)
83         
84         $query_string = '';
85         
86         // get all available module types
87         $module_types = array_merge(array('all'), array_values(search_get_document_types()));
88         $adv->module = in_array($adv->module, $module_types) ? $adv->module : 'all';
89         
90         // convert '1 2' into '+1 +2' for required words field
91         if (strlen(trim($adv->mustappear)) > 0) {
92             $query_string  = ' +'.implode(' +', preg_split("/[\s,;]+/", $adv->mustappear));
93         } 
94         
95         // convert '1 2' into '-1 -2' for not wanted words field
96         if (strlen(trim($adv->notappear)) > 0) {
97             $query_string .= ' -'.implode(' -', preg_split("/[\s,;]+/", $adv->notappear));
98         } 
99         
100         // this field is left untouched, apart from whitespace being stripped
101         if (strlen(trim($adv->canappear)) > 0) {
102             $query_string .= ' '.implode(' ', preg_split("/[\s,;]+/", $adv->canappear));
103         } 
104         
105         // add module restriction
106         $doctypestr = get_string('doctype', 'search');
107         $titlestr = get_string('title', 'search');
108         $authorstr = get_string('author', 'search');
109         if ($adv->module != 'all') {
110             $query_string .= " +{$doctypestr}:".$adv->module;
111         } 
112         
113         // create title search string
114         if (strlen(trim($adv->title)) > 0) {
115             $query_string .= " +{$titlestr}:".implode(" +{$titlestr}:", preg_split("/[\s,;]+/", $adv->title));
116         } 
117         
118         // create author search string
119         if (strlen(trim($adv->author)) > 0) {
120             $query_string .= " +{$authorstr}:".implode(" +{$authorstr}:", preg_split("/[\s,;]+/", $adv->author));
121         } 
122         
123         // save our options if the query is valid
124         if (!empty($query_string)) {
125             $_SESSION['search_advanced_query'] = serialize($adv);
126         } 
127     } 
129     // normalise page number
130     if ($page_number < 1) {
131         $page_number = 1;
132     } 
134     //run the query against the index
135     $sq = new SearchQuery($query_string, $page_number, 10, false);
137     if (!$site = get_site()) {
138         redirect("index.php");
139     } 
140     
141     $strsearch = get_string('search', 'search');
142     $strquery  = get_string('enteryoursearchquery', 'search');
143     
144 //    if ($CFG->version < 2007032200){ NOT RELIABLE
145     if (!function_exists('build_navigation')){
146         print_header("$site->shortname: $strsearch: $strquery", "$site->fullname",
147                "<a href=\"index.php\">$strsearch</a> -> $strquery");
148     } else {
149         $navlinks[] = array('name' => $strsearch, 'link' => "index.php", 'type' => 'misc');
150         $navlinks[] = array('name' => $strquery, 'link' => null, 'type' => 'misc');
151         $navigation = build_navigation($navlinks);
152         $site = get_site();
153         print_header("$strsearch", "$site->fullname" , $navigation, "", "", true, "&nbsp;", navmenu($site));
154     }
155     
156     print_box_start();
157     print_heading($strquery);
158     
159     print_box_start();
160     
161     $vars = get_object_vars($adv);
162     
163     if (isset($vars)) {
164         foreach ($vars as $key => $value) {
165             // htmlentities breaks non-ascii chars
166             $adv->key = stripslashes($value);
167             //$adv->$key = stripslashes(htmlentities($value));
168         } 
169     }
170     ?>
171     
172     <form id="query" method="get" action="query.php">
173     <?php 
174     if (!$advanced) { 
175     ?>
176         <input type="text" name="query_string" length="50" value="<?php print stripslashes($query_string) ?>" />
177         &nbsp;<input type="submit" value="<?php print_string('search', 'search') ?>" /> &nbsp;
178         <a href="query.php?a=1"><?php print_string('advancedsearch', 'search') ?></a> |
179         <a href="stats.php"><?php print_string('statistics', 'search') ?></a>
180     <?php 
181     } else {
182         print_box_start();
183       ?>
184         <input type="hidden" name="a" value="<?php print $advanced; ?>"/>
185     
186         <table border="0" cellpadding="3" cellspacing="3">
187     
188         <tr>
189           <td width="240"><?php print_string('thesewordsmustappear', 'search') ?>:</td>
190           <td><input type="text" name="mustappear" length="50" value="<?php print $adv->mustappear; ?>" /></td>
191         </tr>
192     
193         <tr>
194           <td><?php print_string('thesewordsmustnotappear', 'search') ?>:</td>
195           <td><input type="text" name="notappear" length="50" value="<?php print $adv->notappear; ?>" /></td>
196         </tr>
197     
198         <tr>
199           <td><?php print_string('thesewordshelpimproverank', 'search') ?>:</td>
200           <td><input type="text" name="canappear" length="50" value="<?php print $adv->canappear; ?>" /></td>
201         </tr>
202     
203         <tr>
204           <td><?php print_string('whichmodulestosearch?', 'search') ?>:</td>
205           <td>
206             <select name="module">
207     <?php 
208         foreach($module_types as $mod) {
209             if ($mod == $adv->module) {
210                 if ($mod != 'all'){
211                     print "<option value='$mod' selected=\"selected\">".get_string('modulenameplural', $mod)."</option>\n";
212                 }
213                 else{
214                     print "<option value='$mod' selected=\"selected\">".get_string('all', 'search')."</option>\n";
215                 }
216             } 
217             else {
218                 if ($mod != 'all'){
219                     print "<option value='$mod'>".get_string('modulenameplural', $mod)."</option>\n";
220                 }
221                 else{
222                     print "<option value='$mod'>".get_string('all', 'search')."</option>\n";
223                 }
224             } 
225         } 
226     ?>
227             </select>
228           </td>
229         </tr>
230     
231         <tr>
232           <td><?php print_string('wordsintitle', 'search') ?>:</td>
233           <td><input type="text" name="title" length="50" value="<?php print $adv->title; ?>" /></td>
234         </tr>
235     
236         <tr>
237           <td><?php print_string('authorname', 'search') ?>:</td>
238           <td><input type="text" name="author" length="50" value="<?php print $adv->author; ?>" /></td>
239         </tr>
240     
241         <tr>
242           <td colspan="3" align="center"><br /><input type="submit" value="<?php print_string('search', 'search') ?>" /></td>
243         </tr>
244     
245         <tr>
246           <td colspan="3" align="center">
247             <table border="0" cellpadding="0" cellspacing="0">
248               <tr>
249                 <td><a href="query.php"><?php print_string('normalsearch', 'search') ?></a> |</td>
250                 <td>&nbsp;<a href="stats.php"><?php print_string('statistics', 'search') ?></a></td>
251               </tr>
252             </table>
253           </td>
254         </tr>
255         </table>
256     <?php
257         print_box_end();
258         } 
259     ?>
260     </form>
261     <br/>
262     
263     <div align="center">
264     <?php
265     print_string('searching', 'search') . ': ';
266     
267     if ($sq->is_valid_index()) {
268         //use cached variable to show up-to-date index size (takes deletions into account)
269         print $CFG->search_index_size;
270     } else {
271         print "0";
272     } 
273     
274     print ' ';
275     print_string('documents', 'search');
276     print '.';
277     
278     if (!$sq->is_valid_index() and isadmin()) {
279         print '<p>' . get_string('noindexmessage', 'search') . '<a href="indexersplash.php">' . get_string('createanindex', 'search')."</a></p>\n";
280     } 
281     
282     ?>
283     </div>
284     <?php
285     print_box_end();
286     
287     // prints all the results in a box
288     if ($sq->is_valid()) {
289         print_box_start();
290         
291         search_stopwatch();
292         $hit_count = $sq->count();
293         
294         print "<br />";
295         
296         print $hit_count.' '.get_string('resultsreturnedfor', 'search') . " '".stripslashes($query_string)."'.";
297         print "<br />";
298         
299         if ($hit_count > 0) {
300             $page_links = $sq->page_numbers();
301             $hits = $sq->results();
302             
303             if ($advanced) {
304                 // if in advanced mode, search options are saved in the session, so
305                 // we can remove the query string var from the page links, and replace
306                 // it with a=1 (Advanced = on) instead
307                 $page_links = preg_replace("/query_string=[^&]+/", 'a=1', $page_links);
308             } 
309             
310             print "<ol>";
311             
312             $typestr = get_string('type', 'search');
313             $scorestr = get_string('score', 'search');
314             $authorstr = get_string('author', 'search');
315             foreach ($hits as $listing) {
316                 //if ($CFG->unicodedb) {
317                 //$listing->title = mb_convert_encoding($listing->title, 'auto', 'UTF8');
318                 //}
319                 $title_post_processing_function = $listing->doctype.'_link_post_processing';
320                 require_once "{$CFG->dirroot}/search/documents/{$listing->doctype}_document.php";
321                 if (function_exists($title_post_processing_function)) {
322                     $listing->title = $title_post_processing_function($listing->title);
323                 }
324     
325                 print "<li value='".($listing->number+1)."'><a href='".str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)."'>$listing->title</a><br />\n"
326                    ."<em>".search_shorten_url($listing->url, 70)."</em><br />\n"
327                    ."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3);
328                 if (!empty($listing->author)){
329                     print ", {$authorstr}: ".$listing->author."\n"
330                         ."</li>\n";
331                 }
332             }            
333             print "</ol>";
334             print $page_links;
335         }     
336         print_box_end();
337     ?>
338     <div align="center">
339     <?php 
340         print_string('ittook', 'search');
341         search_stopwatch(); 
342         print_string('tofetchtheseresults', 'search');
343     ?>.
344     </div>
345     
346     <?php
347     }
348     print_box_end();
349     print_footer();
350 ?>