Merge branch 'MDL-56724-master' of git://github.com/damyon/moodle
[moodle.git] / group / externallib.php
blob5359a373f17a8c1dca2d316d7e46b18db90dd951
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.
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 groups API
21 * @package core_group
22 * @category external
23 * @copyright 2009 Petr Skodak
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 require_once("$CFG->libdir/externallib.php");
29 /**
30 * Group external functions
32 * @package core_group
33 * @category external
34 * @copyright 2011 Jerome Mouneyrac
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 * @since Moodle 2.2
38 class core_group_external extends external_api {
40 /**
41 * Returns description of method parameters
43 * @return external_function_parameters
44 * @since Moodle 2.2
46 public static function create_groups_parameters() {
47 return new external_function_parameters(
48 array(
49 'groups' => new external_multiple_structure(
50 new external_single_structure(
51 array(
52 'courseid' => new external_value(PARAM_INT, 'id of course'),
53 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
54 'description' => new external_value(PARAM_RAW, 'group description text'),
55 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
56 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase', VALUE_OPTIONAL),
57 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
59 ), 'List of group object. A group has a courseid, a name, a description and an enrolment key.'
65 /**
66 * Create groups
68 * @param array $groups array of group description arrays (with keys groupname and courseid)
69 * @return array of newly created groups
70 * @since Moodle 2.2
72 public static function create_groups($groups) {
73 global $CFG, $DB;
74 require_once("$CFG->dirroot/group/lib.php");
76 $params = self::validate_parameters(self::create_groups_parameters(), array('groups'=>$groups));
78 $transaction = $DB->start_delegated_transaction();
80 $groups = array();
82 foreach ($params['groups'] as $group) {
83 $group = (object)$group;
85 if (trim($group->name) == '') {
86 throw new invalid_parameter_exception('Invalid group name');
88 if ($DB->get_record('groups', array('courseid'=>$group->courseid, 'name'=>$group->name))) {
89 throw new invalid_parameter_exception('Group with the same name already exists in the course');
91 if (!empty($group->idnumber) && $DB->count_records('groups', array('idnumber' => $group->idnumber))) {
92 throw new invalid_parameter_exception('Group with the same idnumber already exists');
95 // now security checks
96 $context = context_course::instance($group->courseid, IGNORE_MISSING);
97 try {
98 self::validate_context($context);
99 } catch (Exception $e) {
100 $exceptionparam = new stdClass();
101 $exceptionparam->message = $e->getMessage();
102 $exceptionparam->courseid = $group->courseid;
103 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
105 require_capability('moodle/course:managegroups', $context);
107 // Validate format.
108 $group->descriptionformat = external_validate_format($group->descriptionformat);
110 // finally create the group
111 $group->id = groups_create_group($group, false);
112 if (!isset($group->enrolmentkey)) {
113 $group->enrolmentkey = '';
115 if (!isset($group->idnumber)) {
116 $group->idnumber = '';
119 $groups[] = (array)$group;
122 $transaction->allow_commit();
124 return $groups;
128 * Returns description of method result value
130 * @return external_description
131 * @since Moodle 2.2
133 public static function create_groups_returns() {
134 return new external_multiple_structure(
135 new external_single_structure(
136 array(
137 'id' => new external_value(PARAM_INT, 'group record id'),
138 'courseid' => new external_value(PARAM_INT, 'id of course'),
139 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
140 'description' => new external_value(PARAM_RAW, 'group description text'),
141 'descriptionformat' => new external_format_value('description'),
142 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
143 'idnumber' => new external_value(PARAM_RAW, 'id number')
145 ), 'List of group object. A group has an id, a courseid, a name, a description and an enrolment key.'
150 * Returns description of method parameters
152 * @return external_function_parameters
153 * @since Moodle 2.2
155 public static function get_groups_parameters() {
156 return new external_function_parameters(
157 array(
158 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')
159 ,'List of group id. A group id is an integer.'),
165 * Get groups definition specified by ids
167 * @param array $groupids arrays of group ids
168 * @return array of group objects (id, courseid, name, enrolmentkey)
169 * @since Moodle 2.2
171 public static function get_groups($groupids) {
172 $params = self::validate_parameters(self::get_groups_parameters(), array('groupids'=>$groupids));
174 $groups = array();
175 foreach ($params['groupids'] as $groupid) {
176 // validate params
177 $group = groups_get_group($groupid, 'id, courseid, name, idnumber, description, descriptionformat, enrolmentkey', MUST_EXIST);
179 // now security checks
180 $context = context_course::instance($group->courseid, IGNORE_MISSING);
181 try {
182 self::validate_context($context);
183 } catch (Exception $e) {
184 $exceptionparam = new stdClass();
185 $exceptionparam->message = $e->getMessage();
186 $exceptionparam->courseid = $group->courseid;
187 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
189 require_capability('moodle/course:managegroups', $context);
191 list($group->description, $group->descriptionformat) =
192 external_format_text($group->description, $group->descriptionformat,
193 $context->id, 'group', 'description', $group->id);
195 $groups[] = (array)$group;
198 return $groups;
202 * Returns description of method result value
204 * @return external_description
205 * @since Moodle 2.2
207 public static function get_groups_returns() {
208 return new external_multiple_structure(
209 new external_single_structure(
210 array(
211 'id' => new external_value(PARAM_INT, 'group record id'),
212 'courseid' => new external_value(PARAM_INT, 'id of course'),
213 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
214 'description' => new external_value(PARAM_RAW, 'group description text'),
215 'descriptionformat' => new external_format_value('description'),
216 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
217 'idnumber' => new external_value(PARAM_RAW, 'id number')
224 * Returns description of method parameters
226 * @return external_function_parameters
227 * @since Moodle 2.2
229 public static function get_course_groups_parameters() {
230 return new external_function_parameters(
231 array(
232 'courseid' => new external_value(PARAM_INT, 'id of course'),
238 * Get all groups in the specified course
240 * @param int $courseid id of course
241 * @return array of group objects (id, courseid, name, enrolmentkey)
242 * @since Moodle 2.2
244 public static function get_course_groups($courseid) {
245 $params = self::validate_parameters(self::get_course_groups_parameters(), array('courseid'=>$courseid));
247 // now security checks
248 $context = context_course::instance($params['courseid'], IGNORE_MISSING);
249 try {
250 self::validate_context($context);
251 } catch (Exception $e) {
252 $exceptionparam = new stdClass();
253 $exceptionparam->message = $e->getMessage();
254 $exceptionparam->courseid = $params['courseid'];
255 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
257 require_capability('moodle/course:managegroups', $context);
259 $gs = groups_get_all_groups($params['courseid'], 0, 0,
260 'g.id, g.courseid, g.name, g.idnumber, g.description, g.descriptionformat, g.enrolmentkey');
262 $groups = array();
263 foreach ($gs as $group) {
264 list($group->description, $group->descriptionformat) =
265 external_format_text($group->description, $group->descriptionformat,
266 $context->id, 'group', 'description', $group->id);
267 $groups[] = (array)$group;
270 return $groups;
274 * Returns description of method result value
276 * @return external_description
277 * @since Moodle 2.2
279 public static function get_course_groups_returns() {
280 return new external_multiple_structure(
281 new external_single_structure(
282 array(
283 'id' => new external_value(PARAM_INT, 'group record id'),
284 'courseid' => new external_value(PARAM_INT, 'id of course'),
285 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
286 'description' => new external_value(PARAM_RAW, 'group description text'),
287 'descriptionformat' => new external_format_value('description'),
288 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
289 'idnumber' => new external_value(PARAM_RAW, 'id number')
296 * Returns description of method parameters
298 * @return external_function_parameters
299 * @since Moodle 2.2
301 public static function delete_groups_parameters() {
302 return new external_function_parameters(
303 array(
304 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
310 * Delete groups
312 * @param array $groupids array of group ids
313 * @since Moodle 2.2
315 public static function delete_groups($groupids) {
316 global $CFG, $DB;
317 require_once("$CFG->dirroot/group/lib.php");
319 $params = self::validate_parameters(self::delete_groups_parameters(), array('groupids'=>$groupids));
321 $transaction = $DB->start_delegated_transaction();
323 foreach ($params['groupids'] as $groupid) {
324 // validate params
325 $groupid = validate_param($groupid, PARAM_INT);
326 if (!$group = groups_get_group($groupid, '*', IGNORE_MISSING)) {
327 // silently ignore attempts to delete nonexisting groups
328 continue;
331 // now security checks
332 $context = context_course::instance($group->courseid, IGNORE_MISSING);
333 try {
334 self::validate_context($context);
335 } catch (Exception $e) {
336 $exceptionparam = new stdClass();
337 $exceptionparam->message = $e->getMessage();
338 $exceptionparam->courseid = $group->courseid;
339 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
341 require_capability('moodle/course:managegroups', $context);
343 groups_delete_group($group);
346 $transaction->allow_commit();
350 * Returns description of method result value
352 * @return null
353 * @since Moodle 2.2
355 public static function delete_groups_returns() {
356 return null;
361 * Returns description of method parameters
363 * @return external_function_parameters
364 * @since Moodle 2.2
366 public static function get_group_members_parameters() {
367 return new external_function_parameters(
368 array(
369 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
375 * Return all members for a group
377 * @param array $groupids array of group ids
378 * @return array with group id keys containing arrays of user ids
379 * @since Moodle 2.2
381 public static function get_group_members($groupids) {
382 $members = array();
384 $params = self::validate_parameters(self::get_group_members_parameters(), array('groupids'=>$groupids));
386 foreach ($params['groupids'] as $groupid) {
387 // validate params
388 $group = groups_get_group($groupid, 'id, courseid, name, enrolmentkey', MUST_EXIST);
389 // now security checks
390 $context = context_course::instance($group->courseid, IGNORE_MISSING);
391 try {
392 self::validate_context($context);
393 } catch (Exception $e) {
394 $exceptionparam = new stdClass();
395 $exceptionparam->message = $e->getMessage();
396 $exceptionparam->courseid = $group->courseid;
397 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
399 require_capability('moodle/course:managegroups', $context);
401 $groupmembers = groups_get_members($group->id, 'u.id', 'lastname ASC, firstname ASC');
403 $members[] = array('groupid'=>$groupid, 'userids'=>array_keys($groupmembers));
406 return $members;
410 * Returns description of method result value
412 * @return external_description
413 * @since Moodle 2.2
415 public static function get_group_members_returns() {
416 return new external_multiple_structure(
417 new external_single_structure(
418 array(
419 'groupid' => new external_value(PARAM_INT, 'group record id'),
420 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user id')),
428 * Returns description of method parameters
430 * @return external_function_parameters
431 * @since Moodle 2.2
433 public static function add_group_members_parameters() {
434 return new external_function_parameters(
435 array(
436 'members'=> new external_multiple_structure(
437 new external_single_structure(
438 array(
439 'groupid' => new external_value(PARAM_INT, 'group record id'),
440 'userid' => new external_value(PARAM_INT, 'user id'),
449 * Add group members
451 * @param array $members of arrays with keys userid, groupid
452 * @since Moodle 2.2
454 public static function add_group_members($members) {
455 global $CFG, $DB;
456 require_once("$CFG->dirroot/group/lib.php");
458 $params = self::validate_parameters(self::add_group_members_parameters(), array('members'=>$members));
460 $transaction = $DB->start_delegated_transaction();
461 foreach ($params['members'] as $member) {
462 // validate params
463 $groupid = $member['groupid'];
464 $userid = $member['userid'];
466 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
467 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
469 // now security checks
470 $context = context_course::instance($group->courseid, IGNORE_MISSING);
471 try {
472 self::validate_context($context);
473 } catch (Exception $e) {
474 $exceptionparam = new stdClass();
475 $exceptionparam->message = $e->getMessage();
476 $exceptionparam->courseid = $group->courseid;
477 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
479 require_capability('moodle/course:managegroups', $context);
481 // now make sure user is enrolled in course - this is mandatory requirement,
482 // unfortunately this is slow
483 if (!is_enrolled($context, $userid)) {
484 throw new invalid_parameter_exception('Only enrolled users may be members of groups');
487 groups_add_member($group, $user);
490 $transaction->allow_commit();
494 * Returns description of method result value
496 * @return null
497 * @since Moodle 2.2
499 public static function add_group_members_returns() {
500 return null;
505 * Returns description of method parameters
507 * @return external_function_parameters
508 * @since Moodle 2.2
510 public static function delete_group_members_parameters() {
511 return new external_function_parameters(
512 array(
513 'members'=> new external_multiple_structure(
514 new external_single_structure(
515 array(
516 'groupid' => new external_value(PARAM_INT, 'group record id'),
517 'userid' => new external_value(PARAM_INT, 'user id'),
526 * Delete group members
528 * @param array $members of arrays with keys userid, groupid
529 * @since Moodle 2.2
531 public static function delete_group_members($members) {
532 global $CFG, $DB;
533 require_once("$CFG->dirroot/group/lib.php");
535 $params = self::validate_parameters(self::delete_group_members_parameters(), array('members'=>$members));
537 $transaction = $DB->start_delegated_transaction();
539 foreach ($params['members'] as $member) {
540 // validate params
541 $groupid = $member['groupid'];
542 $userid = $member['userid'];
544 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
545 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
547 // now security checks
548 $context = context_course::instance($group->courseid, IGNORE_MISSING);
549 try {
550 self::validate_context($context);
551 } catch (Exception $e) {
552 $exceptionparam = new stdClass();
553 $exceptionparam->message = $e->getMessage();
554 $exceptionparam->courseid = $group->courseid;
555 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
557 require_capability('moodle/course:managegroups', $context);
559 if (!groups_remove_member_allowed($group, $user)) {
560 throw new moodle_exception('errorremovenotpermitted', 'group', '', fullname($user));
562 groups_remove_member($group, $user);
565 $transaction->allow_commit();
569 * Returns description of method result value
571 * @return null
572 * @since Moodle 2.2
574 public static function delete_group_members_returns() {
575 return null;
579 * Returns description of method parameters
581 * @return external_function_parameters
582 * @since Moodle 2.3
584 public static function create_groupings_parameters() {
585 return new external_function_parameters(
586 array(
587 'groupings' => new external_multiple_structure(
588 new external_single_structure(
589 array(
590 'courseid' => new external_value(PARAM_INT, 'id of course'),
591 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
592 'description' => new external_value(PARAM_RAW, 'grouping description text'),
593 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
594 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
596 ), 'List of grouping object. A grouping has a courseid, a name and a description.'
603 * Create groupings
605 * @param array $groupings array of grouping description arrays (with keys groupname and courseid)
606 * @return array of newly created groupings
607 * @since Moodle 2.3
609 public static function create_groupings($groupings) {
610 global $CFG, $DB;
611 require_once("$CFG->dirroot/group/lib.php");
613 $params = self::validate_parameters(self::create_groupings_parameters(), array('groupings'=>$groupings));
615 $transaction = $DB->start_delegated_transaction();
617 $groupings = array();
619 foreach ($params['groupings'] as $grouping) {
620 $grouping = (object)$grouping;
622 if (trim($grouping->name) == '') {
623 throw new invalid_parameter_exception('Invalid grouping name');
625 if ($DB->count_records('groupings', array('courseid'=>$grouping->courseid, 'name'=>$grouping->name))) {
626 throw new invalid_parameter_exception('Grouping with the same name already exists in the course');
628 if (!empty($grouping->idnumber) && $DB->count_records('groupings', array('idnumber' => $grouping->idnumber))) {
629 throw new invalid_parameter_exception('Grouping with the same idnumber already exists');
632 // Now security checks .
633 $context = context_course::instance($grouping->courseid);
634 try {
635 self::validate_context($context);
636 } catch (Exception $e) {
637 $exceptionparam = new stdClass();
638 $exceptionparam->message = $e->getMessage();
639 $exceptionparam->courseid = $grouping->courseid;
640 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
642 require_capability('moodle/course:managegroups', $context);
644 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
646 // Finally create the grouping.
647 $grouping->id = groups_create_grouping($grouping);
648 $groupings[] = (array)$grouping;
651 $transaction->allow_commit();
653 return $groupings;
657 * Returns description of method result value
659 * @return external_description
660 * @since Moodle 2.3
662 public static function create_groupings_returns() {
663 return new external_multiple_structure(
664 new external_single_structure(
665 array(
666 'id' => new external_value(PARAM_INT, 'grouping record id'),
667 'courseid' => new external_value(PARAM_INT, 'id of course'),
668 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
669 'description' => new external_value(PARAM_RAW, 'grouping description text'),
670 'descriptionformat' => new external_format_value('description'),
671 'idnumber' => new external_value(PARAM_RAW, 'id number')
673 ), 'List of grouping object. A grouping has an id, a courseid, a name and a description.'
678 * Returns description of method parameters
680 * @return external_function_parameters
681 * @since Moodle 2.3
683 public static function update_groupings_parameters() {
684 return new external_function_parameters(
685 array(
686 'groupings' => new external_multiple_structure(
687 new external_single_structure(
688 array(
689 'id' => new external_value(PARAM_INT, 'id of grouping'),
690 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
691 'description' => new external_value(PARAM_RAW, 'grouping description text'),
692 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
693 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
695 ), 'List of grouping object. A grouping has a courseid, a name and a description.'
702 * Update groupings
704 * @param array $groupings array of grouping description arrays (with keys groupname and courseid)
705 * @return array of newly updated groupings
706 * @since Moodle 2.3
708 public static function update_groupings($groupings) {
709 global $CFG, $DB;
710 require_once("$CFG->dirroot/group/lib.php");
712 $params = self::validate_parameters(self::update_groupings_parameters(), array('groupings'=>$groupings));
714 $transaction = $DB->start_delegated_transaction();
716 foreach ($params['groupings'] as $grouping) {
717 $grouping = (object)$grouping;
719 if (trim($grouping->name) == '') {
720 throw new invalid_parameter_exception('Invalid grouping name');
723 if (! $currentgrouping = $DB->get_record('groupings', array('id'=>$grouping->id))) {
724 throw new invalid_parameter_exception("Grouping $grouping->id does not exist in the course");
727 // Check if the new modified grouping name already exists in the course.
728 if ($grouping->name != $currentgrouping->name and
729 $DB->count_records('groupings', array('courseid'=>$currentgrouping->courseid, 'name'=>$grouping->name))) {
730 throw new invalid_parameter_exception('A different grouping with the same name already exists in the course');
732 // Check if the new modified grouping idnumber already exists.
733 if (!empty($grouping->idnumber) && $grouping->idnumber != $currentgrouping->idnumber &&
734 $DB->count_records('groupings', array('idnumber' => $grouping->idnumber))) {
735 throw new invalid_parameter_exception('A different grouping with the same idnumber already exists');
738 $grouping->courseid = $currentgrouping->courseid;
740 // Now security checks.
741 $context = context_course::instance($grouping->courseid);
742 try {
743 self::validate_context($context);
744 } catch (Exception $e) {
745 $exceptionparam = new stdClass();
746 $exceptionparam->message = $e->getMessage();
747 $exceptionparam->courseid = $grouping->courseid;
748 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
750 require_capability('moodle/course:managegroups', $context);
752 // We must force allways FORMAT_HTML.
753 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
755 // Finally update the grouping.
756 groups_update_grouping($grouping);
759 $transaction->allow_commit();
761 return null;
765 * Returns description of method result value
767 * @return external_description
768 * @since Moodle 2.3
770 public static function update_groupings_returns() {
771 return null;
775 * Returns description of method parameters
777 * @return external_function_parameters
778 * @since Moodle 2.3
780 public static function get_groupings_parameters() {
781 return new external_function_parameters(
782 array(
783 'groupingids' => new external_multiple_structure(new external_value(PARAM_INT, 'grouping ID')
784 , 'List of grouping id. A grouping id is an integer.'),
785 'returngroups' => new external_value(PARAM_BOOL, 'return associated groups', VALUE_DEFAULT, 0)
791 * Get groupings definition specified by ids
793 * @param array $groupingids arrays of grouping ids
794 * @param boolean $returngroups return the associated groups if true. The default is false.
795 * @return array of grouping objects (id, courseid, name)
796 * @since Moodle 2.3
798 public static function get_groupings($groupingids, $returngroups = false) {
799 global $CFG, $DB;
800 require_once("$CFG->dirroot/group/lib.php");
801 require_once("$CFG->libdir/filelib.php");
803 $params = self::validate_parameters(self::get_groupings_parameters(),
804 array('groupingids' => $groupingids,
805 'returngroups' => $returngroups));
807 $groupings = array();
808 foreach ($params['groupingids'] as $groupingid) {
809 // Validate params.
810 $grouping = groups_get_grouping($groupingid, '*', MUST_EXIST);
812 // Now security checks.
813 $context = context_course::instance($grouping->courseid);
814 try {
815 self::validate_context($context);
816 } catch (Exception $e) {
817 $exceptionparam = new stdClass();
818 $exceptionparam->message = $e->getMessage();
819 $exceptionparam->courseid = $grouping->courseid;
820 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
822 require_capability('moodle/course:managegroups', $context);
824 list($grouping->description, $grouping->descriptionformat) =
825 external_format_text($grouping->description, $grouping->descriptionformat,
826 $context->id, 'grouping', 'description', $grouping->id);
828 $groupingarray = (array)$grouping;
830 if ($params['returngroups']) {
831 $grouprecords = $DB->get_records_sql("SELECT * FROM {groups} g INNER JOIN {groupings_groups} gg ".
832 "ON g.id = gg.groupid WHERE gg.groupingid = ? ".
833 "ORDER BY groupid", array($groupingid));
834 if ($grouprecords) {
835 $groups = array();
836 foreach ($grouprecords as $grouprecord) {
837 list($grouprecord->description, $grouprecord->descriptionformat) =
838 external_format_text($grouprecord->description, $grouprecord->descriptionformat,
839 $context->id, 'group', 'description', $grouprecord->groupid);
840 $groups[] = array('id' => $grouprecord->groupid,
841 'name' => $grouprecord->name,
842 'idnumber' => $grouprecord->idnumber,
843 'description' => $grouprecord->description,
844 'descriptionformat' => $grouprecord->descriptionformat,
845 'enrolmentkey' => $grouprecord->enrolmentkey,
846 'courseid' => $grouprecord->courseid
849 $groupingarray['groups'] = $groups;
852 $groupings[] = $groupingarray;
855 return $groupings;
859 * Returns description of method result value
861 * @return external_description
862 * @since Moodle 2.3
864 public static function get_groupings_returns() {
865 return new external_multiple_structure(
866 new external_single_structure(
867 array(
868 'id' => new external_value(PARAM_INT, 'grouping record id'),
869 'courseid' => new external_value(PARAM_INT, 'id of course'),
870 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
871 'description' => new external_value(PARAM_RAW, 'grouping description text'),
872 'descriptionformat' => new external_format_value('description'),
873 'idnumber' => new external_value(PARAM_RAW, 'id number'),
874 'groups' => new external_multiple_structure(
875 new external_single_structure(
876 array(
877 'id' => new external_value(PARAM_INT, 'group record id'),
878 'courseid' => new external_value(PARAM_INT, 'id of course'),
879 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
880 'description' => new external_value(PARAM_RAW, 'group description text'),
881 'descriptionformat' => new external_format_value('description'),
882 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
883 'idnumber' => new external_value(PARAM_RAW, 'id number')
886 'optional groups', VALUE_OPTIONAL)
893 * Returns description of method parameters
895 * @return external_function_parameters
896 * @since Moodle 2.3
898 public static function get_course_groupings_parameters() {
899 return new external_function_parameters(
900 array(
901 'courseid' => new external_value(PARAM_INT, 'id of course'),
907 * Get all groupings in the specified course
909 * @param int $courseid id of course
910 * @return array of grouping objects (id, courseid, name, enrolmentkey)
911 * @since Moodle 2.3
913 public static function get_course_groupings($courseid) {
914 global $CFG;
915 require_once("$CFG->dirroot/group/lib.php");
916 require_once("$CFG->libdir/filelib.php");
918 $params = self::validate_parameters(self::get_course_groupings_parameters(), array('courseid'=>$courseid));
920 // Now security checks.
921 $context = context_course::instance($params['courseid']);
923 try {
924 self::validate_context($context);
925 } catch (Exception $e) {
926 $exceptionparam = new stdClass();
927 $exceptionparam->message = $e->getMessage();
928 $exceptionparam->courseid = $params['courseid'];
929 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
931 require_capability('moodle/course:managegroups', $context);
933 $gs = groups_get_all_groupings($params['courseid']);
935 $groupings = array();
936 foreach ($gs as $grouping) {
937 list($grouping->description, $grouping->descriptionformat) =
938 external_format_text($grouping->description, $grouping->descriptionformat,
939 $context->id, 'grouping', 'description', $grouping->id);
940 $groupings[] = (array)$grouping;
943 return $groupings;
947 * Returns description of method result value
949 * @return external_description
950 * @since Moodle 2.3
952 public static function get_course_groupings_returns() {
953 return new external_multiple_structure(
954 new external_single_structure(
955 array(
956 'id' => new external_value(PARAM_INT, 'grouping record id'),
957 'courseid' => new external_value(PARAM_INT, 'id of course'),
958 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
959 'description' => new external_value(PARAM_RAW, 'grouping description text'),
960 'descriptionformat' => new external_format_value('description'),
961 'idnumber' => new external_value(PARAM_RAW, 'id number')
968 * Returns description of method parameters
970 * @return external_function_parameters
971 * @since Moodle 2.3
973 public static function delete_groupings_parameters() {
974 return new external_function_parameters(
975 array(
976 'groupingids' => new external_multiple_structure(new external_value(PARAM_INT, 'grouping ID')),
982 * Delete groupings
984 * @param array $groupingids array of grouping ids
985 * @return void
986 * @since Moodle 2.3
988 public static function delete_groupings($groupingids) {
989 global $CFG, $DB;
990 require_once("$CFG->dirroot/group/lib.php");
992 $params = self::validate_parameters(self::delete_groupings_parameters(), array('groupingids'=>$groupingids));
994 $transaction = $DB->start_delegated_transaction();
996 foreach ($params['groupingids'] as $groupingid) {
998 if (!$grouping = groups_get_grouping($groupingid, 'id, courseid', IGNORE_MISSING)) {
999 // Silently ignore attempts to delete nonexisting groupings.
1000 continue;
1003 // Now security checks.
1004 $context = context_course::instance($grouping->courseid);
1005 try {
1006 self::validate_context($context);
1007 } catch (Exception $e) {
1008 $exceptionparam = new stdClass();
1009 $exceptionparam->message = $e->getMessage();
1010 $exceptionparam->courseid = $grouping->courseid;
1011 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1013 require_capability('moodle/course:managegroups', $context);
1015 groups_delete_grouping($grouping);
1018 $transaction->allow_commit();
1022 * Returns description of method result value
1024 * @return external_description
1025 * @since Moodle 2.3
1027 public static function delete_groupings_returns() {
1028 return null;
1032 * Returns description of method parameters
1034 * @return external_function_parameters
1035 * @since Moodle 2.3
1037 public static function assign_grouping_parameters() {
1038 return new external_function_parameters(
1039 array(
1040 'assignments'=> new external_multiple_structure(
1041 new external_single_structure(
1042 array(
1043 'groupingid' => new external_value(PARAM_INT, 'grouping record id'),
1044 'groupid' => new external_value(PARAM_INT, 'group record id'),
1053 * Assign a group to a grouping
1055 * @param array $assignments of arrays with keys groupid, groupingid
1056 * @return void
1057 * @since Moodle 2.3
1059 public static function assign_grouping($assignments) {
1060 global $CFG, $DB;
1061 require_once("$CFG->dirroot/group/lib.php");
1063 $params = self::validate_parameters(self::assign_grouping_parameters(), array('assignments'=>$assignments));
1065 $transaction = $DB->start_delegated_transaction();
1066 foreach ($params['assignments'] as $assignment) {
1067 // Validate params.
1068 $groupingid = $assignment['groupingid'];
1069 $groupid = $assignment['groupid'];
1071 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1072 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1074 if ($DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) {
1075 // Continue silently if the group is yet assigned to the grouping.
1076 continue;
1079 // Now security checks.
1080 $context = context_course::instance($grouping->courseid);
1081 try {
1082 self::validate_context($context);
1083 } catch (Exception $e) {
1084 $exceptionparam = new stdClass();
1085 $exceptionparam->message = $e->getMessage();
1086 $exceptionparam->courseid = $group->courseid;
1087 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1089 require_capability('moodle/course:managegroups', $context);
1091 groups_assign_grouping($groupingid, $groupid);
1094 $transaction->allow_commit();
1098 * Returns description of method result value
1100 * @return null
1101 * @since Moodle 2.3
1103 public static function assign_grouping_returns() {
1104 return null;
1108 * Returns description of method parameters
1110 * @return external_function_parameters
1111 * @since Moodle 2.3
1113 public static function unassign_grouping_parameters() {
1114 return new external_function_parameters(
1115 array(
1116 'unassignments'=> new external_multiple_structure(
1117 new external_single_structure(
1118 array(
1119 'groupingid' => new external_value(PARAM_INT, 'grouping record id'),
1120 'groupid' => new external_value(PARAM_INT, 'group record id'),
1129 * Unassign a group from a grouping
1131 * @param array $unassignments of arrays with keys groupid, groupingid
1132 * @return void
1133 * @since Moodle 2.3
1135 public static function unassign_grouping($unassignments) {
1136 global $CFG, $DB;
1137 require_once("$CFG->dirroot/group/lib.php");
1139 $params = self::validate_parameters(self::unassign_grouping_parameters(), array('unassignments'=>$unassignments));
1141 $transaction = $DB->start_delegated_transaction();
1142 foreach ($params['unassignments'] as $unassignment) {
1143 // Validate params.
1144 $groupingid = $unassignment['groupingid'];
1145 $groupid = $unassignment['groupid'];
1147 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1148 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1150 if (!$DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) {
1151 // Continue silently if the group is not assigned to the grouping.
1152 continue;
1155 // Now security checks.
1156 $context = context_course::instance($grouping->courseid);
1157 try {
1158 self::validate_context($context);
1159 } catch (Exception $e) {
1160 $exceptionparam = new stdClass();
1161 $exceptionparam->message = $e->getMessage();
1162 $exceptionparam->courseid = $group->courseid;
1163 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1165 require_capability('moodle/course:managegroups', $context);
1167 groups_unassign_grouping($groupingid, $groupid);
1170 $transaction->allow_commit();
1174 * Returns description of method result value
1176 * @return null
1177 * @since Moodle 2.3
1179 public static function unassign_grouping_returns() {
1180 return null;
1184 * Returns description of method parameters
1186 * @return external_function_parameters
1187 * @since Moodle 2.9
1189 public static function get_course_user_groups_parameters() {
1190 return new external_function_parameters(
1191 array(
1192 'courseid' => new external_value(PARAM_INT, 'id of course'),
1193 'userid' => new external_value(PARAM_INT, 'id of user'),
1194 'groupingid' => new external_value(PARAM_INT, 'returns only groups in the specified grouping', VALUE_DEFAULT, 0)
1200 * Get all groups in the specified course for the specified user.
1202 * @throws moodle_exception
1203 * @param int $courseid id of course.
1204 * @param int $userid id of user.
1205 * @param int $groupingid optional returns only groups in the specified grouping.
1206 * @return array of group objects (id, name, description, format) and possible warnings.
1207 * @since Moodle 2.9
1209 public static function get_course_user_groups($courseid, $userid, $groupingid = 0) {
1210 global $USER;
1212 // Warnings array, it can be empty at the end but is mandatory.
1213 $warnings = array();
1215 $params = array(
1216 'courseid' => $courseid,
1217 'userid' => $userid,
1218 'groupingid' => $groupingid
1220 $params = self::validate_parameters(self::get_course_user_groups_parameters(), $params);
1221 $courseid = $params['courseid'];
1222 $userid = $params['userid'];
1223 $groupingid = $params['groupingid'];
1225 // Validate course and user. get_course throws an exception if the course does not exists.
1226 $course = get_course($courseid);
1227 $user = core_user::get_user($userid, '*', MUST_EXIST);
1228 core_user::require_active_user($user);
1230 // Security checks.
1231 $context = context_course::instance($course->id);
1232 self::validate_context($context);
1234 // Check if we have permissions for retrieve the information.
1235 if ($user->id != $USER->id) {
1236 if (!has_capability('moodle/course:managegroups', $context)) {
1237 throw new moodle_exception('accessdenied', 'admin');
1239 // Validate if the user is enrolled in the course.
1240 if (!is_enrolled($context, $user->id)) {
1241 // We return a warning because the function does not fail for not enrolled users.
1242 $warning['item'] = 'course';
1243 $warning['itemid'] = $course->id;
1244 $warning['warningcode'] = '1';
1245 $warning['message'] = "User $user->id is not enrolled in course $course->id";
1246 $warnings[] = $warning;
1250 $usergroups = array();
1251 if (empty($warnings)) {
1252 $groups = groups_get_all_groups($course->id, $user->id, 0, 'g.id, g.name, g.description, g.descriptionformat, g.idnumber');
1254 foreach ($groups as $group) {
1255 list($group->description, $group->descriptionformat) =
1256 external_format_text($group->description, $group->descriptionformat,
1257 $context->id, 'group', 'description', $group->id);
1258 $group->courseid = $course->id;
1259 $usergroups[] = $group;
1263 $results = array(
1264 'groups' => $usergroups,
1265 'warnings' => $warnings
1267 return $results;
1271 * Returns description of method result value.
1273 * @return external_description A single structure containing groups and possible warnings.
1274 * @since Moodle 2.9
1276 public static function get_course_user_groups_returns() {
1277 return new external_single_structure(
1278 array(
1279 'groups' => new external_multiple_structure(self::group_description()),
1280 'warnings' => new external_warnings(),
1286 * Create group return value description.
1288 * @return external_single_structure The group description
1290 public static function group_description() {
1291 return new external_single_structure(
1292 array(
1293 'id' => new external_value(PARAM_INT, 'group record id'),
1294 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
1295 'description' => new external_value(PARAM_RAW, 'group description text'),
1296 'descriptionformat' => new external_format_value('description'),
1297 'idnumber' => new external_value(PARAM_RAW, 'id number'),
1298 'courseid' => new external_value(PARAM_INT, 'course id', VALUE_OPTIONAL),
1304 * Returns description of method parameters
1306 * @return external_function_parameters
1307 * @since Moodle 3.0
1309 public static function get_activity_allowed_groups_parameters() {
1310 return new external_function_parameters(
1311 array(
1312 'cmid' => new external_value(PARAM_INT, 'course module id'),
1313 'userid' => new external_value(PARAM_INT, 'id of user, empty for current user', VALUE_DEFAULT, 0)
1319 * Gets a list of groups that the user is allowed to access within the specified activity.
1321 * @throws moodle_exception
1322 * @param int $cmid course module id
1323 * @param int $userid id of user.
1324 * @return array of group objects (id, name, description, format) and possible warnings.
1325 * @since Moodle 3.0
1327 public static function get_activity_allowed_groups($cmid, $userid = 0) {
1328 global $USER;
1330 // Warnings array, it can be empty at the end but is mandatory.
1331 $warnings = array();
1333 $params = array(
1334 'cmid' => $cmid,
1335 'userid' => $userid
1337 $params = self::validate_parameters(self::get_activity_allowed_groups_parameters(), $params);
1338 $cmid = $params['cmid'];
1339 $userid = $params['userid'];
1341 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1343 // Security checks.
1344 $context = context_module::instance($cm->id);
1345 $coursecontext = context_course::instance($cm->course);
1346 self::validate_context($context);
1348 if (empty($userid)) {
1349 $userid = $USER->id;
1352 $user = core_user::get_user($userid, '*', MUST_EXIST);
1353 core_user::require_active_user($user);
1355 // Check if we have permissions for retrieve the information.
1356 if ($user->id != $USER->id) {
1357 if (!has_capability('moodle/course:managegroups', $context)) {
1358 throw new moodle_exception('accessdenied', 'admin');
1361 // Validate if the user is enrolled in the course.
1362 $course = get_course($cm->course);
1363 if (!can_access_course($course, $user, '', true)) {
1364 // We return a warning because the function does not fail for not enrolled users.
1365 $warning = array();
1366 $warning['item'] = 'course';
1367 $warning['itemid'] = $cm->course;
1368 $warning['warningcode'] = '1';
1369 $warning['message'] = "User $user->id cannot access course $cm->course";
1370 $warnings[] = $warning;
1374 $usergroups = array();
1375 if (empty($warnings)) {
1376 $groups = groups_get_activity_allowed_groups($cm, $user->id);
1378 foreach ($groups as $group) {
1379 list($group->description, $group->descriptionformat) =
1380 external_format_text($group->description, $group->descriptionformat,
1381 $coursecontext->id, 'group', 'description', $group->id);
1382 $group->courseid = $cm->course;
1383 $usergroups[] = $group;
1387 $results = array(
1388 'groups' => $usergroups,
1389 'warnings' => $warnings
1391 return $results;
1395 * Returns description of method result value.
1397 * @return external_description A single structure containing groups and possible warnings.
1398 * @since Moodle 3.0
1400 public static function get_activity_allowed_groups_returns() {
1401 return new external_single_structure(
1402 array(
1403 'groups' => new external_multiple_structure(self::group_description()),
1404 'warnings' => new external_warnings(),
1410 * Returns description of method parameters
1412 * @return external_function_parameters
1413 * @since Moodle 3.0
1415 public static function get_activity_groupmode_parameters() {
1416 return new external_function_parameters(
1417 array(
1418 'cmid' => new external_value(PARAM_INT, 'course module id')
1424 * Returns effective groupmode used in a given activity.
1426 * @throws moodle_exception
1427 * @param int $cmid course module id.
1428 * @return array containing the group mode and possible warnings.
1429 * @since Moodle 3.0
1430 * @throws moodle_exception
1432 public static function get_activity_groupmode($cmid) {
1433 global $USER;
1435 // Warnings array, it can be empty at the end but is mandatory.
1436 $warnings = array();
1438 $params = array(
1439 'cmid' => $cmid
1441 $params = self::validate_parameters(self::get_activity_groupmode_parameters(), $params);
1442 $cmid = $params['cmid'];
1444 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1446 // Security checks.
1447 $context = context_module::instance($cm->id);
1448 self::validate_context($context);
1450 $groupmode = groups_get_activity_groupmode($cm);
1452 $results = array(
1453 'groupmode' => $groupmode,
1454 'warnings' => $warnings
1456 return $results;
1460 * Returns description of method result value.
1462 * @return external_description
1463 * @since Moodle 3.0
1465 public static function get_activity_groupmode_returns() {
1466 return new external_single_structure(
1467 array(
1468 'groupmode' => new external_value(PARAM_INT, 'group mode:
1469 0 for no groups, 1 for separate groups, 2 for visible groups'),
1470 'warnings' => new external_warnings(),