5ff3be1ddca7a1db20bf871af78dade1c26a173b
[moodle.git] / course / search.php
1 <?php
3 /// Displays external information about a course
5     require_once("../config.php");
6     require_once("lib.php");
8     $search    = optional_param('search', '', PARAM_RAW);  // search words
9     $page      = optional_param('page', 0, PARAM_INT);     // which page to show
10     $perpage   = optional_param('perpage', 10, PARAM_INT); // how many per page
11     $moveto    = optional_param('moveto', 0, PARAM_INT);   // move to category
12     $edit      = optional_param('edit', -1, PARAM_BOOL);
13     $hide      = optional_param('hide', 0, PARAM_INT);
14     $show      = optional_param('show', 0, PARAM_INT);
15     $blocklist = optional_param('blocklist', 0, PARAM_INT);
16     $modulelist= optional_param('modulelist', '', PARAM_PLUGIN);
18     // List of minimum capabilities which user need to have for editing/moving course
19     $capabilities = array('moodle/course:create', 'moodle/category:manage');
21     // List of category id's in which current user has course:create and category:manage capability.
22     $usercatlist = array();
24     // List of parent category id's
25     $catparentlist = array();
27     //Populate usercatlist with list of category id's with required capabilities.
28     make_categories_list($usercatlist, $catparentlist, $capabilities);
30     $search = trim(strip_tags($search)); // trim & clean raw searched string
31     if ($search) {
32         $searchterms = explode(" ", $search);    // Search for words independently
33         foreach ($searchterms as $key => $searchterm) {
34             if (strlen($searchterm) < 2) {
35                 unset($searchterms[$key]);
36             }
37         }
38         $search = trim(implode(" ", $searchterms));
39     }
41     $site = get_site();
43     $urlparams = array();
44     foreach (array('search', 'page', 'blocklist', 'modulelist', 'edit') as $param) {
45         if (!empty($$param)) {
46             $urlparams[$param] = $$param;
47         }
48     }
49     if ($perpage != 10) {
50         $urlparams['perpage'] = $perpage;
51     }
52     $PAGE->set_url('/course/search.php', $urlparams);
53     $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
54     $PAGE->set_pagelayout('standard');
56     if ($CFG->forcelogin) {
57         require_login();
58     }
60     //Editing is possible if user have system or category level create and manage capability
61     if (can_edit_in_category() || !empty($usercatlist)) {
62         if ($edit !== -1) {
63             $USER->editing = $edit;
64         }
65         $adminediting = $PAGE->user_is_editing();
66     } else {
67         $adminediting = false;
68     }
70 /// Editing functions
71     if (has_capability('moodle/course:visibility', get_context_instance(CONTEXT_SYSTEM))) {
72     /// Hide or show a course
73         if ($hide or $show and confirm_sesskey()) {
74             if ($hide) {
75                 $course = $DB->get_record("course", array("id"=>$hide));
76                 $visible = 0;
77             } else {
78                 $course = $DB->get_record("course", array("id"=>$show));
79                 $visible = 1;
80             }
81             if ($course) {
82                 $DB->set_field("course", "visible", $visible, array("id"=>$course->id));
83             }
84         }
85     }
87     if (has_any_capability($capabilities, get_context_instance(CONTEXT_SYSTEM)) && ($perpage != 99999)) {
88         $perpage = 30;
89     }
91     $displaylist = array();
92     $parentlist = array();
93     make_categories_list($displaylist, $parentlist);
95     $strcourses = get_string("courses");
96     $strsearch = get_string("search");
97     $strsearchresults = get_string("searchresults");
98     $strcategory = get_string("category");
99     $strselect   = get_string("select");
100     $strselectall = get_string("selectall");
101     $strdeselectall = get_string("deselectall");
102     $stredit = get_string("edit");
103     $strfrontpage = get_string('frontpage', 'admin');
104     $strnovalidcourses = get_string('novalidcourses');
106     if (empty($search) and empty($blocklist) and empty($modulelist) and empty($moveto) and ($edit != -1)) {
107         $PAGE->navbar->add($strcourses, new moodle_url('/course/index.php'));
108         $PAGE->navbar->add($strsearch);
109         $PAGE->set_title("$site->fullname : $strsearch");
110         $PAGE->set_heading($site->fullname);
112         echo $OUTPUT->header();
113         echo $OUTPUT->box_start();
114         echo "<center>";
115         echo "<br />";
116         print_course_search("", false, "plain");
117         echo "<br /><p>";
118         print_string("searchhelp");
119         echo "</p>";
120         echo "</center>";
121         echo $OUTPUT->box_end();
122         echo $OUTPUT->footer();
123         exit;
124     }
126     $courses = array();
127     if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) {   // Some courses are being moved
128         if (!$destcategory = $DB->get_record("course_categories", array("id" => $moveto))) {
129             print_error('cannotfindcategory', '', '', $moveto);
130         }
132         //User should have manage and create capablity on destination category.
133         require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $moveto));
134         require_capability('moodle/course:create', get_context_instance(CONTEXT_COURSECAT, $moveto));
136         foreach ( $data as $key => $value ) {
137             if (preg_match('/^c\d+$/', $key)) {
138                 $courseid = substr($key, 1);
139                 // user must have category:manage and course:create capability for the course to be moved.
140                 if (has_all_capabilities($capabilities, get_context_instance(CONTEXT_COURSE, $courseid))) {
141                     array_push($courses, $courseid);
142                 } else {
143                     print_error('cannotmovecoursetocategory');
144                 }
145             }
146         }
147         move_courses($courses, $moveto);
148     }
150     // get list of courses containing blocks if required
151     if (!empty($blocklist) and confirm_sesskey()) {
152         $blockname = $DB->get_field('block', 'name', array('id' => $blocklist));
153         $courses = array();
154         $courses = $DB->get_records_sql("
155                 SELECT * FROM {course} WHERE id IN (
156                     SELECT DISTINCT ctx.instanceid
157                     FROM {context} ctx
158                     JOIN {block_instances} bi ON bi.parentcontextid = ctx.id
159                     WHERE ctx.contextlevel = " . CONTEXT_COURSE . " AND bi.blockname = ?)",
160                 array($blockname));
161         $totalcount = count($courses);
162         //Keep only chunk of array which you want to display
163         if ($totalcount > $perpage) {
164             $courses = array_chunk($courses, $perpage, true);
165             $courses = $courses[$page];
166         }
167         foreach ($courses as $course) {
168             $courses[$course->id] = $course;
169         }
170     } elseif (!empty($modulelist) and confirm_sesskey()) { // get list of courses containing modules
171         $modulename = $modulelist;
172         $sql =  "SELECT DISTINCT c.id FROM {".$modulelist."} module, {course} c"
173             ." WHERE module.course=c.id";
175         $courseids = $DB->get_records_sql($sql);
176         $courses = array();
177         if (!empty($courseids)) {
178             $firstcourse = $page*$perpage;
179             $lastcourse = $page*$perpage + $perpage -1;
180             $i = 0;
181             foreach ($courseids as $courseid) {
182                 if ($i>= $firstcourse && $i<=$lastcourse) {
183                     $courses[$courseid->id] = $DB->get_record('course', array('id'=> $courseid->id));
184                 }
185                 $i++;
186             }
187             $totalcount = count($courseids);
188         }
189         else {
190             $totalcount = 0;
191         }
192     } else if (!empty($searchterm)) { //Donot do search for empty search request.
193         $courses = get_courses_search($searchterms, "fullname ASC",
194             $page, $perpage, $totalcount);
195     }
197     $searchform = '';
198     //Turn editing should be visible if user have system or category level capability
199     if (!empty($courses) && (can_edit_in_category() || !empty($usercatlist))) {
200         if ($PAGE->user_is_editing()) {
201             $string = get_string("turneditingoff");
202             $edit = "off";
203         } else {
204             $string = get_string("turneditingon");
205             $edit = "on";
206         }
207         $params = array_merge($urlparams, array('sesskey' => sesskey(), 'edit' => $edit));
208         $aurl = new moodle_url("$CFG->wwwroot/course/search.php", $params);
209         $searchform = $OUTPUT->single_button($aurl, $string, 'get');
210     } else {
211         $searchform = print_course_search($search, true, "navbar");
212     }
214     $PAGE->navbar->add($strcourses, new moodle_url('/course/index.php'));
215     $PAGE->navbar->add($strsearch, new moodle_url('/course/search.php'));
216     if (!empty($search)) {
217         $PAGE->navbar->add(s($search));
218     }
219     $PAGE->set_title("$site->fullname : $strsearchresults");
220     $PAGE->set_heading($site->fullname);
221     $PAGE->set_button($searchform);
223     echo $OUTPUT->header();
225     $lastcategory = -1;
226     if ($courses) {
227         echo $OUTPUT->heading("$strsearchresults: $totalcount");
228         $encodedsearch = urlencode($search);
230         // add the module/block parameter to the paging bar if they exists
231         $modulelink = "";
232         if (!empty($modulelist) and confirm_sesskey()) {
233             $modulelink = "&amp;modulelist=".$modulelist."&amp;sesskey=".sesskey();
234         } else if (!empty($blocklist) and confirm_sesskey()) {
235             $modulelink = "&amp;blocklist=".$blocklist."&amp;sesskey=".sesskey();
236         }
238         print_navigation_bar($totalcount, $page, $perpage, $encodedsearch, $modulelink);
240         // Show list of courses
241         if (!$adminediting) { //Not editing mode
242             foreach ($courses as $course) {
243                 // front page don't belong to any category and block can exist.
244                 if ($course->category > 0) {
245                     $course->summary .= "<br /><p class=\"category\">";
246                     $course->summary .= "$strcategory: <a href=\"category.php?id=$course->category\">";
247                     $course->summary .= $displaylist[$course->category];
248                     $course->summary .= "</a></p>";
249                 }
250                 print_course($course, $search);
251                 echo $OUTPUT->spacer(array('height'=>5, 'width'=>5, 'br'=>true)); // should be done with CSS instead
252             }
253         } else { //editing mode
254             echo "<form id=\"movecourses\" action=\"search.php?".$modulelink."\" method=\"post\">\n";
255             echo "<div><input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
256             echo "<input type=\"hidden\" name=\"search\" value=\"".s($search)."\" />\n";
257             echo "<input type=\"hidden\" name=\"page\" value=\"$page\" />\n";
258             echo "<input type=\"hidden\" name=\"perpage\" value=\"$perpage\" /></div>\n";
259             echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"4\" class=\"generalbox boxaligncenter\">\n<tr>\n";
260             echo "<th scope=\"col\">$strcourses</th>\n";
261             echo "<th scope=\"col\">$strcategory</th>\n";
262             echo "<th scope=\"col\">$strselect</th>\n";
263             echo "<th scope=\"col\">$stredit</th></tr>\n";
265             foreach ($courses as $course) {
267                 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
269                 $linkcss = $course->visible ? "" : " class=\"dimmed\" ";
271                 // are we displaying the front page (courseid=1)?
272                 if ($course->id == 1) {
273                     echo "<tr>\n";
274                     echo "<td><a href=\"$CFG->wwwroot\">$strfrontpage</a></td>\n";
276                     // can't do anything else with the front page
277                     echo "  <td>&nbsp;</td>\n"; // category place
278                     echo "  <td>&nbsp;</td>\n"; // select place
279                     echo "  <td>&nbsp;</td>\n"; // edit place
280                     echo "</tr>\n";
281                     continue;
282                 }
284                 echo "<tr>\n";
285                 echo "<td><a $linkcss href=\"view.php?id=$course->id\">"
286                     . highlight($search, format_string($course->fullname)) . "</a></td>\n";
287                 echo "<td>".$displaylist[$course->category]."</td>\n";
288                 echo "<td>\n";
290                 // If user has all required capabilities to move course then show selectable checkbox
291                 if (has_all_capabilities($capabilities, $coursecontext)) {
292                     echo "<input type=\"checkbox\" name=\"c$course->id\" />\n";
293                 } else {
294                     echo "<input type=\"checkbox\" name=\"c$course->id\" disabled=\"disabled\" />\n";
295                 }
297                 echo "</td>\n";
298                 echo "<td>\n";
300                 // checks whether user can update course settings
301                 if (has_capability('moodle/course:update', $coursecontext)) {
302                     echo "<a title=\"".get_string("settings")."\" href=\"$CFG->wwwroot/course/edit.php?id=$course->id\">\n<img".
303                         " src=\"" . $OUTPUT->pix_url('t/edit') . "\" class=\"iconsmall\" alt=\"".get_string("settings")."\" /></a>\n ";
304                 }
306                 // checks whether user can do role assignment
307                 if (has_capability('moodle/course:enrolreview', $coursecontext)) {
308                     echo'<a title="'.get_string('enrolledusers', 'enrol').'" href="'.$CFG->wwwroot.'/enrol/users.php?id='.$course->id.'">';
309                     echo '<img src="'.$OUTPUT->pix_url('i/users') . '" class="iconsmall" alt="'.get_string('enrolledusers', 'enrol').'" /></a> ' . "\n";
310                 }
312                 // checks whether user can delete course
313                 if (has_capability('moodle/course:delete', $coursecontext)) {
314                     echo "<a title=\"".get_string("delete")."\" href=\"delete.php?id=$course->id\">\n<img".
315                         " src=\"" . $OUTPUT->pix_url('t/delete') . "\" class=\"iconsmall\" alt=\"".get_string("delete")."\" /></a>\n ";
316                 }
318                 // checks whether user can change visibility
319                 if (has_capability('moodle/course:visibility', $coursecontext)) {
320                     if (!empty($course->visible)) {
321                         echo "<a title=\"".get_string("hide")."\" href=\"search.php?search=$encodedsearch&amp;perpage=$perpage&amp;page=$page&amp;hide=$course->id&amp;sesskey=".sesskey()."\">\n<img".
322                             " src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"".get_string("hide")."\" /></a>\n ";
323                     } else {
324                         echo "<a title=\"".get_string("show")."\" href=\"search.php?search=$encodedsearch&amp;perpage=$perpage&amp;page=$page&amp;show=$course->id&amp;sesskey=".sesskey()."\">\n<img".
325                             " src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"".get_string("show")."\" /></a>\n ";
326                     }
327                 }
329                 // checks whether user can do site backup
330                 if (has_capability('moodle/backup:backupcourse', $coursecontext)) {
331                     $backupurl = new moodle_url('/backup/backup.php', array('id' => $course->id));
332                     echo "<a title=\"".get_string("backup")."\" href=\"".$backupurl."\">\n<img".
333                         " src=\"" . $OUTPUT->pix_url('t/backup') . "\" class=\"iconsmall\" alt=\"".get_string("backup")."\" /></a>\n ";
334                 }
336                 // checks whether user can do restore
337                 if (has_capability('moodle/restore:restorecourse', $coursecontext)) {
338                     $restoreurl = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id));
339                     echo "<a title=\"".get_string("restore")."\" href=\"".$restoreurl."\">\n<img".
340                         " src=\"" . $OUTPUT->pix_url('t/restore') . "\" class=\"iconsmall\" alt=\"".get_string("restore")."\" /></a>\n ";
341                 }
343                 echo "</td>\n</tr>\n";
344             }
345             echo "<tr>\n<td colspan=\"4\" style=\"text-align:center\">\n";
346             echo "<br />";
347             echo "<input type=\"button\" onclick=\"checkall()\" value=\"$strselectall\" />\n";
348             echo "<input type=\"button\" onclick=\"checknone()\" value=\"$strdeselectall\" />\n";
349             //Select box should only show categories in which user has min capability to move course.
350             echo html_writer::select($usercatlist, 'moveto', '', array(''=>get_string('moveselectedcoursesto')), array('id'=>'movetoid'));
351             $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
352             echo "</td>\n</tr>\n";
353             echo "</table>\n</form>";
355         }
357         print_navigation_bar($totalcount,$page,$perpage,$encodedsearch,$modulelink);
359     } else {
360         if (!empty($search)) {
361             echo $OUTPUT->heading(get_string("nocoursesfound",'', s($search)));
362         }
363         else {
364             echo $OUTPUT->heading( $strnovalidcourses );
365         }
366     }
368     echo "<br /><br />";
370     print_course_search($search);
372     echo $OUTPUT->footer();
374    /**
375      * Print a list navigation bar
376      * Display page numbers, and a link for displaying all entries
377      * @param integer $totalcount - number of entry to display
378      * @param integer $page - page number
379      * @param integer $perpage - number of entry per page
380      * @param string $encodedsearch
381      * @param string $modulelink - module name
382      */
383     function print_navigation_bar($totalcount,$page,$perpage,$encodedsearch,$modulelink) {
384         global $OUTPUT;
385         echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "search.php?search=$encodedsearch".$modulelink."&perpage=$perpage");
387         //display
388         if ($perpage != 99999 && $totalcount > $perpage) {
389             echo "<center><p>";
390             echo "<a href=\"search.php?search=$encodedsearch".$modulelink."&amp;perpage=99999\">".get_string("showall", "", $totalcount)."</a>";
391             echo "</p></center>";
392         } else if ($perpage === 99999) {
393             $defaultperpage = 10;
394             //If user has course:create or category:manage capability the show 30 records.
395             $capabilities = array('moodle/course:create', 'moodle/category:manage');
396             if (has_any_capability($capabilities, get_context_instance(CONTEXT_SYSTEM))) {
397                 $defaultperpage = 30;
398             }
400             echo "<center><p>";
401             echo "<a href=\"search.php?search=$encodedsearch".$modulelink."&amp;perpage=".$defaultperpage."\">".get_string("showperpage", "", $defaultperpage)."</a>";
402             echo "</p></center>";
403         }
404     }