weekly release 3.10.1+
[moodle.git] / group / externallib.php
CommitLineData
9a0df45a 1<?php
9a0df45a 2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
4615817d 17
9a0df45a 18/**
19 * External groups API
20 *
4d8e2417 21 * @package core_group
4615817d
JM
22 * @category external
23 * @copyright 2009 Petr Skodak
9a0df45a 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
e71687ba
JL
27defined('MOODLE_INTERNAL') || die();
28
9a0df45a 29require_once("$CFG->libdir/externallib.php");
30
5d1017e1 31/**
4615817d 32 * Group external functions
4d8e2417
AG
33 *
34 * @package core_group
4615817d
JM
35 * @category external
36 * @copyright 2011 Jerome Mouneyrac
4d8e2417 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4615817d 38 * @since Moodle 2.2
5d1017e1
JM
39 */
40class core_group_external extends external_api {
9a0df45a 41
0c96468c 42 /**
43 * Returns description of method parameters
4615817d 44 *
f5072177 45 * @return external_function_parameters
4615817d 46 * @since Moodle 2.2
0c96468c 47 */
48 public static function create_groups_parameters() {
f5072177 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'),
93ce0e82 57 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
32435a69 58 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase', VALUE_OPTIONAL),
ed0fd1f6 59 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
f5072177 60 )
d4c6ef70 61 ), 'List of group object. A group has a courseid, a name, a description and an enrolment key.'
f5072177 62 )
63 )
64 );
0c96468c 65 }
66
67 /**
9a0df45a 68 * Create groups
4615817d 69 *
b4c1a34e 70 * @param array $groups array of group description arrays (with keys groupname and courseid)
f5072177 71 * @return array of newly created groups
4615817d 72 * @since Moodle 2.2
9a0df45a 73 */
b4c1a34e 74 public static function create_groups($groups) {
f5072177 75 global $CFG, $DB;
9a0df45a 76 require_once("$CFG->dirroot/group/lib.php");
77
c9c5cc81 78 $params = self::validate_parameters(self::create_groups_parameters(), array('groups'=>$groups));
0c96468c 79
d5a8d9aa
PS
80 $transaction = $DB->start_delegated_transaction();
81
82 $groups = array();
83
84 foreach ($params['groups'] as $group) {
85 $group = (object)$group;
86
87 if (trim($group->name) == '') {
88 throw new invalid_parameter_exception('Invalid group name');
89 }
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');
ab9a01f2 92 }
d5a8d9aa
PS
93
94 // now security checks
0d4d49d1 95 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 102 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 103 }
d5a8d9aa
PS
104 require_capability('moodle/course:managegroups', $context);
105
93ce0e82
JM
106 // Validate format.
107 $group->descriptionformat = external_validate_format($group->descriptionformat);
108
d5a8d9aa
PS
109 // finally create the group
110 $group->id = groups_create_group($group, false);
e5f0e519
SH
111 if (!isset($group->enrolmentkey)) {
112 $group->enrolmentkey = '';
113 }
ed0fd1f6
DM
114 if (!isset($group->idnumber)) {
115 $group->idnumber = '';
116 }
117
d5a8d9aa 118 $groups[] = (array)$group;
9a0df45a 119 }
d5a8d9aa
PS
120
121 $transaction->allow_commit();
9a0df45a 122
2e13b916 123 return $groups;
9a0df45a 124 }
125
4d8e2417 126 /**
0c96468c 127 * Returns description of method result value
4615817d
JM
128 *
129 * @return external_description
130 * @since Moodle 2.2
0c96468c 131 */
132 public static function create_groups_returns() {
f5072177 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'),
93ce0e82 140 'descriptionformat' => new external_format_value('description'),
f5072177 141 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
ed0fd1f6 142 'idnumber' => new external_value(PARAM_RAW, 'id number')
f5072177 143 )
d4c6ef70 144 ), 'List of group object. A group has an id, a courseid, a name, a description and an enrolment key.'
f5072177 145 );
0c96468c 146 }
147
f5072177 148 /**
149 * Returns description of method parameters
4615817d 150 *
f5072177 151 * @return external_function_parameters
4615817d 152 * @since Moodle 2.2
f5072177 153 */
0c96468c 154 public static function get_groups_parameters() {
8c772ad7 155 return new external_function_parameters(
156 array(
d4c6ef70 157 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')
158 ,'List of group id. A group id is an integer.'),
8c772ad7 159 )
160 );
0c96468c 161 }
162
9a0df45a 163 /**
246f6da2 164 * Get groups definition specified by ids
4615817d 165 *
b4c1a34e 166 * @param array $groupids arrays of group ids
9a0df45a 167 * @return array of group objects (id, courseid, name, enrolmentkey)
4615817d 168 * @since Moodle 2.2
9a0df45a 169 */
b4c1a34e 170 public static function get_groups($groupids) {
c9c5cc81 171 $params = self::validate_parameters(self::get_groups_parameters(), array('groupids'=>$groupids));
0c96468c 172
246f6da2 173 $groups = array();
0c96468c 174 foreach ($params['groupids'] as $groupid) {
ab9a01f2 175 // validate params
ed0fd1f6 176 $group = groups_get_group($groupid, 'id, courseid, name, idnumber, description, descriptionformat, enrolmentkey', MUST_EXIST);
ab9a01f2 177
9a0df45a 178 // now security checks
0d4d49d1 179 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 186 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 187 }
9a0df45a 188 require_capability('moodle/course:managegroups', $context);
189
93ce0e82
JM
190 list($group->description, $group->descriptionformat) =
191 external_format_text($group->description, $group->descriptionformat,
192 $context->id, 'group', 'description', $group->id);
193
2e13b916 194 $groups[] = (array)$group;
9a0df45a 195 }
196
197 return $groups;
198 }
199
4d8e2417 200 /**
f5072177 201 * Returns description of method result value
4615817d
JM
202 *
203 * @return external_description
204 * @since Moodle 2.2
f5072177 205 */
0c96468c 206 public static function get_groups_returns() {
246f6da2 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'),
93ce0e82 214 'descriptionformat' => new external_format_value('description'),
246f6da2 215 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
ed0fd1f6 216 'idnumber' => new external_value(PARAM_RAW, 'id number')
246f6da2 217 )
218 )
219 );
220 }
221
222 /**
223 * Returns description of method parameters
4615817d 224 *
246f6da2 225 * @return external_function_parameters
4615817d 226 * @since Moodle 2.2
246f6da2 227 */
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'),
232 )
233 );
234 }
235
236 /**
237 * Get all groups in the specified course
4615817d 238 *
246f6da2 239 * @param int $courseid id of course
240 * @return array of group objects (id, courseid, name, enrolmentkey)
4615817d 241 * @since Moodle 2.2
246f6da2 242 */
243 public static function get_course_groups($courseid) {
244 $params = self::validate_parameters(self::get_course_groups_parameters(), array('courseid'=>$courseid));
245
246 // now security checks
0d4d49d1 247 $context = context_course::instance($params['courseid'], IGNORE_MISSING);
41e962ff 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'];
96d3b93b 254 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 255 }
246f6da2 256 require_capability('moodle/course:managegroups', $context);
257
93ce0e82 258 $gs = groups_get_all_groups($params['courseid'], 0, 0,
ed0fd1f6 259 'g.id, g.courseid, g.name, g.idnumber, g.description, g.descriptionformat, g.enrolmentkey');
246f6da2 260
261 $groups = array();
262 foreach ($gs as $group) {
93ce0e82
JM
263 list($group->description, $group->descriptionformat) =
264 external_format_text($group->description, $group->descriptionformat,
265 $context->id, 'group', 'description', $group->id);
246f6da2 266 $groups[] = (array)$group;
267 }
268
269 return $groups;
270 }
271
4d8e2417 272 /**
246f6da2 273 * Returns description of method result value
4615817d
JM
274 *
275 * @return external_description
276 * @since Moodle 2.2
246f6da2 277 */
278 public static function get_course_groups_returns() {
8c772ad7 279 return new external_multiple_structure(
280 new external_single_structure(
281 array(
f5072177 282 'id' => new external_value(PARAM_INT, 'group record id'),
283 'courseid' => new external_value(PARAM_INT, 'id of course'),
04d212ce 284 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
f5072177 285 'description' => new external_value(PARAM_RAW, 'group description text'),
93ce0e82 286 'descriptionformat' => new external_format_value('description'),
f5072177 287 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
ed0fd1f6 288 'idnumber' => new external_value(PARAM_RAW, 'id number')
8c772ad7 289 )
290 )
291 );
0c96468c 292 }
293
0f4e72de
PS
294 /**
295 * Returns description of method parameters
4615817d 296 *
0f4e72de 297 * @return external_function_parameters
4615817d 298 * @since Moodle 2.2
0f4e72de 299 */
0c96468c 300 public static function delete_groups_parameters() {
0f4e72de
PS
301 return new external_function_parameters(
302 array(
303 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
304 )
305 );
0c96468c 306 }
307
9a0df45a 308 /**
309 * Delete groups
4615817d 310 *
b4c1a34e 311 * @param array $groupids array of group ids
4615817d 312 * @since Moodle 2.2
9a0df45a 313 */
b4c1a34e 314 public static function delete_groups($groupids) {
2cb1ee78 315 global $CFG, $DB;
9a0df45a 316 require_once("$CFG->dirroot/group/lib.php");
317
c9c5cc81 318 $params = self::validate_parameters(self::delete_groups_parameters(), array('groupids'=>$groupids));
0c96468c 319
d5a8d9aa
PS
320 $transaction = $DB->start_delegated_transaction();
321
d5a8d9aa
PS
322 foreach ($params['groupids'] as $groupid) {
323 // validate params
1e12c120 324 $groupid = validate_param($groupid, PARAM_INT);
cd5be9a5 325 if (!$group = groups_get_group($groupid, '*', IGNORE_MISSING)) {
d5a8d9aa
PS
326 // silently ignore attempts to delete nonexisting groups
327 continue;
0f4e72de 328 }
d5a8d9aa
PS
329
330 // now security checks
0d4d49d1 331 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 338 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 339 }
d5a8d9aa
PS
340 require_capability('moodle/course:managegroups', $context);
341
342 groups_delete_group($group);
9a0df45a 343 }
d5a8d9aa
PS
344
345 $transaction->allow_commit();
9a0df45a 346 }
347
4d8e2417 348 /**
0f4e72de 349 * Returns description of method result value
4615817d
JM
350 *
351 * @return null
352 * @since Moodle 2.2
0f4e72de 353 */
0c96468c 354 public static function delete_groups_returns() {
0f4e72de 355 return null;
0c96468c 356 }
357
358
0f4e72de
PS
359 /**
360 * Returns description of method parameters
4615817d 361 *
0f4e72de 362 * @return external_function_parameters
4615817d 363 * @since Moodle 2.2
0f4e72de 364 */
5d1017e1 365 public static function get_group_members_parameters() {
0f4e72de
PS
366 return new external_function_parameters(
367 array(
368 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
369 )
370 );
0c96468c 371 }
9a0df45a 372
373 /**
374 * Return all members for a group
4615817d 375 *
b4c1a34e 376 * @param array $groupids array of group ids
9a0df45a 377 * @return array with group id keys containing arrays of user ids
4615817d 378 * @since Moodle 2.2
9a0df45a 379 */
5d1017e1 380 public static function get_group_members($groupids) {
0f4e72de 381 $members = array();
9a0df45a 382
5d1017e1 383 $params = self::validate_parameters(self::get_group_members_parameters(), array('groupids'=>$groupids));
0c96468c 384
385 foreach ($params['groupids'] as $groupid) {
ab9a01f2 386 // validate params
9a0df45a 387 $group = groups_get_group($groupid, 'id, courseid, name, enrolmentkey', MUST_EXIST);
388 // now security checks
0d4d49d1 389 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 396 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 397 }
9a0df45a 398 require_capability('moodle/course:managegroups', $context);
399
400 $groupmembers = groups_get_members($group->id, 'u.id', 'lastname ASC, firstname ASC');
401
0f4e72de 402 $members[] = array('groupid'=>$groupid, 'userids'=>array_keys($groupmembers));
9a0df45a 403 }
404
0f4e72de 405 return $members;
9a0df45a 406 }
407
4d8e2417 408 /**
0f4e72de 409 * Returns description of method result value
4615817d 410 *
0f4e72de 411 * @return external_description
4615817d 412 * @since Moodle 2.2
0f4e72de 413 */
5d1017e1 414 public static function get_group_members_returns() {
0f4e72de
PS
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')),
420 )
421 )
422 );
0c96468c 423 }
424
425
0f4e72de
PS
426 /**
427 * Returns description of method parameters
4615817d 428 *
0f4e72de 429 * @return external_function_parameters
4615817d 430 * @since Moodle 2.2
0f4e72de 431 */
5d1017e1 432 public static function add_group_members_parameters() {
4efa2483
PS
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'),
440 )
441 )
0f4e72de
PS
442 )
443 )
444 );
0c96468c 445 }
9a0df45a 446
447 /**
448 * Add group members
4615817d 449 *
b4c1a34e 450 * @param array $members of arrays with keys userid, groupid
4615817d 451 * @since Moodle 2.2
9a0df45a 452 */
5d1017e1 453 public static function add_group_members($members) {
2cb1ee78 454 global $CFG, $DB;
9a0df45a 455 require_once("$CFG->dirroot/group/lib.php");
456
5d1017e1 457 $params = self::validate_parameters(self::add_group_members_parameters(), array('members'=>$members));
9a0df45a 458
d5a8d9aa 459 $transaction = $DB->start_delegated_transaction();
d5a8d9aa
PS
460 foreach ($params['members'] as $member) {
461 // validate params
462 $groupid = $member['groupid'];
463 $userid = $member['userid'];
0c96468c 464
301783d9 465 $group = groups_get_group($groupid, '*', MUST_EXIST);
d5a8d9aa 466 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
9a0df45a 467
d5a8d9aa 468 // now security checks
0d4d49d1 469 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 476 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 477 }
d5a8d9aa 478 require_capability('moodle/course:managegroups', $context);
9a0df45a 479
d5a8d9aa 480 // now make sure user is enrolled in course - this is mandatory requirement,
4f0c2d00
PS
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');
484 }
4efa2483 485
d5a8d9aa 486 groups_add_member($group, $user);
9a0df45a 487 }
d5a8d9aa
PS
488
489 $transaction->allow_commit();
9a0df45a 490 }
491
4d8e2417 492 /**
0f4e72de 493 * Returns description of method result value
4615817d 494 *
5d1017e1 495 * @return null
4615817d 496 * @since Moodle 2.2
0f4e72de 497 */
5d1017e1 498 public static function add_group_members_returns() {
0f4e72de 499 return null;
0c96468c 500 }
501
502
0f4e72de
PS
503 /**
504 * Returns description of method parameters
4615817d 505 *
0f4e72de 506 * @return external_function_parameters
4615817d 507 * @since Moodle 2.2
0f4e72de 508 */
5d1017e1 509 public static function delete_group_members_parameters() {
4efa2483
PS
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'),
517 )
518 )
0f4e72de
PS
519 )
520 )
521 );
0c96468c 522 }
9a0df45a 523
524 /**
525 * Delete group members
4615817d 526 *
b4c1a34e 527 * @param array $members of arrays with keys userid, groupid
4615817d 528 * @since Moodle 2.2
9a0df45a 529 */
5d1017e1 530 public static function delete_group_members($members) {
2cb1ee78 531 global $CFG, $DB;
9a0df45a 532 require_once("$CFG->dirroot/group/lib.php");
533
5d1017e1 534 $params = self::validate_parameters(self::delete_group_members_parameters(), array('members'=>$members));
9a0df45a 535
d5a8d9aa
PS
536 $transaction = $DB->start_delegated_transaction();
537
0c96468c 538 foreach ($params['members'] as $member) {
d5a8d9aa
PS
539 // validate params
540 $groupid = $member['groupid'];
541 $userid = $member['userid'];
0c96468c 542
301783d9 543 $group = groups_get_group($groupid, '*', MUST_EXIST);
d5a8d9aa 544 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
9a0df45a 545
d5a8d9aa 546 // now security checks
0d4d49d1 547 $context = context_course::instance($group->courseid, IGNORE_MISSING);
41e962ff 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;
96d3b93b 554 throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam);
41e962ff 555 }
d5a8d9aa 556 require_capability('moodle/course:managegroups', $context);
9a0df45a 557
1d1917ae 558 if (!groups_remove_member_allowed($group, $user)) {
6e8ed1a8
PH
559 $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
560 throw new moodle_exception('errorremovenotpermitted', 'group', '', $fullname);
1d1917ae 561 }
d5a8d9aa 562 groups_remove_member($group, $user);
9a0df45a 563 }
d5a8d9aa
PS
564
565 $transaction->allow_commit();
9a0df45a 566 }
567
4d8e2417 568 /**
0f4e72de 569 * Returns description of method result value
4615817d 570 *
5d1017e1 571 * @return null
4615817d 572 * @since Moodle 2.2
0f4e72de 573 */
5d1017e1 574 public static function delete_group_members_returns() {
0f4e72de 575 return null;
0c96468c 576 }
577
882bac85
JL
578 /**
579 * Returns description of method parameters
67aa60f9 580 *
882bac85 581 * @return external_function_parameters
67aa60f9 582 * @since Moodle 2.3
882bac85
JL
583 */
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'),
93ce0e82 592 'description' => new external_value(PARAM_RAW, 'grouping description text'),
ed0fd1f6
DM
593 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
594 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
882bac85
JL
595 )
596 ), 'List of grouping object. A grouping has a courseid, a name and a description.'
597 )
598 )
599 );
600 }
601
602 /**
603 * Create groupings
2c8ad38e 604 *
882bac85
JL
605 * @param array $groupings array of grouping description arrays (with keys groupname and courseid)
606 * @return array of newly created groupings
67aa60f9 607 * @since Moodle 2.3
882bac85
JL
608 */
609 public static function create_groupings($groupings) {
610 global $CFG, $DB;
611 require_once("$CFG->dirroot/group/lib.php");
612
613 $params = self::validate_parameters(self::create_groupings_parameters(), array('groupings'=>$groupings));
614
615 $transaction = $DB->start_delegated_transaction();
616
617 $groupings = array();
618
619 foreach ($params['groupings'] as $grouping) {
620 $grouping = (object)$grouping;
621
622 if (trim($grouping->name) == '') {
623 throw new invalid_parameter_exception('Invalid grouping name');
624 }
67aa60f9 625 if ($DB->count_records('groupings', array('courseid'=>$grouping->courseid, 'name'=>$grouping->name))) {
882bac85
JL
626 throw new invalid_parameter_exception('Grouping with the same name already exists in the course');
627 }
628
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);
638 }
639 require_capability('moodle/course:managegroups', $context);
640
93ce0e82 641 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
882bac85
JL
642
643 // Finally create the grouping.
644 $grouping->id = groups_create_grouping($grouping);
645 $groupings[] = (array)$grouping;
646 }
647
648 $transaction->allow_commit();
649
650 return $groupings;
651 }
652
653 /**
654 * Returns description of method result value
67aa60f9 655 *
882bac85 656 * @return external_description
67aa60f9 657 * @since Moodle 2.3
882bac85
JL
658 */
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'),
93ce0e82 666 'description' => new external_value(PARAM_RAW, 'grouping description text'),
ed0fd1f6
DM
667 'descriptionformat' => new external_format_value('description'),
668 'idnumber' => new external_value(PARAM_RAW, 'id number')
882bac85
JL
669 )
670 ), 'List of grouping object. A grouping has an id, a courseid, a name and a description.'
671 );
672 }
673
87e959f3
JL
674 /**
675 * Returns description of method parameters
67aa60f9 676 *
87e959f3 677 * @return external_function_parameters
67aa60f9 678 * @since Moodle 2.3
87e959f3
JL
679 */
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'),
93ce0e82 688 'description' => new external_value(PARAM_RAW, 'grouping description text'),
ed0fd1f6
DM
689 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
690 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL)
87e959f3
JL
691 )
692 ), 'List of grouping object. A grouping has a courseid, a name and a description.'
693 )
694 )
695 );
696 }
697
698 /**
699 * Update groupings
67aa60f9 700 *
87e959f3
JL
701 * @param array $groupings array of grouping description arrays (with keys groupname and courseid)
702 * @return array of newly updated groupings
67aa60f9 703 * @since Moodle 2.3
87e959f3
JL
704 */
705 public static function update_groupings($groupings) {
706 global $CFG, $DB;
707 require_once("$CFG->dirroot/group/lib.php");
708
709 $params = self::validate_parameters(self::update_groupings_parameters(), array('groupings'=>$groupings));
710
711 $transaction = $DB->start_delegated_transaction();
712
87e959f3
JL
713 foreach ($params['groupings'] as $grouping) {
714 $grouping = (object)$grouping;
715
716 if (trim($grouping->name) == '') {
717 throw new invalid_parameter_exception('Invalid grouping name');
718 }
719
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");
722 }
2c8ad38e
JL
723
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');
728 }
729
87e959f3
JL
730 $grouping->courseid = $currentgrouping->courseid;
731
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);
741 }
742 require_capability('moodle/course:managegroups', $context);
743
744 // We must force allways FORMAT_HTML.
93ce0e82 745 $grouping->descriptionformat = external_validate_format($grouping->descriptionformat);
87e959f3
JL
746
747 // Finally update the grouping.
748 groups_update_grouping($grouping);
87e959f3
JL
749 }
750
751 $transaction->allow_commit();
752
67aa60f9 753 return null;
87e959f3
JL
754 }
755
67aa60f9 756 /**
87e959f3 757 * Returns description of method result value
67aa60f9 758 *
87e959f3 759 * @return external_description
67aa60f9 760 * @since Moodle 2.3
87e959f3
JL
761 */
762 public static function update_groupings_returns() {
67aa60f9 763 return null;
87e959f3
JL
764 }
765
ed849fba
JL
766 /**
767 * Returns description of method parameters
67aa60f9 768 *
ed849fba 769 * @return external_function_parameters
67aa60f9 770 * @since Moodle 2.3
ed849fba
JL
771 */
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')
67aa60f9 776 , 'List of grouping id. A grouping id is an integer.'),
45c0a7d0 777 'returngroups' => new external_value(PARAM_BOOL, 'return associated groups', VALUE_DEFAULT, 0)
ed849fba
JL
778 )
779 );
780 }
781
782 /**
783 * Get groupings definition specified by ids
67aa60f9 784 *
ed849fba 785 * @param array $groupingids arrays of grouping ids
45c0a7d0 786 * @param boolean $returngroups return the associated groups if true. The default is false.
ed849fba 787 * @return array of grouping objects (id, courseid, name)
67aa60f9 788 * @since Moodle 2.3
ed849fba 789 */
45c0a7d0
PC
790 public static function get_groupings($groupingids, $returngroups = false) {
791 global $CFG, $DB;
ed849fba 792 require_once("$CFG->dirroot/group/lib.php");
67aa60f9 793 require_once("$CFG->libdir/filelib.php");
ed849fba 794
45c0a7d0
PC
795 $params = self::validate_parameters(self::get_groupings_parameters(),
796 array('groupingids' => $groupingids,
797 'returngroups' => $returngroups));
ed849fba
JL
798
799 $groupings = array();
800 foreach ($params['groupingids'] as $groupingid) {
801 // Validate params.
802 $grouping = groups_get_grouping($groupingid, '*', MUST_EXIST);
803
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);
813 }
814 require_capability('moodle/course:managegroups', $context);
815
93ce0e82
JM
816 list($grouping->description, $grouping->descriptionformat) =
817 external_format_text($grouping->description, $grouping->descriptionformat,
818 $context->id, 'grouping', 'description', $grouping->id);
ed849fba 819
45c0a7d0
PC
820 $groupingarray = (array)$grouping;
821
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,
ed0fd1f6 834 'idnumber' => $grouprecord->idnumber,
45c0a7d0
PC
835 'description' => $grouprecord->description,
836 'descriptionformat' => $grouprecord->descriptionformat,
837 'enrolmentkey' => $grouprecord->enrolmentkey,
838 'courseid' => $grouprecord->courseid
839 );
840 }
841 $groupingarray['groups'] = $groups;
842 }
843 }
844 $groupings[] = $groupingarray;
ed849fba
JL
845 }
846
847 return $groupings;
848 }
849
67aa60f9 850 /**
ed849fba 851 * Returns description of method result value
67aa60f9 852 *
ed849fba 853 * @return external_description
67aa60f9 854 * @since Moodle 2.3
ed849fba
JL
855 */
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'),
93ce0e82 863 'description' => new external_value(PARAM_RAW, 'grouping description text'),
45c0a7d0 864 'descriptionformat' => new external_format_value('description'),
ed0fd1f6 865 'idnumber' => new external_value(PARAM_RAW, 'id number'),
45c0a7d0
PC
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'),
ed0fd1f6
DM
874 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
875 'idnumber' => new external_value(PARAM_RAW, 'id number')
45c0a7d0
PC
876 )
877 ),
878 'optional groups', VALUE_OPTIONAL)
ed849fba
JL
879 )
880 )
881 );
882 }
883
85e42d22
JL
884 /**
885 * Returns description of method parameters
67aa60f9 886 *
85e42d22 887 * @return external_function_parameters
67aa60f9 888 * @since Moodle 2.3
85e42d22
JL
889 */
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'),
894 )
895 );
896 }
897
898 /**
899 * Get all groupings in the specified course
67aa60f9 900 *
85e42d22
JL
901 * @param int $courseid id of course
902 * @return array of grouping objects (id, courseid, name, enrolmentkey)
67aa60f9 903 * @since Moodle 2.3
85e42d22
JL
904 */
905 public static function get_course_groupings($courseid) {
906 global $CFG;
907 require_once("$CFG->dirroot/group/lib.php");
67aa60f9 908 require_once("$CFG->libdir/filelib.php");
85e42d22
JL
909
910 $params = self::validate_parameters(self::get_course_groupings_parameters(), array('courseid'=>$courseid));
911
912 // Now security checks.
913 $context = context_course::instance($params['courseid']);
914
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);
922 }
923 require_capability('moodle/course:managegroups', $context);
924
925 $gs = groups_get_all_groupings($params['courseid']);
926
927 $groupings = array();
928 foreach ($gs as $grouping) {
93ce0e82
JM
929 list($grouping->description, $grouping->descriptionformat) =
930 external_format_text($grouping->description, $grouping->descriptionformat,
931 $context->id, 'grouping', 'description', $grouping->id);
85e42d22
JL
932 $groupings[] = (array)$grouping;
933 }
934
935 return $groupings;
936 }
937
67aa60f9 938 /**
85e42d22 939 * Returns description of method result value
67aa60f9 940 *
85e42d22 941 * @return external_description
67aa60f9 942 * @since Moodle 2.3
85e42d22
JL
943 */
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'),
93ce0e82 951 'description' => new external_value(PARAM_RAW, 'grouping description text'),
ed0fd1f6
DM
952 'descriptionformat' => new external_format_value('description'),
953 'idnumber' => new external_value(PARAM_RAW, 'id number')
85e42d22
JL
954 )
955 )
956 );
957 }
958
a531136e
JL
959 /**
960 * Returns description of method parameters
67aa60f9 961 *
a531136e 962 * @return external_function_parameters
67aa60f9 963 * @since Moodle 2.3
a531136e
JL
964 */
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')),
969 )
970 );
971 }
972
973 /**
974 * Delete groupings
67aa60f9 975 *
a531136e
JL
976 * @param array $groupingids array of grouping ids
977 * @return void
67aa60f9 978 * @since Moodle 2.3
a531136e
JL
979 */
980 public static function delete_groupings($groupingids) {
981 global $CFG, $DB;
982 require_once("$CFG->dirroot/group/lib.php");
983
984 $params = self::validate_parameters(self::delete_groupings_parameters(), array('groupingids'=>$groupingids));
985
986 $transaction = $DB->start_delegated_transaction();
987
988 foreach ($params['groupingids'] as $groupingid) {
67aa60f9 989
301783d9 990 if (!$grouping = groups_get_grouping($groupingid)) {
a531136e
JL
991 // Silently ignore attempts to delete nonexisting groupings.
992 continue;
993 }
994
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);
1004 }
1005 require_capability('moodle/course:managegroups', $context);
1006
1007 groups_delete_grouping($grouping);
1008 }
1009
1010 $transaction->allow_commit();
1011 }
1012
67aa60f9 1013 /**
a531136e 1014 * Returns description of method result value
67aa60f9 1015 *
a531136e 1016 * @return external_description
67aa60f9 1017 * @since Moodle 2.3
a531136e
JL
1018 */
1019 public static function delete_groupings_returns() {
1020 return null;
1021 }
1022
20053b8c
JL
1023 /**
1024 * Returns description of method parameters
67aa60f9 1025 *
20053b8c 1026 * @return external_function_parameters
67aa60f9 1027 * @since Moodle 2.3
20053b8c
JL
1028 */
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'),
1037 )
1038 )
1039 )
1040 )
1041 );
1042 }
1043
1044 /**
1045 * Assign a group to a grouping
67aa60f9 1046 *
20053b8c
JL
1047 * @param array $assignments of arrays with keys groupid, groupingid
1048 * @return void
67aa60f9 1049 * @since Moodle 2.3
20053b8c
JL
1050 */
1051 public static function assign_grouping($assignments) {
1052 global $CFG, $DB;
1053 require_once("$CFG->dirroot/group/lib.php");
1054
1055 $params = self::validate_parameters(self::assign_grouping_parameters(), array('assignments'=>$assignments));
1056
1057 $transaction = $DB->start_delegated_transaction();
1058 foreach ($params['assignments'] as $assignment) {
1059 // Validate params.
1060 $groupingid = $assignment['groupingid'];
1061 $groupid = $assignment['groupid'];
1062
1063 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1064 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1065
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;
1069 }
1070
67aa60f9 1071 // Now security checks.
20053b8c
JL
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);
1080 }
1081 require_capability('moodle/course:managegroups', $context);
1082
1083 groups_assign_grouping($groupingid, $groupid);
1084 }
1085
1086 $transaction->allow_commit();
1087 }
1088
67aa60f9 1089 /**
20053b8c 1090 * Returns description of method result value
67aa60f9 1091 *
20053b8c 1092 * @return null
67aa60f9 1093 * @since Moodle 2.3
20053b8c
JL
1094 */
1095 public static function assign_grouping_returns() {
1096 return null;
1097 }
1098
fb3f5d31
JL
1099 /**
1100 * Returns description of method parameters
67aa60f9 1101 *
fb3f5d31 1102 * @return external_function_parameters
67aa60f9 1103 * @since Moodle 2.3
fb3f5d31
JL
1104 */
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'),
1113 )
1114 )
1115 )
1116 )
1117 );
1118 }
1119
1120 /**
1121 * Unassign a group from a grouping
67aa60f9 1122 *
fb3f5d31
JL
1123 * @param array $unassignments of arrays with keys groupid, groupingid
1124 * @return void
67aa60f9 1125 * @since Moodle 2.3
fb3f5d31
JL
1126 */
1127 public static function unassign_grouping($unassignments) {
1128 global $CFG, $DB;
1129 require_once("$CFG->dirroot/group/lib.php");
1130
1131 $params = self::validate_parameters(self::unassign_grouping_parameters(), array('unassignments'=>$unassignments));
1132
1133 $transaction = $DB->start_delegated_transaction();
1134 foreach ($params['unassignments'] as $unassignment) {
1135 // Validate params.
1136 $groupingid = $unassignment['groupingid'];
1137 $groupid = $unassignment['groupid'];
1138
1139 $grouping = groups_get_grouping($groupingid, 'id, courseid', MUST_EXIST);
1140 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
1141
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;
1145 }
1146
67aa60f9 1147 // Now security checks.
fb3f5d31
JL
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);
1156 }
1157 require_capability('moodle/course:managegroups', $context);
1158
1159 groups_unassign_grouping($groupingid, $groupid);
1160 }
1161
1162 $transaction->allow_commit();
1163 }
1164
67aa60f9 1165 /**
fb3f5d31 1166 * Returns description of method result value
67aa60f9 1167 *
fb3f5d31 1168 * @return null
67aa60f9 1169 * @since Moodle 2.3
fb3f5d31
JL
1170 */
1171 public static function unassign_grouping_returns() {
1172 return null;
1173 }
1174
5d62e813
JL
1175 /**
1176 * Returns description of method parameters
1177 *
1178 * @return external_function_parameters
1179 * @since Moodle 2.9
1180 */
1181 public static function get_course_user_groups_parameters() {
1182 return new external_function_parameters(
1183 array(
b8a35674
JL
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),
5d62e813
JL
1187 'groupingid' => new external_value(PARAM_INT, 'returns only groups in the specified grouping', VALUE_DEFAULT, 0)
1188 )
1189 );
1190 }
1191
1192 /**
1193 * Get all groups in the specified course for the specified user.
1194 *
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
1201 */
b8a35674 1202 public static function get_course_user_groups($courseid = 0, $userid = 0, $groupingid = 0) {
5d62e813
JL
1203 global $USER;
1204
1205 // Warnings array, it can be empty at the end but is mandatory.
1206 $warnings = array();
1207
1208 $params = array(
1209 'courseid' => $courseid,
1210 'userid' => $userid,
1211 'groupingid' => $groupingid
1212 );
1213 $params = self::validate_parameters(self::get_course_user_groups_parameters(), $params);
b8a35674 1214
5d62e813
JL
1215 $courseid = $params['courseid'];
1216 $userid = $params['userid'];
1217 $groupingid = $params['groupingid'];
1218
b8a35674
JL
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);
1225 }
1226
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;
1234 }
5d62e813
JL
1235
1236 // Security checks.
b8a35674 1237 list($courses, $warnings) = external_util::validate_courses(array_keys($courses), $courses, true);
5d62e813 1238
b8a35674
JL
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",
1248 );
1249 continue;
5d62e813 1250 }
b8a35674
JL
1251
1252 // Check if the user being check is enrolled in the given course.
1253 if ($checkenrolments && !is_enrolled($course->context, $userid)) {
5d62e813 1254 // We return a warning because the function does not fail for not enrolled users.
b8a35674
JL
1255 $warnings[] = array(
1256 'item' => 'course',
1257 'itemid' => $course->id,
1258 'warningcode' => 'notenrolled',
1259 'message' => "User $userid is not enrolled in course $course->id",
1260 );
5d62e813 1261 }
5d62e813 1262
6f89b33b 1263 $groups = groups_get_all_groups($course->id, $userid, $groupingid,
b8a35674 1264 'g.id, g.name, g.description, g.descriptionformat, g.idnumber');
5d62e813
JL
1265
1266 foreach ($groups as $group) {
1267 list($group->description, $group->descriptionformat) =
1268 external_format_text($group->description, $group->descriptionformat,
b8a35674 1269 $course->context->id, 'group', 'description', $group->id);
7107c2f0
JL
1270 $group->courseid = $course->id;
1271 $usergroups[] = $group;
5d62e813
JL
1272 }
1273 }
1274
1275 $results = array(
1276 'groups' => $usergroups,
1277 'warnings' => $warnings
1278 );
1279 return $results;
1280 }
1281
1282 /**
1283 * Returns description of method result value.
1284 *
1285 * @return external_description A single structure containing groups and possible warnings.
1286 * @since Moodle 2.9
1287 */
1288 public static function get_course_user_groups_returns() {
1289 return new external_single_structure(
1290 array(
7107c2f0
JL
1291 'groups' => new external_multiple_structure(self::group_description()),
1292 'warnings' => new external_warnings(),
1293 )
1294 );
1295 }
1296
1297 /**
1298 * Create group return value description.
1299 *
1300 * @return external_single_structure The group description
1301 */
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),
1311 )
1312 );
1313 }
1314
1315 /**
1316 * Returns description of method parameters
1317 *
1318 * @return external_function_parameters
1319 * @since Moodle 3.0
1320 */
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'),
4d9edf1b 1325 'userid' => new external_value(PARAM_INT, 'id of user, empty for current user', VALUE_DEFAULT, 0)
7107c2f0
JL
1326 )
1327 );
1328 }
1329
1330 /**
1331 * Gets a list of groups that the user is allowed to access within the specified activity.
1332 *
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
1338 */
1339 public static function get_activity_allowed_groups($cmid, $userid = 0) {
1340 global $USER;
1341
1342 // Warnings array, it can be empty at the end but is mandatory.
1343 $warnings = array();
1344
1345 $params = array(
1346 'cmid' => $cmid,
1347 'userid' => $userid
1348 );
1349 $params = self::validate_parameters(self::get_activity_allowed_groups_parameters(), $params);
1350 $cmid = $params['cmid'];
1351 $userid = $params['userid'];
1352
1353 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1354
1355 // Security checks.
1356 $context = context_module::instance($cm->id);
1357 $coursecontext = context_course::instance($cm->course);
1358 self::validate_context($context);
1359
1360 if (empty($userid)) {
1361 $userid = $USER->id;
1362 }
1363
4485f7c5
JL
1364 $user = core_user::get_user($userid, '*', MUST_EXIST);
1365 core_user::require_active_user($user);
7107c2f0
JL
1366
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');
1371 }
1372
1373 // Validate if the user is enrolled in the course.
48a90a21
JL
1374 $course = get_course($cm->course);
1375 if (!can_access_course($course, $user, '', true)) {
7107c2f0
JL
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';
48a90a21 1381 $warning['message'] = "User $user->id cannot access course $cm->course";
7107c2f0
JL
1382 $warnings[] = $warning;
1383 }
1384 }
1385
1386 $usergroups = array();
1387 if (empty($warnings)) {
1388 $groups = groups_get_activity_allowed_groups($cm, $user->id);
1389
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;
1396 }
1397 }
1398
1399 $results = array(
1400 'groups' => $usergroups,
0f398b50 1401 'canaccessallgroups' => has_capability('moodle/site:accessallgroups', $context, $user),
7107c2f0
JL
1402 'warnings' => $warnings
1403 );
1404 return $results;
1405 }
1406
1407 /**
1408 * Returns description of method result value.
1409 *
1410 * @return external_description A single structure containing groups and possible warnings.
1411 * @since Moodle 3.0
1412 */
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()),
0f398b50
JL
1417 'canaccessallgroups' => new external_value(PARAM_BOOL,
1418 'Whether the user will be able to access all the activity groups.', VALUE_OPTIONAL),
5d62e813
JL
1419 'warnings' => new external_warnings(),
1420 )
1421 );
1422 }
1423
c0ef63eb
JL
1424 /**
1425 * Returns description of method parameters
1426 *
1427 * @return external_function_parameters
1428 * @since Moodle 3.0
1429 */
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')
1434 )
1435 );
1436 }
1437
1438 /**
1439 * Returns effective groupmode used in a given activity.
1440 *
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
1446 */
1447 public static function get_activity_groupmode($cmid) {
1448 global $USER;
1449
1450 // Warnings array, it can be empty at the end but is mandatory.
1451 $warnings = array();
1452
1453 $params = array(
1454 'cmid' => $cmid
1455 );
1456 $params = self::validate_parameters(self::get_activity_groupmode_parameters(), $params);
1457 $cmid = $params['cmid'];
1458
1459 $cm = get_coursemodule_from_id(null, $cmid, 0, false, MUST_EXIST);
1460
1461 // Security checks.
1462 $context = context_module::instance($cm->id);
1463 self::validate_context($context);
1464
1465 $groupmode = groups_get_activity_groupmode($cm);
1466
1467 $results = array(
1468 'groupmode' => $groupmode,
1469 'warnings' => $warnings
1470 );
1471 return $results;
1472 }
1473
1474 /**
1475 * Returns description of method result value.
1476 *
1477 * @return external_description
1478 * @since Moodle 3.0
1479 */
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(),
1486 )
1487 );
1488 }
1489
474dd887
R
1490 /**
1491 * Returns description of method parameters
1492 *
1493 * @return external_function_parameters
1494 * @since Moodle 3.6
1495 */
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)
1508 )
1509 ), 'List of group objects. A group is found by the id, then all other details provided will be updated.'
1510 )
1511 )
1512 );
1513 }
1514
1515 /**
1516 * Update groups
1517 *
1518 * @param array $groups
1519 * @return null
1520 * @since Moodle 3.6
1521 */
1522 public static function update_groups($groups) {
1523 global $CFG, $DB;
1524 require_once("$CFG->dirroot/group/lib.php");
1525
1526 $params = self::validate_parameters(self::update_groups_parameters(), array('groups' => $groups));
1527
1528 $transaction = $DB->start_delegated_transaction();
1529
1530 foreach ($params['groups'] as $group) {
1531 $group = (object)$group;
1532
1533 if (trim($group->name) == '') {
1534 throw new invalid_parameter_exception('Invalid group name');
1535 }
1536
1537 if (! $currentgroup = $DB->get_record('groups', array('id' => $group->id))) {
1538 throw new invalid_parameter_exception("Group $group->id does not exist");
1539 }
1540
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');
1545 }
1546
1547 $group->courseid = $currentgroup->courseid;
1548
1549 // Now security checks.
1550 $context = context_course::instance($group->courseid);
1551 try {
1552 self::validate_context($context);
1553 } catch (Exception $e) {
17af25ce 1554 $exceptionparam = new stdClass();
474dd887
R
1555 $exceptionparam->message = $e->getMessage();
1556 $exceptionparam->courseid = $group->courseid;
1557 throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam);
1558 }
1559 require_capability('moodle/course:managegroups', $context);
1560
1561 if (!empty($group->description)) {
1562 $group->descriptionformat = external_validate_format($group->descriptionformat);
1563 }
1564
1565 groups_update_group($group);
1566 }
1567
1568 $transaction->allow_commit();
1569
1570 return null;
1571 }
1572
1573 /**
1574 * Returns description of method result value
1575 *
1576 * @return null
1577 * @since Moodle 3.6
1578 */
1579 public static function update_groups_returns() {
1580 return null;
1581 }
4ca6cfbf 1582}