Merge branch 'MDL-76071-master' of https://github.com/laurentdavid/moodle
[moodle.git] / group / externallib.php
blob341e72750a8869af2416c44d7ff64e7ad0af5bdb
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 defined('MOODLE_INTERNAL') || die();
29 require_once("$CFG->libdir/externallib.php");
31 /**
32 * Group external functions
34 * @package core_group
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
40 class core_group_external extends external_api {
42 /**
43 * Returns description of method parameters
45 * @return external_function_parameters
46 * @since Moodle 2.2
48 public static function create_groups_parameters() {
49 return new external_function_parameters(
50 array(
51 'groups' => new external_multiple_structure(
52 new external_single_structure(
53 array(
54 'courseid' => new external_value(PARAM_INT, 'id of course'),
55 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
56 'description' => new external_value(PARAM_RAW, 'group description text'),
57 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
58 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase', VALUE_OPTIONAL),
59 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
61 ), 'List of group object. A group has a courseid, a name, a description and an enrolment key.'
67 /**
68 * Create groups
70 * @param array $groups array of group description arrays (with keys groupname and courseid)
71 * @return array of newly created groups
72 * @since Moodle 2.2
74 public static function create_groups($groups) {
75 global $CFG, $DB;
76 require_once("$CFG->dirroot/group/lib.php");
78 $params = self::validate_parameters(self::create_groups_parameters(), array('groups'=>$groups));
80 $transaction = $DB->start_delegated_transaction();
82 $groups = array();
84 foreach ($params['groups'] as $group) {
85 $group = (object)$group;
87 if (trim($group->name) == '') {
88 throw new invalid_parameter_exception('Invalid group name');
90 if ($DB->get_record('groups', array('courseid'=>$group->courseid, 'name'=>$group->name))) {
91 throw new invalid_parameter_exception('Group with the same name already exists in the course');
94 // now security checks
95 $context = context_course::instance($group->courseid, IGNORE_MISSING);
96 try {
97 self::validate_context($context);
98 } catch (Exception $e) {
99 $exceptionparam = new stdClass();
100 $exceptionparam->message = $e->getMessage();
101 $exceptionparam->courseid = $group->courseid;
102 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
104 require_capability('moodle/course:managegroups', $context);
106 // Validate format.
107 $group->descriptionformat = external_validate_format($group->descriptionformat);
109 // finally create the group
110 $group->id = groups_create_group($group, false);
111 if (!isset($group->enrolmentkey)) {
112 $group->enrolmentkey = '';
114 if (!isset($group->idnumber)) {
115 $group->idnumber = '';
118 $groups[] = (array)$group;
121 $transaction->allow_commit();
123 return $groups;
127 * Returns description of method result value
129 * @return external_description
130 * @since Moodle 2.2
132 public static function create_groups_returns() {
133 return new external_multiple_structure(
134 new external_single_structure(
135 array(
136 'id' => new external_value(PARAM_INT, 'group record id'),
137 'courseid' => new external_value(PARAM_INT, 'id of course'),
138 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
139 'description' => new external_value(PARAM_RAW, 'group description text'),
140 'descriptionformat' => new external_format_value('description'),
141 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
142 'idnumber' => new external_value(PARAM_RAW, 'id number')
144 ), 'List of group object. A group has an id, a courseid, a name, a description and an enrolment key.'
149 * Returns description of method parameters
151 * @return external_function_parameters
152 * @since Moodle 2.2
154 public static function get_groups_parameters() {
155 return new external_function_parameters(
156 array(
157 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')
158 ,'List of group id. A group id is an integer.'),
164 * Get groups definition specified by ids
166 * @param array $groupids arrays of group ids
167 * @return array of group objects (id, courseid, name, enrolmentkey)
168 * @since Moodle 2.2
170 public static function get_groups($groupids) {
171 $params = self::validate_parameters(self::get_groups_parameters(), array('groupids'=>$groupids));
173 $groups = array();
174 foreach ($params['groupids'] as $groupid) {
175 // validate params
176 $group = groups_get_group($groupid, 'id, courseid, name, idnumber, description, descriptionformat, enrolmentkey', MUST_EXIST);
178 // now security checks
179 $context = context_course::instance($group->courseid, IGNORE_MISSING);
180 try {
181 self::validate_context($context);
182 } catch (Exception $e) {
183 $exceptionparam = new stdClass();
184 $exceptionparam->message = $e->getMessage();
185 $exceptionparam->courseid = $group->courseid;
186 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
188 require_capability('moodle/course:managegroups', $context);
190 list($group->description, $group->descriptionformat) =
191 external_format_text($group->description, $group->descriptionformat,
192 $context->id, 'group', 'description', $group->id);
194 $groups[] = (array)$group;
197 return $groups;
201 * Returns description of method result value
203 * @return external_description
204 * @since Moodle 2.2
206 public static function get_groups_returns() {
207 return new external_multiple_structure(
208 new external_single_structure(
209 array(
210 'id' => new external_value(PARAM_INT, 'group record id'),
211 'courseid' => new external_value(PARAM_INT, 'id of course'),
212 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
213 'description' => new external_value(PARAM_RAW, 'group description text'),
214 'descriptionformat' => new external_format_value('description'),
215 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
216 'idnumber' => new external_value(PARAM_RAW, 'id number')
223 * Returns description of method parameters
225 * @return external_function_parameters
226 * @since Moodle 2.2
228 public static function get_course_groups_parameters() {
229 return new external_function_parameters(
230 array(
231 'courseid' => new external_value(PARAM_INT, 'id of course'),
237 * Get all groups in the specified course
239 * @param int $courseid id of course
240 * @return array of group objects (id, courseid, name, enrolmentkey)
241 * @since Moodle 2.2
243 public static function get_course_groups($courseid) {
244 $params = self::validate_parameters(self::get_course_groups_parameters(), array('courseid'=>$courseid));
246 // now security checks
247 $context = context_course::instance($params['courseid'], IGNORE_MISSING);
248 try {
249 self::validate_context($context);
250 } catch (Exception $e) {
251 $exceptionparam = new stdClass();
252 $exceptionparam->message = $e->getMessage();
253 $exceptionparam->courseid = $params['courseid'];
254 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
256 require_capability('moodle/course:managegroups', $context);
258 $gs = groups_get_all_groups($params['courseid'], 0, 0,
259 'g.id, g.courseid, g.name, g.idnumber, g.description, g.descriptionformat, g.enrolmentkey');
261 $groups = array();
262 foreach ($gs as $group) {
263 list($group->description, $group->descriptionformat) =
264 external_format_text($group->description, $group->descriptionformat,
265 $context->id, 'group', 'description', $group->id);
266 $groups[] = (array)$group;
269 return $groups;
273 * Returns description of method result value
275 * @return external_description
276 * @since Moodle 2.2
278 public static function get_course_groups_returns() {
279 return new external_multiple_structure(
280 new external_single_structure(
281 array(
282 'id' => new external_value(PARAM_INT, 'group record id'),
283 'courseid' => new external_value(PARAM_INT, 'id of course'),
284 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
285 'description' => new external_value(PARAM_RAW, 'group description text'),
286 'descriptionformat' => new external_format_value('description'),
287 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
288 'idnumber' => new external_value(PARAM_RAW, 'id number')
295 * Returns description of method parameters
297 * @return external_function_parameters
298 * @since Moodle 2.2
300 public static function delete_groups_parameters() {
301 return new external_function_parameters(
302 array(
303 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
309 * Delete groups
311 * @param array $groupids array of group ids
312 * @since Moodle 2.2
314 public static function delete_groups($groupids) {
315 global $CFG, $DB;
316 require_once("$CFG->dirroot/group/lib.php");
318 $params = self::validate_parameters(self::delete_groups_parameters(), array('groupids'=>$groupids));
320 $transaction = $DB->start_delegated_transaction();
322 foreach ($params['groupids'] as $groupid) {
323 // validate params
324 $groupid = validate_param($groupid, PARAM_INT);
325 if (!$group = groups_get_group($groupid, '*', IGNORE_MISSING)) {
326 // silently ignore attempts to delete nonexisting groups
327 continue;
330 // now security checks
331 $context = context_course::instance($group->courseid, IGNORE_MISSING);
332 try {
333 self::validate_context($context);
334 } catch (Exception $e) {
335 $exceptionparam = new stdClass();
336 $exceptionparam->message = $e->getMessage();
337 $exceptionparam->courseid = $group->courseid;
338 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
340 require_capability('moodle/course:managegroups', $context);
342 groups_delete_group($group);
345 $transaction->allow_commit();
349 * Returns description of method result value
351 * @return null
352 * @since Moodle 2.2
354 public static function delete_groups_returns() {
355 return null;
360 * Returns description of method parameters
362 * @return external_function_parameters
363 * @since Moodle 2.2
365 public static function get_group_members_parameters() {
366 return new external_function_parameters(
367 array(
368 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
374 * Return all members for a group
376 * @param array $groupids array of group ids
377 * @return array with group id keys containing arrays of user ids
378 * @since Moodle 2.2
380 public static function get_group_members($groupids) {
381 $members = array();
383 $params = self::validate_parameters(self::get_group_members_parameters(), array('groupids'=>$groupids));
385 foreach ($params['groupids'] as $groupid) {
386 // validate params
387 $group = groups_get_group($groupid, 'id, courseid, name, enrolmentkey', MUST_EXIST);
388 // now security checks
389 $context = context_course::instance($group->courseid, IGNORE_MISSING);
390 try {
391 self::validate_context($context);
392 } catch (Exception $e) {
393 $exceptionparam = new stdClass();
394 $exceptionparam->message = $e->getMessage();
395 $exceptionparam->courseid = $group->courseid;
396 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
398 require_capability('moodle/course:managegroups', $context);
400 $groupmembers = groups_get_members($group->id, 'u.id', 'lastname ASC, firstname ASC');
402 $members[] = array('groupid'=>$groupid, 'userids'=>array_keys($groupmembers));
405 return $members;
409 * Returns description of method result value
411 * @return external_description
412 * @since Moodle 2.2
414 public static function get_group_members_returns() {
415 return new external_multiple_structure(
416 new external_single_structure(
417 array(
418 'groupid' => new external_value(PARAM_INT, 'group record id'),
419 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user id')),
427 * Returns description of method parameters
429 * @return external_function_parameters
430 * @since Moodle 2.2
432 public static function add_group_members_parameters() {
433 return new external_function_parameters(
434 array(
435 'members'=> new external_multiple_structure(
436 new external_single_structure(
437 array(
438 'groupid' => new external_value(PARAM_INT, 'group record id'),
439 'userid' => new external_value(PARAM_INT, 'user id'),
448 * Add group members
450 * @param array $members of arrays with keys userid, groupid
451 * @since Moodle 2.2
453 public static function add_group_members($members) {
454 global $CFG, $DB;
455 require_once("$CFG->dirroot/group/lib.php");
457 $params = self::validate_parameters(self::add_group_members_parameters(), array('members'=>$members));
459 $transaction = $DB->start_delegated_transaction();
460 foreach ($params['members'] as $member) {
461 // validate params
462 $groupid = $member['groupid'];
463 $userid = $member['userid'];
465 $group = groups_get_group($groupid, '*', MUST_EXIST);
466 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
468 // now security checks
469 $context = context_course::instance($group->courseid, IGNORE_MISSING);
470 try {
471 self::validate_context($context);
472 } catch (Exception $e) {
473 $exceptionparam = new stdClass();
474 $exceptionparam->message = $e->getMessage();
475 $exceptionparam->courseid = $group->courseid;
476 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
478 require_capability('moodle/course:managegroups', $context);
480 // now make sure user is enrolled in course - this is mandatory requirement,
481 // unfortunately this is slow
482 if (!is_enrolled($context, $userid)) {
483 throw new invalid_parameter_exception('Only enrolled users may be members of groups');
486 groups_add_member($group, $user);
489 $transaction->allow_commit();
493 * Returns description of method result value
495 * @return null
496 * @since Moodle 2.2
498 public static function add_group_members_returns() {
499 return null;
504 * Returns description of method parameters
506 * @return external_function_parameters
507 * @since Moodle 2.2
509 public static function delete_group_members_parameters() {
510 return new external_function_parameters(
511 array(
512 'members'=> new external_multiple_structure(
513 new external_single_structure(
514 array(
515 'groupid' => new external_value(PARAM_INT, 'group record id'),
516 'userid' => new external_value(PARAM_INT, 'user id'),
525 * Delete group members
527 * @param array $members of arrays with keys userid, groupid
528 * @since Moodle 2.2
530 public static function delete_group_members($members) {
531 global $CFG, $DB;
532 require_once("$CFG->dirroot/group/lib.php");
534 $params = self::validate_parameters(self::delete_group_members_parameters(), array('members'=>$members));
536 $transaction = $DB->start_delegated_transaction();
538 foreach ($params['members'] as $member) {
539 // validate params
540 $groupid = $member['groupid'];
541 $userid = $member['userid'];
543 $group = groups_get_group($groupid, '*', MUST_EXIST);
544 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
546 // now security checks
547 $context = context_course::instance($group->courseid, IGNORE_MISSING);
548 try {
549 self::validate_context($context);
550 } catch (Exception $e) {
551 $exceptionparam = new stdClass();
552 $exceptionparam->message = $e->getMessage();
553 $exceptionparam->courseid = $group->courseid;
554 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
556 require_capability('moodle/course:managegroups', $context);
558 if (!groups_remove_member_allowed($group, $user)) {
559 $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
560 throw new moodle_exception('errorremovenotpermitted', 'group', '', $fullname);
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');
629 // Now security checks .
630 $context = context_course::instance($grouping->courseid);
631 try {
632 self::validate_context($context);
633 } catch (Exception $e) {
634 $exceptionparam = new stdClass();
635 $exceptionparam->message = $e->getMessage();
636 $exceptionparam->courseid = $grouping->courseid;
637 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
639 require_capability('moodle/course:managegroups', $context);
641 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
643 // Finally create the grouping.
644 $grouping->id = groups_create_grouping($grouping);
645 $groupings[] = (array)$grouping;
648 $transaction->allow_commit();
650 return $groupings;
654 * Returns description of method result value
656 * @return external_description
657 * @since Moodle 2.3
659 public static function create_groupings_returns() {
660 return new external_multiple_structure(
661 new external_single_structure(
662 array(
663 'id' => new external_value(PARAM_INT, 'grouping record id'),
664 'courseid' => new external_value(PARAM_INT, 'id of course'),
665 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
666 'description' => new external_value(PARAM_RAW, 'grouping description text'),
667 'descriptionformat' => new external_format_value('description'),
668 'idnumber' => new external_value(PARAM_RAW, 'id number')
670 ), 'List of grouping object. A grouping has an id, a courseid, a name and a description.'
675 * Returns description of method parameters
677 * @return external_function_parameters
678 * @since Moodle 2.3
680 public static function update_groupings_parameters() {
681 return new external_function_parameters(
682 array(
683 'groupings' => new external_multiple_structure(
684 new external_single_structure(
685 array(
686 'id' => new external_value(PARAM_INT, 'id of grouping'),
687 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
688 'description' => new external_value(PARAM_RAW, 'grouping description text'),
689 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
690 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
692 ), 'List of grouping object. A grouping has a courseid, a name and a description.'
699 * Update groupings
701 * @param array $groupings array of grouping description arrays (with keys groupname and courseid)
702 * @return array of newly updated groupings
703 * @since Moodle 2.3
705 public static function update_groupings($groupings) {
706 global $CFG, $DB;
707 require_once("$CFG->dirroot/group/lib.php");
709 $params = self::validate_parameters(self::update_groupings_parameters(), array('groupings'=>$groupings));
711 $transaction = $DB->start_delegated_transaction();
713 foreach ($params['groupings'] as $grouping) {
714 $grouping = (object)$grouping;
716 if (trim($grouping->name) == '') {
717 throw new invalid_parameter_exception('Invalid grouping name');
720 if (! $currentgrouping = $DB->get_record('groupings', array('id'=>$grouping->id))) {
721 throw new invalid_parameter_exception("Grouping $grouping->id does not exist in the course");
724 // Check if the new modified grouping name already exists in the course.
725 if ($grouping->name != $currentgrouping->name and
726 $DB->count_records('groupings', array('courseid'=>$currentgrouping->courseid, 'name'=>$grouping->name))) {
727 throw new invalid_parameter_exception('A different grouping with the same name already exists in the course');
730 $grouping->courseid = $currentgrouping->courseid;
732 // Now security checks.
733 $context = context_course::instance($grouping->courseid);
734 try {
735 self::validate_context($context);
736 } catch (Exception $e) {
737 $exceptionparam = new stdClass();
738 $exceptionparam->message = $e->getMessage();
739 $exceptionparam->courseid = $grouping->courseid;
740 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
742 require_capability('moodle/course:managegroups', $context);
744 // We must force allways FORMAT_HTML.
745 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
747 // Finally update the grouping.
748 groups_update_grouping($grouping);
751 $transaction->allow_commit();
753 return null;
757 * Returns description of method result value
759 * @return external_description
760 * @since Moodle 2.3
762 public static function update_groupings_returns() {
763 return null;
767 * Returns description of method parameters
769 * @return external_function_parameters
770 * @since Moodle 2.3
772 public static function get_groupings_parameters() {
773 return new external_function_parameters(
774 array(
775 'groupingids' => new external_multiple_structure(new external_value(PARAM_INT, 'grouping ID')
776 , 'List of grouping id. A grouping id is an integer.'),
777 'returngroups' => new external_value(PARAM_BOOL, 'return associated groups', VALUE_DEFAULT, 0)
783 * Get groupings definition specified by ids
785 * @param array $groupingids arrays of grouping ids
786 * @param boolean $returngroups return the associated groups if true. The default is false.
787 * @return array of grouping objects (id, courseid, name)
788 * @since Moodle 2.3
790 public static function get_groupings($groupingids, $returngroups = false) {
791 global $CFG, $DB;
792 require_once("$CFG->dirroot/group/lib.php");
793 require_once("$CFG->libdir/filelib.php");
795 $params = self::validate_parameters(self::get_groupings_parameters(),
796 array('groupingids' => $groupingids,
797 'returngroups' => $returngroups));
799 $groupings = array();
800 foreach ($params['groupingids'] as $groupingid) {
801 // Validate params.
802 $grouping = groups_get_grouping($groupingid, '*', MUST_EXIST);
804 // Now security checks.
805 $context = context_course::instance($grouping->courseid);
806 try {
807 self::validate_context($context);
808 } catch (Exception $e) {
809 $exceptionparam = new stdClass();
810 $exceptionparam->message = $e->getMessage();
811 $exceptionparam->courseid = $grouping->courseid;
812 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
814 require_capability('moodle/course:managegroups', $context);
816 list($grouping->description, $grouping->descriptionformat) =
817 external_format_text($grouping->description, $grouping->descriptionformat,
818 $context->id, 'grouping', 'description', $grouping->id);
820 $groupingarray = (array)$grouping;
822 if ($params['returngroups']) {
823 $grouprecords = $DB->get_records_sql("SELECT * FROM {groups} g INNER JOIN {groupings_groups} gg ".
824 "ON g.id = gg.groupid WHERE gg.groupingid = ? ".
825 "ORDER BY groupid", array($groupingid));
826 if ($grouprecords) {
827 $groups = array();
828 foreach ($grouprecords as $grouprecord) {
829 list($grouprecord->description, $grouprecord->descriptionformat) =
830 external_format_text($grouprecord->description, $grouprecord->descriptionformat,
831 $context->id, 'group', 'description', $grouprecord->groupid);
832 $groups[] = array('id' => $grouprecord->groupid,
833 'name' => $grouprecord->name,
834 'idnumber' => $grouprecord->idnumber,
835 'description' => $grouprecord->description,
836 'descriptionformat' => $grouprecord->descriptionformat,
837 'enrolmentkey' => $grouprecord->enrolmentkey,
838 'courseid' => $grouprecord->courseid
841 $groupingarray['groups'] = $groups;
844 $groupings[] = $groupingarray;
847 return $groupings;
851 * Returns description of method result value
853 * @return external_description
854 * @since Moodle 2.3
856 public static function get_groupings_returns() {
857 return new external_multiple_structure(
858 new external_single_structure(
859 array(
860 'id' => new external_value(PARAM_INT, 'grouping record id'),
861 'courseid' => new external_value(PARAM_INT, 'id of course'),
862 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
863 'description' => new external_value(PARAM_RAW, 'grouping description text'),
864 'descriptionformat' => new external_format_value('description'),
865 'idnumber' => new external_value(PARAM_RAW, 'id number'),
866 'groups' => new external_multiple_structure(
867 new external_single_structure(
868 array(
869 'id' => new external_value(PARAM_INT, 'group record id'),
870 'courseid' => new external_value(PARAM_INT, 'id of course'),
871 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
872 'description' => new external_value(PARAM_RAW, 'group description text'),
873 'descriptionformat' => new external_format_value('description'),
874 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
875 'idnumber' => new external_value(PARAM_RAW, 'id number')
878 'optional groups', VALUE_OPTIONAL)
885 * Returns description of method parameters
887 * @return external_function_parameters
888 * @since Moodle 2.3
890 public static function get_course_groupings_parameters() {
891 return new external_function_parameters(
892 array(
893 'courseid' => new external_value(PARAM_INT, 'id of course'),
899 * Get all groupings in the specified course
901 * @param int $courseid id of course
902 * @return array of grouping objects (id, courseid, name, enrolmentkey)
903 * @since Moodle 2.3
905 public static function get_course_groupings($courseid) {
906 global $CFG;
907 require_once("$CFG->dirroot/group/lib.php");
908 require_once("$CFG->libdir/filelib.php");
910 $params = self::validate_parameters(self::get_course_groupings_parameters(), array('courseid'=>$courseid));
912 // Now security checks.
913 $context = context_course::instance($params['courseid']);
915 try {
916 self::validate_context($context);
917 } catch (Exception $e) {
918 $exceptionparam = new stdClass();
919 $exceptionparam->message = $e->getMessage();
920 $exceptionparam->courseid = $params['courseid'];
921 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
923 require_capability('moodle/course:managegroups', $context);
925 $gs = groups_get_all_groupings($params['courseid']);
927 $groupings = array();
928 foreach ($gs as $grouping) {
929 list($grouping->description, $grouping->descriptionformat) =
930 external_format_text($grouping->description, $grouping->descriptionformat,
931 $context->id, 'grouping', 'description', $grouping->id);
932 $groupings[] = (array)$grouping;
935 return $groupings;
939 * Returns description of method result value
941 * @return external_description
942 * @since Moodle 2.3
944 public static function get_course_groupings_returns() {
945 return new external_multiple_structure(
946 new external_single_structure(
947 array(
948 'id' => new external_value(PARAM_INT, 'grouping record id'),
949 'courseid' => new external_value(PARAM_INT, 'id of course'),
950 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
951 'description' => new external_value(PARAM_RAW, 'grouping description text'),
952 'descriptionformat' => new external_format_value('description'),
953 'idnumber' => new external_value(PARAM_RAW, 'id number')
960 * Returns description of method parameters
962 * @return external_function_parameters
963 * @since Moodle 2.3
965 public static function delete_groupings_parameters() {
966 return new external_function_parameters(
967 array(
968 'groupingids' => new external_multiple_structure(new external_value(PARAM_INT, 'grouping ID')),
974 * Delete groupings
976 * @param array $groupingids array of grouping ids
977 * @return void
978 * @since Moodle 2.3
980 public static function delete_groupings($groupingids) {
981 global $CFG, $DB;
982 require_once("$CFG->dirroot/group/lib.php");
984 $params = self::validate_parameters(self::delete_groupings_parameters(), array('groupingids'=>$groupingids));
986 $transaction = $DB->start_delegated_transaction();
988 foreach ($params['groupingids'] as $groupingid) {
990 if (!$grouping = groups_get_grouping($groupingid)) {
991 // Silently ignore attempts to delete nonexisting groupings.
992 continue;
995 // Now security checks.
996 $context = context_course::instance($grouping->courseid);
997 try {
998 self::validate_context($context);
999 } catch (Exception $e) {
1000 $exceptionparam = new stdClass();
1001 $exceptionparam->message = $e->getMessage();
1002 $exceptionparam->courseid = $grouping->courseid;
1003 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1005 require_capability('moodle/course:managegroups', $context);
1007 groups_delete_grouping($grouping);
1010 $transaction->allow_commit();
1014 * Returns description of method result value
1016 * @return external_description
1017 * @since Moodle 2.3
1019 public static function delete_groupings_returns() {
1020 return null;
1024 * Returns description of method parameters
1026 * @return external_function_parameters
1027 * @since Moodle 2.3
1029 public static function assign_grouping_parameters() {
1030 return new external_function_parameters(
1031 array(
1032 'assignments'=> new external_multiple_structure(
1033 new external_single_structure(
1034 array(
1035 'groupingid' => new external_value(PARAM_INT, 'grouping record id'),
1036 'groupid' => new external_value(PARAM_INT, 'group record id'),
1045 * Assign a group to a grouping
1047 * @param array $assignments of arrays with keys groupid, groupingid
1048 * @return void
1049 * @since Moodle 2.3
1051 public static function assign_grouping($assignments) {
1052 global $CFG, $DB;
1053 require_once("$CFG->dirroot/group/lib.php");
1055 $params = self::validate_parameters(self::assign_grouping_parameters(), array('assignments'=>$assignments));
1057 $transaction = $DB->start_delegated_transaction();
1058 foreach ($params['assignments'] as $assignment) {
1059 // Validate params.
1060 $groupingid = $assignment['groupingid'];
1061 $groupid = $assignment['groupid'];
1063 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1064 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1066 if ($DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) {
1067 // Continue silently if the group is yet assigned to the grouping.
1068 continue;
1071 // Now security checks.
1072 $context = context_course::instance($grouping->courseid);
1073 try {
1074 self::validate_context($context);
1075 } catch (Exception $e) {
1076 $exceptionparam = new stdClass();
1077 $exceptionparam->message = $e->getMessage();
1078 $exceptionparam->courseid = $group->courseid;
1079 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1081 require_capability('moodle/course:managegroups', $context);
1083 groups_assign_grouping($groupingid, $groupid);
1086 $transaction->allow_commit();
1090 * Returns description of method result value
1092 * @return null
1093 * @since Moodle 2.3
1095 public static function assign_grouping_returns() {
1096 return null;
1100 * Returns description of method parameters
1102 * @return external_function_parameters
1103 * @since Moodle 2.3
1105 public static function unassign_grouping_parameters() {
1106 return new external_function_parameters(
1107 array(
1108 'unassignments'=> new external_multiple_structure(
1109 new external_single_structure(
1110 array(
1111 'groupingid' => new external_value(PARAM_INT, 'grouping record id'),
1112 'groupid' => new external_value(PARAM_INT, 'group record id'),
1121 * Unassign a group from a grouping
1123 * @param array $unassignments of arrays with keys groupid, groupingid
1124 * @return void
1125 * @since Moodle 2.3
1127 public static function unassign_grouping($unassignments) {
1128 global $CFG, $DB;
1129 require_once("$CFG->dirroot/group/lib.php");
1131 $params = self::validate_parameters(self::unassign_grouping_parameters(), array('unassignments'=>$unassignments));
1133 $transaction = $DB->start_delegated_transaction();
1134 foreach ($params['unassignments'] as $unassignment) {
1135 // Validate params.
1136 $groupingid = $unassignment['groupingid'];
1137 $groupid = $unassignment['groupid'];
1139 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1140 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1142 if (!$DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) {
1143 // Continue silently if the group is not assigned to the grouping.
1144 continue;
1147 // Now security checks.
1148 $context = context_course::instance($grouping->courseid);
1149 try {
1150 self::validate_context($context);
1151 } catch (Exception $e) {
1152 $exceptionparam = new stdClass();
1153 $exceptionparam->message = $e->getMessage();
1154 $exceptionparam->courseid = $group->courseid;
1155 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
1157 require_capability('moodle/course:managegroups', $context);
1159 groups_unassign_grouping($groupingid, $groupid);
1162 $transaction->allow_commit();
1166 * Returns description of method result value
1168 * @return null
1169 * @since Moodle 2.3
1171 public static function unassign_grouping_returns() {
1172 return null;
1176 * Returns description of method parameters
1178 * @return external_function_parameters
1179 * @since Moodle 2.9
1181 public static function get_course_user_groups_parameters() {
1182 return new external_function_parameters(
1183 array(
1184 'courseid' => new external_value(PARAM_INT,
1185 'Id of course (empty or 0 for all the courses where the user is enrolled).', VALUE_DEFAULT, 0),
1186 'userid' => new external_value(PARAM_INT, 'Id of user (empty or 0 for current user).', VALUE_DEFAULT, 0),
1187 'groupingid' => new external_value(PARAM_INT, 'returns only groups in the specified grouping', VALUE_DEFAULT, 0)
1193 * Get all groups in the specified course for the specified user.
1195 * @throws moodle_exception
1196 * @param int $courseid id of course.
1197 * @param int $userid id of user.
1198 * @param int $groupingid optional returns only groups in the specified grouping.
1199 * @return array of group objects (id, name, description, format) and possible warnings.
1200 * @since Moodle 2.9
1202 public static function get_course_user_groups($courseid = 0, $userid = 0, $groupingid = 0) {
1203 global $USER;
1205 // Warnings array, it can be empty at the end but is mandatory.
1206 $warnings = array();
1208 $params = array(
1209 'courseid' => $courseid,
1210 'userid' => $userid,
1211 'groupingid' => $groupingid
1213 $params = self::validate_parameters(self::get_course_user_groups_parameters(), $params);
1215 $courseid = $params['courseid'];
1216 $userid = $params['userid'];
1217 $groupingid = $params['groupingid'];
1219 // Validate user.
1220 if (empty($userid)) {
1221 $userid = $USER->id;
1222 } else {
1223 $user = core_user::get_user($userid, '*', MUST_EXIST);
1224 core_user::require_active_user($user);
1227 // Get courses.
1228 if (empty($courseid)) {
1229 $courses = enrol_get_users_courses($userid, true);
1230 $checkenrolments = false; // No need to check enrolments here since they are my courses.
1231 } else {
1232 $courses = array($courseid => get_course($courseid));
1233 $checkenrolments = true;
1236 // Security checks.
1237 list($courses, $warnings) = external_util::validate_courses(array_keys($courses), $courses, true);
1239 $usergroups = array();
1240 foreach ($courses as $course) {
1241 // Check if we have permissions for retrieve the information.
1242 if ($userid != $USER->id && !has_capability('moodle/course:managegroups', $course->context)) {
1243 $warnings[] = array(
1244 'item' => 'course',
1245 'itemid' => $course->id,
1246 'warningcode' => 'cannotmanagegroups',
1247 'message' => "User $USER->id cannot manage groups in course $course->id",
1249 continue;
1252 // Check if the user being check is enrolled in the given course.
1253 if ($checkenrolments && !is_enrolled($course->context, $userid)) {
1254 // We return a warning because the function does not fail for not enrolled users.
1255 $warnings[] = array(
1256 'item' => 'course',
1257 'itemid' => $course->id,
1258 'warningcode' => 'notenrolled',
1259 'message' => "User $userid is not enrolled in course $course->id",
1263 $groups = groups_get_all_groups($course->id, $userid, $groupingid,
1264 'g.id, g.name, g.description, g.descriptionformat, g.idnumber');
1266 foreach ($groups as $group) {
1267 list($group->description, $group->descriptionformat) =
1268 external_format_text($group->description, $group->descriptionformat,
1269 $course->context->id, 'group', 'description', $group->id);
1270 $group->courseid = $course->id;
1271 $usergroups[] = $group;
1275 $results = array(
1276 'groups' => $usergroups,
1277 'warnings' => $warnings
1279 return $results;
1283 * Returns description of method result value.
1285 * @return external_description A single structure containing groups and possible warnings.
1286 * @since Moodle 2.9
1288 public static function get_course_user_groups_returns() {
1289 return new external_single_structure(
1290 array(
1291 'groups' => new external_multiple_structure(self::group_description()),
1292 'warnings' => new external_warnings(),
1298 * Create group return value description.
1300 * @return external_single_structure The group description
1302 public static function group_description() {
1303 return new external_single_structure(
1304 array(
1305 'id' => new external_value(PARAM_INT, 'group record id'),
1306 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
1307 'description' => new external_value(PARAM_RAW, 'group description text'),
1308 'descriptionformat' => new external_format_value('description'),
1309 'idnumber' => new external_value(PARAM_RAW, 'id number'),
1310 'courseid' => new external_value(PARAM_INT, 'course id', VALUE_OPTIONAL),
1316 * Returns description of method parameters
1318 * @return external_function_parameters
1319 * @since Moodle 3.0
1321 public static function get_activity_allowed_groups_parameters() {
1322 return new external_function_parameters(
1323 array(
1324 'cmid' => new external_value(PARAM_INT, 'course module id'),
1325 'userid' => new external_value(PARAM_INT, 'id of user, empty for current user', VALUE_DEFAULT, 0)
1331 * Gets a list of groups that the user is allowed to access within the specified activity.
1333 * @throws moodle_exception
1334 * @param int $cmid course module id
1335 * @param int $userid id of user.
1336 * @return array of group objects (id, name, description, format) and possible warnings.
1337 * @since Moodle 3.0
1339 public static function get_activity_allowed_groups($cmid, $userid = 0) {
1340 global $USER;
1342 // Warnings array, it can be empty at the end but is mandatory.
1343 $warnings = array();
1345 $params = array(
1346 'cmid' => $cmid,
1347 'userid' => $userid
1349 $params = self::validate_parameters(self::get_activity_allowed_groups_parameters(), $params);
1350 $cmid = $params['cmid'];
1351 $userid = $params['userid'];
1353 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1355 // Security checks.
1356 $context = context_module::instance($cm->id);
1357 $coursecontext = context_course::instance($cm->course);
1358 self::validate_context($context);
1360 if (empty($userid)) {
1361 $userid = $USER->id;
1364 $user = core_user::get_user($userid, '*', MUST_EXIST);
1365 core_user::require_active_user($user);
1367 // Check if we have permissions for retrieve the information.
1368 if ($user->id != $USER->id) {
1369 if (!has_capability('moodle/course:managegroups', $context)) {
1370 throw new moodle_exception('accessdenied', 'admin');
1373 // Validate if the user is enrolled in the course.
1374 $course = get_course($cm->course);
1375 if (!can_access_course($course, $user, '', true)) {
1376 // We return a warning because the function does not fail for not enrolled users.
1377 $warning = array();
1378 $warning['item'] = 'course';
1379 $warning['itemid'] = $cm->course;
1380 $warning['warningcode'] = '1';
1381 $warning['message'] = "User $user->id cannot access course $cm->course";
1382 $warnings[] = $warning;
1386 $usergroups = array();
1387 if (empty($warnings)) {
1388 $groups = groups_get_activity_allowed_groups($cm, $user->id);
1390 foreach ($groups as $group) {
1391 list($group->description, $group->descriptionformat) =
1392 external_format_text($group->description, $group->descriptionformat,
1393 $coursecontext->id, 'group', 'description', $group->id);
1394 $group->courseid = $cm->course;
1395 $usergroups[] = $group;
1399 $results = array(
1400 'groups' => $usergroups,
1401 'canaccessallgroups' => has_capability('moodle/site:accessallgroups', $context, $user),
1402 'warnings' => $warnings
1404 return $results;
1408 * Returns description of method result value.
1410 * @return external_description A single structure containing groups and possible warnings.
1411 * @since Moodle 3.0
1413 public static function get_activity_allowed_groups_returns() {
1414 return new external_single_structure(
1415 array(
1416 'groups' => new external_multiple_structure(self::group_description()),
1417 'canaccessallgroups' => new external_value(PARAM_BOOL,
1418 'Whether the user will be able to access all the activity groups.', VALUE_OPTIONAL),
1419 'warnings' => new external_warnings(),
1425 * Returns description of method parameters
1427 * @return external_function_parameters
1428 * @since Moodle 3.0
1430 public static function get_activity_groupmode_parameters() {
1431 return new external_function_parameters(
1432 array(
1433 'cmid' => new external_value(PARAM_INT, 'course module id')
1439 * Returns effective groupmode used in a given activity.
1441 * @throws moodle_exception
1442 * @param int $cmid course module id.
1443 * @return array containing the group mode and possible warnings.
1444 * @since Moodle 3.0
1445 * @throws moodle_exception
1447 public static function get_activity_groupmode($cmid) {
1448 global $USER;
1450 // Warnings array, it can be empty at the end but is mandatory.
1451 $warnings = array();
1453 $params = array(
1454 'cmid' => $cmid
1456 $params = self::validate_parameters(self::get_activity_groupmode_parameters(), $params);
1457 $cmid = $params['cmid'];
1459 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1461 // Security checks.
1462 $context = context_module::instance($cm->id);
1463 self::validate_context($context);
1465 $groupmode = groups_get_activity_groupmode($cm);
1467 $results = array(
1468 'groupmode' => $groupmode,
1469 'warnings' => $warnings
1471 return $results;
1475 * Returns description of method result value.
1477 * @return external_description
1478 * @since Moodle 3.0
1480 public static function get_activity_groupmode_returns() {
1481 return new external_single_structure(
1482 array(
1483 'groupmode' => new external_value(PARAM_INT, 'group mode:
1484 0 for no groups, 1 for separate groups, 2 for visible groups'),
1485 'warnings' => new external_warnings(),
1491 * Returns description of method parameters
1493 * @return external_function_parameters
1494 * @since Moodle 3.6
1496 public static function update_groups_parameters() {
1497 return new external_function_parameters(
1498 array(
1499 'groups' => new external_multiple_structure(
1500 new external_single_structure(
1501 array(
1502 'id' => new external_value(PARAM_INT, 'ID of the group'),
1503 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
1504 'description' => new external_value(PARAM_RAW, 'group description text', VALUE_OPTIONAL),
1505 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
1506 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase', VALUE_OPTIONAL),
1507 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
1509 ), 'List of group objects. A group is found by the id, then all other details provided will be updated.'
1516 * Update groups
1518 * @param array $groups
1519 * @return null
1520 * @since Moodle 3.6
1522 public static function update_groups($groups) {
1523 global $CFG, $DB;
1524 require_once("$CFG->dirroot/group/lib.php");
1526 $params = self::validate_parameters(self::update_groups_parameters(), array('groups' => $groups));
1528 $transaction = $DB->start_delegated_transaction();
1530 foreach ($params['groups'] as $group) {
1531 $group = (object)$group;
1533 if (trim($group->name) == '') {
1534 throw new invalid_parameter_exception('Invalid group name');
1537 if (! $currentgroup = $DB->get_record('groups', array('id' => $group->id))) {
1538 throw new invalid_parameter_exception("Group $group->id does not exist");
1541 // Check if the modified group name already exists in the course.
1542 if ($group->name != $currentgroup->name and
1543 $DB->get_record('groups', array('courseid' => $currentgroup->courseid, 'name' => $group->name))) {
1544 throw new invalid_parameter_exception('A different group with the same name already exists in the course');
1547 $group->courseid = $currentgroup->courseid;
1549 // Now security checks.
1550 $context = context_course::instance($group->courseid);
1551 try {
1552 self::validate_context($context);
1553 } catch (Exception $e) {
1554 $exceptionparam = new stdClass();
1555 $exceptionparam->message = $e->getMessage();
1556 $exceptionparam->courseid = $group->courseid;
1557 throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam);
1559 require_capability('moodle/course:managegroups', $context);
1561 if (!empty($group->description)) {
1562 $group->descriptionformat = external_validate_format($group->descriptionformat);
1565 groups_update_group($group);
1568 $transaction->allow_commit();
1570 return null;
1574 * Returns description of method result value
1576 * @return null
1577 * @since Moodle 3.6
1579 public static function update_groups_returns() {
1580 return null;