[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/course/ -> externallib.php (source)

   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  /**
  19   * External course API
  20   *
  21   * @package    core_course
  22   * @category   external
  23   * @copyright  2009 Petr Skodak
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die;
  28  
  29  require_once("$CFG->libdir/externallib.php");
  30  
  31  /**
  32   * Course external functions
  33   *
  34   * @package    core_course
  35   * @category   external
  36   * @copyright  2011 Jerome Mouneyrac
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   * @since Moodle 2.2
  39   */
  40  class core_course_external extends external_api {
  41  
  42      /**
  43       * Returns description of method parameters
  44       *
  45       * @return external_function_parameters
  46       * @since Moodle 2.2
  47       */
  48      public static function get_course_contents_parameters() {
  49          return new external_function_parameters(
  50                  array('courseid' => new external_value(PARAM_INT, 'course id'),
  51                        'options' => new external_multiple_structure (
  52                                new external_single_structure(
  53                                      array('name' => new external_value(PARAM_ALPHANUM, 'option name'),
  54                                            'value' => new external_value(PARAM_RAW, 'the value of the option, this param is personaly validated in the external function.')
  55                                )
  56                        ), 'Options, not used yet, might be used in later version', VALUE_DEFAULT, array())
  57                  )
  58          );
  59      }
  60  
  61      /**
  62       * Get course contents
  63       *
  64       * @param int $courseid course id
  65       * @param array $options These options are not used yet, might be used in later version
  66       * @return array
  67       * @since Moodle 2.2
  68       */
  69      public static function get_course_contents($courseid, $options = array()) {
  70          global $CFG, $DB;
  71          require_once($CFG->dirroot . "/course/lib.php");
  72  
  73          //validate parameter
  74          $params = self::validate_parameters(self::get_course_contents_parameters(),
  75                          array('courseid' => $courseid, 'options' => $options));
  76  
  77          //retrieve the course
  78          $course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST);
  79  
  80          //check course format exist
  81          if (!file_exists($CFG->dirroot . '/course/format/' . $course->format . '/lib.php')) {
  82              throw new moodle_exception('cannotgetcoursecontents', 'webservice', '', null, get_string('courseformatnotfound', 'error', '', $course->format));
  83          } else {
  84              require_once($CFG->dirroot . '/course/format/' . $course->format . '/lib.php');
  85          }
  86  
  87          // now security checks
  88          $context = context_course::instance($course->id, IGNORE_MISSING);
  89          try {
  90              self::validate_context($context);
  91          } catch (Exception $e) {
  92              $exceptionparam = new stdClass();
  93              $exceptionparam->message = $e->getMessage();
  94              $exceptionparam->courseid = $course->id;
  95              throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam);
  96          }
  97  
  98          $canupdatecourse = has_capability('moodle/course:update', $context);
  99  
 100          //create return value
 101          $coursecontents = array();
 102  
 103          if ($canupdatecourse or $course->visible
 104                  or has_capability('moodle/course:viewhiddencourses', $context)) {
 105  
 106              //retrieve sections
 107              $modinfo = get_fast_modinfo($course);
 108              $sections = $modinfo->get_section_info_all();
 109  
 110              //for each sections (first displayed to last displayed)
 111              $modinfosections = $modinfo->get_sections();
 112              foreach ($sections as $key => $section) {
 113  
 114                  if (!$section->uservisible) {
 115                      continue;
 116                  }
 117  
 118                  // reset $sectioncontents
 119                  $sectionvalues = array();
 120                  $sectionvalues['id'] = $section->id;
 121                  $sectionvalues['name'] = get_section_name($course, $section);
 122                  $sectionvalues['visible'] = $section->visible;
 123                  list($sectionvalues['summary'], $sectionvalues['summaryformat']) =
 124                          external_format_text($section->summary, $section->summaryformat,
 125                                  $context->id, 'course', 'section', $section->id);
 126                  $sectioncontents = array();
 127  
 128                  //for each module of the section
 129                  if (!empty($modinfosections[$section->section])) {
 130                      foreach ($modinfosections[$section->section] as $cmid) {
 131                          $cm = $modinfo->cms[$cmid];
 132  
 133                          // stop here if the module is not visible to the user
 134                          if (!$cm->uservisible) {
 135                              continue;
 136                          }
 137  
 138                          $module = array();
 139  
 140                          //common info (for people being able to see the module or availability dates)
 141                          $module['id'] = $cm->id;
 142                          $module['name'] = format_string($cm->name, true);
 143                          $module['instance'] = $cm->instance;
 144                          $module['modname'] = $cm->modname;
 145                          $module['modplural'] = $cm->modplural;
 146                          $module['modicon'] = $cm->get_icon_url()->out(false);
 147                          $module['indent'] = $cm->indent;
 148  
 149                          $modcontext = context_module::instance($cm->id);
 150  
 151                          if (!empty($cm->showdescription) or $cm->modname == 'label') {
 152                              // We want to use the external format. However from reading get_formatted_content(), $cm->content format is always FORMAT_HTML.
 153                              list($module['description'], $descriptionformat) = external_format_text($cm->content,
 154                                  FORMAT_HTML, $modcontext->id, $cm->modname, 'intro', $cm->id);
 155                          }
 156  
 157                          //url of the module
 158                          $url = $cm->url;
 159                          if ($url) { //labels don't have url
 160                              $module['url'] = $url->out(false);
 161                          }
 162  
 163                          $canviewhidden = has_capability('moodle/course:viewhiddenactivities',
 164                                              context_module::instance($cm->id));
 165                          //user that can view hidden module should know about the visibility
 166                          $module['visible'] = $cm->visible;
 167  
 168                          // Availability date (also send to user who can see hidden module).
 169                          if ($CFG->enableavailability && ($canviewhidden || $canupdatecourse)) {
 170                              $module['availability'] = $cm->availability;
 171                          }
 172  
 173                          $baseurl = 'webservice/pluginfile.php';
 174  
 175                          //call $modulename_export_contents
 176                          //(each module callback take care about checking the capabilities)
 177                          require_once($CFG->dirroot . '/mod/' . $cm->modname . '/lib.php');
 178                          $getcontentfunction = $cm->modname.'_export_contents';
 179                          if (function_exists($getcontentfunction)) {
 180                              if ($contents = $getcontentfunction($cm, $baseurl)) {
 181                                  $module['contents'] = $contents;
 182                              }
 183                          }
 184  
 185                          //assign result to $sectioncontents
 186                          $sectioncontents[] = $module;
 187  
 188                      }
 189                  }
 190                  $sectionvalues['modules'] = $sectioncontents;
 191  
 192                  // assign result to $coursecontents
 193                  $coursecontents[] = $sectionvalues;
 194              }
 195          }
 196          return $coursecontents;
 197      }
 198  
 199      /**
 200       * Returns description of method result value
 201       *
 202       * @return external_description
 203       * @since Moodle 2.2
 204       */
 205      public static function get_course_contents_returns() {
 206          return new external_multiple_structure(
 207              new external_single_structure(
 208                  array(
 209                      'id' => new external_value(PARAM_INT, 'Section ID'),
 210                      'name' => new external_value(PARAM_TEXT, 'Section name'),
 211                      'visible' => new external_value(PARAM_INT, 'is the section visible', VALUE_OPTIONAL),
 212                      'summary' => new external_value(PARAM_RAW, 'Section description'),
 213                      'summaryformat' => new external_format_value('summary'),
 214                      'modules' => new external_multiple_structure(
 215                              new external_single_structure(
 216                                  array(
 217                                      'id' => new external_value(PARAM_INT, 'activity id'),
 218                                      'url' => new external_value(PARAM_URL, 'activity url', VALUE_OPTIONAL),
 219                                      'name' => new external_value(PARAM_RAW, 'activity module name'),
 220                                      'description' => new external_value(PARAM_RAW, 'activity description', VALUE_OPTIONAL),
 221                                      'visible' => new external_value(PARAM_INT, 'is the module visible', VALUE_OPTIONAL),
 222                                      'modicon' => new external_value(PARAM_URL, 'activity icon url'),
 223                                      'modname' => new external_value(PARAM_PLUGIN, 'activity module type'),
 224                                      'modplural' => new external_value(PARAM_TEXT, 'activity module plural name'),
 225                                      'availability' => new external_value(PARAM_RAW, 'module availability settings', VALUE_OPTIONAL),
 226                                      'indent' => new external_value(PARAM_INT, 'number of identation in the site'),
 227                                      'contents' => new external_multiple_structure(
 228                                            new external_single_structure(
 229                                                array(
 230                                                    // content info
 231                                                    'type'=> new external_value(PARAM_TEXT, 'a file or a folder or external link'),
 232                                                    'filename'=> new external_value(PARAM_FILE, 'filename'),
 233                                                    'filepath'=> new external_value(PARAM_PATH, 'filepath'),
 234                                                    'filesize'=> new external_value(PARAM_INT, 'filesize'),
 235                                                    'fileurl' => new external_value(PARAM_URL, 'downloadable file url', VALUE_OPTIONAL),
 236                                                    'content' => new external_value(PARAM_RAW, 'Raw content, will be used when type is content', VALUE_OPTIONAL),
 237                                                    'timecreated' => new external_value(PARAM_INT, 'Time created'),
 238                                                    'timemodified' => new external_value(PARAM_INT, 'Time modified'),
 239                                                    'sortorder' => new external_value(PARAM_INT, 'Content sort order'),
 240  
 241                                                    // copyright related info
 242                                                    'userid' => new external_value(PARAM_INT, 'User who added this content to moodle'),
 243                                                    'author' => new external_value(PARAM_TEXT, 'Content owner'),
 244                                                    'license' => new external_value(PARAM_TEXT, 'Content license'),
 245                                                )
 246                                            ), VALUE_DEFAULT, array()
 247                                        )
 248                                  )
 249                              ), 'list of module'
 250                      )
 251                  )
 252              )
 253          );
 254      }
 255  
 256      /**
 257       * Returns description of method parameters
 258       *
 259       * @return external_function_parameters
 260       * @since Moodle 2.3
 261       */
 262      public static function get_courses_parameters() {
 263          return new external_function_parameters(
 264                  array('options' => new external_single_structure(
 265                              array('ids' => new external_multiple_structure(
 266                                          new external_value(PARAM_INT, 'Course id')
 267                                          , 'List of course id. If empty return all courses
 268                                              except front page course.',
 269                                          VALUE_OPTIONAL)
 270                              ), 'options - operator OR is used', VALUE_DEFAULT, array())
 271                  )
 272          );
 273      }
 274  
 275      /**
 276       * Get courses
 277       *
 278       * @param array $options It contains an array (list of ids)
 279       * @return array
 280       * @since Moodle 2.2
 281       */
 282      public static function get_courses($options = array()) {
 283          global $CFG, $DB;
 284          require_once($CFG->dirroot . "/course/lib.php");
 285  
 286          //validate parameter
 287          $params = self::validate_parameters(self::get_courses_parameters(),
 288                          array('options' => $options));
 289  
 290          //retrieve courses
 291          if (!array_key_exists('ids', $params['options'])
 292                  or empty($params['options']['ids'])) {
 293              $courses = $DB->get_records('course');
 294          } else {
 295              $courses = $DB->get_records_list('course', 'id', $params['options']['ids']);
 296          }
 297  
 298          //create return value
 299          $coursesinfo = array();
 300          foreach ($courses as $course) {
 301  
 302              // now security checks
 303              $context = context_course::instance($course->id, IGNORE_MISSING);
 304              $courseformatoptions = course_get_format($course)->get_format_options();
 305              try {
 306                  self::validate_context($context);
 307              } catch (Exception $e) {
 308                  $exceptionparam = new stdClass();
 309                  $exceptionparam->message = $e->getMessage();
 310                  $exceptionparam->courseid = $course->id;
 311                  throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam);
 312              }
 313              require_capability('moodle/course:view', $context);
 314  
 315              $courseinfo = array();
 316              $courseinfo['id'] = $course->id;
 317              $courseinfo['fullname'] = $course->fullname;
 318              $courseinfo['shortname'] = $course->shortname;
 319              $courseinfo['categoryid'] = $course->category;
 320              list($courseinfo['summary'], $courseinfo['summaryformat']) =
 321                  external_format_text($course->summary, $course->summaryformat, $context->id, 'course', 'summary', 0);
 322              $courseinfo['format'] = $course->format;
 323              $courseinfo['startdate'] = $course->startdate;
 324              if (array_key_exists('numsections', $courseformatoptions)) {
 325                  // For backward-compartibility
 326                  $courseinfo['numsections'] = $courseformatoptions['numsections'];
 327              }
 328  
 329              //some field should be returned only if the user has update permission
 330              $courseadmin = has_capability('moodle/course:update', $context);
 331              if ($courseadmin) {
 332                  $courseinfo['categorysortorder'] = $course->sortorder;
 333                  $courseinfo['idnumber'] = $course->idnumber;
 334                  $courseinfo['showgrades'] = $course->showgrades;
 335                  $courseinfo['showreports'] = $course->showreports;
 336                  $courseinfo['newsitems'] = $course->newsitems;
 337                  $courseinfo['visible'] = $course->visible;
 338                  $courseinfo['maxbytes'] = $course->maxbytes;
 339                  if (array_key_exists('hiddensections', $courseformatoptions)) {
 340                      // For backward-compartibility
 341                      $courseinfo['hiddensections'] = $courseformatoptions['hiddensections'];
 342                  }
 343                  $courseinfo['groupmode'] = $course->groupmode;
 344                  $courseinfo['groupmodeforce'] = $course->groupmodeforce;
 345                  $courseinfo['defaultgroupingid'] = $course->defaultgroupingid;
 346                  $courseinfo['lang'] = $course->lang;
 347                  $courseinfo['timecreated'] = $course->timecreated;
 348                  $courseinfo['timemodified'] = $course->timemodified;
 349                  $courseinfo['forcetheme'] = $course->theme;
 350                  $courseinfo['enablecompletion'] = $course->enablecompletion;
 351                  $courseinfo['completionnotify'] = $course->completionnotify;
 352                  $courseinfo['courseformatoptions'] = array();
 353                  foreach ($courseformatoptions as $key => $value) {
 354                      $courseinfo['courseformatoptions'][] = array(
 355                          'name' => $key,
 356                          'value' => $value
 357                      );
 358                  }
 359              }
 360  
 361              if ($courseadmin or $course->visible
 362                      or has_capability('moodle/course:viewhiddencourses', $context)) {
 363                  $coursesinfo[] = $courseinfo;
 364              }
 365          }
 366  
 367          return $coursesinfo;
 368      }
 369  
 370      /**
 371       * Returns description of method result value
 372       *
 373       * @return external_description
 374       * @since Moodle 2.2
 375       */
 376      public static function get_courses_returns() {
 377          return new external_multiple_structure(
 378                  new external_single_structure(
 379                          array(
 380                              'id' => new external_value(PARAM_INT, 'course id'),
 381                              'shortname' => new external_value(PARAM_TEXT, 'course short name'),
 382                              'categoryid' => new external_value(PARAM_INT, 'category id'),
 383                              'categorysortorder' => new external_value(PARAM_INT,
 384                                      'sort order into the category', VALUE_OPTIONAL),
 385                              'fullname' => new external_value(PARAM_TEXT, 'full name'),
 386                              'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
 387                              'summary' => new external_value(PARAM_RAW, 'summary'),
 388                              'summaryformat' => new external_format_value('summary'),
 389                              'format' => new external_value(PARAM_PLUGIN,
 390                                      'course format: weeks, topics, social, site,..'),
 391                              'showgrades' => new external_value(PARAM_INT,
 392                                      '1 if grades are shown, otherwise 0', VALUE_OPTIONAL),
 393                              'newsitems' => new external_value(PARAM_INT,
 394                                      'number of recent items appearing on the course page', VALUE_OPTIONAL),
 395                              'startdate' => new external_value(PARAM_INT,
 396                                      'timestamp when the course start'),
 397                              'numsections' => new external_value(PARAM_INT,
 398                                      '(deprecated, use courseformatoptions) number of weeks/topics',
 399                                      VALUE_OPTIONAL),
 400                              'maxbytes' => new external_value(PARAM_INT,
 401                                      'largest size of file that can be uploaded into the course',
 402                                      VALUE_OPTIONAL),
 403                              'showreports' => new external_value(PARAM_INT,
 404                                      'are activity report shown (yes = 1, no =0)', VALUE_OPTIONAL),
 405                              'visible' => new external_value(PARAM_INT,
 406                                      '1: available to student, 0:not available', VALUE_OPTIONAL),
 407                              'hiddensections' => new external_value(PARAM_INT,
 408                                      '(deprecated, use courseformatoptions) How the hidden sections in the course are displayed to students',
 409                                      VALUE_OPTIONAL),
 410                              'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
 411                                      VALUE_OPTIONAL),
 412                              'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
 413                                      VALUE_OPTIONAL),
 414                              'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
 415                                      VALUE_OPTIONAL),
 416                              'timecreated' => new external_value(PARAM_INT,
 417                                      'timestamp when the course have been created', VALUE_OPTIONAL),
 418                              'timemodified' => new external_value(PARAM_INT,
 419                                      'timestamp when the course have been modified', VALUE_OPTIONAL),
 420                              'enablecompletion' => new external_value(PARAM_INT,
 421                                      'Enabled, control via completion and activity settings. Disbaled,
 422                                          not shown in activity settings.',
 423                                      VALUE_OPTIONAL),
 424                              'completionnotify' => new external_value(PARAM_INT,
 425                                      '1: yes 0: no', VALUE_OPTIONAL),
 426                              'lang' => new external_value(PARAM_SAFEDIR,
 427                                      'forced course language', VALUE_OPTIONAL),
 428                              'forcetheme' => new external_value(PARAM_PLUGIN,
 429                                      'name of the force theme', VALUE_OPTIONAL),
 430                              'courseformatoptions' => new external_multiple_structure(
 431                                  new external_single_structure(
 432                                      array('name' => new external_value(PARAM_ALPHANUMEXT, 'course format option name'),
 433                                          'value' => new external_value(PARAM_RAW, 'course format option value')
 434                                  )),
 435                                      'additional options for particular course format', VALUE_OPTIONAL
 436                               ),
 437                          ), 'course'
 438                  )
 439          );
 440      }
 441  
 442      /**
 443       * Returns description of method parameters
 444       *
 445       * @return external_function_parameters
 446       * @since Moodle 2.2
 447       */
 448      public static function create_courses_parameters() {
 449          $courseconfig = get_config('moodlecourse'); //needed for many default values
 450          return new external_function_parameters(
 451              array(
 452                  'courses' => new external_multiple_structure(
 453                      new external_single_structure(
 454                          array(
 455                              'fullname' => new external_value(PARAM_TEXT, 'full name'),
 456                              'shortname' => new external_value(PARAM_TEXT, 'course short name'),
 457                              'categoryid' => new external_value(PARAM_INT, 'category id'),
 458                              'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
 459                              'summary' => new external_value(PARAM_RAW, 'summary', VALUE_OPTIONAL),
 460                              'summaryformat' => new external_format_value('summary', VALUE_DEFAULT),
 461                              'format' => new external_value(PARAM_PLUGIN,
 462                                      'course format: weeks, topics, social, site,..',
 463                                      VALUE_DEFAULT, $courseconfig->format),
 464                              'showgrades' => new external_value(PARAM_INT,
 465                                      '1 if grades are shown, otherwise 0', VALUE_DEFAULT,
 466                                      $courseconfig->showgrades),
 467                              'newsitems' => new external_value(PARAM_INT,
 468                                      'number of recent items appearing on the course page',
 469                                      VALUE_DEFAULT, $courseconfig->newsitems),
 470                              'startdate' => new external_value(PARAM_INT,
 471                                      'timestamp when the course start', VALUE_OPTIONAL),
 472                              'numsections' => new external_value(PARAM_INT,
 473                                      '(deprecated, use courseformatoptions) number of weeks/topics',
 474                                      VALUE_OPTIONAL),
 475                              'maxbytes' => new external_value(PARAM_INT,
 476                                      'largest size of file that can be uploaded into the course',
 477                                      VALUE_DEFAULT, $courseconfig->maxbytes),
 478                              'showreports' => new external_value(PARAM_INT,
 479                                      'are activity report shown (yes = 1, no =0)', VALUE_DEFAULT,
 480                                      $courseconfig->showreports),
 481                              'visible' => new external_value(PARAM_INT,
 482                                      '1: available to student, 0:not available', VALUE_OPTIONAL),
 483                              'hiddensections' => new external_value(PARAM_INT,
 484                                      '(deprecated, use courseformatoptions) How the hidden sections in the course are displayed to students',
 485                                      VALUE_OPTIONAL),
 486                              'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
 487                                      VALUE_DEFAULT, $courseconfig->groupmode),
 488                              'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
 489                                      VALUE_DEFAULT, $courseconfig->groupmodeforce),
 490                              'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
 491                                      VALUE_DEFAULT, 0),
 492                              'enablecompletion' => new external_value(PARAM_INT,
 493                                      'Enabled, control via completion and activity settings. Disabled,
 494                                          not shown in activity settings.',
 495                                      VALUE_OPTIONAL),
 496                              'completionnotify' => new external_value(PARAM_INT,
 497                                      '1: yes 0: no', VALUE_OPTIONAL),
 498                              'lang' => new external_value(PARAM_SAFEDIR,
 499                                      'forced course language', VALUE_OPTIONAL),
 500                              'forcetheme' => new external_value(PARAM_PLUGIN,
 501                                      'name of the force theme', VALUE_OPTIONAL),
 502                              'courseformatoptions' => new external_multiple_structure(
 503                                  new external_single_structure(
 504                                      array('name' => new external_value(PARAM_ALPHANUMEXT, 'course format option name'),
 505                                          'value' => new external_value(PARAM_RAW, 'course format option value')
 506                                  )),
 507                                      'additional options for particular course format', VALUE_OPTIONAL),
 508                          )
 509                      ), 'courses to create'
 510                  )
 511              )
 512          );
 513      }
 514  
 515      /**
 516       * Create  courses
 517       *
 518       * @param array $courses
 519       * @return array courses (id and shortname only)
 520       * @since Moodle 2.2
 521       */
 522      public static function create_courses($courses) {
 523          global $CFG, $DB;
 524          require_once($CFG->dirroot . "/course/lib.php");
 525          require_once($CFG->libdir . '/completionlib.php');
 526  
 527          $params = self::validate_parameters(self::create_courses_parameters(),
 528                          array('courses' => $courses));
 529  
 530          $availablethemes = core_component::get_plugin_list('theme');
 531          $availablelangs = get_string_manager()->get_list_of_translations();
 532  
 533          $transaction = $DB->start_delegated_transaction();
 534  
 535          foreach ($params['courses'] as $course) {
 536  
 537              // Ensure the current user is allowed to run this function
 538              $context = context_coursecat::instance($course['categoryid'], IGNORE_MISSING);
 539              try {
 540                  self::validate_context($context);
 541              } catch (Exception $e) {
 542                  $exceptionparam = new stdClass();
 543                  $exceptionparam->message = $e->getMessage();
 544                  $exceptionparam->catid = $course['categoryid'];
 545                  throw new moodle_exception('errorcatcontextnotvalid', 'webservice', '', $exceptionparam);
 546              }
 547              require_capability('moodle/course:create', $context);
 548  
 549              // Make sure lang is valid
 550              if (array_key_exists('lang', $course) and empty($availablelangs[$course['lang']])) {
 551                  throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang');
 552              }
 553  
 554              // Make sure theme is valid
 555              if (array_key_exists('forcetheme', $course)) {
 556                  if (!empty($CFG->allowcoursethemes)) {
 557                      if (empty($availablethemes[$course['forcetheme']])) {
 558                          throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme');
 559                      } else {
 560                          $course['theme'] = $course['forcetheme'];
 561                      }
 562                  }
 563              }
 564  
 565              //force visibility if ws user doesn't have the permission to set it
 566              $category = $DB->get_record('course_categories', array('id' => $course['categoryid']));
 567              if (!has_capability('moodle/course:visibility', $context)) {
 568                  $course['visible'] = $category->visible;
 569              }
 570  
 571              //set default value for completion
 572              $courseconfig = get_config('moodlecourse');
 573              if (completion_info::is_enabled_for_site()) {
 574                  if (!array_key_exists('enablecompletion', $course)) {
 575                      $course['enablecompletion'] = $courseconfig->enablecompletion;
 576                  }
 577              } else {
 578                  $course['enablecompletion'] = 0;
 579              }
 580  
 581              $course['category'] = $course['categoryid'];
 582  
 583              // Summary format.
 584              $course['summaryformat'] = external_validate_format($course['summaryformat']);
 585  
 586              if (!empty($course['courseformatoptions'])) {
 587                  foreach ($course['courseformatoptions'] as $option) {
 588                      $course[$option['name']] = $option['value'];
 589                  }
 590              }
 591  
 592              //Note: create_course() core function check shortname, idnumber, category
 593              $course['id'] = create_course((object) $course)->id;
 594  
 595              $resultcourses[] = array('id' => $course['id'], 'shortname' => $course['shortname']);
 596          }
 597  
 598          $transaction->allow_commit();
 599  
 600          return $resultcourses;
 601      }
 602  
 603      /**
 604       * Returns description of method result value
 605       *
 606       * @return external_description
 607       * @since Moodle 2.2
 608       */
 609      public static function create_courses_returns() {
 610          return new external_multiple_structure(
 611              new external_single_structure(
 612                  array(
 613                      'id'       => new external_value(PARAM_INT, 'course id'),
 614                      'shortname' => new external_value(PARAM_TEXT, 'short name'),
 615                  )
 616              )
 617          );
 618      }
 619  
 620      /**
 621       * Update courses
 622       *
 623       * @return external_function_parameters
 624       * @since Moodle 2.5
 625       */
 626      public static function update_courses_parameters() {
 627          return new external_function_parameters(
 628              array(
 629                  'courses' => new external_multiple_structure(
 630                      new external_single_structure(
 631                          array(
 632                              'id' => new external_value(PARAM_INT, 'ID of the course'),
 633                              'fullname' => new external_value(PARAM_TEXT, 'full name', VALUE_OPTIONAL),
 634                              'shortname' => new external_value(PARAM_TEXT, 'course short name', VALUE_OPTIONAL),
 635                              'categoryid' => new external_value(PARAM_INT, 'category id', VALUE_OPTIONAL),
 636                              'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
 637                              'summary' => new external_value(PARAM_RAW, 'summary', VALUE_OPTIONAL),
 638                              'summaryformat' => new external_format_value('summary', VALUE_OPTIONAL),
 639                              'format' => new external_value(PARAM_PLUGIN,
 640                                      'course format: weeks, topics, social, site,..', VALUE_OPTIONAL),
 641                              'showgrades' => new external_value(PARAM_INT,
 642                                      '1 if grades are shown, otherwise 0', VALUE_OPTIONAL),
 643                              'newsitems' => new external_value(PARAM_INT,
 644                                      'number of recent items appearing on the course page', VALUE_OPTIONAL),
 645                              'startdate' => new external_value(PARAM_INT,
 646                                      'timestamp when the course start', VALUE_OPTIONAL),
 647                              'numsections' => new external_value(PARAM_INT,
 648                                      '(deprecated, use courseformatoptions) number of weeks/topics', VALUE_OPTIONAL),
 649                              'maxbytes' => new external_value(PARAM_INT,
 650                                      'largest size of file that can be uploaded into the course', VALUE_OPTIONAL),
 651                              'showreports' => new external_value(PARAM_INT,
 652                                      'are activity report shown (yes = 1, no =0)', VALUE_OPTIONAL),
 653                              'visible' => new external_value(PARAM_INT,
 654                                      '1: available to student, 0:not available', VALUE_OPTIONAL),
 655                              'hiddensections' => new external_value(PARAM_INT,
 656                                      '(deprecated, use courseformatoptions) How the hidden sections in the course are
 657                                          displayed to students', VALUE_OPTIONAL),
 658                              'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible', VALUE_OPTIONAL),
 659                              'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no', VALUE_OPTIONAL),
 660                              'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id', VALUE_OPTIONAL),
 661                              'enablecompletion' => new external_value(PARAM_INT,
 662                                      'Enabled, control via completion and activity settings. Disabled,
 663                                          not shown in activity settings.', VALUE_OPTIONAL),
 664                              'completionnotify' => new external_value(PARAM_INT, '1: yes 0: no', VALUE_OPTIONAL),
 665                              'lang' => new external_value(PARAM_SAFEDIR, 'forced course language', VALUE_OPTIONAL),
 666                              'forcetheme' => new external_value(PARAM_PLUGIN, 'name of the force theme', VALUE_OPTIONAL),
 667                              'courseformatoptions' => new external_multiple_structure(
 668                                  new external_single_structure(
 669                                      array('name' => new external_value(PARAM_ALPHANUMEXT, 'course format option name'),
 670                                          'value' => new external_value(PARAM_RAW, 'course format option value')
 671                                  )),
 672                                      'additional options for particular course format', VALUE_OPTIONAL),
 673                          )
 674                      ), 'courses to update'
 675                  )
 676              )
 677          );
 678      }
 679  
 680      /**
 681       * Update courses
 682       *
 683       * @param array $courses
 684       * @since Moodle 2.5
 685       */
 686      public static function update_courses($courses) {
 687          global $CFG, $DB;
 688          require_once($CFG->dirroot . "/course/lib.php");
 689          $warnings = array();
 690  
 691          $params = self::validate_parameters(self::update_courses_parameters(),
 692                          array('courses' => $courses));
 693  
 694          $availablethemes = core_component::get_plugin_list('theme');
 695          $availablelangs = get_string_manager()->get_list_of_translations();
 696  
 697          foreach ($params['courses'] as $course) {
 698              // Catch any exception while updating course and return as warning to user.
 699              try {
 700                  // Ensure the current user is allowed to run this function.
 701                  $context = context_course::instance($course['id'], MUST_EXIST);
 702                  self::validate_context($context);
 703  
 704                  $oldcourse = course_get_format($course['id'])->get_course();
 705  
 706                  require_capability('moodle/course:update', $context);
 707  
 708                  // Check if user can change category.
 709                  if (array_key_exists('categoryid', $course) && ($oldcourse->category != $course['categoryid'])) {
 710                      require_capability('moodle/course:changecategory', $context);
 711                      $course['category'] = $course['categoryid'];
 712                  }
 713  
 714                  // Check if the user can change fullname.
 715                  if (array_key_exists('fullname', $course) && ($oldcourse->fullname != $course['fullname'])) {
 716                      require_capability('moodle/course:changefullname', $context);
 717                  }
 718  
 719                  // Check if the user can change shortname.
 720                  if (array_key_exists('shortname', $course) && ($oldcourse->shortname != $course['shortname'])) {
 721                      require_capability('moodle/course:changeshortname', $context);
 722                  }
 723  
 724                  // Check if the user can change the idnumber.
 725                  if (array_key_exists('idnumber', $course) && ($oldcourse->idnumber != $course['idnumber'])) {
 726                      require_capability('moodle/course:changeidnumber', $context);
 727                  }
 728  
 729                  // Check if user can change summary.
 730                  if (array_key_exists('summary', $course) && ($oldcourse->summary != $course['summary'])) {
 731                      require_capability('moodle/course:changesummary', $context);
 732                  }
 733  
 734                  // Summary format.
 735                  if (array_key_exists('summaryformat', $course) && ($oldcourse->summaryformat != $course['summaryformat'])) {
 736                      require_capability('moodle/course:changesummary', $context);
 737                      $course['summaryformat'] = external_validate_format($course['summaryformat']);
 738                  }
 739  
 740                  // Check if user can change visibility.
 741                  if (array_key_exists('visible', $course) && ($oldcourse->visible != $course['visible'])) {
 742                      require_capability('moodle/course:visibility', $context);
 743                  }
 744  
 745                  // Make sure lang is valid.
 746                  if (array_key_exists('lang', $course) && empty($availablelangs[$course['lang']])) {
 747                      throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang');
 748                  }
 749  
 750                  // Make sure theme is valid.
 751                  if (array_key_exists('forcetheme', $course)) {
 752                      if (!empty($CFG->allowcoursethemes)) {
 753                          if (empty($availablethemes[$course['forcetheme']])) {
 754                              throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme');
 755                          } else {
 756                              $course['theme'] = $course['forcetheme'];
 757                          }
 758                      }
 759                  }
 760  
 761                  // Make sure completion is enabled before setting it.
 762                  if (array_key_exists('enabledcompletion', $course) && !completion_info::is_enabled_for_site()) {
 763                      $course['enabledcompletion'] = 0;
 764                  }
 765  
 766                  // Make sure maxbytes are less then CFG->maxbytes.
 767                  if (array_key_exists('maxbytes', $course)) {
 768                      $course['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $course['maxbytes']);
 769                  }
 770  
 771                  if (!empty($course['courseformatoptions'])) {
 772                      foreach ($course['courseformatoptions'] as $option) {
 773                          if (isset($option['name']) && isset($option['value'])) {
 774                              $course[$option['name']] = $option['value'];
 775                          }
 776                      }
 777                  }
 778  
 779                  // Update course if user has all required capabilities.
 780                  update_course((object) $course);
 781              } catch (Exception $e) {
 782                  $warning = array();
 783                  $warning['item'] = 'course';
 784                  $warning['itemid'] = $course['id'];
 785                  if ($e instanceof moodle_exception) {
 786                      $warning['warningcode'] = $e->errorcode;
 787                  } else {
 788                      $warning['warningcode'] = $e->getCode();
 789                  }
 790                  $warning['message'] = $e->getMessage();
 791                  $warnings[] = $warning;
 792              }
 793          }
 794  
 795          $result = array();
 796          $result['warnings'] = $warnings;
 797          return $result;
 798      }
 799  
 800      /**
 801       * Returns description of method result value
 802       *
 803       * @return external_description
 804       * @since Moodle 2.5
 805       */
 806      public static function update_courses_returns() {
 807          return new external_single_structure(
 808              array(
 809                  'warnings' => new external_warnings()
 810              )
 811          );
 812      }
 813  
 814      /**
 815       * Returns description of method parameters
 816       *
 817       * @return external_function_parameters
 818       * @since Moodle 2.2
 819       */
 820      public static function delete_courses_parameters() {
 821          return new external_function_parameters(
 822              array(
 823                  'courseids' => new external_multiple_structure(new external_value(PARAM_INT, 'course ID')),
 824              )
 825          );
 826      }
 827  
 828      /**
 829       * Delete courses
 830       *
 831       * @param array $courseids A list of course ids
 832       * @since Moodle 2.2
 833       */
 834      public static function delete_courses($courseids) {
 835          global $CFG, $DB;
 836          require_once($CFG->dirroot."/course/lib.php");
 837  
 838          // Parameter validation.
 839          $params = self::validate_parameters(self::delete_courses_parameters(), array('courseids'=>$courseids));
 840  
 841          $transaction = $DB->start_delegated_transaction();
 842  
 843          foreach ($params['courseids'] as $courseid) {
 844              $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
 845  
 846              // Check if the context is valid.
 847              $coursecontext = context_course::instance($course->id);
 848              self::validate_context($coursecontext);
 849  
 850              // Check if the current user has enought permissions.
 851              if (!can_delete_course($courseid)) {
 852                  throw new moodle_exception('cannotdeletecategorycourse', 'error',
 853                      '', format_string($course->fullname)." (id: $courseid)");
 854              }
 855  
 856              delete_course($course, false);
 857          }
 858  
 859          $transaction->allow_commit();
 860  
 861          return null;
 862      }
 863  
 864      /**
 865       * Returns description of method result value
 866       *
 867       * @return external_description
 868       * @since Moodle 2.2
 869       */
 870      public static function delete_courses_returns() {
 871          return null;
 872      }
 873  
 874      /**
 875       * Returns description of method parameters
 876       *
 877       * @return external_function_parameters
 878       * @since Moodle 2.3
 879       */
 880      public static function duplicate_course_parameters() {
 881          return new external_function_parameters(
 882              array(
 883                  'courseid' => new external_value(PARAM_INT, 'course to duplicate id'),
 884                  'fullname' => new external_value(PARAM_TEXT, 'duplicated course full name'),
 885                  'shortname' => new external_value(PARAM_TEXT, 'duplicated course short name'),
 886                  'categoryid' => new external_value(PARAM_INT, 'duplicated course category parent'),
 887                  'visible' => new external_value(PARAM_INT, 'duplicated course visible, default to yes', VALUE_DEFAULT, 1),
 888                  'options' => new external_multiple_structure(
 889                      new external_single_structure(
 890                          array(
 891                                  'name' => new external_value(PARAM_ALPHAEXT, 'The backup option name:
 892                                              "activities" (int) Include course activites (default to 1 that is equal to yes),
 893                                              "blocks" (int) Include course blocks (default to 1 that is equal to yes),
 894                                              "filters" (int) Include course filters  (default to 1 that is equal to yes),
 895                                              "users" (int) Include users (default to 0 that is equal to no),
 896                                              "role_assignments" (int) Include role assignments  (default to 0 that is equal to no),
 897                                              "comments" (int) Include user comments  (default to 0 that is equal to no),
 898                                              "userscompletion" (int) Include user course completion information  (default to 0 that is equal to no),
 899                                              "logs" (int) Include course logs  (default to 0 that is equal to no),
 900                                              "grade_histories" (int) Include histories  (default to 0 that is equal to no)'
 901                                              ),
 902                                  'value' => new external_value(PARAM_RAW, 'the value for the option 1 (yes) or 0 (no)'
 903                              )
 904                          )
 905                      ), VALUE_DEFAULT, array()
 906                  ),
 907              )
 908          );
 909      }
 910  
 911      /**
 912       * Duplicate a course
 913       *
 914       * @param int $courseid
 915       * @param string $fullname Duplicated course fullname
 916       * @param string $shortname Duplicated course shortname
 917       * @param int $categoryid Duplicated course parent category id
 918       * @param int $visible Duplicated course availability
 919       * @param array $options List of backup options
 920       * @return array New course info
 921       * @since Moodle 2.3
 922       */
 923      public static function duplicate_course($courseid, $fullname, $shortname, $categoryid, $visible = 1, $options = array()) {
 924          global $CFG, $USER, $DB;
 925          require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
 926          require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
 927  
 928          // Parameter validation.
 929          $params = self::validate_parameters(
 930                  self::duplicate_course_parameters(),
 931                  array(
 932                        'courseid' => $courseid,
 933                        'fullname' => $fullname,
 934                        'shortname' => $shortname,
 935                        'categoryid' => $categoryid,
 936                        'visible' => $visible,
 937                        'options' => $options
 938                  )
 939          );
 940  
 941          // Context validation.
 942  
 943          if (! ($course = $DB->get_record('course', array('id'=>$params['courseid'])))) {
 944              throw new moodle_exception('invalidcourseid', 'error');
 945          }
 946  
 947          // Category where duplicated course is going to be created.
 948          $categorycontext = context_coursecat::instance($params['categoryid']);
 949          self::validate_context($categorycontext);
 950  
 951          // Course to be duplicated.
 952          $coursecontext = context_course::instance($course->id);
 953          self::validate_context($coursecontext);
 954  
 955          $backupdefaults = array(
 956              'activities' => 1,
 957              'blocks' => 1,
 958              'filters' => 1,
 959              'users' => 0,
 960              'role_assignments' => 0,
 961              'comments' => 0,
 962              'userscompletion' => 0,
 963              'logs' => 0,
 964              'grade_histories' => 0
 965          );
 966  
 967          $backupsettings = array();
 968          // Check for backup and restore options.
 969          if (!empty($params['options'])) {
 970              foreach ($params['options'] as $option) {
 971  
 972                  // Strict check for a correct value (allways 1 or 0, true or false).
 973                  $value = clean_param($option['value'], PARAM_INT);
 974  
 975                  if ($value !== 0 and $value !== 1) {
 976                      throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
 977                  }
 978  
 979                  if (!isset($backupdefaults[$option['name']])) {
 980                      throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
 981                  }
 982  
 983                  $backupsettings[$option['name']] = $value;
 984              }
 985          }
 986  
 987          // Capability checking.
 988  
 989          // The backup controller check for this currently, this may be redundant.
 990          require_capability('moodle/course:create', $categorycontext);
 991          require_capability('moodle/restore:restorecourse', $categorycontext);
 992          require_capability('moodle/backup:backupcourse', $coursecontext);
 993  
 994          if (!empty($backupsettings['users'])) {
 995              require_capability('moodle/backup:userinfo', $coursecontext);
 996              require_capability('moodle/restore:userinfo', $categorycontext);
 997          }
 998  
 999          // Check if the shortname is used.
1000          if ($foundcourses = $DB->get_records('course', array('shortname'=>$shortname))) {
1001              foreach ($foundcourses as $foundcourse) {
1002                  $foundcoursenames[] = $foundcourse->fullname;
1003              }
1004  
1005              $foundcoursenamestring = implode(',', $foundcoursenames);
1006              throw new moodle_exception('shortnametaken', '', '', $foundcoursenamestring);
1007          }
1008  
1009          // Backup the course.
1010  
1011          $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE,
1012          backup::INTERACTIVE_NO, backup::MODE_SAMESITE, $USER->id);
1013  
1014          foreach ($backupsettings as $name => $value) {
1015              $bc->get_plan()->get_setting($name)->set_value($value);
1016          }
1017  
1018          $backupid       = $bc->get_backupid();
1019          $backupbasepath = $bc->get_plan()->get_basepath();
1020  
1021          $bc->execute_plan();
1022          $results = $bc->get_results();
1023          $file = $results['backup_destination'];
1024  
1025          $bc->destroy();
1026  
1027          // Restore the backup immediately.
1028  
1029          // Check if we need to unzip the file because the backup temp dir does not contains backup files.
1030          if (!file_exists($backupbasepath . "/moodle_backup.xml")) {
1031              $file->extract_to_pathname(get_file_packer(), $backupbasepath);
1032          }
1033  
1034          // Create new course.
1035          $newcourseid = restore_dbops::create_new_course($params['fullname'], $params['shortname'], $params['categoryid']);
1036  
1037          $rc = new restore_controller($backupid, $newcourseid,
1038                  backup::INTERACTIVE_NO, backup::MODE_SAMESITE, $USER->id, backup::TARGET_NEW_COURSE);
1039  
1040          foreach ($backupsettings as $name => $value) {
1041              $setting = $rc->get_plan()->get_setting($name);
1042              if ($setting->get_status() == backup_setting::NOT_LOCKED) {
1043                  $setting->set_value($value);
1044              }
1045          }
1046  
1047          if (!$rc->execute_precheck()) {
1048              $precheckresults = $rc->get_precheck_results();
1049              if (is_array($precheckresults) && !empty($precheckresults['errors'])) {
1050                  if (empty($CFG->keeptempdirectoriesonbackup)) {
1051                      fulldelete($backupbasepath);
1052                  }
1053  
1054                  $errorinfo = '';
1055  
1056                  foreach ($precheckresults['errors'] as $error) {
1057                      $errorinfo .= $error;
1058                  }
1059  
1060                  if (array_key_exists('warnings', $precheckresults)) {
1061                      foreach ($precheckresults['warnings'] as $warning) {
1062                          $errorinfo .= $warning;
1063                      }
1064                  }
1065  
1066                  throw new moodle_exception('backupprecheckerrors', 'webservice', '', $errorinfo);
1067              }
1068          }
1069  
1070          $rc->execute_plan();
1071          $rc->destroy();
1072  
1073          $course = $DB->get_record('course', array('id' => $newcourseid), '*', MUST_EXIST);
1074          $course->fullname = $params['fullname'];
1075          $course->shortname = $params['shortname'];
1076          $course->visible = $params['visible'];
1077  
1078          // Set shortname and fullname back.
1079          $DB->update_record('course', $course);
1080  
1081          if (empty($CFG->keeptempdirectoriesonbackup)) {
1082              fulldelete($backupbasepath);
1083          }
1084  
1085          // Delete the course backup file created by this WebService. Originally located in the course backups area.
1086          $file->delete();
1087  
1088          return array('id' => $course->id, 'shortname' => $course->shortname);
1089      }
1090  
1091      /**
1092       * Returns description of method result value
1093       *
1094       * @return external_description
1095       * @since Moodle 2.3
1096       */
1097      public static function duplicate_course_returns() {
1098          return new external_single_structure(
1099              array(
1100                  'id'       => new external_value(PARAM_INT, 'course id'),
1101                  'shortname' => new external_value(PARAM_TEXT, 'short name'),
1102              )
1103          );
1104      }
1105  
1106      /**
1107       * Returns description of method parameters for import_course
1108       *
1109       * @return external_function_parameters
1110       * @since Moodle 2.4
1111       */
1112      public static function import_course_parameters() {
1113          return new external_function_parameters(
1114              array(
1115                  'importfrom' => new external_value(PARAM_INT, 'the id of the course we are importing from'),
1116                  'importto' => new external_value(PARAM_INT, 'the id of the course we are importing to'),
1117                  'deletecontent' => new external_value(PARAM_INT, 'whether to delete the course content where we are importing to (default to 0 = No)', VALUE_DEFAULT, 0),
1118                  'options' => new external_multiple_structure(
1119                      new external_single_structure(
1120                          array(
1121                                  'name' => new external_value(PARAM_ALPHA, 'The backup option name:
1122                                              "activities" (int) Include course activites (default to 1 that is equal to yes),
1123                                              "blocks" (int) Include course blocks (default to 1 that is equal to yes),
1124                                              "filters" (int) Include course filters  (default to 1 that is equal to yes)'
1125                                              ),
1126                                  'value' => new external_value(PARAM_RAW, 'the value for the option 1 (yes) or 0 (no)'
1127                              )
1128                          )
1129                      ), VALUE_DEFAULT, array()
1130                  ),
1131              )
1132          );
1133      }
1134  
1135      /**
1136       * Imports a course
1137       *
1138       * @param int $importfrom The id of the course we are importing from
1139       * @param int $importto The id of the course we are importing to
1140       * @param bool $deletecontent Whether to delete the course we are importing to content
1141       * @param array $options List of backup options
1142       * @return null
1143       * @since Moodle 2.4
1144       */
1145      public static function import_course($importfrom, $importto, $deletecontent = 0, $options = array()) {
1146          global $CFG, $USER, $DB;
1147          require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
1148          require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
1149  
1150          // Parameter validation.
1151          $params = self::validate_parameters(
1152              self::import_course_parameters(),
1153              array(
1154                  'importfrom' => $importfrom,
1155                  'importto' => $importto,
1156                  'deletecontent' => $deletecontent,
1157                  'options' => $options
1158              )
1159          );
1160  
1161          if ($params['deletecontent'] !== 0 and $params['deletecontent'] !== 1) {
1162              throw new moodle_exception('invalidextparam', 'webservice', '', $params['deletecontent']);
1163          }
1164  
1165          // Context validation.
1166  
1167          if (! ($importfrom = $DB->get_record('course', array('id'=>$params['importfrom'])))) {
1168              throw new moodle_exception('invalidcourseid', 'error');
1169          }
1170  
1171          if (! ($importto = $DB->get_record('course', array('id'=>$params['importto'])))) {
1172              throw new moodle_exception('invalidcourseid', 'error');
1173          }
1174  
1175          $importfromcontext = context_course::instance($importfrom->id);
1176          self::validate_context($importfromcontext);
1177  
1178          $importtocontext = context_course::instance($importto->id);
1179          self::validate_context($importtocontext);
1180  
1181          $backupdefaults = array(
1182              'activities' => 1,
1183              'blocks' => 1,
1184              'filters' => 1
1185          );
1186  
1187          $backupsettings = array();
1188  
1189          // Check for backup and restore options.
1190          if (!empty($params['options'])) {
1191              foreach ($params['options'] as $option) {
1192  
1193                  // Strict check for a correct value (allways 1 or 0, true or false).
1194                  $value = clean_param($option['value'], PARAM_INT);
1195  
1196                  if ($value !== 0 and $value !== 1) {
1197                      throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
1198                  }
1199  
1200                  if (!isset($backupdefaults[$option['name']])) {
1201                      throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
1202                  }
1203  
1204                  $backupsettings[$option['name']] = $value;
1205              }
1206          }
1207  
1208          // Capability checking.
1209  
1210          require_capability('moodle/backup:backuptargetimport', $importfromcontext);
1211          require_capability('moodle/restore:restoretargetimport', $importtocontext);
1212  
1213          $bc = new backup_controller(backup::TYPE_1COURSE, $importfrom->id, backup::FORMAT_MOODLE,
1214                  backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id);
1215  
1216          foreach ($backupsettings as $name => $value) {
1217              $bc->get_plan()->get_setting($name)->set_value($value);
1218          }
1219  
1220          $backupid       = $bc->get_backupid();
1221          $backupbasepath = $bc->get_plan()->get_basepath();
1222  
1223          $bc->execute_plan();
1224          $bc->destroy();
1225  
1226          // Restore the backup immediately.
1227  
1228          // Check if we must delete the contents of the destination course.
1229          if ($params['deletecontent']) {
1230              $restoretarget = backup::TARGET_EXISTING_DELETING;
1231          } else {
1232              $restoretarget = backup::TARGET_EXISTING_ADDING;
1233          }
1234  
1235          $rc = new restore_controller($backupid, $importto->id,
1236                  backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, $restoretarget);
1237  
1238          foreach ($backupsettings as $name => $value) {
1239              $rc->get_plan()->get_setting($name)->set_value($value);
1240          }
1241  
1242          if (!$rc->execute_precheck()) {
1243              $precheckresults = $rc->get_precheck_results();
1244              if (is_array($precheckresults) && !empty($precheckresults['errors'])) {
1245                  if (empty($CFG->keeptempdirectoriesonbackup)) {
1246                      fulldelete($backupbasepath);
1247                  }
1248  
1249                  $errorinfo = '';
1250  
1251                  foreach ($precheckresults['errors'] as $error) {
1252                      $errorinfo .= $error;
1253                  }
1254  
1255                  if (array_key_exists('warnings', $precheckresults)) {
1256                      foreach ($precheckresults['warnings'] as $warning) {
1257                          $errorinfo .= $warning;
1258                      }
1259                  }
1260  
1261                  throw new moodle_exception('backupprecheckerrors', 'webservice', '', $errorinfo);
1262              }
1263          } else {
1264              if ($restoretarget == backup::TARGET_EXISTING_DELETING) {
1265                  restore_dbops::delete_course_content($importto->id);
1266              }
1267          }
1268  
1269          $rc->execute_plan();
1270          $rc->destroy();
1271  
1272          if (empty($CFG->keeptempdirectoriesonbackup)) {
1273              fulldelete($backupbasepath);
1274          }
1275  
1276          return null;
1277      }
1278  
1279      /**
1280       * Returns description of method result value
1281       *
1282       * @return external_description
1283       * @since Moodle 2.4
1284       */
1285      public static function import_course_returns() {
1286          return null;
1287      }
1288  
1289      /**
1290       * Returns description of method parameters
1291       *
1292       * @return external_function_parameters
1293       * @since Moodle 2.3
1294       */
1295      public static function get_categories_parameters() {
1296          return new external_function_parameters(
1297              array(
1298                  'criteria' => new external_multiple_structure(
1299                      new external_single_structure(
1300                          array(
1301                              'key' => new external_value(PARAM_ALPHA,
1302                                           'The category column to search, expected keys (value format) are:'.
1303                                           '"id" (int) the category id,'.
1304                                           '"name" (string) the category name,'.
1305                                           '"parent" (int) the parent category id,'.
1306                                           '"idnumber" (string) category idnumber'.
1307                                           ' - user must have \'moodle/category:manage\' to search on idnumber,'.
1308                                           '"visible" (int) whether the returned categories must be visible or hidden. If the key is not passed,
1309                                               then the function return all categories that the user can see.'.
1310                                           ' - user must have \'moodle/category:manage\' or \'moodle/category:viewhiddencategories\' to search on visible,'.
1311                                           '"theme" (string) only return the categories having this theme'.
1312                                           ' - user must have \'moodle/category:manage\' to search on theme'),
1313                              'value' => new external_value(PARAM_RAW, 'the value to match')
1314                          )
1315                      ), 'criteria', VALUE_DEFAULT, array()
1316                  ),
1317                  'addsubcategories' => new external_value(PARAM_BOOL, 'return the sub categories infos
1318                                            (1 - default) otherwise only the category info (0)', VALUE_DEFAULT, 1)
1319              )
1320          );
1321      }
1322  
1323      /**
1324       * Get categories
1325       *
1326       * @param array $criteria Criteria to match the results
1327       * @param booln $addsubcategories obtain only the category (false) or its subcategories (true - default)
1328       * @return array list of categories
1329       * @since Moodle 2.3
1330       */
1331      public static function get_categories($criteria = array(), $addsubcategories = true) {
1332          global $CFG, $DB;
1333          require_once($CFG->dirroot . "/course/lib.php");
1334  
1335          // Validate parameters.
1336          $params = self::validate_parameters(self::get_categories_parameters(),
1337                  array('criteria' => $criteria, 'addsubcategories' => $addsubcategories));
1338  
1339          // Retrieve the categories.
1340          $categories = array();
1341          if (!empty($params['criteria'])) {
1342  
1343              $conditions = array();
1344              $wheres = array();
1345              foreach ($params['criteria'] as $crit) {
1346                  $key = trim($crit['key']);
1347  
1348                  // Trying to avoid duplicate keys.
1349                  if (!isset($conditions[$key])) {
1350  
1351                      $context = context_system::instance();
1352                      $value = null;
1353                      switch ($key) {
1354                          case 'id':
1355                              $value = clean_param($crit['value'], PARAM_INT);
1356                              break;
1357  
1358                          case 'idnumber':
1359                              if (has_capability('moodle/category:manage', $context)) {
1360                                  $value = clean_param($crit['value'], PARAM_RAW);
1361                              } else {
1362                                  // We must throw an exception.
1363                                  // Otherwise the dev client would think no idnumber exists.
1364                                  throw new moodle_exception('criteriaerror',
1365                                          'webservice', '', null,
1366                                          'You don\'t have the permissions to search on the "idnumber" field.');
1367                              }
1368                              break;
1369  
1370                          case 'name':
1371                              $value = clean_param($crit['value'], PARAM_TEXT);
1372                              break;
1373  
1374                          case 'parent':
1375                              $value = clean_param($crit['value'], PARAM_INT);
1376                              break;
1377  
1378                          case 'visible':
1379                              if (has_capability('moodle/category:manage', $context)
1380                                  or has_capability('moodle/category:viewhiddencategories',
1381                                          context_system::instance())) {
1382                                  $value = clean_param($crit['value'], PARAM_INT);
1383                              } else {
1384                                  throw new moodle_exception('criteriaerror',
1385                                          'webservice', '', null,
1386                                          'You don\'t have the permissions to search on the "visible" field.');
1387                              }
1388                              break;
1389  
1390                          case 'theme':
1391                              if (has_capability('moodle/category:manage', $context)) {
1392                                  $value = clean_param($crit['value'], PARAM_THEME);
1393                              } else {
1394                                  throw new moodle_exception('criteriaerror',
1395                                          'webservice', '', null,
1396                                          'You don\'t have the permissions to search on the "theme" field.');
1397                              }
1398                              break;
1399  
1400                          default:
1401                              throw new moodle_exception('criteriaerror',
1402                                      'webservice', '', null,
1403                                      'You can not search on this criteria: ' . $key);
1404                      }
1405  
1406                      if (isset($value)) {
1407                          $conditions[$key] = $crit['value'];
1408                          $wheres[] = $key . " = :" . $key;
1409                      }
1410                  }
1411              }
1412  
1413              if (!empty($wheres)) {
1414                  $wheres = implode(" AND ", $wheres);
1415  
1416                  $categories = $DB->get_records_select('course_categories', $wheres, $conditions);
1417  
1418                  // Retrieve its sub subcategories (all levels).
1419                  if ($categories and !empty($params['addsubcategories'])) {
1420                      $newcategories = array();
1421  
1422                      // Check if we required visible/theme checks.
1423                      $additionalselect = '';
1424                      $additionalparams = array();
1425                      if (isset($conditions['visible'])) {
1426                          $additionalselect .= ' AND visible = :visible';
1427                          $additionalparams['visible'] = $conditions['visible'];
1428                      }
1429                      if (isset($conditions['theme'])) {
1430                          $additionalselect .= ' AND theme= :theme';
1431                          $additionalparams['theme'] = $conditions['theme'];
1432                      }
1433  
1434                      foreach ($categories as $category) {
1435                          $sqlselect = $DB->sql_like('path', ':path') . $additionalselect;
1436                          $sqlparams = array('path' => $category->path.'/%') + $additionalparams; // It will NOT include the specified category.
1437                          $subcategories = $DB->get_records_select('course_categories', $sqlselect, $sqlparams);
1438                          $newcategories = $newcategories + $subcategories;   // Both arrays have integer as keys.
1439                      }
1440                      $categories = $categories + $newcategories;
1441                  }
1442              }
1443  
1444          } else {
1445              // Retrieve all categories in the database.
1446              $categories = $DB->get_records('course_categories');
1447          }
1448  
1449          // The not returned categories. key => category id, value => reason of exclusion.
1450          $excludedcats = array();
1451  
1452          // The returned categories.
1453          $categoriesinfo = array();
1454  
1455          // We need to sort the categories by path.
1456          // The parent cats need to be checked by the algo first.
1457          usort($categories, "core_course_external::compare_categories_by_path");
1458  
1459          foreach ($categories as $category) {
1460  
1461              // Check if the category is a child of an excluded category, if yes exclude it too (excluded => do not return).
1462              $parents = explode('/', $category->path);
1463              unset($parents[0]); // First key is always empty because path start with / => /1/2/4.
1464              foreach ($parents as $parentid) {
1465                  // Note: when the parent exclusion was due to the context,
1466                  // the sub category could still be returned.
1467                  if (isset($excludedcats[$parentid]) and $excludedcats[$parentid] != 'context') {
1468                      $excludedcats[$category->id] = 'parent';
1469                  }
1470              }
1471  
1472              // Check category depth is <= maxdepth (do not check for user who can manage categories).
1473              if ((!empty($CFG->maxcategorydepth) && count($parents) > $CFG->maxcategorydepth)
1474                      and !has_capability('moodle/category:manage', $context)) {
1475                  $excludedcats[$category->id] = 'depth';
1476              }
1477  
1478              // Check the user can use the category context.
1479              $context = context_coursecat::instance($category->id);
1480              try {
1481                  self::validate_context($context);
1482              } catch (Exception $e) {
1483                  $excludedcats[$category->id] = 'context';
1484  
1485                  // If it was the requested category then throw an exception.
1486                  if (isset($params['categoryid']) && $category->id == $params['categoryid']) {
1487                      $exceptionparam = new stdClass();
1488                      $exceptionparam->message = $e->getMessage();
1489                      $exceptionparam->catid = $category->id;
1490                      throw new moodle_exception('errorcatcontextnotvalid', 'webservice', '', $exceptionparam);
1491                  }
1492              }
1493  
1494              // Return the category information.
1495              if (!isset($excludedcats[$category->id])) {
1496  
1497                  // Final check to see if the category is visible to the user.
1498                  if ($category->visible
1499                          or has_capability('moodle/category:viewhiddencategories', context_system::instance())
1500                          or has_capability('moodle/category:manage', $context)) {
1501  
1502                      $categoryinfo = array();
1503                      $categoryinfo['id'] = $category->id;
1504                      $categoryinfo['name'] = $category->name;
1505                      list($categoryinfo['description'], $categoryinfo['descriptionformat']) =
1506                          external_format_text($category->description, $category->descriptionformat,
1507                                  $context->id, 'coursecat', 'description', null);
1508                      $categoryinfo['parent'] = $category->parent;
1509                      $categoryinfo['sortorder'] = $category->sortorder;
1510                      $categoryinfo['coursecount'] = $category->coursecount;
1511                      $categoryinfo['depth'] = $category->depth;
1512                      $categoryinfo['path'] = $category->path;
1513  
1514                      // Some fields only returned for admin.
1515                      if (has_capability('moodle/category:manage', $context)) {
1516                          $categoryinfo['idnumber'] = $category->idnumber;
1517                          $categoryinfo['visible'] = $category->visible;
1518                          $categoryinfo['visibleold'] = $category->visibleold;
1519                          $categoryinfo['timemodified'] = $category->timemodified;
1520                          $categoryinfo['theme'] = $category->theme;
1521                      }
1522  
1523                      $categoriesinfo[] = $categoryinfo;
1524                  } else {
1525                      $excludedcats[$category->id] = 'visibility';
1526                  }
1527              }
1528          }
1529  
1530          // Sorting the resulting array so it looks a bit better for the client developer.
1531          usort($categoriesinfo, "core_course_external::compare_categories_by_sortorder");
1532  
1533          return $categoriesinfo;
1534      }
1535  
1536      /**
1537       * Sort categories array by path
1538       * private function: only used by get_categories
1539       *
1540       * @param array $category1
1541       * @param array $category2
1542       * @return int result of strcmp
1543       * @since Moodle 2.3
1544       */
1545      private static function compare_categories_by_path($category1, $category2) {
1546          return strcmp($category1->path, $category2->path);
1547      }
1548  
1549      /**
1550       * Sort categories array by sortorder
1551       * private function: only used by get_categories
1552       *
1553       * @param array $category1
1554       * @param array $category2
1555       * @return int result of strcmp
1556       * @since Moodle 2.3
1557       */
1558      private static function compare_categories_by_sortorder($category1, $category2) {
1559          return strcmp($category1['sortorder'], $category2['sortorder']);
1560      }
1561  
1562      /**
1563       * Returns description of method result value
1564       *
1565       * @return external_description
1566       * @since Moodle 2.3
1567       */
1568      public static function get_categories_returns() {
1569          return new external_multiple_structure(
1570              new external_single_structure(
1571                  array(
1572                      'id' => new external_value(PARAM_INT, 'category id'),
1573                      'name' => new external_value(PARAM_TEXT, 'category name'),
1574                      'idnumber' => new external_value(PARAM_RAW, 'category id number', VALUE_OPTIONAL),
1575                      'description' => new external_value(PARAM_RAW, 'category description'),
1576                      'descriptionformat' => new external_format_value('description'),
1577                      'parent' => new external_value(PARAM_INT, 'parent category id'),
1578                      'sortorder' => new external_value(PARAM_INT, 'category sorting order'),
1579                      'coursecount' => new external_value(PARAM_INT, 'number of courses in this category'),
1580                      'visible' => new external_value(PARAM_INT, '1: available, 0:not available', VALUE_OPTIONAL),
1581                      'visibleold' => new external_value(PARAM_INT, '1: available, 0:not available', VALUE_OPTIONAL),
1582                      'timemodified' => new external_value(PARAM_INT, 'timestamp', VALUE_OPTIONAL),
1583                      'depth' => new external_value(PARAM_INT, 'category depth'),
1584                      'path' => new external_value(PARAM_TEXT, 'category path'),
1585                      'theme' => new external_value(PARAM_THEME, 'category theme', VALUE_OPTIONAL),
1586                  ), 'List of categories'
1587              )
1588          );
1589      }
1590  
1591      /**
1592       * Returns description of method parameters
1593       *
1594       * @return external_function_parameters
1595       * @since Moodle 2.3
1596       */
1597      public static function create_categories_parameters() {
1598          return new external_function_parameters(
1599              array(
1600                  'categories' => new external_multiple_structure(
1601                          new external_single_structure(
1602                              array(
1603                                  'name' => new external_value(PARAM_TEXT, 'new category name'),
1604                                  'parent' => new external_value(PARAM_INT,
1605                                          'the parent category id inside which the new category will be created
1606                                           - set to 0 for a root category',
1607                                          VALUE_DEFAULT, 0),
1608                                  'idnumber' => new external_value(PARAM_RAW,
1609                                          'the new category idnumber', VALUE_OPTIONAL),
1610                                  'description' => new external_value(PARAM_RAW,
1611                                          'the new category description', VALUE_OPTIONAL),
1612                                  'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
1613                                  'theme' => new external_value(PARAM_THEME,
1614                                          'the new category theme. This option must be enabled on moodle',
1615                                          VALUE_OPTIONAL),
1616                          )
1617                      )
1618                  )
1619              )
1620          );
1621      }
1622  
1623      /**
1624       * Create categories
1625       *
1626       * @param array $categories - see create_categories_parameters() for the array structure
1627       * @return array - see create_categories_returns() for the array structure
1628       * @since Moodle 2.3
1629       */
1630      public static function create_categories($categories) {
1631          global $CFG, $DB;
1632          require_once($CFG->libdir . "/coursecatlib.php");
1633  
1634          $params = self::validate_parameters(self::create_categories_parameters(),
1635                          array('categories' => $categories));
1636  
1637          $transaction = $DB->start_delegated_transaction();
1638  
1639          $createdcategories = array();
1640          foreach ($params['categories'] as $category) {
1641              if ($category['parent']) {
1642                  if (!$DB->record_exists('course_categories', array('id' => $category['parent']))) {
1643                      throw new moodle_exception('unknowcategory');
1644                  }
1645                  $context = context_coursecat::instance($category['parent']);
1646              } else {
1647                  $context = context_system::instance();
1648              }
1649              self::validate_context($context);
1650              require_capability('moodle/category:manage', $context);
1651  
1652              // this will validate format and throw an exception if there are errors
1653              external_validate_format($category['descriptionformat']);
1654  
1655              $newcategory = coursecat::create($category);
1656  
1657              $createdcategories[] = array('id' => $newcategory->id, 'name' => $newcategory->name);
1658          }
1659  
1660          $transaction->allow_commit();
1661  
1662          return $createdcategories;
1663      }
1664  
1665      /**
1666       * Returns description of method parameters
1667       *
1668       * @return external_function_parameters
1669       * @since Moodle 2.3
1670       */
1671      public static function create_categories_returns() {
1672          return new external_multiple_structure(
1673              new external_single_structure(
1674                  array(
1675                      'id' => new external_value(PARAM_INT, 'new category id'),
1676                      'name' => new external_value(PARAM_TEXT, 'new category name'),
1677                  )
1678              )
1679          );
1680      }
1681  
1682      /**
1683       * Returns description of method parameters
1684       *
1685       * @return external_function_parameters
1686       * @since Moodle 2.3
1687       */
1688      public static function update_categories_parameters() {
1689          return new external_function_parameters(
1690              array(
1691                  'categories' => new external_multiple_structure(
1692                      new external_single_structure(
1693                          array(
1694                              'id'       => new external_value(PARAM_INT, 'course id'),
1695                              'name' => new external_value(PARAM_TEXT, 'category name', VALUE_OPTIONAL),
1696                              'idnumber' => new external_value(PARAM_RAW, 'category id number', VALUE_OPTIONAL),
1697                              'parent' => new external_value(PARAM_INT, 'parent category id', VALUE_OPTIONAL),
1698                              'description' => new external_value(PARAM_RAW, 'category description', VALUE_OPTIONAL),
1699                              'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
1700                              'theme' => new external_value(PARAM_THEME,
1701                                      'the category theme. This option must be enabled on moodle', VALUE_OPTIONAL),
1702                          )
1703                      )
1704                  )
1705              )
1706          );
1707      }
1708  
1709      /**
1710       * Update categories
1711       *
1712       * @param array $categories The list of categories to update
1713       * @return null
1714       * @since Moodle 2.3
1715       */
1716      public static function update_categories($categories) {
1717          global $CFG, $DB;
1718          require_once($CFG->libdir . "/coursecatlib.php");
1719  
1720          // Validate parameters.
1721          $params = self::validate_parameters(self::update_categories_parameters(), array('categories' => $categories));
1722  
1723          $transaction = $DB->start_delegated_transaction();
1724  
1725          foreach ($params['categories'] as $cat) {
1726              $category = coursecat::get($cat['id']);
1727  
1728              $categorycontext = context_coursecat::instance($cat['id']);
1729              self::validate_context($categorycontext);
1730              require_capability('moodle/category:manage', $categorycontext);
1731  
1732              // this will throw an exception if descriptionformat is not valid
1733              external_validate_format($cat['descriptionformat']);
1734  
1735              $category->update($cat);
1736          }
1737  
1738          $transaction->allow_commit();
1739      }
1740  
1741      /**
1742       * Returns description of method result value
1743       *
1744       * @return external_description
1745       * @since Moodle 2.3
1746       */
1747      public static function update_categories_returns() {
1748          return null;
1749      }
1750  
1751      /**
1752       * Returns description of method parameters
1753       *
1754       * @return external_function_parameters
1755       * @since Moodle 2.3
1756       */
1757      public static function delete_categories_parameters() {
1758          return new external_function_parameters(
1759              array(
1760                  'categories' => new external_multiple_structure(
1761                      new external_single_structure(
1762                          array(
1763                              'id' => new external_value(PARAM_INT, 'category id to delete'),
1764                              'newparent' => new external_value(PARAM_INT,
1765                                  'the parent category to move the contents to, if specified', VALUE_OPTIONAL),
1766                              'recursive' => new external_value(PARAM_BOOL, '1: recursively delete all contents inside this
1767                                  category, 0 (default): move contents to newparent or current parent category (except if parent is root)', VALUE_DEFAULT, 0)
1768                          )
1769                      )
1770                  )
1771              )
1772          );
1773      }
1774  
1775      /**
1776       * Delete categories
1777       *
1778       * @param array $categories A list of category ids
1779       * @return array
1780       * @since Moodle 2.3
1781       */
1782      public static function delete_categories($categories) {
1783          global $CFG, $DB;
1784          require_once($CFG->dirroot . "/course/lib.php");
1785          require_once($CFG->libdir . "/coursecatlib.php");
1786  
1787          // Validate parameters.
1788          $params = self::validate_parameters(self::delete_categories_parameters(), array('categories' => $categories));
1789  
1790          $transaction = $DB->start_delegated_transaction();
1791  
1792          foreach ($params['categories'] as $category) {
1793              $deletecat = coursecat::get($category['id'], MUST_EXIST);
1794              $context = context_coursecat::instance($deletecat->id);
1795              require_capability('moodle/category:manage', $context);
1796              self::validate_context($context);
1797              self::validate_context(get_category_or_system_context($deletecat->parent));
1798  
1799              if ($category['recursive']) {
1800                  // If recursive was specified, then we recursively delete the category's contents.
1801                  if ($deletecat->can_delete_full()) {
1802                      $deletecat->delete_full(false);
1803                  } else {
1804                      throw new moodle_exception('youcannotdeletecategory', '', '', $deletecat->get_formatted_name());
1805                  }
1806              } else {
1807                  // In this situation, we don't delete the category's contents, we either move it to newparent or parent.
1808                  // If the parent is the root, moving is not supported (because a course must always be inside a category).
1809                  // We must move to an existing category.
1810                  if (!empty($category['newparent'])) {
1811                      $newparentcat = coursecat::get($category['newparent']);
1812                  } else {
1813                      $newparentcat = coursecat::get($deletecat->parent);
1814                  }
1815  
1816                  // This operation is not allowed. We must move contents to an existing category.
1817                  if (!$newparentcat->id) {
1818                      throw new moodle_exception('movecatcontentstoroot');
1819                  }
1820  
1821                  self::validate_context(context_coursecat::instance($newparentcat->id));
1822                  if ($deletecat->can_move_content_to($newparentcat->id)) {
1823                      $deletecat->delete_move($newparentcat->id, false);
1824                  } else {
1825                      throw new moodle_exception('youcannotdeletecategory', '', '', $deletecat->get_formatted_name());
1826                  }
1827              }
1828          }
1829  
1830          $transaction->allow_commit();
1831      }
1832  
1833      /**
1834       * Returns description of method parameters
1835       *
1836       * @return external_function_parameters
1837       * @since Moodle 2.3
1838       */
1839      public static function delete_categories_returns() {
1840          return null;
1841      }
1842  
1843      /**
1844       * Describes the parameters for delete_modules.
1845       *
1846       * @return external_external_function_parameters
1847       * @since Moodle 2.5
1848       */
1849      public static function delete_modules_parameters() {
1850          return new external_function_parameters (
1851              array(
1852                  'cmids' => new external_multiple_structure(new external_value(PARAM_INT, 'course module ID',
1853                          VALUE_REQUIRED, '', NULL_NOT_ALLOWED), 'Array of course module IDs'),
1854              )
1855          );
1856      }
1857  
1858      /**
1859       * Deletes a list of provided module instances.
1860       *
1861       * @param array $cmids the course module ids
1862       * @since Moodle 2.5
1863       */
1864      public static function delete_modules($cmids) {
1865          global $CFG, $DB;
1866  
1867          // Require course file containing the course delete module function.
1868          require_once($CFG->dirroot . "/course/lib.php");
1869  
1870          // Clean the parameters.
1871          $params = self::validate_parameters(self::delete_modules_parameters(), array('cmids' => $cmids));
1872  
1873          // Keep track of the course ids we have performed a capability check on to avoid repeating.
1874          $arrcourseschecked = array();
1875  
1876          foreach ($params['cmids'] as $cmid) {
1877              // Get the course module.
1878              $cm = $DB->get_record('course_modules', array('id' => $cmid), '*', MUST_EXIST);
1879  
1880              // Check if we have not yet confirmed they have permission in this course.
1881              if (!in_array($cm->course, $arrcourseschecked)) {
1882                  // Ensure the current user has required permission in this course.
1883                  $context = context_course::instance($cm->course);
1884                  self::validate_context($context);
1885                  // Add to the array.
1886                  $arrcourseschecked[] = $cm->course;
1887              }
1888  
1889              // Ensure they can delete this module.
1890              $modcontext = context_module::instance($cm->id);
1891              require_capability('moodle/course:manageactivities', $modcontext);
1892  
1893              // Delete the module.
1894              course_delete_module($cm->id);
1895          }
1896      }
1897  
1898      /**
1899       * Describes the delete_modules return value.
1900       *
1901       * @return external_single_structure
1902       * @since Moodle 2.5
1903       */
1904      public static function delete_modules_returns() {
1905          return null;
1906      }
1907  }
1908  
1909  /**
1910   * Deprecated course external functions
1911   *
1912   * @package    core_course
1913   * @copyright  2009 Petr Skodak
1914   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1915   * @since Moodle 2.0
1916   * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
1917   * @see core_course_external
1918   */
1919  class moodle_course_external extends external_api {
1920  
1921      /**
1922       * Returns description of method parameters
1923       *
1924       * @return external_function_parameters
1925       * @since Moodle 2.0
1926       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1927       * @see core_course_external::get_courses_parameters()
1928       */
1929      public static function get_courses_parameters() {
1930          return core_course_external::get_courses_parameters();
1931      }
1932  
1933      /**
1934       * Get courses
1935       *
1936       * @param array $options
1937       * @return array
1938       * @since Moodle 2.0
1939       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1940       * @see core_course_external::get_courses()
1941       */
1942      public static function get_courses($options) {
1943          return core_course_external::get_courses($options);
1944      }
1945  
1946      /**
1947       * Returns description of method result value
1948       *
1949       * @return external_description
1950       * @since Moodle 2.0
1951       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1952       * @see core_course_external::get_courses_returns()
1953       */
1954      public static function get_courses_returns() {
1955          return core_course_external::get_courses_returns();
1956      }
1957  
1958      /**
1959       * Returns description of method parameters
1960       *
1961       * @return external_function_parameters
1962       * @since Moodle 2.0
1963       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1964       * @see core_course_external::create_courses_parameters()
1965       */
1966      public static function create_courses_parameters() {
1967          return core_course_external::create_courses_parameters();
1968      }
1969  
1970      /**
1971       * Create  courses
1972       *
1973       * @param array $courses
1974       * @return array courses (id and shortname only)
1975       * @since Moodle 2.0
1976       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1977       * @see core_course_external::create_courses()
1978       */
1979      public static function create_courses($courses) {
1980          return core_course_external::create_courses($courses);
1981      }
1982  
1983      /**
1984       * Returns description of method result value
1985       *
1986       * @return external_description
1987       * @since Moodle 2.0
1988       * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1989       * @see core_course_external::create_courses_returns()
1990       */
1991      public static function create_courses_returns() {
1992          return core_course_external::create_courses_returns();
1993      }
1994  
1995  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1