Search moodle.org's
Developer Documentation


   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Course and category management interfaces.
  19   *
  20   * @package    core_course
  21   * @copyright  2013 Sam Hemelryk
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  require_once('../config.php');
  26  require_once($CFG->dirroot.'/lib/coursecatlib.php');
  27  require_once($CFG->dirroot.'/course/lib.php');
  28  
  29  $categoryid = optional_param('categoryid', null, PARAM_INT);
  30  $selectedcategoryid = optional_param('selectedcategoryid', null, PARAM_INT);
  31  $courseid = optional_param('courseid', null, PARAM_INT);
  32  $action = optional_param('action', false, PARAM_ALPHA);
  33  $page = optional_param('page', 0, PARAM_INT);
  34  $perpage = optional_param('perpage', null, PARAM_INT);
  35  $viewmode = optional_param('view', 'default', PARAM_ALPHA); // Can be one of default, combined, courses, or categories.
  36  
  37  // Search related params.
  38  $search = optional_param('search', '', PARAM_RAW); // Search words. Shortname, fullname, idnumber and summary get searched.
  39  $blocklist = optional_param('blocklist', 0, PARAM_INT); // Find courses containing this block.
  40  $modulelist = optional_param('modulelist', '', PARAM_PLUGIN); // Find courses containing the given modules.
  41  
  42  if (!in_array($viewmode, array('default', 'combined', 'courses', 'categories'))) {
  43      $viewmode = 'default';
  44  }
  45  
  46  $issearching = ($search !== '' || $blocklist !== 0 || $modulelist !== '');
  47  if ($issearching) {
  48      $viewmode = 'courses';
  49  }
  50  
  51  $url = new moodle_url('/course/management.php');
  52  $systemcontext = $context = context_system::instance();
  53  if ($courseid) {
  54      $record = get_course($courseid);
  55      $course = new course_in_list($record);
  56      $category = coursecat::get($course->category);
  57      $categoryid = $category->id;
  58      $context = context_coursecat::instance($category->id);
  59      $url->param('categoryid', $categoryid);
  60      $url->param('courseid', $course->id);
  61  
  62  } else if ($categoryid) {
  63      $courseid = null;
  64      $course = null;
  65      $category = coursecat::get($categoryid);
  66      $context = context_coursecat::instance($category->id);
  67      $url->param('categoryid', $category->id);
  68  
  69  } else {
  70      $course = null;
  71      $courseid = null;
  72      $category = coursecat::get_default();
  73      $categoryid = $category->id;
  74      $context = context_coursecat::instance($category->id);
  75      $url->param('categoryid', $category->id);
  76  }
  77  
  78  // Check if there is a selected category param, and if there is apply it.
  79  if ($course === null && $selectedcategoryid !== null && $selectedcategoryid !== $categoryid) {
  80      $url->param('categoryid', $selectedcategoryid);
  81  }
  82  
  83  if ($page !== 0) {
  84      $url->param('page', $page);
  85  }
  86  if ($viewmode !== 'default') {
  87      $url->param('view', $viewmode);
  88  }
  89  if ($search !== '') {
  90      $url->param('search', $search);
  91  }
  92  if ($blocklist !== 0) {
  93      $url->param('blocklist', $search);
  94  }
  95  if ($modulelist !== '') {
  96      $url->param('modulelist', $search);
  97  }
  98  
  99  $strmanagement = new lang_string('coursecatmanagement');
 100  $pageheading = format_string($SITE->fullname, true, array('context' => $systemcontext));
 101  
 102  $PAGE->set_context($context);
 103  $PAGE->set_url($url);
 104  $PAGE->set_pagelayout('admin');
 105  $PAGE->set_title($strmanagement);
 106  $PAGE->set_heading($pageheading);
 107  
 108  // This is a system level page that operates on other contexts.
 109  require_login();
 110  
 111  if (!coursecat::has_capability_on_any(array('moodle/category:manage', 'moodle/course:create'))) {
 112      // The user isn't able to manage any categories. Lets redirect them to the relevant course/index.php page.
 113      $url = new moodle_url('/course/index.php');
 114      if ($categoryid) {
 115          $url->param('categoryid', $categoryid);
 116      }
 117      redirect($url);
 118  }
 119  
 120  // If the user poses any of these capabilities then they will be able to see the admin
 121  // tree and the management link within it.
 122  // This is the most accurate form of navigation.
 123  $capabilities = array(
 124      'moodle/site:config',
 125      'moodle/backup:backupcourse',
 126      'moodle/category:manage',
 127      'moodle/course:create',
 128      'moodle/site:approvecourse'
 129  );
 130  if ($category && !has_any_capability($capabilities, $systemcontext)) {
 131      // If the user doesn't poses any of these system capabilities then we're going to mark the manage link in the settings block
 132      // as active, tell the page to ignore the active path and just build what the user would expect.
 133      // This will at least give the page some relevant navigation.
 134      navigation_node::override_active_url(new moodle_url('/course/management.php', array('categoryid' => $category->id)));
 135      $PAGE->set_category_by_id($category->id);
 136      $PAGE->navbar->ignore_active(true);
 137      $PAGE->navbar->add(get_string('coursemgmt', 'admin'), $PAGE->url->out_omit_querystring());
 138  } else {
 139      // If user has system capabilities, make sure the "Manage courses and categories" item in Administration block is active.
 140      navigation_node::require_admin_tree();
 141      navigation_node::override_active_url(new moodle_url('/course/management.php'));
 142  }
 143  if (!$issearching && $category !== null) {
 144      $parents = coursecat::get_many($category->get_parents());
 145      $parents[] = $category;
 146      foreach ($parents as $parent) {
 147          $PAGE->navbar->add(
 148              $parent->get_formatted_name(),
 149              new moodle_url('/course/management.php', array('categoryid' => $parent->id))
 150          );
 151      }
 152      if ($course instanceof course_in_list) {
 153          // Use the list name so that it matches whats being displayed below.
 154          $PAGE->navbar->add($course->get_formatted_name());
 155      }
 156  }
 157  
 158  $notificationspass = array();
 159  $notificationsfail = array();
 160  
 161  if ($action !== false && confirm_sesskey()) {
 162      // Actions:
 163      // - resortcategories : Resort the courses in the given category.
 164      // - resortcourses : Resort courses
 165      // - showcourse : make a course visible.
 166      // - hidecourse : make a course hidden.
 167      // - movecourseup : move the selected course up one.
 168      // - movecoursedown : move the selected course down.
 169      // - showcategory : make a category visible.
 170      // - hidecategory : make a category hidden.
 171      // - movecategoryup : move category up.
 172      // - movecategorydown : move category down.
 173      // - deletecategory : delete the category either in full, or moving contents.
 174      // - bulkaction : performs bulk actions:
 175      //    - bulkmovecourses.
 176      //    - bulkmovecategories.
 177      //    - bulkresortcategories.
 178      $redirectback = false;
 179      $redirectmessage = false;
 180      switch ($action) {
 181          case 'resortcategories' :
 182              $sort = required_param('resort', PARAM_ALPHA);
 183              $cattosort = coursecat::get((int)optional_param('categoryid', 0, PARAM_INT));
 184              $redirectback = \core_course\management\helper::action_category_resort_subcategories($cattosort, $sort);
 185              break;
 186          case 'resortcourses' :
 187              // They must have specified a category.
 188              required_param('categoryid', PARAM_INT);
 189              $sort = required_param('resort', PARAM_ALPHA);
 190              \core_course\management\helper::action_category_resort_courses($category, $sort);
 191              break;
 192          case 'showcourse' :
 193              $redirectback = \core_course\management\helper::action_course_show($course);
 194              break;
 195          case 'hidecourse' :
 196              $redirectback = \core_course\management\helper::action_course_hide($course);
 197              break;
 198          case 'movecourseup' :
 199              // They must have specified a category and a course.
 200              required_param('categoryid', PARAM_INT);
 201              required_param('courseid', PARAM_INT);
 202              $redirectback = \core_course\management\helper::action_course_change_sortorder_up_one($course, $category);
 203              break;
 204          case 'movecoursedown' :
 205              // They must have specified a category and a course.
 206              required_param('categoryid', PARAM_INT);
 207              required_param('courseid', PARAM_INT);
 208              $redirectback = \core_course\management\helper::action_course_change_sortorder_down_one($course, $category);
 209              break;
 210          case 'showcategory' :
 211              // They must have specified a category.
 212              required_param('categoryid', PARAM_INT);
 213              $redirectback = \core_course\management\helper::action_category_show($category);
 214              break;
 215          case 'hidecategory' :
 216              // They must have specified a category.
 217              required_param('categoryid', PARAM_INT);
 218              $redirectback = \core_course\management\helper::action_category_hide($category);
 219              break;
 220          case 'movecategoryup' :
 221              // They must have specified a category.
 222              required_param('categoryid', PARAM_INT);
 223              $redirectback = \core_course\management\helper::action_category_change_sortorder_up_one($category);
 224              break;
 225          case 'movecategorydown' :
 226              // They must have specified a category.
 227              required_param('categoryid', PARAM_INT);
 228              $redirectback = \core_course\management\helper::action_category_change_sortorder_down_one($category);
 229              break;
 230          case 'deletecategory':
 231              // They must have specified a category.
 232              required_param('categoryid', PARAM_INT);
 233              if (!$category->can_delete()) {
 234                  throw new moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
 235              }
 236              $mform = new core_course_deletecategory_form(null, $category);
 237              if ($mform->is_cancelled()) {
 238                  redirect($PAGE->url);
 239              }
 240              // Start output.
 241              /* @var core_course_management_renderer|core_renderer $renderer */
 242              $renderer = $PAGE->get_renderer('core_course', 'management');
 243              echo $renderer->header();
 244              echo $renderer->heading(get_string('deletecategory', 'moodle', $category->get_formatted_name()));
 245  
 246              if ($data = $mform->get_data()) {
 247                  // The form has been submit handle it.
 248                  if ($data->fulldelete == 1 && $category->can_delete_full()) {
 249                      $continueurl = new moodle_url('/course/management.php');
 250                      if ($category->parent != '0') {
 251                          $continueurl->param('categoryid', $category->parent);
 252                      }
 253                      $notification = get_string('coursecategorydeleted', '', $category->get_formatted_name());
 254                      $deletedcourses = $category->delete_full(true);
 255                      foreach ($deletedcourses as $course) {
 256                          echo $renderer->notification(get_string('coursedeleted', '', $course->shortname), 'notifysuccess');
 257                      }
 258                      echo $renderer->notification($notification, 'notifysuccess');
 259                      echo $renderer->continue_button($continueurl);
 260                  } else if ($data->fulldelete == 0 && $category->can_move_content_to($data->newparent)) {
 261                      $continueurl = new moodle_url('/course/management.php', array('categoryid' => $data->newparent));
 262                      $category->delete_move($data->newparent, true);
 263                      echo $renderer->continue_button($continueurl);
 264                  } else {
 265                      // Some error in parameters (user is cheating?)
 266                      $mform->display();
 267                  }
 268              } else {
 269                  // Display the form.
 270                  $mform->display();
 271              }
 272              // Finish output and exit.
 273              echo $renderer->footer();
 274              exit();
 275              break;
 276          case 'bulkaction':
 277              $bulkmovecourses = optional_param('bulkmovecourses', false, PARAM_BOOL);
 278              $bulkmovecategories = optional_param('bulkmovecategories', false, PARAM_BOOL);
 279              $bulkresortcategories = optional_param('bulksort', false, PARAM_BOOL);
 280  
 281              if ($bulkmovecourses) {
 282                  // Move courses out of the current category and into a new category.
 283                  // They must have specified a category.
 284                  required_param('categoryid', PARAM_INT);
 285                  $movetoid = required_param('movecoursesto', PARAM_INT);
 286                  $courseids = optional_param_array('bc', false, PARAM_INT);
 287                  if ($courseids === false) {
 288                      break;
 289                  }
 290                  $moveto = coursecat::get($movetoid);
 291                  try {
 292                      // If this fails we want to catch the exception and report it.
 293                      $redirectback = \core_course\management\helper::move_courses_into_category($moveto,
 294                          $courseids);
 295                      if ($redirectback) {
 296                          $a = new stdClass;
 297                          $a->category = $moveto->get_formatted_name();
 298                          $a->courses = count($courseids);
 299                          $redirectmessage = get_string('bulkmovecoursessuccess', 'moodle', $a);
 300                      }
 301                  } catch (moodle_exception $ex) {
 302                      $redirectback = false;
 303                      $notificationsfail[] = $ex->getMessage();
 304                  }
 305              } else if ($bulkmovecategories) {
 306                  $categoryids = optional_param_array('bcat', array(), PARAM_INT);
 307                  $movetocatid = required_param('movecategoriesto', PARAM_INT);
 308                  $movetocat = coursecat::get($movetocatid);
 309                  $movecount = 0;
 310                  foreach ($categoryids as $id) {
 311                      $cattomove = coursecat::get($id);
 312                      if ($id == $movetocatid) {
 313                          $notificationsfail[] = get_string('movecategoryownparent', 'error', $cattomove->get_formatted_name());
 314                          continue;
 315                      }
 316                      if (strpos($movetocat->path, $cattomove->path) === 0) {
 317                          $notificationsfail[] = get_string('movecategoryparentconflict', 'error', $cattomove->get_formatted_name());
 318                          continue;
 319                      }
 320                      if ($cattomove->parent != $movetocatid) {
 321                          if ($cattomove->can_change_parent($movetocatid)) {
 322                              $cattomove->change_parent($movetocatid);
 323                              $movecount++;
 324                          } else {
 325                              $notificationsfail[] = get_string('movecategorynotpossible', 'error', $cattomove->get_formatted_name());
 326                          }
 327                      }
 328                  }
 329                  if ($movecount > 1) {
 330                      $a = new stdClass;
 331                      $a->count = $movecount;
 332                      $a->to = $movetocat->get_formatted_name();
 333                      $movesuccessstrkey = 'movecategoriessuccess';
 334                      if ($movetocatid == 0) {
 335                          $movesuccessstrkey = 'movecategoriestotopsuccess';
 336                      }
 337                      $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
 338                  } else if ($movecount === 1) {
 339                      $a = new stdClass;
 340                      $a->moved = $cattomove->get_formatted_name();
 341                      $a->to = $movetocat->get_formatted_name();
 342                      $movesuccessstrkey = 'movecategorysuccess';
 343                      if ($movetocatid == 0) {
 344                          $movesuccessstrkey = 'movecategorytotopsuccess';
 345                      }
 346                      $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
 347                  }
 348              } else if ($bulkresortcategories) {
 349                  $for = required_param('selectsortby', PARAM_ALPHA);
 350                  $sortcategoriesby = required_param('resortcategoriesby', PARAM_ALPHA);
 351                  $sortcoursesby = required_param('resortcoursesby', PARAM_ALPHA);
 352  
 353                  if ($sortcategoriesby === 'none' && $sortcoursesby === 'none') {
 354                      // They're not sorting anything.
 355                      break;
 356                  }
 357                  if (!in_array($sortcategoriesby, array('idnumber', 'idnumberdesc',
 358                                                         'name', 'namedesc'))) {
 359                      $sortcategoriesby = false;
 360                  }
 361                  if (!in_array($sortcoursesby, array('timecreated', 'timecreateddesc',
 362                                                      'idnumber', 'idnumberdesc',
 363                                                      'fullname', 'fullnamedesc',
 364                                                      'shortname', 'shortnamedesc'))) {
 365                      $sortcoursesby = false;
 366                  }
 367  
 368                  if ($for === 'thiscategory') {
 369                      $categoryids = array(
 370                          required_param('currentcategoryid', PARAM_INT)
 371                      );
 372                      $categories = coursecat::get_many($categoryids);
 373                  } else if ($for === 'selectedcategories') {
 374                      // Bulk resort selected categories.
 375                      $categoryids = optional_param_array('bcat', false, PARAM_INT);
 376                      $sort = required_param('resortcategoriesby', PARAM_ALPHA);
 377                      if ($categoryids === false) {
 378                          break;
 379                      }
 380                      $categories = coursecat::get_many($categoryids);
 381                  } else if ($for === 'allcategories') {
 382                      if ($sortcategoriesby && coursecat::get(0)->can_resort_subcategories()) {
 383                          \core_course\management\helper::action_category_resort_subcategories(coursecat::get(0), $sortcategoriesby);
 384                      }
 385                      $categorieslist = coursecat::make_categories_list('moodle/category:manage');
 386                      $categoryids = array_keys($categorieslist);
 387                      $categories = coursecat::get_many($categoryids);
 388                      unset($categorieslist);
 389                  } else {
 390                      break;
 391                  }
 392                  foreach ($categories as $cat) {
 393                      if ($sortcategoriesby && $cat->can_resort_subcategories()) {
 394                          // Don't clean up here, we'll do it once we're all done.
 395                          \core_course\management\helper::action_category_resort_subcategories($cat, $sortcategoriesby, false);
 396                      }
 397                      if ($sortcoursesby && $cat->can_resort_courses()) {
 398                          \core_course\management\helper::action_category_resort_courses($cat, $sortcoursesby, false);
 399                      }
 400                  }
 401                  coursecat::resort_categories_cleanup($sortcoursesby !== false);
 402                  if ($category === null && count($categoryids) === 1) {
 403                      // They're bulk sorting just a single category and they've not selected a category.
 404                      // Lets for convenience sake auto-select the category that has been resorted for them.
 405                      redirect(new moodle_url($PAGE->url, array('categoryid' => reset($categoryids))));
 406                  }
 407              }
 408      }
 409      if ($redirectback) {
 410          if ($redirectmessage) {
 411              redirect($PAGE->url, $redirectmessage, 5);
 412          } else {
 413              redirect($PAGE->url);
 414          }
 415      }
 416  }
 417  
 418  if (!is_null($perpage)) {
 419      set_user_preference('coursecat_management_perpage', $perpage);
 420  } else {
 421      $perpage = get_user_preferences('coursecat_management_perpage', $CFG->coursesperpage);
 422  }
 423  if ((int)$perpage != $perpage || $perpage < 2) {
 424      $perpage = $CFG->coursesperpage;
 425  }
 426  
 427  $categorysize = 4;
 428  $coursesize = 4;
 429  $detailssize = 4;
 430  if ($viewmode === 'default' || $viewmode === 'combined') {
 431      if (isset($courseid)) {
 432          $class = 'columns-3';
 433      } else {
 434          $categorysize = 5;
 435          $coursesize = 7;
 436          $class = 'columns-2';
 437      }
 438  } else if ($viewmode === 'categories') {
 439      $categorysize = 12;
 440      $class = 'columns-1';
 441  } else if ($viewmode === 'courses') {
 442      if (isset($courseid)) {
 443          $coursesize = 6;
 444          $detailssize = 6;
 445          $class = 'columns-2';
 446      } else {
 447          $coursesize = 12;
 448          $class = 'columns-1';
 449      }
 450  }
 451  if ($viewmode === 'default' || $viewmode === 'combined') {
 452      $class .= ' viewmode-cobmined';
 453  } else {
 454      $class .= ' viewmode-'.$viewmode;
 455  }
 456  if (($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'courses') && !empty($courseid)) {
 457      $class .= ' course-selected';
 458  }
 459  
 460  /* @var core_course_management_renderer|core_renderer $renderer */
 461  $renderer = $PAGE->get_renderer('core_course', 'management');
 462  $renderer->enhance_management_interface();
 463  
 464  $displaycategorylisting = ($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'categories');
 465  $displaycourselisting = ($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'courses');
 466  $displaycoursedetail = (isset($courseid));
 467  
 468  echo $renderer->header();
 469  
 470  if (!$issearching) {
 471      echo $renderer->management_heading($strmanagement, $viewmode, $categoryid);
 472  } else {
 473      echo $renderer->management_heading(new lang_string('searchresults'));
 474  }
 475  
 476  if (count($notificationspass) > 0) {
 477      echo $renderer->notification(join('<br />', $notificationspass), 'notifysuccess');
 478  }
 479  if (count($notificationsfail) > 0) {
 480      echo $renderer->notification(join('<br />', $notificationsfail));
 481  }
 482  
 483  // Start the management form.
 484  echo $renderer->management_form_start();
 485  
 486  echo $renderer->accessible_skipto_links($displaycategorylisting, $displaycourselisting, $displaycoursedetail);
 487  
 488  echo $renderer->grid_start('course-category-listings', $class);
 489  
 490  if ($displaycategorylisting) {
 491      echo $renderer->grid_column_start($categorysize, 'category-listing');
 492      echo $renderer->category_listing($category);
 493      echo $renderer->grid_column_end();
 494  }
 495  if ($displaycourselisting) {
 496      echo $renderer->grid_column_start($coursesize, 'course-listing');
 497      if (!$issearching) {
 498          echo $renderer->course_listing($category, $course, $page, $perpage);
 499      } else {
 500          list($courses, $coursescount, $coursestotal) =
 501              \core_course\management\helper::search_courses($search, $blocklist, $modulelist, $page, $perpage);
 502          echo $renderer->search_listing($courses, $coursestotal, $course, $page, $perpage, $search);
 503      }
 504      echo $renderer->grid_column_end();
 505      if ($displaycoursedetail) {
 506          echo $renderer->grid_column_start($detailssize, 'course-detail');
 507          echo $renderer->course_detail($course);
 508          echo $renderer->grid_column_end();
 509      }
 510  }
 511  echo $renderer->grid_end();
 512  
 513  // End of the management form.
 514  echo $renderer->management_form_end();
 515  echo $renderer->course_search_form($search);
 516  
 517  echo $renderer->footer();

Search This Site: