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 helper class.
  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  namespace core_course\management;
  26  
  27  defined('MOODLE_INTERNAL') || die;
  28  
  29  /**
  30   * Course and category management interface helper class.
  31   *
  32   * This class provides methods useful to the course and category management interfaces.
  33   * Many of the methods on this class are static and serve one of two purposes.
  34   *  1.  encapsulate functionality in an effort to ensure minimal changes between the different
  35   *      methods of interaction. Specifically browser, AJAX and webservice.
  36   *  2.  abstract logic for acquiring actions away from output so that renderers may use them without
  37   *      having to include any logic or capability checks.
  38   *
  39   * @package    core_course
  40   * @copyright  2013 Sam Hemelryk
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class helper {
  44  
  45      /**
  46       * The expanded category structure if its already being loaded from the cache.
  47       * @var null|array
  48       */
  49      protected static $expandedcategories = null;
  50  
  51      /**
  52       * Returns course details in an array ready to be printed.
  53       *
  54       * @global \moodle_database $DB
  55       * @param \course_in_list $course
  56       * @return array
  57       */
  58      public static function get_course_detail_array(\course_in_list $course) {
  59          global $DB;
  60  
  61          $canaccess = $course->can_access();
  62  
  63          $format = \course_get_format($course->id);
  64          $modinfo = \get_fast_modinfo($course->id);
  65          $modules = $modinfo->get_used_module_names();
  66          $sections = array();
  67          if ($format->uses_sections()) {
  68              foreach ($modinfo->get_section_info_all() as $section) {
  69                  if ($section->uservisible) {
  70                      $sections[] = $format->get_section_name($section);
  71                  }
  72              }
  73          }
  74  
  75          $category = \coursecat::get($course->category);
  76          $categoryurl = new \moodle_url('/course/management.php', array('categoryid' => $course->category));
  77          $categoryname = $category->get_formatted_name();
  78  
  79          $details = array(
  80              'fullname' => array(
  81                  'key' => \get_string('fullname'),
  82                  'value' => $course->get_formatted_fullname()
  83              ),
  84              'shortname' => array(
  85                  'key' => \get_string('shortname'),
  86                  'value' => $course->get_formatted_shortname()
  87              ),
  88              'idnumber' => array(
  89                  'key' => \get_string('idnumber'),
  90                  'value' => s($course->idnumber)
  91              ),
  92              'category' => array(
  93                  'key' => \get_string('category'),
  94                  'value' => \html_writer::link($categoryurl, $categoryname)
  95              )
  96          );
  97          if (has_capability('moodle/site:accessallgroups', $course->get_context())) {
  98              $groups = \groups_get_course_data($course->id);
  99              $details += array(
 100                  'groupings' => array(
 101                      'key' => \get_string('groupings', 'group'),
 102                      'value' => count($groups->groupings)
 103                  ),
 104                  'groups' => array(
 105                      'key' => \get_string('groups'),
 106                      'value' => count($groups->groups)
 107                  )
 108              );
 109          }
 110          if ($canaccess) {
 111              $names = \role_get_names($course->get_context());
 112              $sql = 'SELECT ra.roleid, COUNT(ra.id) AS rolecount
 113                        FROM {role_assignments} ra
 114                       WHERE ra.contextid = :contextid
 115                    GROUP BY ra.roleid';
 116              $rolecounts = $DB->get_records_sql($sql, array('contextid' => $course->get_context()->id));
 117              $roledetails = array();
 118              foreach ($rolecounts as $result) {
 119                  $a = new \stdClass;
 120                  $a->role = $names[$result->roleid]->localname;
 121                  $a->count = $result->rolecount;
 122                  $roledetails[] = \get_string('assignedrolecount', 'moodle', $a);
 123              }
 124  
 125              $details['roleassignments'] = array(
 126                  'key' => \get_string('roleassignments'),
 127                  'value' => join('<br />', $roledetails)
 128              );
 129          }
 130          if ($course->can_review_enrolments()) {
 131              $enrolmentlines = array();
 132              $instances = \enrol_get_instances($course->id, true);
 133              $plugins = \enrol_get_plugins(true);
 134              foreach ($instances as $instance) {
 135                  if (!isset($plugins[$instance->enrol])) {
 136                      // Weird.
 137                      continue;
 138                  }
 139                  $plugin = $plugins[$instance->enrol];
 140                  $enrolmentlines[] = $plugin->get_instance_name($instance);
 141              }
 142              $details['enrolmentmethods'] = array(
 143                  'key' => \get_string('enrolmentmethods'),
 144                  'value' => join('<br />', $enrolmentlines)
 145              );
 146          }
 147          if ($canaccess) {
 148              $details['format'] = array(
 149                  'key' => \get_string('format'),
 150                  'value' => \course_get_format($course)->get_format_name()
 151              );
 152              $details['sections'] = array(
 153                  'key' => \get_string('sections'),
 154                  'value' => join('<br />', $sections)
 155              );
 156              $details['modulesused'] = array(
 157                  'key' => \get_string('modulesused'),
 158                  'value' =>  join('<br />', $modules)
 159              );
 160          }
 161          return $details;
 162      }
 163  
 164      /**
 165       * Returns an array of actions that can be performed upon a category being shown in a list.
 166       *
 167       * @param \coursecat $category
 168       * @return array
 169       */
 170      public static function get_category_listitem_actions(\coursecat $category) {
 171          $baseurl = new \moodle_url('/course/management.php', array('categoryid' => $category->id, 'sesskey' => \sesskey()));
 172          $actions = array();
 173          // Edit.
 174          if ($category->can_edit()) {
 175              $actions['edit'] = array(
 176                  'url' => new \moodle_url('/course/editcategory.php', array('id' => $category->id)),
 177                  'icon' => new \pix_icon('t/edit', new \lang_string('edit')),
 178                  'string' => new \lang_string('edit')
 179              );
 180          }
 181  
 182          // Show/Hide.
 183          if ($category->can_change_visibility()) {
 184              // We always show both icons and then just toggle the display of the invalid option with CSS.
 185              $actions['hide'] = array(
 186                  'url' => new \moodle_url($baseurl, array('action' => 'hidecategory')),
 187                  'icon' => new \pix_icon('t/hide', new \lang_string('hide')),
 188                  'string' => new \lang_string('hide')
 189              );
 190              $actions['show'] = array(
 191                  'url' => new \moodle_url($baseurl, array('action' => 'showcategory')),
 192                  'icon' => new \pix_icon('t/show', new \lang_string('show')),
 193                  'string' => new \lang_string('show')
 194              );
 195          }
 196  
 197          // Move up/down.
 198          if ($category->can_change_sortorder()) {
 199              $actions['moveup'] = array(
 200                  'url' => new \moodle_url($baseurl, array('action' => 'movecategoryup')),
 201                  'icon' => new \pix_icon('t/up', new \lang_string('up')),
 202                  'string' => new \lang_string('up')
 203              );
 204              $actions['movedown'] = array(
 205                  'url' => new \moodle_url($baseurl, array('action' => 'movecategorydown')),
 206                  'icon' => new \pix_icon('t/down', new \lang_string('down')),
 207                  'string' => new \lang_string('down')
 208              );
 209          }
 210  
 211          if ($category->can_create_subcategory()) {
 212              $actions['createnewsubcategory'] = array(
 213                  'url' => new \moodle_url('/course/editcategory.php', array('parent' => $category->id)),
 214                  'icon' => new \pix_icon('i/withsubcat', new \lang_string('createnewsubcategory')),
 215                  'string' => new \lang_string('createnewsubcategory')
 216              );
 217          }
 218  
 219          // Resort.
 220          if ($category->can_resort_subcategories() && $category->has_children()) {
 221              $actions['resortbyname'] = array(
 222                  'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'name')),
 223                  'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
 224                  'string' => new \lang_string('resortsubcategoriesby', 'moodle' , get_string('categoryname'))
 225              );
 226              $actions['resortbynamedesc'] = array(
 227                  'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'namedesc')),
 228                  'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
 229                  'string' => new \lang_string('resortsubcategoriesbyreverse', 'moodle', get_string('categoryname'))
 230              );
 231              $actions['resortbyidnumber'] = array(
 232                  'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'idnumber')),
 233                  'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
 234                  'string' => new \lang_string('resortsubcategoriesby', 'moodle', get_string('idnumbercoursecategory'))
 235              );
 236              $actions['resortbyidnumberdesc'] = array(
 237                  'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'idnumberdesc')),
 238                  'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
 239                  'string' => new \lang_string('resortsubcategoriesbyreverse', 'moodle', get_string('idnumbercoursecategory'))
 240              );
 241          }
 242  
 243          // Delete.
 244          if ($category->can_delete_full()) {
 245              $actions['delete'] = array(
 246                  'url' => new \moodle_url($baseurl, array('action' => 'deletecategory')),
 247                  'icon' => new \pix_icon('t/delete', new \lang_string('delete')),
 248                  'string' => new \lang_string('delete')
 249              );
 250          }
 251  
 252          // Roles.
 253          if ($category->can_review_roles()) {
 254              $actions['assignroles'] = array(
 255                  'url' => new \moodle_url('/admin/roles/assign.php', array('contextid' => $category->get_context()->id,
 256                      'return' => 'management')),
 257                  'icon' => new \pix_icon('t/assignroles', new \lang_string('assignroles', 'role')),
 258                  'string' => new \lang_string('assignroles', 'role')
 259              );
 260          }
 261  
 262          // Permissions.
 263          if ($category->can_review_permissions()) {
 264              $actions['permissions'] = array(
 265                  'url' => new \moodle_url('/admin/roles/permissions.php', array('contextid' => $category->get_context()->id,
 266                      'return' => 'management')),
 267                  'icon' => new \pix_icon('i/permissions', new \lang_string('permissions', 'role')),
 268                  'string' => new \lang_string('permissions', 'role')
 269              );
 270          }
 271  
 272          // Cohorts.
 273          if ($category->can_review_cohorts()) {
 274              $actions['cohorts'] = array(
 275                  'url' => new \moodle_url('/cohort/index.php', array('contextid' => $category->get_context()->id)),
 276                  'icon' => new \pix_icon('t/cohort', new \lang_string('cohorts', 'cohort')),
 277                  'string' => new \lang_string('cohorts', 'cohort')
 278              );
 279          }
 280  
 281          // Filters.
 282          if ($category->can_review_filters()) {
 283              $actions['filters'] = array(
 284                  'url' => new \moodle_url('/filter/manage.php', array('contextid' => $category->get_context()->id,
 285                      'return' => 'management')),
 286                  'icon' => new \pix_icon('i/filter', new \lang_string('filters', 'admin')),
 287                  'string' => new \lang_string('filters', 'admin')
 288              );
 289          }
 290  
 291          if ($category->can_restore_courses_into()) {
 292              $actions['restore'] = array(
 293                  'url' => new \moodle_url('/backup/restorefile.php', array('contextid' => $category->get_context()->id)),
 294                  'icon' => new \pix_icon('i/restore', new \lang_string('restorecourse', 'admin')),
 295                  'string' => new \lang_string('restorecourse', 'admin')
 296              );
 297          }
 298  
 299          return $actions;
 300      }
 301  
 302      /**
 303       * Returns an array of actions for a course listitem.
 304       *
 305       * @param \coursecat $category
 306       * @param \course_in_list $course
 307       * @return string
 308       */
 309      public static function get_course_listitem_actions(\coursecat $category, \course_in_list $course) {
 310          $baseurl = new \moodle_url(
 311              '/course/management.php',
 312              array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => \sesskey())
 313          );
 314          $actions = array();
 315          // Edit.
 316          if ($course->can_edit()) {
 317              $actions[] = array(
 318                  'url' => new \moodle_url('/course/edit.php', array('id' => $course->id)),
 319                  'icon' => new \pix_icon('t/edit', \get_string('edit')),
 320                  'attributes' => array('class' => 'action-edit')
 321              );
 322          }
 323          // Delete.
 324          if ($course->can_delete()) {
 325              $actions[] = array(
 326                  'url' => new \moodle_url('/course/delete.php', array('id' => $course->id)),
 327                  'icon' => new \pix_icon('t/delete', \get_string('delete')),
 328                  'attributes' => array('class' => 'action-delete')
 329              );
 330          }
 331          // Show/Hide.
 332          if ($course->can_change_visibility()) {
 333              $actions[] = array(
 334                  'url' => new \moodle_url($baseurl, array('action' => 'hidecourse')),
 335                  'icon' => new \pix_icon('t/hide', \get_string('hide')),
 336                  'attributes' => array('data-action' => 'hide', 'class' => 'action-hide')
 337              );
 338              $actions[] = array(
 339                  'url' => new \moodle_url($baseurl, array('action' => 'showcourse')),
 340                  'icon' => new \pix_icon('t/show', \get_string('show')),
 341                  'attributes' => array('data-action' => 'show', 'class' => 'action-show')
 342              );
 343          }
 344          // Move up/down.
 345          if ($category->can_resort_courses()) {
 346              $actions[] = array(
 347                  'url' => new \moodle_url($baseurl, array('action' => 'movecourseup')),
 348                  'icon' => new \pix_icon('t/up', \get_string('up')),
 349                  'attributes' => array('data-action' => 'moveup', 'class' => 'action-moveup')
 350              );
 351              $actions[] = array(
 352                  'url' => new \moodle_url($baseurl, array('action' => 'movecoursedown')),
 353                  'icon' => new \pix_icon('t/down', \get_string('down')),
 354                  'attributes' => array('data-action' => 'movedown', 'class' => 'action-movedown')
 355              );
 356          }
 357          return $actions;
 358      }
 359  
 360      /**
 361       * Returns an array of actions that can be performed on the course being displayed.
 362       *
 363       * @param \course_in_list $course
 364       * @return array
 365       */
 366      public static function get_course_detail_actions(\course_in_list $course) {
 367          $params = array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => \sesskey());
 368          $baseurl = new \moodle_url('/course/management.php', $params);
 369          $actions = array();
 370          // View.
 371          if ($course->is_uservisible()) {
 372              $actions['view'] = array(
 373                  'url' => new \moodle_url('/course/view.php', array('id' => $course->id)),
 374                  'string' => \get_string('view')
 375              );
 376          }
 377          // Edit.
 378          if ($course->can_edit()) {
 379              $actions['edit'] = array(
 380                  'url' => new \moodle_url('/course/edit.php', array('id' => $course->id)),
 381                  'string' => \get_string('edit')
 382              );
 383          }
 384          // Permissions.
 385          if ($course->can_review_enrolments()) {
 386              $actions['enrolledusers'] = array(
 387                  'url' => new \moodle_url('/enrol/users.php', array('id' => $course->id)),
 388                  'string' => \get_string('enrolledusers', 'enrol')
 389              );
 390          }
 391          // Delete.
 392          if ($course->can_delete()) {
 393              $actions['delete'] = array(
 394                  'url' => new \moodle_url('/course/delete.php', array('id' => $course->id)),
 395                  'string' => \get_string('delete')
 396              );
 397          }
 398          // Show/Hide.
 399          if ($course->can_change_visibility()) {
 400              if ($course->visible) {
 401                  $actions['hide'] = array(
 402                      'url' => new \moodle_url($baseurl, array('action' => 'hidecourse')),
 403                      'string' => \get_string('hide')
 404                  );
 405              } else {
 406                  $actions['show'] = array(
 407                      'url' => new \moodle_url($baseurl, array('action' => 'showcourse')),
 408                      'string' => \get_string('show')
 409                  );
 410              }
 411          }
 412          // Backup.
 413          if ($course->can_backup()) {
 414              $actions['backup'] = array(
 415                  'url' => new \moodle_url('/backup/backup.php', array('id' => $course->id)),
 416                  'string' => \get_string('backup')
 417              );
 418          }
 419          // Restore.
 420          if ($course->can_restore()) {
 421              $actions['restore'] = array(
 422                  'url' => new \moodle_url('/backup/restorefile.php', array('contextid' => $course->get_context()->id)),
 423                  'string' => \get_string('restore')
 424              );
 425          }
 426          return $actions;
 427      }
 428  
 429      /**
 430       * Resorts the courses within a category moving the given course up by one.
 431       *
 432       * @param \course_in_list $course
 433       * @param \coursecat $category
 434       * @return bool
 435       * @throws \moodle_exception
 436       */
 437      public static function action_course_change_sortorder_up_one(\course_in_list $course, \coursecat $category) {
 438          if (!$category->can_resort_courses()) {
 439              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
 440          }
 441          return \course_change_sortorder_by_one($course, true);
 442      }
 443  
 444      /**
 445       * Resorts the courses within a category moving the given course down by one.
 446       *
 447       * @param \course_in_list $course
 448       * @param \coursecat $category
 449       * @return bool
 450       * @throws \moodle_exception
 451       */
 452      public static function action_course_change_sortorder_down_one(\course_in_list $course, \coursecat $category) {
 453          if (!$category->can_resort_courses()) {
 454              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
 455          }
 456          return \course_change_sortorder_by_one($course, false);
 457      }
 458  
 459      /**
 460       * Resorts the courses within a category moving the given course up by one.
 461       *
 462       * @global \moodle_database $DB
 463       * @param int|\stdClass $courserecordorid
 464       * @return bool
 465       */
 466      public static function action_course_change_sortorder_up_one_by_record($courserecordorid) {
 467          if (is_int($courserecordorid)) {
 468              $courserecordorid = get_course($courserecordorid);
 469          }
 470          $course = new \course_in_list($courserecordorid);
 471          $category = \coursecat::get($course->category);
 472          return self::action_course_change_sortorder_up_one($course, $category);
 473      }
 474  
 475      /**
 476       * Resorts the courses within a category moving the given course down by one.
 477       *
 478       * @global \moodle_database $DB
 479       * @param int|\stdClass $courserecordorid
 480       * @return bool
 481       */
 482      public static function action_course_change_sortorder_down_one_by_record($courserecordorid) {
 483          if (is_int($courserecordorid)) {
 484              $courserecordorid = get_course($courserecordorid);
 485          }
 486          $course = new \course_in_list($courserecordorid);
 487          $category = \coursecat::get($course->category);
 488          return self::action_course_change_sortorder_down_one($course, $category);
 489      }
 490  
 491      /**
 492       * Changes the sort order so that the first course appears after the second course.
 493       *
 494       * @param int|\stdClass $courserecordorid
 495       * @param int $moveaftercourseid
 496       * @return bool
 497       * @throws \moodle_exception
 498       */
 499      public static function action_course_change_sortorder_after_course($courserecordorid, $moveaftercourseid) {
 500          $course = \get_course($courserecordorid);
 501          $category = \coursecat::get($course->category);
 502          if (!$category->can_resort_courses()) {
 503              $url = '/course/management.php?categoryid='.$course->category;
 504              throw new \moodle_exception('nopermissions', 'error', $url, \get_string('resortcourses', 'moodle'));
 505          }
 506          return \course_change_sortorder_after_course($course, $moveaftercourseid);
 507      }
 508  
 509      /**
 510       * Makes a course visible given a \course_in_list object.
 511       *
 512       * @param \course_in_list $course
 513       * @return bool
 514       * @throws \moodle_exception
 515       */
 516      public static function action_course_show(\course_in_list $course) {
 517          if (!$course->can_change_visibility()) {
 518              throw new \moodle_exception('permissiondenied', 'error', '', null, 'course_in_list::can_change_visbility');
 519          }
 520          return course_change_visibility($course->id, true);
 521      }
 522  
 523      /**
 524       * Makes a course hidden given a \course_in_list object.
 525       *
 526       * @param \course_in_list $course
 527       * @return bool
 528       * @throws \moodle_exception
 529       */
 530      public static function action_course_hide(\course_in_list $course) {
 531          if (!$course->can_change_visibility()) {
 532              throw new \moodle_exception('permissiondenied', 'error', '', null, 'course_in_list::can_change_visbility');
 533          }
 534          return course_change_visibility($course->id, false);
 535      }
 536  
 537      /**
 538       * Makes a course visible given a course id or a database record.
 539       *
 540       * @global \moodle_database $DB
 541       * @param int|\stdClass $courserecordorid
 542       * @return bool
 543       */
 544      public static function action_course_show_by_record($courserecordorid) {
 545          if (is_int($courserecordorid)) {
 546              $courserecordorid = get_course($courserecordorid);
 547          }
 548          $course = new \course_in_list($courserecordorid);
 549          return self::action_course_show($course);
 550      }
 551  
 552      /**
 553       * Makes a course hidden given a course id or a database record.
 554       *
 555       * @global \moodle_database $DB
 556       * @param int|\stdClass $courserecordorid
 557       * @return bool
 558       */
 559      public static function action_course_hide_by_record($courserecordorid) {
 560          if (is_int($courserecordorid)) {
 561              $courserecordorid = get_course($courserecordorid);
 562          }
 563          $course = new \course_in_list($courserecordorid);
 564          return self::action_course_hide($course);
 565      }
 566  
 567      /**
 568       * Resort a categories subcategories shifting the given category up one.
 569       *
 570       * @param \coursecat $category
 571       * @return bool
 572       * @throws \moodle_exception
 573       */
 574      public static function action_category_change_sortorder_up_one(\coursecat $category) {
 575          if (!$category->can_change_sortorder()) {
 576              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_sortorder');
 577          }
 578          return $category->change_sortorder_by_one(true);
 579      }
 580  
 581      /**
 582       * Resort a categories subcategories shifting the given category down one.
 583       *
 584       * @param \coursecat $category
 585       * @return bool
 586       * @throws \moodle_exception
 587       */
 588      public static function action_category_change_sortorder_down_one(\coursecat $category) {
 589          if (!$category->can_change_sortorder()) {
 590              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_sortorder');
 591          }
 592          return $category->change_sortorder_by_one(false);
 593      }
 594  
 595      /**
 596       * Resort a categories subcategories shifting the given category up one.
 597       *
 598       * @param int $categoryid
 599       * @return bool
 600       */
 601      public static function action_category_change_sortorder_up_one_by_id($categoryid) {
 602          $category = \coursecat::get($categoryid);
 603          return self::action_category_change_sortorder_up_one($category);
 604      }
 605  
 606      /**
 607       * Resort a categories subcategories shifting the given category down one.
 608       *
 609       * @param int $categoryid
 610       * @return bool
 611       */
 612      public static function action_category_change_sortorder_down_one_by_id($categoryid) {
 613          $category = \coursecat::get($categoryid);
 614          return self::action_category_change_sortorder_down_one($category);
 615      }
 616  
 617      /**
 618       * Makes a category hidden given a \coursecat record.
 619       *
 620       * @param \coursecat $category
 621       * @return bool
 622       * @throws \moodle_exception
 623       */
 624      public static function action_category_hide(\coursecat $category) {
 625          if (!$category->can_change_visibility()) {
 626              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_visbility');
 627          }
 628          $category->hide();
 629          return true;
 630      }
 631  
 632      /**
 633       * Makes a category visible given a \coursecat record.
 634       *
 635       * @param \coursecat $category
 636       * @return bool
 637       * @throws \moodle_exception
 638       */
 639      public static function action_category_show(\coursecat $category) {
 640          if (!$category->can_change_visibility()) {
 641              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_visbility');
 642          }
 643          $category->show();
 644          return true;
 645      }
 646  
 647      /**
 648       * Makes a category visible given a \coursecat id or database record.
 649       *
 650       * @param int|\stdClass $categoryid
 651       * @return bool
 652       */
 653      public static function action_category_show_by_id($categoryid) {
 654          return self::action_category_show(\coursecat::get($categoryid));
 655      }
 656  
 657      /**
 658       * Makes a category hidden given a \coursecat id or database record.
 659       *
 660       * @param int|\stdClass $categoryid
 661       * @return bool
 662       */
 663      public static function action_category_hide_by_id($categoryid) {
 664          return self::action_category_hide(\coursecat::get($categoryid));
 665      }
 666  
 667      /**
 668       * Resorts the sub categories of the given category.
 669       *
 670       * @param \coursecat $category
 671       * @param string $sort One of idnumber or name.
 672       * @param bool $cleanup If true cleanup will be done, if false you will need to do it manually later.
 673       * @return bool
 674       * @throws \moodle_exception
 675       */
 676      public static function action_category_resort_subcategories(\coursecat $category, $sort, $cleanup = true) {
 677          if (!$category->can_resort_subcategories()) {
 678              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
 679          }
 680          return $category->resort_subcategories($sort, $cleanup);
 681      }
 682  
 683      /**
 684       * Resorts the courses within the given category.
 685       *
 686       * @param \coursecat $category
 687       * @param string $sort One of fullname, shortname or idnumber
 688       * @param bool $cleanup If true cleanup will be done, if false you will need to do it manually later.
 689       * @return bool
 690       * @throws \moodle_exception
 691       */
 692      public static function action_category_resort_courses(\coursecat $category, $sort, $cleanup = true) {
 693          if (!$category->can_resort_courses()) {
 694              throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
 695          }
 696          return $category->resort_courses($sort, $cleanup);
 697      }
 698  
 699      /**
 700       * Moves courses out of one category and into a new category.
 701       *
 702       * @param \coursecat $oldcategory The category we are moving courses out of.
 703       * @param \coursecat $newcategory The category we are moving courses into.
 704       * @param array $courseids The ID's of the courses we want to move.
 705       * @return bool True on success.
 706       * @throws \moodle_exception
 707       */
 708      public static function action_category_move_courses_into(\coursecat $oldcategory, \coursecat $newcategory, array $courseids) {
 709          global $DB;
 710  
 711          list($where, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
 712          $params['categoryid'] = $oldcategory->id;
 713          $sql = "SELECT c.id FROM {course} c WHERE c.id {$where} AND c.category <> :categoryid";
 714          if ($DB->record_exists_sql($sql, $params)) {
 715              // Likely being tinkered with.
 716              throw new \moodle_exception('coursedoesnotbelongtocategory');
 717          }
 718  
 719          // All courses are currently within the old category.
 720          return self::move_courses_into_category($newcategory, $courseids);
 721      }
 722  
 723      /**
 724       * Returns the view modes for the management interface.
 725       * @return array
 726       */
 727      public static function get_management_viewmodes() {
 728          return array(
 729              'combined' => new \lang_string('categoriesandcoures'),
 730              'categories' => new \lang_string('categories'),
 731              'courses' => new \lang_string('courses')
 732          );
 733      }
 734  
 735      /**
 736       * Search for courses with matching params.
 737       *
 738       * Please note that only one of search, blocklist, or modulelist can be specified at a time.
 739       * Specifying more than one will result in only the first being used.
 740       *
 741       * @param string $search Words to search for. We search fullname, shortname, idnumber and summary.
 742       * @param int $blocklist The ID of a block, courses will only be returned if they use this block.
 743       * @param string $modulelist The name of a module (relates to database table name). Only courses containing this module
 744       *      will be returned.
 745       * @param int $page The page number to display, starting at 0.
 746       * @param int $perpage The number of courses to display per page.
 747       * @return array
 748       */
 749      public static function search_courses($search, $blocklist, $modulelist, $page = 0, $perpage = null) {
 750          global $CFG;
 751  
 752          if ($perpage === null) {
 753              $perpage = $CFG->coursesperpage;
 754          }
 755  
 756          $searchcriteria = array();
 757          if (!empty($search)) {
 758              $searchcriteria = array('search' => $search);
 759          } else if (!empty($blocklist)) {
 760              $searchcriteria = array('blocklist' => $blocklist);
 761          } else if (!empty($modulelist)) {
 762              $searchcriteria = array('modulelist' => $modulelist);
 763          }
 764  
 765          $courses = \coursecat::get(0)->search_courses($searchcriteria, array(
 766              'recursive' => true,
 767              'offset' => $page * $perpage,
 768              'limit' => $perpage,
 769              'sort' => array('fullname' => 1)
 770          ));
 771          $totalcount = \coursecat::get(0)->search_courses_count($searchcriteria, array('recursive' => true));
 772  
 773          return array($courses, \count($courses), $totalcount);
 774      }
 775  
 776      /**
 777       * Moves one or more courses out of the category they are currently in and into a new category.
 778       *
 779       * This function works much the same way as action_category_move_courses_into however it allows courses from multiple
 780       * categories to be moved into a single category.
 781       *
 782       * @param int|\coursecat $categoryorid The category to move them into.
 783       * @param array|int $courseids An array of course id's or optionally just a single course id.
 784       * @return bool True on success or false on failure.
 785       * @throws \moodle_exception
 786       */
 787      public static function move_courses_into_category($categoryorid, $courseids = array()) {
 788          global $DB;
 789          if (!is_array($courseids)) {
 790              // Just a single course ID.
 791              $courseids = array($courseids);
 792          }
 793          // Bulk move courses from one category to another.
 794          if (count($courseids) === 0) {
 795              return false;
 796          }
 797          if ($categoryorid instanceof \coursecat) {
 798              $moveto = $categoryorid;
 799          } else {
 800              $moveto = \coursecat::get($categoryorid);
 801          }
 802          if (!$moveto->can_move_courses_out_of() || !$moveto->can_move_courses_into()) {
 803              throw new \moodle_exception('cannotmovecourses');
 804          }
 805  
 806          list($where, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
 807          $sql = "SELECT c.id, c.category FROM {course} c WHERE c.id {$where}";
 808          $courses = $DB->get_records_sql($sql, $params);
 809          $checks = array();
 810          foreach ($courseids as $id) {
 811              if (!isset($courses[$id])) {
 812                  throw new \moodle_exception('invalidcourseid');
 813              }
 814              $catid = $courses[$id]->category;
 815              if (!isset($checks[$catid])) {
 816                  $coursecat = \coursecat::get($catid);
 817                  $checks[$catid] = $coursecat->can_move_courses_out_of() && $coursecat->can_move_courses_into();
 818              }
 819              if (!$checks[$catid]) {
 820                  throw new \moodle_exception('cannotmovecourses');
 821              }
 822          }
 823          return \move_courses($courseids, $moveto->id);
 824      }
 825  
 826      /**
 827       * Returns an array of courseids and visiblity for all courses within the given category.
 828       * @param int $categoryid
 829       * @return array
 830       */
 831      public static function get_category_courses_visibility($categoryid) {
 832          global $DB;
 833          $sql = "SELECT c.id, c.visible
 834                    FROM {course} c
 835                   WHERE c.category = :category";
 836          $params = array('category' => (int)$categoryid);
 837          return $DB->get_records_sql($sql, $params);
 838      }
 839  
 840      /**
 841       * Returns an array of all categoryids that have the given category as a parent and their visible value.
 842       * @param int $categoryid
 843       * @return array
 844       */
 845      public static function get_category_children_visibility($categoryid) {
 846          global $DB;
 847          $category = \coursecat::get($categoryid);
 848          $select = $DB->sql_like('path', ':path');
 849          $path = $category->path . '/%';
 850  
 851          $sql = "SELECT c.id, c.visible
 852                    FROM {course_categories} c
 853                   WHERE ".$select;
 854          $params = array('path' => $path);
 855          return $DB->get_records_sql($sql, $params);
 856      }
 857  
 858      /**
 859       * Records when a category is expanded or collapsed so that when the user
 860       *
 861       * @param \coursecat $coursecat The category we're working with.
 862       * @param bool $expanded True if the category is expanded now.
 863       */
 864      public static function record_expanded_category(\coursecat $coursecat, $expanded = true) {
 865          // If this ever changes we are going to reset it and reload the categories as required.
 866          self::$expandedcategories = null;
 867          $categoryid = $coursecat->id;
 868          $path = $coursecat->get_parents();
 869          /* @var \cache_session $cache */
 870          $cache = \cache::make('core', 'userselections');
 871          $categories = $cache->get('categorymanagementexpanded');
 872          if (!is_array($categories)) {
 873              if (!$expanded) {
 874                  // No categories recorded, nothing to remove.
 875                  return;
 876              }
 877              $categories = array();
 878          }
 879          if ($expanded) {
 880              $ref =& $categories;
 881              foreach ($coursecat->get_parents() as $path) {
 882                  if (!isset($ref[$path]) || !is_array($ref[$path])) {
 883                      $ref[$path] = array();
 884                  }
 885                  $ref =& $ref[$path];
 886              }
 887              if (!isset($ref[$categoryid])) {
 888                  $ref[$categoryid] = true;
 889              }
 890          } else {
 891              $found = true;
 892              $ref =& $categories;
 893              foreach ($coursecat->get_parents() as $path) {
 894                  if (!isset($ref[$path])) {
 895                      $found = false;
 896                      break;
 897                  }
 898                  $ref =& $ref[$path];
 899              }
 900              if ($found) {
 901                  $ref[$categoryid] = null;
 902                  unset($ref[$categoryid]);
 903              }
 904          }
 905          $cache->set('categorymanagementexpanded', $categories);
 906      }
 907  
 908      /**
 909       * Returns the categories that should be expanded when displaying the interface.
 910       *
 911       * @param int|null $withpath If specified a path to require as the parent.
 912       * @return \coursecat[] An array of Category ID's to expand.
 913       */
 914      public static function get_expanded_categories($withpath = null) {
 915          if (self::$expandedcategories === null) {
 916              /* @var \cache_session $cache */
 917              $cache = \cache::make('core', 'userselections');
 918              self::$expandedcategories = $cache->get('categorymanagementexpanded');
 919              if (self::$expandedcategories === false) {
 920                  self::$expandedcategories = array();
 921              }
 922          }
 923          if (empty($withpath)) {
 924              return array_keys(self::$expandedcategories);
 925          }
 926          $parents = explode('/', trim($withpath, '/'));
 927          $ref =& self::$expandedcategories;
 928          foreach ($parents as $parent) {
 929              if (!isset($ref[$parent])) {
 930                  return array();
 931              }
 932              $ref =& $ref[$parent];
 933          }
 934          if (is_array($ref)) {
 935              return array_keys($ref);
 936          } else {
 937              return array($parent);
 938          }
 939      }
 940  }

Search This Site: