MDL-31640 course: removed extra error message, perpage is set properly, modulelink...
[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(context_system::instance());
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();
67         // Set perpage if user can edit in category
68         if ($perpage != 99999) {
69             $perpage = 30;
70         }
71     } else {
72         $adminediting = false;
73     }
75 /// Editing functions
76     if (has_capability('moodle/course:visibility', context_system::instance())) {
77     /// Hide or show a course
78         if ($hide or $show and confirm_sesskey()) {
79             if ($hide) {
80                 $course = $DB->get_record("course", array("id"=>$hide));
81                 $visible = 0;
82             } else {
83                 $course = $DB->get_record("course", array("id"=>$show));
84                 $visible = 1;
85             }
86             if ($course) {
87                 $DB->set_field("course", "visible", $visible, array("id"=>$course->id));
88             }
89         }
90     }
92     $displaylist = array();
93     $parentlist = array();
94     make_categories_list($displaylist, $parentlist);
96     $strcourses = get_string("courses");
97     $strsearch = get_string("search");
98     $strsearchresults = get_string("searchresults");
99     $strcategory = get_string("category");
100     $strselect   = get_string("select");
101     $strselectall = get_string("selectall");
102     $strdeselectall = get_string("deselectall");
103     $stredit = get_string("edit");
104     $strfrontpage = get_string('frontpage', 'admin');
105     $strnovalidcourses = get_string('novalidcourses');
107     if (empty($search) and empty($blocklist) and empty($modulelist) and empty($moveto) and ($edit != -1)) {
108         $PAGE->navbar->add($strcourses, new moodle_url('/course/index.php'));
109         $PAGE->navbar->add($strsearch);
110         $PAGE->set_title("$site->fullname : $strsearch");
111         $PAGE->set_heading($site->fullname);
113         echo $OUTPUT->header();
114         echo $OUTPUT->box_start();
115         echo "<center>";
116         echo "<br />";
117         print_course_search("", false, "plain");
118         echo "<br /><p>";
119         print_string("searchhelp");
120         echo "</p>";
121         echo "</center>";
122         echo $OUTPUT->box_end();
123         echo $OUTPUT->footer();
124         exit;
125     }
127     $courses = array();
128     if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) {   // Some courses are being moved
129         if (!$destcategory = $DB->get_record("course_categories", array("id" => $moveto))) {
130             print_error('cannotfindcategory', '', '', $moveto);
131         }
133         //User should have manage and create capablity on destination category.
134         require_capability('moodle/category:manage', context_coursecat::instance($moveto));
135         require_capability('moodle/course:create', context_coursecat::instance($moveto));
137         foreach ( $data as $key => $value ) {
138             if (preg_match('/^c\d+$/', $key)) {
139                 $courseid = substr($key, 1);
140                 // user must have category:manage and course:create capability for the course to be moved.
141                 $coursecontext = context_course::instance($courseid);
142                 foreach ($capabilities as $capability) {
143                     require_capability($capability, $coursecontext);
144                     array_push($courses, $courseid);
145                 }
146             }
147         }
148         move_courses($courses, $moveto);
149     }
151     // get list of courses containing blocks if required
152     if (!empty($blocklist) and confirm_sesskey()) {
153         $blockname = $DB->get_field('block', 'name', array('id' => $blocklist));
154         $courses = array();
155         $courses = $DB->get_records_sql("
156                 SELECT * FROM {course} WHERE id IN (
157                     SELECT DISTINCT ctx.instanceid
158                     FROM {context} ctx
159                     JOIN {block_instances} bi ON bi.parentcontextid = ctx.id
160                     WHERE ctx.contextlevel = " . CONTEXT_COURSE . " AND bi.blockname = ?)",
161                 array($blockname));
162         $totalcount = count($courses);
163         //Keep only chunk of array which you want to display
164         if ($totalcount > $perpage) {
165             $courses = array_chunk($courses, $perpage, true);
166             $courses = $courses[$page];
167         }
168         foreach ($courses as $course) {
169             $courses[$course->id] = $course;
170         }
171     } elseif (!empty($modulelist) and confirm_sesskey()) { // get list of courses containing modules
172         $modulename = $modulelist;
173         $sql =  "SELECT DISTINCT c.id FROM {".$modulelist."} module, {course} c"
174             ." WHERE module.course=c.id";
176         $courseids = $DB->get_records_sql($sql);
177         $courses = array();
178         if (!empty($courseids)) {
179             $firstcourse = $page*$perpage;
180             $lastcourse = $page*$perpage + $perpage -1;
181             $i = 0;
182             foreach ($courseids as $courseid) {
183                 if ($i>= $firstcourse && $i<=$lastcourse) {
184                     $courses[$courseid->id] = $DB->get_record('course', array('id'=> $courseid->id));
185                 }
186                 $i++;
187             }
188             $totalcount = count($courseids);
189         }
190         else {
191             $totalcount = 0;
192         }
193     } else if (!empty($searchterm)) { //Donot do search for empty search request.
194         $courses = get_courses_search($searchterms, "fullname ASC",
195             $page, $perpage, $totalcount);
196     }
198     $searchform = '';
199     //Turn editing should be visible if user have system or category level capability
200     if (!empty($courses) && (can_edit_in_category() || !empty($usercatlist))) {
201         if ($PAGE->user_is_editing()) {
202             $string = get_string("turneditingoff");
203             $edit = "off";
204         } else {
205             $string = get_string("turneditingon");
206             $edit = "on";
207         }
208         $params = array_merge($urlparams, array('sesskey' => sesskey(), 'edit' => $edit));
209         $aurl = new moodle_url("$CFG->wwwroot/course/search.php", $params);
210         $searchform = $OUTPUT->single_button($aurl, $string, 'get');
211     } else {
212         $searchform = print_course_search($search, true, "navbar");
213     }
215     $PAGE->navbar->add($strcourses, new moodle_url('/course/index.php'));
216     $PAGE->navbar->add($strsearch, new moodle_url('/course/search.php'));
217     if (!empty($search)) {
218         $PAGE->navbar->add(s($search));
219     }
220     $PAGE->set_title("$site->fullname : $strsearchresults");
221     $PAGE->set_heading($site->fullname);
222     $PAGE->set_button($searchform);
224     echo $OUTPUT->header();
226     $lastcategory = -1;
227     if ($courses) {
228         echo $OUTPUT->heading("$strsearchresults: $totalcount");
229         $encodedsearch = urlencode($search);
231         // add the module/block parameter to the paging bar if they exists
232         $modulelink = "";
233         if (!empty($modulelist) and confirm_sesskey()) {
234             $modulelink = "&amp;modulelist=".$modulelist."&amp;sesskey=".sesskey();
235         } else if (!empty($blocklist) and confirm_sesskey()) {
236             $modulelink = "&amp;blocklist=".$blocklist."&amp;sesskey=".sesskey();
237         }
239         print_navigation_bar($totalcount, $page, $perpage, $encodedsearch, $modulelink);
241         // Show list of courses
242         if (!$adminediting) { //Not editing mode
243             foreach ($courses as $course) {
244                 // front page don't belong to any category and block can exist.
245                 if ($course->category > 0) {
246                     $course->summary .= "<br /><p class=\"category\">";
247                     $course->summary .= "$strcategory: <a href=\"category.php?id=$course->category\">";
248                     $course->summary .= $displaylist[$course->category];
249                     $course->summary .= "</a></p>";
250                 }
251                 print_course($course, $search);
252                 echo $OUTPUT->spacer(array('height'=>5, 'width'=>5, 'br'=>true)); // should be done with CSS instead
253             }
254         } else { //editing mode
255             echo "<form id=\"movecourses\" action=\"search.php\" method=\"post\">\n";
256             echo "<div><input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
257             echo "<input type=\"hidden\" name=\"search\" value=\"".s($search)."\" />\n";
258             echo "<input type=\"hidden\" name=\"page\" value=\"$page\" />\n";
259             echo "<input type=\"hidden\" name=\"perpage\" value=\"$perpage\" /></div>\n";
260             if (!empty($modulelist) and confirm_sesskey()) {
261                 echo "<input type=\"hidden\" name=\"modulelist\" value=\"$modulelist\" /></div>\n";
262             } else if (!empty($blocklist) and confirm_sesskey()) {
263                 echo "<input type=\"hidden\" name=\"blocklist\" value=\"$blocklist\" /></div>\n";
264             }
265             echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"4\" class=\"generalbox boxaligncenter\">\n<tr>\n";
266             echo "<th scope=\"col\">$strcourses</th>\n";
267             echo "<th scope=\"col\">$strcategory</th>\n";
268             echo "<th scope=\"col\">$strselect</th>\n";
269             echo "<th scope=\"col\">$stredit</th></tr>\n";
271             foreach ($courses as $course) {
273                 $coursecontext = context_course::instance($course->id);
275                 $linkcss = $course->visible ? "" : " class=\"dimmed\" ";
277                 // are we displaying the front page (courseid=1)?
278                 if ($course->id == 1) {
279                     echo "<tr>\n";
280                     echo "<td><a href=\"$CFG->wwwroot\">$strfrontpage</a></td>\n";
282                     // can't do anything else with the front page
283                     echo "  <td>&nbsp;</td>\n"; // category place
284                     echo "  <td>&nbsp;</td>\n"; // select place
285                     echo "  <td>&nbsp;</td>\n"; // edit place
286                     echo "</tr>\n";
287                     continue;
288                 }
290                 echo "<tr>\n";
291                 echo "<td><a $linkcss href=\"view.php?id=$course->id\">"
292                     . highlight($search, format_string($course->fullname)) . "</a></td>\n";
293                 echo "<td>".$displaylist[$course->category]."</td>\n";
294                 echo "<td>\n";
296                 // If user has all required capabilities to move course then show selectable checkbox
297                 if (has_all_capabilities($capabilities, $coursecontext)) {
298                     echo "<input type=\"checkbox\" name=\"c$course->id\" />\n";
299                 } else {
300                     echo "<input type=\"checkbox\" name=\"c$course->id\" disabled=\"disabled\" />\n";
301                 }
303                 echo "</td>\n";
304                 echo "<td>\n";
306                 // checks whether user can update course settings
307                 if (has_capability('moodle/course:update', $coursecontext)) {
308                     echo "<a title=\"".get_string("settings")."\" href=\"$CFG->wwwroot/course/edit.php?id=$course->id\">\n<img".
309                         " src=\"" . $OUTPUT->pix_url('t/edit') . "\" class=\"iconsmall\" alt=\"".get_string("settings")."\" /></a>\n ";
310                 }
312                 // checks whether user can do role assignment
313                 if (has_capability('moodle/course:enrolreview', $coursecontext)) {
314                     echo'<a title="'.get_string('enrolledusers', 'enrol').'" href="'.$CFG->wwwroot.'/enrol/users.php?id='.$course->id.'">';
315                     echo '<img src="'.$OUTPUT->pix_url('i/users') . '" class="iconsmall" alt="'.get_string('enrolledusers', 'enrol').'" /></a> ' . "\n";
316                 }
318                 // checks whether user can delete course
319                 if (has_capability('moodle/course:delete', $coursecontext)) {
320                     echo "<a title=\"".get_string("delete")."\" href=\"delete.php?id=$course->id\">\n<img".
321                         " src=\"" . $OUTPUT->pix_url('t/delete') . "\" class=\"iconsmall\" alt=\"".get_string("delete")."\" /></a>\n ";
322                 }
324                 // checks whether user can change visibility
325                 if (has_capability('moodle/course:visibility', $coursecontext)) {
326                     if (!empty($course->visible)) {
327                         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".
328                             " src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"".get_string("hide")."\" /></a>\n ";
329                     } else {
330                         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".
331                             " src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"".get_string("show")."\" /></a>\n ";
332                     }
333                 }
335                 // checks whether user can do site backup
336                 if (has_capability('moodle/backup:backupcourse', $coursecontext)) {
337                     $backupurl = new moodle_url('/backup/backup.php', array('id' => $course->id));
338                     echo "<a title=\"".get_string("backup")."\" href=\"".$backupurl."\">\n<img".
339                         " src=\"" . $OUTPUT->pix_url('t/backup') . "\" class=\"iconsmall\" alt=\"".get_string("backup")."\" /></a>\n ";
340                 }
342                 // checks whether user can do restore
343                 if (has_capability('moodle/restore:restorecourse', $coursecontext)) {
344                     $restoreurl = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id));
345                     echo "<a title=\"".get_string("restore")."\" href=\"".$restoreurl."\">\n<img".
346                         " src=\"" . $OUTPUT->pix_url('t/restore') . "\" class=\"iconsmall\" alt=\"".get_string("restore")."\" /></a>\n ";
347                 }
349                 echo "</td>\n</tr>\n";
350             }
351             echo "<tr>\n<td colspan=\"4\" style=\"text-align:center\">\n";
352             echo "<br />";
353             echo "<input type=\"button\" onclick=\"checkall()\" value=\"$strselectall\" />\n";
354             echo "<input type=\"button\" onclick=\"checknone()\" value=\"$strdeselectall\" />\n";
355             //Select box should only show categories in which user has min capability to move course.
356             echo html_writer::select($usercatlist, 'moveto', '', array(''=>get_string('moveselectedcoursesto')), array('id'=>'movetoid'));
357             $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
358             echo "</td>\n</tr>\n";
359             echo "</table>\n</form>";
361         }
363         print_navigation_bar($totalcount,$page,$perpage,$encodedsearch,$modulelink);
365     } else {
366         if (!empty($search)) {
367             echo $OUTPUT->heading(get_string("nocoursesfound",'', s($search)));
368         }
369         else {
370             echo $OUTPUT->heading( $strnovalidcourses );
371         }
372     }
374     echo "<br /><br />";
376     print_course_search($search);
378     echo $OUTPUT->footer();
380    /**
381      * Print a list navigation bar
382      * Display page numbers, and a link for displaying all entries
383      * @param integer $totalcount - number of entry to display
384      * @param integer $page - page number
385      * @param integer $perpage - number of entry per page
386      * @param string $encodedsearch
387      * @param string $modulelink - module name
388      */
389     function print_navigation_bar($totalcount,$page,$perpage,$encodedsearch,$modulelink) {
390         global $OUTPUT;
391         echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "search.php?search=$encodedsearch".$modulelink."&perpage=$perpage");
393         //display
394         if ($perpage != 99999 && $totalcount > $perpage) {
395             echo "<center><p>";
396             echo "<a href=\"search.php?search=$encodedsearch".$modulelink."&amp;perpage=99999\">".get_string("showall", "", $totalcount)."</a>";
397             echo "</p></center>";
398         } else if ($perpage === 99999) {
399             $defaultperpage = 10;
400             //If user has course:create or category:manage capability the show 30 records.
401             $capabilities = array('moodle/course:create', 'moodle/category:manage');
402             if (has_any_capability($capabilities, context_system::instance())) {
403                 $defaultperpage = 30;
404             }
406             echo "<center><p>";
407             echo "<a href=\"search.php?search=$encodedsearch".$modulelink."&amp;perpage=".$defaultperpage."\">".get_string("showperpage", "", $defaultperpage)."</a>";
408             echo "</p></center>";
409         }
410     }