Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • Differences Between: [Versions 28 and 29] [Versions 28 and 30] [Versions 28 and 31] [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       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: