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