MDL-26037 restore: fixes for mssql, php 5.4 and small improvs
[moodle.git] / course / externallib.php
blobe6a86ea9e87cd96976fcd53110e0f741745c0be8
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * External course API
21 * @package core
22 * @subpackage course
23 * @copyright 2010 Moodle Pty Ltd (http://moodle.com)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die;
29 require_once("$CFG->libdir/externallib.php");
31 /**
32 * Course functions
34 class core_course_external extends external_api {
36 /**
37 * Returns description of method parameters
38 * @return external_function_parameters
40 public static function get_course_contents_parameters() {
41 return new external_function_parameters(
42 array('courseid' => new external_value(PARAM_INT, 'course id'),
43 'options' => new external_multiple_structure (
44 new external_single_structure(
45 array('name' => new external_value(PARAM_ALPHANUM, 'option name'),
46 'value' => new external_value(PARAM_RAW, 'the value of the option, this param is personaly validated in the external function.')
48 ), 'Options, not used yet, might be used in later version', VALUE_DEFAULT, array())
53 /**
54 * Get course contents
55 * @param int $courseid
56 * @param array $options, not used yet, might be used in later version
57 * @return array
59 public static function get_course_contents($courseid, $options) {
60 global $CFG, $DB;
61 require_once($CFG->dirroot . "/course/lib.php");
63 //validate parameter
64 $params = self::validate_parameters(self::get_course_contents_parameters(),
65 array('courseid' => $courseid, 'options' => $options));
67 //retrieve the course
68 $course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST);
70 //check course format exist
71 if (!file_exists($CFG->dirroot . '/course/format/' . $course->format . '/lib.php')) {
72 throw new moodle_exception('cannotgetcoursecontents', 'webservice', '', null, get_string('courseformatnotfound', 'error', '', $course->format));
73 } else {
74 require_once($CFG->dirroot . '/course/format/' . $course->format . '/lib.php');
77 // now security checks
78 $context = get_context_instance(CONTEXT_COURSE, $course->id);
79 try {
80 self::validate_context($context);
81 } catch (Exception $e) {
82 $exceptionparam = new stdClass();
83 $exceptionparam->message = $e->getMessage();
84 $exceptionparam->courseid = $course->id;
85 throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam);
88 $canupdatecourse = has_capability('moodle/course:update', $context);
90 //create return value
91 $coursecontents = array();
93 if ($canupdatecourse or $course->visible
94 or has_capability('moodle/course:viewhiddencourses', $context)) {
96 //retrieve sections
97 $modinfo = get_fast_modinfo($course);
98 $sections = get_all_sections($course->id);
100 //for each sections (first displayed to last displayed)
101 foreach ($sections as $key => $section) {
103 $showsection = (has_capability('moodle/course:viewhiddensections', $context) or $section->visible or !$course->hiddensections);
104 if (!$showsection) {
105 continue;
108 // reset $sectioncontents
109 $sectionvalues = array();
110 $sectionvalues['id'] = $section->id;
111 $sectionvalues['name'] = get_section_name($course, $section);
112 $summary = file_rewrite_pluginfile_urls($section->summary, 'webservice/pluginfile.php', $context->id, 'course', 'section', $section->id);
113 $sectionvalues['visible'] = $section->visible;
114 $sectionvalues['summary'] = format_text($summary, $section->summaryformat);
115 $sectioncontents = array();
117 //for each module of the section
118 foreach ($modinfo->sections[$section->section] as $cmid) { //matching /course/lib.php:print_section() logic
119 $cm = $modinfo->cms[$cmid];
121 // stop here if the module is not visible to the user
122 if (!$cm->uservisible) {
123 continue;
126 $module = array();
128 //common info (for people being able to see the module or availability dates)
129 $module['id'] = $cm->id;
130 $module['name'] = format_string($cm->name, true);
131 $module['modname'] = $cm->modname;
132 $module['modplural'] = $cm->modplural;
133 $module['modicon'] = $cm->get_icon_url()->out(false);
134 $module['indent'] = $cm->indent;
136 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
138 if (!empty($cm->showdescription)) {
139 $module['description'] = $cm->get_content();
142 //url of the module
143 $url = $cm->get_url();
144 if ($url) { //labels don't have url
145 $module['url'] = $cm->get_url()->out();
148 $canviewhidden = has_capability('moodle/course:viewhiddenactivities',
149 get_context_instance(CONTEXT_MODULE, $cm->id));
150 //user that can view hidden module should know about the visibility
151 $module['visible'] = $cm->visible;
153 //availability date (also send to user who can see hidden module when the showavailabilyt is ON)
154 if ($canupdatecourse or ($CFG->enableavailability && $canviewhidden && $cm->showavailability)) {
155 $module['availablefrom'] = $cm->availablefrom;
156 $module['availableuntil'] = $cm->availableuntil;
159 $baseurl = 'webservice/pluginfile.php';
161 //call $modulename_export_contents
162 //(each module callback take care about checking the capabilities)
163 require_once($CFG->dirroot . '/mod/' . $cm->modname . '/lib.php');
164 $getcontentfunction = $cm->modname.'_export_contents';
165 if (function_exists($getcontentfunction)) {
166 if ($contents = $getcontentfunction($cm, $baseurl)) {
167 $module['contents'] = $contents;
171 //assign result to $sectioncontents
172 $sectioncontents[] = $module;
175 $sectionvalues['modules'] = $sectioncontents;
177 // assign result to $coursecontents
178 $coursecontents[] = $sectionvalues;
181 return $coursecontents;
185 * Returns description of method result value
186 * @return external_description
188 public static function get_course_contents_returns() {
189 return new external_multiple_structure(
190 new external_single_structure(
191 array(
192 'id' => new external_value(PARAM_INT, 'Section ID'),
193 'name' => new external_value(PARAM_TEXT, 'Section name'),
194 'visible' => new external_value(PARAM_INT, 'is the section visible', VALUE_OPTIONAL),
195 'summary' => new external_value(PARAM_RAW, 'Section description'),
196 'modules' => new external_multiple_structure(
197 new external_single_structure(
198 array(
199 'id' => new external_value(PARAM_INT, 'activity id'),
200 'url' => new external_value(PARAM_URL, 'activity url', VALUE_OPTIONAL),
201 'name' => new external_value(PARAM_TEXT, 'activity module name'),
202 'description' => new external_value(PARAM_RAW, 'activity description', VALUE_OPTIONAL),
203 'visible' => new external_value(PARAM_INT, 'is the module visible', VALUE_OPTIONAL),
204 'modicon' => new external_value(PARAM_URL, 'activity icon url'),
205 'modname' => new external_value(PARAM_PLUGIN, 'activity module type'),
206 'modplural' => new external_value(PARAM_TEXT, 'activity module plural name'),
207 'availablefrom' => new external_value(PARAM_INT, 'module availability start date', VALUE_OPTIONAL),
208 'availableuntil' => new external_value(PARAM_INT, 'module availability en date', VALUE_OPTIONAL),
209 'indent' => new external_value(PARAM_INT, 'number of identation in the site'),
210 'contents' => new external_multiple_structure(
211 new external_single_structure(
212 array(
213 // content info
214 'type'=> new external_value(PARAM_TEXT, 'a file or a folder or external link'),
215 'filename'=> new external_value(PARAM_FILE, 'filename'),
216 'filepath'=> new external_value(PARAM_PATH, 'filepath'),
217 'filesize'=> new external_value(PARAM_INT, 'filesize'),
218 'fileurl' => new external_value(PARAM_URL, 'downloadable file url', VALUE_OPTIONAL),
219 'content' => new external_value(PARAM_RAW, 'Raw content, will be used when type is content', VALUE_OPTIONAL),
220 'timecreated' => new external_value(PARAM_INT, 'Time created'),
221 'timemodified' => new external_value(PARAM_INT, 'Time modified'),
222 'sortorder' => new external_value(PARAM_INT, 'Content sort order'),
224 // copyright related info
225 'userid' => new external_value(PARAM_INT, 'User who added this content to moodle'),
226 'author' => new external_value(PARAM_TEXT, 'Content owner'),
227 'license' => new external_value(PARAM_TEXT, 'Content license'),
229 ), VALUE_DEFAULT, array()
232 ), 'list of module'
240 * Returns description of method parameters
241 * @return external_function_parameters
243 public static function get_courses_parameters() {
244 return new external_function_parameters(
245 array('options' => new external_single_structure(
246 array('ids' => new external_multiple_structure(
247 new external_value(PARAM_INT, 'Course id')
248 , 'List of course id. If empty return all courses
249 except front page course.',
250 VALUE_OPTIONAL)
251 ), 'options - operator OR is used', VALUE_DEFAULT, array())
257 * Get courses
258 * @param array $options
259 * @return array
261 public static function get_courses($options) {
262 global $CFG, $DB;
263 require_once($CFG->dirroot . "/course/lib.php");
265 //validate parameter
266 $params = self::validate_parameters(self::get_courses_parameters(),
267 array('options' => $options));
269 //retrieve courses
270 if (!key_exists('ids', $params['options'])
271 or empty($params['options']['ids'])) {
272 $courses = $DB->get_records('course');
273 } else {
274 $courses = $DB->get_records_list('course', 'id', $params['options']['ids']);
277 //create return value
278 $coursesinfo = array();
279 foreach ($courses as $course) {
281 // now security checks
282 $context = get_context_instance(CONTEXT_COURSE, $course->id);
283 try {
284 self::validate_context($context);
285 } catch (Exception $e) {
286 $exceptionparam = new stdClass();
287 $exceptionparam->message = $e->getMessage();
288 $exceptionparam->courseid = $course->id;
289 throw new moodle_exception(
290 get_string('errorcoursecontextnotvalid', 'webservice', $exceptionparam));
292 require_capability('moodle/course:view', $context);
294 $courseinfo = array();
295 $courseinfo['id'] = $course->id;
296 $courseinfo['fullname'] = $course->fullname;
297 $courseinfo['shortname'] = $course->shortname;
298 $courseinfo['categoryid'] = $course->category;
299 $courseinfo['summary'] = $course->summary;
300 $courseinfo['summaryformat'] = $course->summaryformat;
301 $courseinfo['format'] = $course->format;
302 $courseinfo['startdate'] = $course->startdate;
303 $courseinfo['numsections'] = $course->numsections;
305 //some field should be returned only if the user has update permission
306 $courseadmin = has_capability('moodle/course:update', $context);
307 if ($courseadmin) {
308 $courseinfo['categorysortorder'] = $course->sortorder;
309 $courseinfo['idnumber'] = $course->idnumber;
310 $courseinfo['showgrades'] = $course->showgrades;
311 $courseinfo['showreports'] = $course->showreports;
312 $courseinfo['newsitems'] = $course->newsitems;
313 $courseinfo['visible'] = $course->visible;
314 $courseinfo['maxbytes'] = $course->maxbytes;
315 $courseinfo['hiddensections'] = $course->hiddensections;
316 $courseinfo['groupmode'] = $course->groupmode;
317 $courseinfo['groupmodeforce'] = $course->groupmodeforce;
318 $courseinfo['defaultgroupingid'] = $course->defaultgroupingid;
319 $courseinfo['lang'] = $course->lang;
320 $courseinfo['timecreated'] = $course->timecreated;
321 $courseinfo['timemodified'] = $course->timemodified;
322 $courseinfo['forcetheme'] = $course->theme;
323 $courseinfo['enablecompletion'] = $course->enablecompletion;
324 $courseinfo['completionstartonenrol'] = $course->completionstartonenrol;
325 $courseinfo['completionnotify'] = $course->completionnotify;
328 if ($courseadmin or $course->visible
329 or has_capability('moodle/course:viewhiddencourses', $context)) {
330 $coursesinfo[] = $courseinfo;
334 return $coursesinfo;
338 * Returns description of method result value
339 * @return external_description
341 public static function get_courses_returns() {
342 return new external_multiple_structure(
343 new external_single_structure(
344 array(
345 'id' => new external_value(PARAM_INT, 'course id'),
346 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
347 'categoryid' => new external_value(PARAM_INT, 'category id'),
348 'categorysortorder' => new external_value(PARAM_INT,
349 'sort order into the category', VALUE_OPTIONAL),
350 'fullname' => new external_value(PARAM_TEXT, 'full name'),
351 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
352 'summary' => new external_value(PARAM_RAW, 'summary'),
353 'summaryformat' => new external_value(PARAM_INT,
354 'the summary text Moodle format'),
355 'format' => new external_value(PARAM_PLUGIN,
356 'course format: weeks, topics, social, site,..'),
357 'showgrades' => new external_value(PARAM_INT,
358 '1 if grades are shown, otherwise 0', VALUE_OPTIONAL),
359 'newsitems' => new external_value(PARAM_INT,
360 'number of recent items appearing on the course page', VALUE_OPTIONAL),
361 'startdate' => new external_value(PARAM_INT,
362 'timestamp when the course start'),
363 'numsections' => new external_value(PARAM_INT, 'number of weeks/topics'),
364 'maxbytes' => new external_value(PARAM_INT,
365 'largest size of file that can be uploaded into the course',
366 VALUE_OPTIONAL),
367 'showreports' => new external_value(PARAM_INT,
368 'are activity report shown (yes = 1, no =0)', VALUE_OPTIONAL),
369 'visible' => new external_value(PARAM_INT,
370 '1: available to student, 0:not available', VALUE_OPTIONAL),
371 'hiddensections' => new external_value(PARAM_INT,
372 'How the hidden sections in the course are displayed to students',
373 VALUE_OPTIONAL),
374 'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
375 VALUE_OPTIONAL),
376 'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
377 VALUE_OPTIONAL),
378 'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
379 VALUE_OPTIONAL),
380 'timecreated' => new external_value(PARAM_INT,
381 'timestamp when the course have been created', VALUE_OPTIONAL),
382 'timemodified' => new external_value(PARAM_INT,
383 'timestamp when the course have been modified', VALUE_OPTIONAL),
384 'enablecompletion' => new external_value(PARAM_INT,
385 'Enabled, control via completion and activity settings. Disbaled,
386 not shown in activity settings.',
387 VALUE_OPTIONAL),
388 'completionstartonenrol' => new external_value(PARAM_INT,
389 '1: begin tracking a student\'s progress in course completion
390 after course enrolment. 0: does not',
391 VALUE_OPTIONAL),
392 'completionnotify' => new external_value(PARAM_INT,
393 '1: yes 0: no', VALUE_OPTIONAL),
394 'lang' => new external_value(PARAM_SAFEDIR,
395 'forced course language', VALUE_OPTIONAL),
396 'forcetheme' => new external_value(PARAM_PLUGIN,
397 'name of the force theme', VALUE_OPTIONAL),
398 ), 'course'
404 * Returns description of method parameters
405 * @return external_function_parameters
407 public static function create_courses_parameters() {
408 $courseconfig = get_config('moodlecourse'); //needed for many default values
409 return new external_function_parameters(
410 array(
411 'courses' => new external_multiple_structure(
412 new external_single_structure(
413 array(
414 'fullname' => new external_value(PARAM_TEXT, 'full name'),
415 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
416 'categoryid' => new external_value(PARAM_INT, 'category id'),
417 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL),
418 'summary' => new external_value(PARAM_RAW, 'summary', VALUE_OPTIONAL),
419 'summaryformat' => new external_value(PARAM_INT,
420 'the summary text Moodle format', VALUE_DEFAULT, FORMAT_MOODLE),
421 'format' => new external_value(PARAM_PLUGIN,
422 'course format: weeks, topics, social, site,..',
423 VALUE_DEFAULT, $courseconfig->format),
424 'showgrades' => new external_value(PARAM_INT,
425 '1 if grades are shown, otherwise 0', VALUE_DEFAULT,
426 $courseconfig->showgrades),
427 'newsitems' => new external_value(PARAM_INT,
428 'number of recent items appearing on the course page',
429 VALUE_DEFAULT, $courseconfig->newsitems),
430 'startdate' => new external_value(PARAM_INT,
431 'timestamp when the course start', VALUE_OPTIONAL),
432 'numsections' => new external_value(PARAM_INT, 'number of weeks/topics',
433 VALUE_DEFAULT, $courseconfig->numsections),
434 'maxbytes' => new external_value(PARAM_INT,
435 'largest size of file that can be uploaded into the course',
436 VALUE_DEFAULT, $courseconfig->maxbytes),
437 'showreports' => new external_value(PARAM_INT,
438 'are activity report shown (yes = 1, no =0)', VALUE_DEFAULT,
439 $courseconfig->showreports),
440 'visible' => new external_value(PARAM_INT,
441 '1: available to student, 0:not available', VALUE_OPTIONAL),
442 'hiddensections' => new external_value(PARAM_INT,
443 'How the hidden sections in the course are displayed to students',
444 VALUE_DEFAULT, $courseconfig->hiddensections),
445 'groupmode' => new external_value(PARAM_INT, 'no group, separate, visible',
446 VALUE_DEFAULT, $courseconfig->groupmode),
447 'groupmodeforce' => new external_value(PARAM_INT, '1: yes, 0: no',
448 VALUE_DEFAULT, $courseconfig->groupmodeforce),
449 'defaultgroupingid' => new external_value(PARAM_INT, 'default grouping id',
450 VALUE_DEFAULT, 0),
451 'enablecompletion' => new external_value(PARAM_INT,
452 'Enabled, control via completion and activity settings. Disabled,
453 not shown in activity settings.',
454 VALUE_OPTIONAL),
455 'completionstartonenrol' => new external_value(PARAM_INT,
456 '1: begin tracking a student\'s progress in course completion after
457 course enrolment. 0: does not',
458 VALUE_OPTIONAL),
459 'completionnotify' => new external_value(PARAM_INT,
460 '1: yes 0: no', VALUE_OPTIONAL),
461 'lang' => new external_value(PARAM_SAFEDIR,
462 'forced course language', VALUE_OPTIONAL),
463 'forcetheme' => new external_value(PARAM_PLUGIN,
464 'name of the force theme', VALUE_OPTIONAL),
466 ), 'courses to create'
473 * Create courses
474 * @param array $courses
475 * @return array courses (id and shortname only)
477 public static function create_courses($courses) {
478 global $CFG, $DB;
479 require_once($CFG->dirroot . "/course/lib.php");
480 require_once($CFG->libdir . '/completionlib.php');
483 $params = self::validate_parameters(self::create_courses_parameters(),
484 array('courses' => $courses));
486 $availablethemes = get_plugin_list('theme');
487 $availablelangs = get_string_manager()->get_list_of_translations();
489 $transaction = $DB->start_delegated_transaction();
491 foreach ($params['courses'] as $course) {
493 // Ensure the current user is allowed to run this function
494 $context = get_context_instance(CONTEXT_COURSECAT, $course['categoryid']);
495 try {
496 self::validate_context($context);
497 } catch (Exception $e) {
498 $exceptionparam = new stdClass();
499 $exceptionparam->message = $e->getMessage();
500 $exceptionparam->catid = $course['categoryid'];
501 throw new moodle_exception(
502 get_string('errorcatcontextnotvalid', 'webservice', $exceptionparam));
504 require_capability('moodle/course:create', $context);
506 // Make sure lang is valid
507 if (key_exists('lang', $course) and empty($availablelangs[$course['lang']])) {
508 throw new moodle_exception(
509 get_string('errorinvalidparam', 'webservice', 'lang'));
512 // Make sure theme is valid
513 if (key_exists('forcetheme', $course)) {
514 if (!empty($CFG->allowcoursethemes)) {
515 if (empty($availablethemes[$course['forcetheme']])) {
516 throw new moodle_exception(
517 get_string('errorinvalidparam', 'webservice', 'forcetheme'));
518 } else {
519 $course['theme'] = $course['forcetheme'];
524 //force visibility if ws user doesn't have the permission to set it
525 $category = $DB->get_record('course_categories', array('id' => $course['categoryid']));
526 if (!has_capability('moodle/course:visibility', $context)) {
527 $course['visible'] = $category->visible;
530 //set default value for completion
531 $courseconfig = get_config('moodlecourse');
532 if (completion_info::is_enabled_for_site()) {
533 if (!key_exists('enablecompletion', $course)) {
534 $course['enablecompletion'] = $courseconfig->enablecompletion;
536 if (!key_exists('completionstartonenrol', $course)) {
537 $course['completionstartonenrol'] = $courseconfig->completionstartonenrol;
539 } else {
540 $course['enablecompletion'] = 0;
541 $course['completionstartonenrol'] = 0;
544 $course['category'] = $course['categoryid'];
546 //Note: create_course() core function check shortname, idnumber, category
547 $course['id'] = create_course((object) $course)->id;
549 $resultcourses[] = array('id' => $course['id'], 'shortname' => $course['shortname']);
552 $transaction->allow_commit();
554 return $resultcourses;
558 * Returns description of method result value
559 * @return external_description
561 public static function create_courses_returns() {
562 return new external_multiple_structure(
563 new external_single_structure(
564 array(
565 'id' => new external_value(PARAM_INT, 'course id'),
566 'shortname' => new external_value(PARAM_TEXT, 'short name'),
575 * Deprecated course functions
576 * @deprecated since Moodle 2.2 please use core_course_external instead
578 class moodle_course_external extends external_api {
581 * Returns description of method parameters
582 * @deprecated since Moodle 2.2 please use core_course_external::get_courses_parameters instead
583 * @return external_function_parameters
585 public static function get_courses_parameters() {
586 return core_course_external::get_courses_parameters();
590 * Get courses
591 * @param array $options
592 * @deprecated since Moodle 2.2 please use core_course_external::get_courses instead
593 * @return array
595 public static function get_courses($options) {
596 return core_course_external::get_courses($options);
600 * Returns description of method result value
601 * @deprecated since Moodle 2.2 please use core_course_external::get_courses_returns instead
602 * @return external_description
604 public static function get_courses_returns() {
605 return core_course_external::get_courses_returns();
609 * Returns description of method parameters
610 * @deprecated since Moodle 2.2 please use core_course_external::create_courses_parameters instead
611 * @return external_function_parameters
613 public static function create_courses_parameters() {
614 return core_course_external::create_courses_parameters();
618 * Create courses
619 * @deprecated since Moodle 2.2 please use core_course_external::create_courses instead
620 * @param array $courses
621 * @return array courses (id and shortname only)
623 public static function create_courses($courses) {
624 return core_course_external::create_courses($courses);
628 * Returns description of method result value
629 * @deprecated since Moodle 2.2 please use core_course_external::create_courses_returns instead
630 * @return external_description
632 public static function create_courses_returns() {
633 return core_course_external::create_courses_returns();