emergency release 2.2dev
[moodle.git] / group / externallib.php
CommitLineData
9a0df45a 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * External groups API
20 *
21 * @package moodlecore
22 * @subpackage webservice
551f4420 23 * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
9a0df45a 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27require_once("$CFG->libdir/externallib.php");
28
29class moodle_group_external extends external_api {
30
0c96468c 31 /**
32 * Returns description of method parameters
f5072177 33 * @return external_function_parameters
0c96468c 34 */
35 public static function create_groups_parameters() {
f5072177 36 return new external_function_parameters(
37 array(
38 'groups' => new external_multiple_structure(
39 new external_single_structure(
40 array(
41 'courseid' => new external_value(PARAM_INT, 'id of course'),
42 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
43 'description' => new external_value(PARAM_RAW, 'group description text'),
44 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
45 )
d4c6ef70 46 ), 'List of group object. A group has a courseid, a name, a description and an enrolment key.'
f5072177 47 )
48 )
49 );
0c96468c 50 }
51
52 /**
9a0df45a 53 * Create groups
b4c1a34e 54 * @param array $groups array of group description arrays (with keys groupname and courseid)
f5072177 55 * @return array of newly created groups
9a0df45a 56 */
b4c1a34e 57 public static function create_groups($groups) {
f5072177 58 global $CFG, $DB;
9a0df45a 59 require_once("$CFG->dirroot/group/lib.php");
60
c9c5cc81 61 $params = self::validate_parameters(self::create_groups_parameters(), array('groups'=>$groups));
0c96468c 62
d5a8d9aa
PS
63 $transaction = $DB->start_delegated_transaction();
64
65 $groups = array();
66
67 foreach ($params['groups'] as $group) {
68 $group = (object)$group;
69
70 if (trim($group->name) == '') {
71 throw new invalid_parameter_exception('Invalid group name');
72 }
73 if ($DB->get_record('groups', array('courseid'=>$group->courseid, 'name'=>$group->name))) {
74 throw new invalid_parameter_exception('Group with the same name already exists in the course');
ab9a01f2 75 }
d5a8d9aa
PS
76
77 // now security checks
78 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 79 try {
80 self::validate_context($context);
81 } catch (Exception $e) {
82 $exceptionparam = new stdClass();
83 $exceptionparam->message = $e->getMessage();
84 $exceptionparam->courseid = $group->courseid;
85 throw new moodle_exception(
86 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
87 }
d5a8d9aa
PS
88 require_capability('moodle/course:managegroups', $context);
89
90 // finally create the group
91 $group->id = groups_create_group($group, false);
92 $groups[] = (array)$group;
9a0df45a 93 }
d5a8d9aa
PS
94
95 $transaction->allow_commit();
9a0df45a 96
2e13b916 97 return $groups;
9a0df45a 98 }
99
0c96468c 100 /**
101 * Returns description of method result value
f5072177 102 * @return external_description
0c96468c 103 */
104 public static function create_groups_returns() {
f5072177 105 return new external_multiple_structure(
106 new external_single_structure(
107 array(
108 'id' => new external_value(PARAM_INT, 'group record id'),
109 'courseid' => new external_value(PARAM_INT, 'id of course'),
110 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
111 'description' => new external_value(PARAM_RAW, 'group description text'),
112 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
113 )
d4c6ef70 114 ), 'List of group object. A group has an id, a courseid, a name, a description and an enrolment key.'
f5072177 115 );
0c96468c 116 }
117
f5072177 118 /**
119 * Returns description of method parameters
120 * @return external_function_parameters
121 */
0c96468c 122 public static function get_groups_parameters() {
8c772ad7 123 return new external_function_parameters(
124 array(
d4c6ef70 125 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')
126 ,'List of group id. A group id is an integer.'),
8c772ad7 127 )
128 );
0c96468c 129 }
130
9a0df45a 131 /**
246f6da2 132 * Get groups definition specified by ids
b4c1a34e 133 * @param array $groupids arrays of group ids
9a0df45a 134 * @return array of group objects (id, courseid, name, enrolmentkey)
135 */
b4c1a34e 136 public static function get_groups($groupids) {
c9c5cc81 137 $params = self::validate_parameters(self::get_groups_parameters(), array('groupids'=>$groupids));
0c96468c 138
246f6da2 139 $groups = array();
0c96468c 140 foreach ($params['groupids'] as $groupid) {
ab9a01f2 141 // validate params
ab9a01f2 142 $group = groups_get_group($groupid, 'id, courseid, name, description, enrolmentkey', MUST_EXIST);
143
9a0df45a 144 // now security checks
145 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 146 try {
147 self::validate_context($context);
148 } catch (Exception $e) {
149 $exceptionparam = new stdClass();
150 $exceptionparam->message = $e->getMessage();
151 $exceptionparam->courseid = $group->courseid;
152 throw new moodle_exception(
153 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
154 }
9a0df45a 155 require_capability('moodle/course:managegroups', $context);
156
2e13b916 157 $groups[] = (array)$group;
9a0df45a 158 }
159
160 return $groups;
161 }
162
f5072177 163 /**
164 * Returns description of method result value
165 * @return external_description
166 */
0c96468c 167 public static function get_groups_returns() {
246f6da2 168 return new external_multiple_structure(
169 new external_single_structure(
170 array(
171 'id' => new external_value(PARAM_INT, 'group record id'),
172 'courseid' => new external_value(PARAM_INT, 'id of course'),
173 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
174 'description' => new external_value(PARAM_RAW, 'group description text'),
175 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
176 )
177 )
178 );
179 }
180
181 /**
182 * Returns description of method parameters
183 * @return external_function_parameters
184 */
185 public static function get_course_groups_parameters() {
186 return new external_function_parameters(
187 array(
188 'courseid' => new external_value(PARAM_INT, 'id of course'),
189 )
190 );
191 }
192
193 /**
194 * Get all groups in the specified course
195 * @param int $courseid id of course
196 * @return array of group objects (id, courseid, name, enrolmentkey)
197 */
198 public static function get_course_groups($courseid) {
199 $params = self::validate_parameters(self::get_course_groups_parameters(), array('courseid'=>$courseid));
200
201 // now security checks
202 $context = get_context_instance(CONTEXT_COURSE, $params['courseid']);
41e962ff 203 try {
204 self::validate_context($context);
205 } catch (Exception $e) {
206 $exceptionparam = new stdClass();
207 $exceptionparam->message = $e->getMessage();
208 $exceptionparam->courseid = $params['courseid'];
209 throw new moodle_exception(
210 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
211 }
246f6da2 212 require_capability('moodle/course:managegroups', $context);
213
214 $gs = groups_get_all_groups($params['courseid'], 0, 0, 'g.id, g.courseid, g.name, g.description, g.enrolmentkey');
215
216 $groups = array();
217 foreach ($gs as $group) {
218 $groups[] = (array)$group;
219 }
220
221 return $groups;
222 }
223
224 /**
225 * Returns description of method result value
226 * @return external_description
227 */
228 public static function get_course_groups_returns() {
8c772ad7 229 return new external_multiple_structure(
230 new external_single_structure(
231 array(
f5072177 232 'id' => new external_value(PARAM_INT, 'group record id'),
233 'courseid' => new external_value(PARAM_INT, 'id of course'),
04d212ce 234 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
f5072177 235 'description' => new external_value(PARAM_RAW, 'group description text'),
236 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
8c772ad7 237 )
238 )
239 );
0c96468c 240 }
241
0f4e72de
PS
242 /**
243 * Returns description of method parameters
244 * @return external_function_parameters
245 */
0c96468c 246 public static function delete_groups_parameters() {
0f4e72de
PS
247 return new external_function_parameters(
248 array(
249 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
250 )
251 );
0c96468c 252 }
253
9a0df45a 254 /**
255 * Delete groups
b4c1a34e 256 * @param array $groupids array of group ids
9a0df45a 257 * @return void
258 */
b4c1a34e 259 public static function delete_groups($groupids) {
2cb1ee78 260 global $CFG, $DB;
9a0df45a 261 require_once("$CFG->dirroot/group/lib.php");
262
c9c5cc81 263 $params = self::validate_parameters(self::delete_groups_parameters(), array('groupids'=>$groupids));
0c96468c 264
d5a8d9aa
PS
265 $transaction = $DB->start_delegated_transaction();
266
6ccaf3f5 267// TODO: this is problematic because the DB rollback does not handle deleting of group images!
d5a8d9aa
PS
268 foreach ($params['groupids'] as $groupid) {
269 // validate params
270 $groupid = validate_param($groupid, PARAM_INTEGER);
271 if (!$group = groups_get_group($groupid, 'id, courseid', IGNORE_MISSING)) {
272 // silently ignore attempts to delete nonexisting groups
273 continue;
0f4e72de 274 }
d5a8d9aa
PS
275
276 // now security checks
277 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 278 try {
279 self::validate_context($context);
280 } catch (Exception $e) {
281 $exceptionparam = new stdClass();
282 $exceptionparam->message = $e->getMessage();
283 $exceptionparam->courseid = $group->courseid;
284 throw new moodle_exception(
285 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
286 }
d5a8d9aa
PS
287 require_capability('moodle/course:managegroups', $context);
288
289 groups_delete_group($group);
9a0df45a 290 }
d5a8d9aa
PS
291
292 $transaction->allow_commit();
9a0df45a 293 }
294
0f4e72de
PS
295 /**
296 * Returns description of method result value
297 * @return external_description
298 */
0c96468c 299 public static function delete_groups_returns() {
0f4e72de 300 return null;
0c96468c 301 }
302
303
0f4e72de
PS
304 /**
305 * Returns description of method parameters
306 * @return external_function_parameters
307 */
0c96468c 308 public static function get_groupmembers_parameters() {
0f4e72de
PS
309 return new external_function_parameters(
310 array(
311 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
312 )
313 );
0c96468c 314 }
9a0df45a 315
316 /**
317 * Return all members for a group
b4c1a34e 318 * @param array $groupids array of group ids
9a0df45a 319 * @return array with group id keys containing arrays of user ids
320 */
b4c1a34e 321 public static function get_groupmembers($groupids) {
0f4e72de 322 $members = array();
9a0df45a 323
c9c5cc81 324 $params = self::validate_parameters(self::get_groupmembers_parameters(), array('groupids'=>$groupids));
0c96468c 325
326 foreach ($params['groupids'] as $groupid) {
ab9a01f2 327 // validate params
9a0df45a 328 $group = groups_get_group($groupid, 'id, courseid, name, enrolmentkey', MUST_EXIST);
329 // now security checks
330 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 331 try {
332 self::validate_context($context);
333 } catch (Exception $e) {
334 $exceptionparam = new stdClass();
335 $exceptionparam->message = $e->getMessage();
336 $exceptionparam->courseid = $group->courseid;
337 throw new moodle_exception(
338 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
339 }
9a0df45a 340 require_capability('moodle/course:managegroups', $context);
341
342 $groupmembers = groups_get_members($group->id, 'u.id', 'lastname ASC, firstname ASC');
343
0f4e72de 344 $members[] = array('groupid'=>$groupid, 'userids'=>array_keys($groupmembers));
9a0df45a 345 }
346
0f4e72de 347 return $members;
9a0df45a 348 }
349
0f4e72de
PS
350 /**
351 * Returns description of method result value
352 * @return external_description
353 */
0c96468c 354 public static function get_groupmembers_returns() {
0f4e72de
PS
355 return new external_multiple_structure(
356 new external_single_structure(
357 array(
358 'groupid' => new external_value(PARAM_INT, 'group record id'),
359 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user id')),
360 )
361 )
362 );
0c96468c 363 }
364
365
0f4e72de
PS
366 /**
367 * Returns description of method parameters
368 * @return external_function_parameters
369 */
0c96468c 370 public static function add_groupmembers_parameters() {
4efa2483
PS
371 return new external_function_parameters(
372 array(
373 'members'=> new external_multiple_structure(
374 new external_single_structure(
375 array(
376 'groupid' => new external_value(PARAM_INT, 'group record id'),
377 'userid' => new external_value(PARAM_INT, 'user id'),
378 )
379 )
0f4e72de
PS
380 )
381 )
382 );
0c96468c 383 }
9a0df45a 384
385 /**
386 * Add group members
b4c1a34e 387 * @param array $members of arrays with keys userid, groupid
9a0df45a 388 * @return void
389 */
b4c1a34e 390 public static function add_groupmembers($members) {
2cb1ee78 391 global $CFG, $DB;
9a0df45a 392 require_once("$CFG->dirroot/group/lib.php");
393
c9c5cc81 394 $params = self::validate_parameters(self::add_groupmembers_parameters(), array('members'=>$members));
9a0df45a 395
d5a8d9aa 396 $transaction = $DB->start_delegated_transaction();
d5a8d9aa
PS
397 foreach ($params['members'] as $member) {
398 // validate params
399 $groupid = $member['groupid'];
400 $userid = $member['userid'];
0c96468c 401
d5a8d9aa
PS
402 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
403 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
9a0df45a 404
d5a8d9aa
PS
405 // now security checks
406 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 407 try {
408 self::validate_context($context);
409 } catch (Exception $e) {
410 $exceptionparam = new stdClass();
411 $exceptionparam->message = $e->getMessage();
412 $exceptionparam->courseid = $group->courseid;
413 throw new moodle_exception(
414 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
415 }
d5a8d9aa 416 require_capability('moodle/course:managegroups', $context);
9a0df45a 417
d5a8d9aa 418 // now make sure user is enrolled in course - this is mandatory requirement,
4f0c2d00
PS
419 // unfortunately this is slow
420 if (!is_enrolled($context, $userid)) {
421 throw new invalid_parameter_exception('Only enrolled users may be members of groups');
422 }
4efa2483 423
d5a8d9aa 424 groups_add_member($group, $user);
9a0df45a 425 }
d5a8d9aa
PS
426
427 $transaction->allow_commit();
9a0df45a 428 }
429
0f4e72de
PS
430 /**
431 * Returns description of method result value
432 * @return external_description
433 */
0c96468c 434 public static function add_groupmembers_returns() {
0f4e72de 435 return null;
0c96468c 436 }
437
438
0f4e72de
PS
439 /**
440 * Returns description of method parameters
441 * @return external_function_parameters
442 */
0c96468c 443 public static function delete_groupmembers_parameters() {
4efa2483
PS
444 return new external_function_parameters(
445 array(
446 'members'=> new external_multiple_structure(
447 new external_single_structure(
448 array(
449 'groupid' => new external_value(PARAM_INT, 'group record id'),
450 'userid' => new external_value(PARAM_INT, 'user id'),
451 )
452 )
0f4e72de
PS
453 )
454 )
455 );
0c96468c 456 }
9a0df45a 457
458 /**
459 * Delete group members
b4c1a34e 460 * @param array $members of arrays with keys userid, groupid
9a0df45a 461 * @return void
462 */
b4c1a34e 463 public static function delete_groupmembers($members) {
2cb1ee78 464 global $CFG, $DB;
9a0df45a 465 require_once("$CFG->dirroot/group/lib.php");
466
443364ab 467 $params = self::validate_parameters(self::delete_groupmembers_parameters(), array('members'=>$members));
9a0df45a 468
d5a8d9aa
PS
469 $transaction = $DB->start_delegated_transaction();
470
0c96468c 471 foreach ($params['members'] as $member) {
d5a8d9aa
PS
472 // validate params
473 $groupid = $member['groupid'];
474 $userid = $member['userid'];
0c96468c 475
d5a8d9aa
PS
476 $group = groups_get_group($groupid, 'id, courseid', MUST_EXIST);
477 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST);
9a0df45a 478
d5a8d9aa
PS
479 // now security checks
480 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
41e962ff 481 try {
482 self::validate_context($context);
483 } catch (Exception $e) {
484 $exceptionparam = new stdClass();
485 $exceptionparam->message = $e->getMessage();
486 $exceptionparam->courseid = $group->courseid;
487 throw new moodle_exception(
488 get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
489 }
d5a8d9aa 490 require_capability('moodle/course:managegroups', $context);
9a0df45a 491
d5a8d9aa 492 groups_remove_member($group, $user);
9a0df45a 493 }
d5a8d9aa
PS
494
495 $transaction->allow_commit();
9a0df45a 496 }
497
0f4e72de
PS
498 /**
499 * Returns description of method result value
500 * @return external_description
501 */
0c96468c 502 public static function delete_groupmembers_returns() {
0f4e72de 503 return null;
0c96468c 504 }
505
4ca6cfbf 506}