MDL-32233 Added WS method core_course_duplicate_course
[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) {
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 = get_context_instance(CONTEXT_COURSE, $course->id);
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 = get_all_sections($course->id);
110             //for each sections (first displayed to last displayed)
111             foreach ($sections as $key => $section) {
113                 $showsection = (has_capability('moodle/course:viewhiddensections', $context) or $section->visible or !$course->hiddensections);
114                 if (!$showsection) {
115                     continue;
116                 }
118                 // reset $sectioncontents
119                 $sectionvalues = array();
120                 $sectionvalues['id'] = $section->id;
121                 $sectionvalues['name'] = get_section_name($course, $section);
122                 $summary = file_rewrite_pluginfile_urls($section->summary, 'webservice/pluginfile.php', $context->id, 'course', 'section', $section->id);
123                 $sectionvalues['visible'] = $section->visible;
124                 $sectionvalues['summary'] = format_text($summary, $section->summaryformat);
125                 $sectioncontents = array();
127                 //for each module of the section
128                 foreach ($modinfo->sections[$section->section] as $cmid) { //matching /course/lib.php:print_section() logic
129                     $cm = $modinfo->cms[$cmid];
131                     // stop here if the module is not visible to the user
132                     if (!$cm->uservisible) {
133                         continue;
134                     }
136                     $module = array();
138                     //common info (for people being able to see the module or availability dates)
139                     $module['id'] = $cm->id;
140                     $module['name'] = format_string($cm->name, true);
141                     $module['modname'] = $cm->modname;
142                     $module['modplural'] = $cm->modplural;
143                     $module['modicon'] = $cm->get_icon_url()->out(false);
144                     $module['indent'] = $cm->indent;
146                     $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
148                     if (!empty($cm->showdescription)) {
149                         $module['description'] = $cm->get_content();
150                     }
152                     //url of the module
153                     $url = $cm->get_url();
154                     if ($url) { //labels don't have url
155                         $module['url'] = $cm->get_url()->out();
156                     }
158                     $canviewhidden = has_capability('moodle/course:viewhiddenactivities',
159                                         get_context_instance(CONTEXT_MODULE, $cm->id));
160                     //user that can view hidden module should know about the visibility
161                     $module['visible'] = $cm->visible;
163                     //availability date (also send to user who can see hidden module when the showavailabilyt is ON)
164                     if ($canupdatecourse or ($CFG->enableavailability && $canviewhidden && $cm->showavailability)) {
165                         $module['availablefrom'] = $cm->availablefrom;
166                         $module['availableuntil'] = $cm->availableuntil;
167                     }
169                     $baseurl = 'webservice/pluginfile.php';
171                     //call $modulename_export_contents
172                     //(each module callback take care about checking the capabilities)
173                     require_once($CFG->dirroot . '/mod/' . $cm->modname . '/lib.php');
174                     $getcontentfunction = $cm->modname.'_export_contents';
175                     if (function_exists($getcontentfunction)) {
176                         if ($contents = $getcontentfunction($cm, $baseurl)) {
177                             $module['contents'] = $contents;
178                         }
179                     }
181                     //assign result to $sectioncontents
182                     $sectioncontents[] = $module;
184                 }
185                 $sectionvalues['modules'] = $sectioncontents;
187                 // assign result to $coursecontents
188                 $coursecontents[] = $sectionvalues;
189             }
190         }
191         return $coursecontents;
192     }
194     /**
195      * Returns description of method result value
196      *
197      * @return external_description
198      * @since Moodle 2.2
199      */
200     public static function get_course_contents_returns() {
201         return new external_multiple_structure(
202             new external_single_structure(
203                 array(
204                     'id' => new external_value(PARAM_INT, 'Section ID'),
205                     'name' => new external_value(PARAM_TEXT, 'Section name'),
206                     'visible' => new external_value(PARAM_INT, 'is the section visible', VALUE_OPTIONAL),
207                     'summary' => new external_value(PARAM_RAW, 'Section description'),
208                     'modules' => new external_multiple_structure(
209                             new external_single_structure(
210                                 array(
211                                     'id' => new external_value(PARAM_INT, 'activity id'),
212                                     'url' => new external_value(PARAM_URL, 'activity url', VALUE_OPTIONAL),
213                                     'name' => new external_value(PARAM_TEXT, 'activity module name'),
214                                     'description' => new external_value(PARAM_RAW, 'activity description', VALUE_OPTIONAL),
215                                     'visible' => new external_value(PARAM_INT, 'is the module visible', VALUE_OPTIONAL),
216                                     'modicon' => new external_value(PARAM_URL, 'activity icon url'),
217                                     'modname' => new external_value(PARAM_PLUGIN, 'activity module type'),
218                                     'modplural' => new external_value(PARAM_TEXT, 'activity module plural name'),
219                                     'availablefrom' => new external_value(PARAM_INT, 'module availability start date', VALUE_OPTIONAL),
220                                     'availableuntil' => new external_value(PARAM_INT, 'module availability en date', VALUE_OPTIONAL),
221                                     'indent' => new external_value(PARAM_INT, 'number of identation in the site'),
222                                     'contents' => new external_multiple_structure(
223                                           new external_single_structure(
224                                               array(
225                                                   // content info
226                                                   'type'=> new external_value(PARAM_TEXT, 'a file or a folder or external link'),
227                                                   'filename'=> new external_value(PARAM_FILE, 'filename'),
228                                                   'filepath'=> new external_value(PARAM_PATH, 'filepath'),
229                                                   'filesize'=> new external_value(PARAM_INT, 'filesize'),
230                                                   'fileurl' => new external_value(PARAM_URL, 'downloadable file url', VALUE_OPTIONAL),
231                                                   'content' => new external_value(PARAM_RAW, 'Raw content, will be used when type is content', VALUE_OPTIONAL),
232                                                   'timecreated' => new external_value(PARAM_INT, 'Time created'),
233                                                   'timemodified' => new external_value(PARAM_INT, 'Time modified'),
234                                                   'sortorder' => new external_value(PARAM_INT, 'Content sort order'),
236                                                   // copyright related info
237                                                   'userid' => new external_value(PARAM_INT, 'User who added this content to moodle'),
238                                                   'author' => new external_value(PARAM_TEXT, 'Content owner'),
239                                                   'license' => new external_value(PARAM_TEXT, 'Content license'),
240                                               )
241                                           ), VALUE_DEFAULT, array()
242                                       )
243                                 )
244                             ), 'list of module'
245                     )
246                 )
247             )
248         );
249     }
251     /**
252      * Returns description of method parameters
253      *
254      * @return external_function_parameters
255      * @since Moodle 2.2
256      */
257     public static function get_courses_parameters() {
258         return new external_function_parameters(
259                 array('options' => new external_single_structure(
260                             array('ids' => new external_multiple_structure(
261                                         new external_value(PARAM_INT, 'Course id')
262                                         , 'List of course id. If empty return all courses
263                                             except front page course.',
264                                         VALUE_OPTIONAL)
265                             ), 'options - operator OR is used', VALUE_DEFAULT, array())
266                 )
267         );
268     }
270     /**
271      * Get courses
272      *
273      * @param array $options It contains an array (list of ids)
274      * @return array
275      * @since Moodle 2.2
276      */
277     public static function get_courses($options) {
278         global $CFG, $DB;
279         require_once($CFG->dirroot . "/course/lib.php");
281         //validate parameter
282         $params = self::validate_parameters(self::get_courses_parameters(),
283                         array('options' => $options));
285         //retrieve courses
286         if (!key_exists('ids', $params['options'])
287                 or empty($params['options']['ids'])) {
288             $courses = $DB->get_records('course');
289         } else {
290             $courses = $DB->get_records_list('course', 'id', $params['options']['ids']);
291         }
293         //create return value
294         $coursesinfo = array();
295         foreach ($courses as $course) {
297             // now security checks
298             $context = get_context_instance(CONTEXT_COURSE, $course->id);
299             try {
300                 self::validate_context($context);
301             } catch (Exception $e) {
302                 $exceptionparam = new stdClass();
303                 $exceptionparam->message = $e->getMessage();
304                 $exceptionparam->courseid = $course->id;
305                 throw new moodle_exception(
306                         get_string('errorcoursecontextnotvalid', 'webservice', $exceptionparam));
307             }
308             require_capability('moodle/course:view', $context);
310             $courseinfo = array();
311             $courseinfo['id'] = $course->id;
312             $courseinfo['fullname'] = $course->fullname;
313             $courseinfo['shortname'] = $course->shortname;
314             $courseinfo['categoryid'] = $course->category;
315             $courseinfo['summary'] = $course->summary;
316             $courseinfo['summaryformat'] = $course->summaryformat;
317             $courseinfo['format'] = $course->format;
318             $courseinfo['startdate'] = $course->startdate;
319             $courseinfo['numsections'] = $course->numsections;
321             //some field should be returned only if the user has update permission
322             $courseadmin = has_capability('moodle/course:update', $context);
323             if ($courseadmin) {
324                 $courseinfo['categorysortorder'] = $course->sortorder;
325                 $courseinfo['idnumber'] = $course->idnumber;
326                 $courseinfo['showgrades'] = $course->showgrades;
327                 $courseinfo['showreports'] = $course->showreports;
328                 $courseinfo['newsitems'] = $course->newsitems;
329                 $courseinfo['visible'] = $course->visible;
330                 $courseinfo['maxbytes'] = $course->maxbytes;
331                 $courseinfo['hiddensections'] = $course->hiddensections;
332                 $courseinfo['groupmode'] = $course->groupmode;
333                 $courseinfo['groupmodeforce'] = $course->groupmodeforce;
334                 $courseinfo['defaultgroupingid'] = $course->defaultgroupingid;
335                 $courseinfo['lang'] = $course->lang;
336                 $courseinfo['timecreated'] = $course->timecreated;
337                 $courseinfo['timemodified'] = $course->timemodified;
338                 $courseinfo['forcetheme'] = $course->theme;
339                 $courseinfo['enablecompletion'] = $course->enablecompletion;
340                 $courseinfo['completionstartonenrol'] = $course->completionstartonenrol;
341                 $courseinfo['completionnotify'] = $course->completionnotify;
342             }
344             if ($courseadmin or $course->visible
345                     or has_capability('moodle/course:viewhiddencourses', $context)) {
346                 $coursesinfo[] = $courseinfo;
347             }
348         }
350         return $coursesinfo;
351     }
353     /**
354      * Returns description of method result value
355      *
356      * @return external_description
357      * @since Moodle 2.2
358      */
359     public static function get_courses_returns() {
360         return new external_multiple_structure(
361                 new external_single_structure(
362                         array(
363                             'id' => new external_value(PARAM_INT, 'course id'),
364                             'shortname' => new external_value(PARAM_TEXT, 'course short name'),
365                             'categoryid' => new external_value(PARAM_INT, 'category id'),
366                             'categorysortorder' => new external_value(PARAM_INT,
367                                     'sort order into the category', VALUE_OPTIONAL),
368                             'fullname' => new external_value(PARAM_TEXT, 'full name'),
369                             'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
370                             'summary' => new external_value(PARAM_RAW, 'summary'),
371                             'summaryformat' => new external_value(PARAM_INT,
372                                     'the summary text Moodle format'),
373                             'format' => new external_value(PARAM_PLUGIN,
374                                     'course format: weeks, topics, social, site,..'),
375                             'showgrades' => new external_value(PARAM_INT,
376                                     '1 if grades are shown, otherwise 0', VALUE_OPTIONAL),
377                             'newsitems' => new external_value(PARAM_INT,
378                                     'number of recent items appearing on the course page', VALUE_OPTIONAL),
379                             'startdate' => new external_value(PARAM_INT,
380                                     'timestamp when the course start'),
381                             'numsections' => new external_value(PARAM_INT, 'number of weeks/topics'),
382                             'maxbytes' => new external_value(PARAM_INT,
383                                     'largest size of file that can be uploaded into the course',
384                                     VALUE_OPTIONAL),
385                             'showreports' => new external_value(PARAM_INT,
386                                     'are activity report shown (yes = 1, no =0)', VALUE_OPTIONAL),
387                             'visible' => new external_value(PARAM_INT,
388                                     '1: available to student, 0:not available', VALUE_OPTIONAL),
389                             'hiddensections' => new external_value(PARAM_INT,
390                                     'How the hidden sections in the course are displayed to students',
391                                     VALUE_OPTIONAL),
392                             'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
393                                     VALUE_OPTIONAL),
394                             'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
395                                     VALUE_OPTIONAL),
396                             'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
397                                     VALUE_OPTIONAL),
398                             'timecreated' => new external_value(PARAM_INT,
399                                     'timestamp when the course have been created', VALUE_OPTIONAL),
400                             'timemodified' => new external_value(PARAM_INT,
401                                     'timestamp when the course have been modified', VALUE_OPTIONAL),
402                             'enablecompletion' => new external_value(PARAM_INT,
403                                     'Enabled, control via completion and activity settings. Disbaled,
404                                         not shown in activity settings.',
405                                     VALUE_OPTIONAL),
406                             'completionstartonenrol' => new external_value(PARAM_INT,
407                                     '1: begin tracking a student\'s progress in course completion
408                                         after course enrolment. 0: does not',
409                                     VALUE_OPTIONAL),
410                             'completionnotify' => new external_value(PARAM_INT,
411                                     '1: yes 0: no', VALUE_OPTIONAL),
412                             'lang' => new external_value(PARAM_SAFEDIR,
413                                     'forced course language', VALUE_OPTIONAL),
414                             'forcetheme' => new external_value(PARAM_PLUGIN,
415                                     'name of the force theme', VALUE_OPTIONAL),
416                         ), 'course'
417                 )
418         );
419     }
421     /**
422      * Returns description of method parameters
423      *
424      * @return external_function_parameters
425      * @since Moodle 2.2
426      */
427     public static function create_courses_parameters() {
428         $courseconfig = get_config('moodlecourse'); //needed for many default values
429         return new external_function_parameters(
430             array(
431                 'courses' => new external_multiple_structure(
432                     new external_single_structure(
433                         array(
434                             'fullname' => new external_value(PARAM_TEXT, 'full name'),
435                             'shortname' => new external_value(PARAM_TEXT, 'course short name'),
436                             'categoryid' => new external_value(PARAM_INT, 'category id'),
437                             'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
438                             'summary' => new external_value(PARAM_RAW, 'summary', VALUE_OPTIONAL),
439                             'summaryformat' => new external_value(PARAM_INT,
440                                     'the summary text Moodle format', VALUE_DEFAULT, FORMAT_MOODLE),
441                             'format' => new external_value(PARAM_PLUGIN,
442                                     'course format: weeks, topics, social, site,..',
443                                     VALUE_DEFAULT, $courseconfig->format),
444                             'showgrades' => new external_value(PARAM_INT,
445                                     '1 if grades are shown, otherwise 0', VALUE_DEFAULT,
446                                     $courseconfig->showgrades),
447                             'newsitems' => new external_value(PARAM_INT,
448                                     'number of recent items appearing on the course page',
449                                     VALUE_DEFAULT, $courseconfig->newsitems),
450                             'startdate' => new external_value(PARAM_INT,
451                                     'timestamp when the course start', VALUE_OPTIONAL),
452                             'numsections' => new external_value(PARAM_INT, 'number of weeks/topics',
453                                     VALUE_DEFAULT, $courseconfig->numsections),
454                             'maxbytes' => new external_value(PARAM_INT,
455                                     'largest size of file that can be uploaded into the course',
456                                     VALUE_DEFAULT, $courseconfig->maxbytes),
457                             'showreports' => new external_value(PARAM_INT,
458                                     'are activity report shown (yes = 1, no =0)', VALUE_DEFAULT,
459                                     $courseconfig->showreports),
460                             'visible' => new external_value(PARAM_INT,
461                                     '1: available to student, 0:not available', VALUE_OPTIONAL),
462                             'hiddensections' => new external_value(PARAM_INT,
463                                     'How the hidden sections in the course are displayed to students',
464                                     VALUE_DEFAULT, $courseconfig->hiddensections),
465                             'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
466                                     VALUE_DEFAULT, $courseconfig->groupmode),
467                             'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
468                                     VALUE_DEFAULT, $courseconfig->groupmodeforce),
469                             'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
470                                     VALUE_DEFAULT, 0),
471                             'enablecompletion' => new external_value(PARAM_INT,
472                                     'Enabled, control via completion and activity settings. Disabled,
473                                         not shown in activity settings.',
474                                     VALUE_OPTIONAL),
475                             'completionstartonenrol' => new external_value(PARAM_INT,
476                                     '1: begin tracking a student\'s progress in course completion after
477                                         course enrolment. 0: does not',
478                                     VALUE_OPTIONAL),
479                             'completionnotify' => new external_value(PARAM_INT,
480                                     '1: yes 0: no', VALUE_OPTIONAL),
481                             'lang' => new external_value(PARAM_SAFEDIR,
482                                     'forced course language', VALUE_OPTIONAL),
483                             'forcetheme' => new external_value(PARAM_PLUGIN,
484                                     'name of the force theme', VALUE_OPTIONAL),
485                         )
486                     ), 'courses to create'
487                 )
488             )
489         );
490     }
492     /**
493      * Create  courses
494      *
495      * @param array $courses
496      * @return array courses (id and shortname only)
497      * @since Moodle 2.2
498      */
499     public static function create_courses($courses) {
500         global $CFG, $DB;
501         require_once($CFG->dirroot . "/course/lib.php");
502         require_once($CFG->libdir . '/completionlib.php');
505         $params = self::validate_parameters(self::create_courses_parameters(),
506                         array('courses' => $courses));
508         $availablethemes = get_plugin_list('theme');
509         $availablelangs = get_string_manager()->get_list_of_translations();
511         $transaction = $DB->start_delegated_transaction();
513         foreach ($params['courses'] as $course) {
515             // Ensure the current user is allowed to run this function
516             $context = get_context_instance(CONTEXT_COURSECAT, $course['categoryid']);
517             try {
518                 self::validate_context($context);
519             } catch (Exception $e) {
520                 $exceptionparam = new stdClass();
521                 $exceptionparam->message = $e->getMessage();
522                 $exceptionparam->catid = $course['categoryid'];
523                 throw new moodle_exception(
524                         get_string('errorcatcontextnotvalid', 'webservice', $exceptionparam));
525             }
526             require_capability('moodle/course:create', $context);
528             // Make sure lang is valid
529             if (key_exists('lang', $course) and empty($availablelangs[$course['lang']])) {
530                 throw new moodle_exception(
531                         get_string('errorinvalidparam', 'webservice', 'lang'));
532             }
534             // Make sure theme is valid
535             if (key_exists('forcetheme', $course)) {
536                 if (!empty($CFG->allowcoursethemes)) {
537                     if (empty($availablethemes[$course['forcetheme']])) {
538                         throw new moodle_exception(
539                                 get_string('errorinvalidparam', 'webservice', 'forcetheme'));
540                     } else {
541                         $course['theme'] = $course['forcetheme'];
542                     }
543                 }
544             }
546             //force visibility if ws user doesn't have the permission to set it
547             $category = $DB->get_record('course_categories', array('id' => $course['categoryid']));
548             if (!has_capability('moodle/course:visibility', $context)) {
549                 $course['visible'] = $category->visible;
550             }
552             //set default value for completion
553             $courseconfig = get_config('moodlecourse');
554             if (completion_info::is_enabled_for_site()) {
555                 if (!key_exists('enablecompletion', $course)) {
556                     $course['enablecompletion'] = $courseconfig->enablecompletion;
557                 }
558                 if (!key_exists('completionstartonenrol', $course)) {
559                     $course['completionstartonenrol'] = $courseconfig->completionstartonenrol;
560                 }
561             } else {
562                 $course['enablecompletion'] = 0;
563                 $course['completionstartonenrol'] = 0;
564             }
566             $course['category'] = $course['categoryid'];
568             //Note: create_course() core function check shortname, idnumber, category
569             $course['id'] = create_course((object) $course)->id;
571             $resultcourses[] = array('id' => $course['id'], 'shortname' => $course['shortname']);
572         }
574         $transaction->allow_commit();
576         return $resultcourses;
577     }
579     /**
580      * Returns description of method result value
581      *
582      * @return external_description
583      * @since Moodle 2.2
584      */
585     public static function create_courses_returns() {
586         return new external_multiple_structure(
587             new external_single_structure(
588                 array(
589                     'id'       => new external_value(PARAM_INT, 'course id'),
590                     'shortname' => new external_value(PARAM_TEXT, 'short name'),
591                 )
592             )
593         );
594     }
596     /**
597      * Returns description of method parameters
598      * @return external_function_parameters
599      */
600     public static function delete_courses_parameters() {
601         return new external_function_parameters(
602             array(
603                 'courseids' => new external_multiple_structure(new external_value(PARAM_INT, 'course ID')),
604             )
605         );
606     }
608     /**
609      * Delete courses
610      * @param array $courseids A list of course ids
611      */
612     public static function delete_courses($courseids) {
613         global $CFG, $DB;
614         require_once($CFG->dirroot."/course/lib.php");
616         // Parameter validation.
617         $params = self::validate_parameters(self::delete_courses_parameters(), array('courseids'=>$courseids));
619         $transaction = $DB->start_delegated_transaction();
621         foreach ($params['courseids'] as $courseid) {
622             $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
624             // Check if the context is valid.
625             $coursecontext = context_course::instance($course->id);
626             self::validate_context($coursecontext);
628             // Check if the current user has enought permissions.
629             if (!can_delete_course($courseid)) {
630                 throw new moodle_exception('cannotdeletecategorycourse', 'error', '', format_string($course->fullname)." (id: $courseid)");
631             }
633             delete_course($course, false);
634         }
636         $transaction->allow_commit();
638         return null;
639     }
641     /**
642      * Returns description of method result value
643      * @return external_description
644      */
645     public static function delete_courses_returns() {
646         return null;
647     }
649     /**
650      * Returns description of method parameters
651      *
652      * @return external_function_parameters
653      * @since Moodle 2.3
654      */
655     public static function duplicate_course_parameters() {
656         return new external_function_parameters(
657             array(
658                 'courseid' => new external_value(PARAM_INT, 'course to duplicate id'),
659                 'fullname' => new external_value(PARAM_TEXT, 'duplicated course full name'),
660                 'shortname' => new external_value(PARAM_TEXT, 'duplicated course short name'),
661                 'categoryid' => new external_value(PARAM_INT, 'duplicated course category parent'),
662                 'visible' => new external_value(PARAM_INT, 'duplicated course visible, default to yes', VALUE_DEFAULT, 1),
663                 'options' => new external_multiple_structure(
664                     new external_single_structure(
665                         array(
666                             'name' => new external_value(PARAM_ALPHA, 'The backup option name:
667                                         "activities" (int) Include course activites (default to 1 that is equal to yes),
668                                         "blocks" (int) Include course blocks (default to 1 that is equal to yes),
669                                         "filters" (int) Include course filters  (default to 1 that is equal to yes),'),
670                             'value' => new external_value(PARAM_RAW, 'the value for the option 1 (yes) or 0 (no)')
671                         )
672                     ), VALUE_DEFAULT, array()
673                 ),
674             )
675         );
676     }
678     /**
679      * Duplicate a course
680      *
681      * @param int $courseid
682      * @param string $fullname Duplicated course fullname
683      * @param string $shortname Duplicated course shortname
684      * @param int $categoryid Duplicated course parent category id
685      * @param int $visible Duplicated course availability
686      * @param array $options List of backup options
687      * @return array New course info
688      * @since Moodle 2.3
689      */
690     public static function duplicate_course($courseid, $fullname, $shortname, $categoryid, $visible, $options) {
691         global $CFG, $USER, $DB;
692         require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
693         require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
695         // Parameter validation.
696         $params = self::validate_parameters(
697                 self::duplicate_course_parameters(),
698                 array(
699                       'courseid' => $courseid,
700                       'fullname' => $fullname,
701                       'shortname' => $shortname,
702                       'categoryid' => $categoryid,
703                       'visible' => $visible,
704                       'options' => $options
705                 )
706         );
708         // Context validation.
710         if (! ($course = $DB->get_record('course', array('id'=>$params['courseid'])))) {
711             throw new moodle_exception('invalidcourseid', 'error', '', $params['courseid']);
712         }
714         // Category where duplicated course is going to be created.
715         $categorycontext = context_coursecat::instance($params['categoryid']);
716         self::validate_context($categorycontext);
718         // Course to be duplicated.
719         $coursecontext = context_course::instance($course->id);
720         self::validate_context($coursecontext);
722         // Capability checking.
724         // The backup controller check for this currently, this may be redundant.
725         require_capability('moodle/course:create', $categorycontext);
726         require_capability('moodle/restore:restorecourse', $categorycontext);
727         require_capability('moodle/restore:restoretargetimport', $categorycontext);
729         require_capability('moodle/backup:backupcourse', $coursecontext);
730         require_capability('moodle/backup:backuptargetimport', $coursecontext);
732         // Check if the shortname is used.
733         if ($foundcourses = $DB->get_records('course', array('shortname'=>$shortname))) {
734             foreach ($foundcourses as $foundcourse) {
735                 $foundcoursenames[] = $foundcourse->fullname;
736             }
738             $foundcoursenamestring = implode(',', $foundcoursenames);
739             throw new moodle_exception('shortnametaken', '', '', $foundcoursenamestring);
740         }
742         $backupsettings = array();
743         // Check for backup and restore options.
744         if (!empty($params['options'])) {
745             foreach ($params['options'] as $option) {
747                 // Strict check for a correct value (allways 1 or 0, true or false).
748                 $value = clean_param($option['value'], PARAM_INT);
750                 if ($value !== 0 and $value !== 1) {
751                     throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
752                 }
754                 switch ($option['name']) {
755                     case 'activities':
756                     case 'blocks':
757                     case 'filters':
758                         $backupsettings[$option['name']] = $value;
759                         break;
760                     default:
761                         throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
762                 }
763             }
764         }
766         // Backup the course.
767         $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE,
768         backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id);
770         foreach ($backupsettings as $name => $value) {
771             $bc->get_plan()->get_setting($name)->set_value($value);
772         }
774         $backupid       = $bc->get_backupid();
775         $backupbasepath = $bc->get_plan()->get_basepath();
777         $bc->execute_plan();
778         $bc->destroy();
780         // Restore the backup immediately.
782         // Create new course.
783         $newcourseid = restore_dbops::create_new_course($params['fullname'], $params['shortname'], $params['categoryid']);
785         $rc = new restore_controller($backupid, $newcourseid,
786                 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_NEW_COURSE);
788         foreach ($backupsettings as $name => $value) {
789             $rc->get_plan()->get_setting($name)->set_value($value);
790         }
792         if (!$rc->execute_precheck()) {
793             $precheckresults = $rc->get_precheck_results();
794             if (is_array($precheckresults) && !empty($precheckresults['errors'])) {
795                 if (empty($CFG->keeptempdirectoriesonbackup)) {
796                     fulldelete($backupbasepath);
797                 }
799                 $errorinfo = '';
801                 foreach ($precheckresults['errors'] as $error) {
802                     $errorinfo .= $error;
803                 }
805                 if (array_key_exists('warnings', $precheckresults)) {
806                     foreach ($precheckresults['warnings'] as $warning) {
807                         $errorinfo .= $warning;
808                     }
809                 }
811                 throw new moodle_exception('backupprecheckerrors', 'webservice', '', $errorinfo);
812             }
813         }
815         $rc->execute_plan();
816         $rc->destroy();
818         $course = $DB->get_record('course', array('id' => $newcourseid), '*', MUST_EXIST);
819         $course->fullname = $params['fullname'];
820         $course->shortname = $params['shortname'];
821         $course->visible = $params['visible'];
823         // Set shortname and fullname back.
824         $DB->update_record('course', $course);
826         if (empty($CFG->keeptempdirectoriesonbackup)) {
827             fulldelete($backupbasepath);
828         }
830         return array('id' => $course->id, 'shortname' => $course->shortname);
831     }
833     /**
834      * Returns description of method result value
835      *
836      * @return external_description
837      * @since Moodle 2.3
838      */
839     public static function duplicate_course_returns() {
840         return new external_single_structure(
841             array(
842                 'id'       => new external_value(PARAM_INT, 'course id'),
843                 'shortname' => new external_value(PARAM_TEXT, 'short name'),
844             )
845         );
846     }
850 /**
851  * Deprecated course external functions
852  *
853  * @package    core_course
854  * @copyright  2009 Petr Skodak
855  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
856  * @since Moodle 2.0
857  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
858  * @todo MDL-31194 This will be deleted in Moodle 2.5.
859  * @see core_course_external
860  */
861 class moodle_course_external extends external_api {
863     /**
864      * Returns description of method parameters
865      *
866      * @return external_function_parameters
867      * @since Moodle 2.0
868      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
869      * @todo MDL-31194 This will be deleted in Moodle 2.5.
870      * @see core_course_external::get_courses_parameters()
871      */
872     public static function get_courses_parameters() {
873         return core_course_external::get_courses_parameters();
874     }
876     /**
877      * Get courses
878      *
879      * @param array $options
880      * @return array
881      * @since Moodle 2.0
882      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
883      * @todo MDL-31194 This will be deleted in Moodle 2.5.
884      * @see core_course_external::get_courses()
885      */
886     public static function get_courses($options) {
887         return core_course_external::get_courses($options);
888     }
890     /**
891      * Returns description of method result value
892      *
893      * @return external_description
894      * @since Moodle 2.0
895      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
896      * @todo MDL-31194 This will be deleted in Moodle 2.5.
897      * @see core_course_external::get_courses_returns()
898      */
899     public static function get_courses_returns() {
900         return core_course_external::get_courses_returns();
901     }
903     /**
904      * Returns description of method parameters
905      *
906      * @return external_function_parameters
907      * @since Moodle 2.0
908      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
909      * @todo MDL-31194 This will be deleted in Moodle 2.5.
910      * @see core_course_external::create_courses_parameters()
911      */
912     public static function create_courses_parameters() {
913         return core_course_external::create_courses_parameters();
914     }
916     /**
917      * Create  courses
918      *
919      * @param array $courses
920      * @return array courses (id and shortname only)
921      * @since Moodle 2.0
922      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
923      * @todo MDL-31194 This will be deleted in Moodle 2.5.
924      * @see core_course_external::create_courses()
925      */
926     public static function create_courses($courses) {
927         return core_course_external::create_courses($courses);
928     }
930     /**
931      * Returns description of method result value
932      *
933      * @return external_description
934      * @since Moodle 2.0
935      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
936      * @todo MDL-31194 This will be deleted in Moodle 2.5.
937      * @see core_course_external::create_courses_returns()
938      */
939     public static function create_courses_returns() {
940         return core_course_external::create_courses_returns();
941     }