2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
20 * @package core_cohort
22 * @copyright MediaTouch 2000 srl
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
28 require_once("$CFG->libdir/externallib.php");
30 class core_cohort_external
extends external_api
{
33 * Returns description of method parameters
35 * @return external_function_parameters
38 public static function create_cohorts_parameters() {
39 return new external_function_parameters(
41 'cohorts' => new external_multiple_structure(
42 new external_single_structure(
44 'categorytype' => new external_single_structure(
46 'type' => new external_value(PARAM_TEXT
, 'the name of the field: id (numeric value
47 of course category id) or idnumber (alphanumeric value of idnumber course category)
48 or system (value ignored)'),
49 'value' => new external_value(PARAM_RAW
, 'the value of the categorytype')
52 'name' => new external_value(PARAM_RAW
, 'cohort name'),
53 'idnumber' => new external_value(PARAM_RAW
, 'cohort idnumber'),
54 'description' => new external_value(PARAM_RAW
, 'cohort description', VALUE_OPTIONAL
),
55 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT
),
56 'visible' => new external_value(PARAM_BOOL
, 'cohort visible', VALUE_OPTIONAL
, true),
65 * Create one or more cohorts
67 * @param array $cohorts An array of cohorts to create.
68 * @return array An array of arrays
71 public static function create_cohorts($cohorts) {
73 require_once("$CFG->dirroot/cohort/lib.php");
75 $params = self
::validate_parameters(self
::create_cohorts_parameters(), array('cohorts' => $cohorts));
77 $transaction = $DB->start_delegated_transaction();
79 $syscontext = context_system
::instance();
82 foreach ($params['cohorts'] as $cohort) {
83 $cohort = (object)$cohort;
85 // Category type (context id).
86 $categorytype = $cohort->categorytype
;
87 if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
88 throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
90 if ($categorytype['type'] === 'system') {
91 $cohort->contextid
= $syscontext->id
;
92 } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
93 $catcontext = context_coursecat
::instance($catid);
94 $cohort->contextid
= $catcontext->id
;
96 throw new invalid_parameter_exception('category not exists: category '
97 .$categorytype['type'].' = '.$categorytype['value']);
99 // Make sure that the idnumber doesn't already exist.
100 if ($DB->record_exists('cohort', array('idnumber' => $cohort->idnumber
))) {
101 throw new invalid_parameter_exception('record already exists: idnumber='.$cohort->idnumber
);
103 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
104 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
105 throw new invalid_parameter_exception('Invalid context');
107 self
::validate_context($context);
108 require_capability('moodle/cohort:manage', $context);
111 $cohort->descriptionformat
= external_validate_format($cohort->descriptionformat
);
112 $cohort->id
= cohort_add_cohort($cohort);
114 list($cohort->description
, $cohort->descriptionformat
) =
115 external_format_text($cohort->description
, $cohort->descriptionformat
,
116 $context->id
, 'cohort', 'description', $cohort->id
);
117 $cohortids[] = (array)$cohort;
119 $transaction->allow_commit();
125 * Returns description of method result value
127 * @return external_description
130 public static function create_cohorts_returns() {
131 return new external_multiple_structure(
132 new external_single_structure(
134 'id' => new external_value(PARAM_INT
, 'cohort id'),
135 'name' => new external_value(PARAM_RAW
, 'cohort name'),
136 'idnumber' => new external_value(PARAM_RAW
, 'cohort idnumber'),
137 'description' => new external_value(PARAM_RAW
, 'cohort description'),
138 'descriptionformat' => new external_format_value('description'),
139 'visible' => new external_value(PARAM_BOOL
, 'cohort visible'),
146 * Returns description of method parameters
148 * @return external_function_parameters
151 public static function delete_cohorts_parameters() {
152 return new external_function_parameters(
154 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT
, 'cohort ID')),
162 * @param array $cohortids
166 public static function delete_cohorts($cohortids) {
168 require_once("$CFG->dirroot/cohort/lib.php");
170 $params = self
::validate_parameters(self
::delete_cohorts_parameters(), array('cohortids' => $cohortids));
172 $transaction = $DB->start_delegated_transaction();
174 foreach ($params['cohortids'] as $cohortid) {
176 $cohortid = validate_param($cohortid, PARAM_INT
);
177 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST
);
179 // Now security checks.
180 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
181 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
182 throw new invalid_parameter_exception('Invalid context');
184 self
::validate_context($context);
185 require_capability('moodle/cohort:manage', $context);
186 cohort_delete_cohort($cohort);
188 $transaction->allow_commit();
194 * Returns description of method result value
199 public static function delete_cohorts_returns() {
204 * Returns description of method parameters
206 * @return external_function_parameters
209 public static function get_cohorts_parameters() {
210 return new external_function_parameters(
212 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT
, 'Cohort ID')
213 , 'List of cohort id. A cohort id is an integer.', VALUE_DEFAULT
, array()),
219 * Get cohorts definition specified by ids
221 * @param array $cohortids array of cohort ids
222 * @return array of cohort objects (id, courseid, name)
225 public static function get_cohorts($cohortids = array()) {
228 $params = self
::validate_parameters(self
::get_cohorts_parameters(), array('cohortids' => $cohortids));
230 if (empty($cohortids)) {
231 $cohorts = $DB->get_records('cohort');
233 $cohorts = $DB->get_records_list('cohort', 'id', $params['cohortids']);
236 $cohortsinfo = array();
237 foreach ($cohorts as $cohort) {
238 // Now security checks.
239 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
240 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
241 throw new invalid_parameter_exception('Invalid context');
243 self
::validate_context($context);
244 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
245 throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
248 list($cohort->description
, $cohort->descriptionformat
) =
249 external_format_text($cohort->description
, $cohort->descriptionformat
,
250 $context->id
, 'cohort', 'description', $cohort->id
);
252 $cohortsinfo[] = (array) $cohort;
259 * Returns description of method result value
261 * @return external_description
264 public static function get_cohorts_returns() {
265 return new external_multiple_structure(
266 new external_single_structure(
268 'id' => new external_value(PARAM_INT
, 'ID of the cohort'),
269 'name' => new external_value(PARAM_RAW
, 'cohort name'),
270 'idnumber' => new external_value(PARAM_RAW
, 'cohort idnumber'),
271 'description' => new external_value(PARAM_RAW
, 'cohort description'),
272 'descriptionformat' => new external_format_value('description'),
273 'visible' => new external_value(PARAM_BOOL
, 'cohort visible'),
280 * Returns the description of external function parameters.
282 * @return external_function_parameters
284 public static function search_cohorts_parameters() {
285 $query = new external_value(
289 $includes = new external_value(
291 'What other contexts to fetch the frameworks from. (all, parents, self)',
295 $limitfrom = new external_value(
297 'limitfrom we are fetching the records from',
301 $limitnum = new external_value(
303 'Number of records to fetch',
307 return new external_function_parameters(array(
309 'context' => self
::get_context_parameters(),
310 'includes' => $includes,
311 'limitfrom' => $limitfrom,
312 'limitnum' => $limitnum
319 * @param string $query
320 * @param array $context
321 * @param string $includes
322 * @param int $limitfrom
323 * @param int $limitnum
326 public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
327 global $DB, $CFG, $PAGE;
328 require_once($CFG->dirroot
. '/cohort/lib.php');
330 $params = self
::validate_parameters(self
::search_cohorts_parameters(), array(
332 'context' => $context,
333 'includes' => $includes,
334 'limitfrom' => $limitfrom,
335 'limitnum' => $limitnum,
337 $query = $params['query'];
338 $includes = $params['includes'];
339 $context = self
::get_context_from_params($params['context']);
340 $limitfrom = $params['limitfrom'];
341 $limitnum = $params['limitnum'];
343 self
::validate_context($context);
344 $output = $PAGE->get_renderer('tool_lp');
346 $manager = has_capability('moodle/cohort:manage', $context);
348 require_capability('moodle/cohort:view', $context);
351 // TODO Make this more efficient.
352 if ($includes == 'self') {
353 $results = cohort_get_cohorts($context->id
, $limitfrom, $limitnum, $query);
354 $results = $results['cohorts'];
355 } else if ($includes == 'parents') {
356 $results = cohort_get_cohorts($context->id
, $limitfrom, $limitnum, $query);
357 $results = $results['cohorts'];
358 if (!$context instanceof context_system
) {
359 $results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL
, $limitfrom, $limitnum, $query));
361 } else if ($includes == 'all') {
362 $results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
363 $results = $results['cohorts'];
365 throw new coding_exception('Invalid parameter value for \'includes\'.');
369 foreach ($results as $key => $cohort) {
370 $cohortcontext = context
::instance_by_id($cohort->contextid
);
371 if (!isset($cohort->description
)) {
372 $cohort->description
= '';
374 if (!isset($cohort->descriptionformat
)) {
375 $cohort->descriptionformat
= FORMAT_PLAIN
;
378 list($cohort->description
, $cohort->descriptionformat
) =
379 external_format_text($cohort->description
, $cohort->descriptionformat
,
380 $cohortcontext->id
, 'cohort', 'description', $cohort->id
);
382 $cohorts[$key] = $cohort;
385 return array('cohorts' => $cohorts);
389 * Returns description of external function result value.
391 * @return external_description
393 public static function search_cohorts_returns() {
394 return new external_single_structure(array(
395 'cohorts' => new external_multiple_structure(
396 new external_single_structure(array(
397 'id' => new external_value(PARAM_INT
, 'ID of the cohort'),
398 'name' => new external_value(PARAM_RAW
, 'cohort name'),
399 'idnumber' => new external_value(PARAM_RAW
, 'cohort idnumber'),
400 'description' => new external_value(PARAM_RAW
, 'cohort description'),
401 'descriptionformat' => new external_format_value('description'),
402 'visible' => new external_value(PARAM_BOOL
, 'cohort visible'),
411 * Returns description of method parameters
413 * @return external_function_parameters
416 public static function update_cohorts_parameters() {
417 return new external_function_parameters(
419 'cohorts' => new external_multiple_structure(
420 new external_single_structure(
422 'id' => new external_value(PARAM_INT
, 'ID of the cohort'),
423 'categorytype' => new external_single_structure(
425 'type' => new external_value(PARAM_TEXT
, 'the name of the field: id (numeric value
426 of course category id) or idnumber (alphanumeric value of idnumber course category)
427 or system (value ignored)'),
428 'value' => new external_value(PARAM_RAW
, 'the value of the categorytype')
431 'name' => new external_value(PARAM_RAW
, 'cohort name'),
432 'idnumber' => new external_value(PARAM_RAW
, 'cohort idnumber'),
433 'description' => new external_value(PARAM_RAW
, 'cohort description', VALUE_OPTIONAL
),
434 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT
),
435 'visible' => new external_value(PARAM_BOOL
, 'cohort visible', VALUE_OPTIONAL
),
446 * @param array $cohorts
450 public static function update_cohorts($cohorts) {
452 require_once("$CFG->dirroot/cohort/lib.php");
454 $params = self
::validate_parameters(self
::update_cohorts_parameters(), array('cohorts' => $cohorts));
456 $transaction = $DB->start_delegated_transaction();
457 $syscontext = context_system
::instance();
459 foreach ($params['cohorts'] as $cohort) {
460 $cohort = (object) $cohort;
462 if (trim($cohort->name
) == '') {
463 throw new invalid_parameter_exception('Invalid cohort name');
466 $oldcohort = $DB->get_record('cohort', array('id' => $cohort->id
), '*', MUST_EXIST
);
467 $oldcontext = context
::instance_by_id($oldcohort->contextid
, MUST_EXIST
);
468 require_capability('moodle/cohort:manage', $oldcontext);
470 // Category type (context id).
471 $categorytype = $cohort->categorytype
;
472 if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
473 throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
475 if ($categorytype['type'] === 'system') {
476 $cohort->contextid
= $syscontext->id
;
477 } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
478 $cohort->contextid
= $DB->get_field('context', 'id', array('instanceid' => $catid,
479 'contextlevel' => CONTEXT_COURSECAT
));
481 throw new invalid_parameter_exception('category not exists: category='.$categorytype['value']);
484 if ($cohort->contextid
!= $oldcohort->contextid
) {
485 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
486 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
487 throw new invalid_parameter_exception('Invalid context');
490 self
::validate_context($context);
491 require_capability('moodle/cohort:manage', $context);
494 if (!empty($cohort->description
)) {
495 $cohort->descriptionformat
= external_validate_format($cohort->descriptionformat
);
498 cohort_update_cohort($cohort);
501 $transaction->allow_commit();
507 * Returns description of method result value
512 public static function update_cohorts_returns() {
517 * Returns description of method parameters
519 * @return external_function_parameters
522 public static function add_cohort_members_parameters() {
523 return new external_function_parameters (
525 'members' => new external_multiple_structure (
526 new external_single_structure (
528 'cohorttype' => new external_single_structure (
530 'type' => new external_value(PARAM_ALPHANUMEXT
, 'The name of the field: id
531 (numeric value of cohortid) or idnumber (alphanumeric value of idnumber) '),
532 'value' => new external_value(PARAM_RAW
, 'The value of the cohort')
535 'usertype' => new external_single_structure (
537 'type' => new external_value(PARAM_ALPHANUMEXT
, 'The name of the field: id
538 (numeric value of id) or username (alphanumeric value of username) '),
539 'value' => new external_value(PARAM_RAW
, 'The value of the cohort')
552 * @param array $members of arrays with keys userid, cohortid
555 public static function add_cohort_members($members) {
557 require_once($CFG->dirroot
."/cohort/lib.php");
559 $params = self
::validate_parameters(self
::add_cohort_members_parameters(), array('members' => $members));
561 $transaction = $DB->start_delegated_transaction();
563 foreach ($params['members'] as $member) {
564 // Cohort parameters.
565 $cohorttype = $member['cohorttype'];
566 $cohortparam = array($cohorttype['type'] => $cohorttype['value']);
568 $usertype = $member['usertype'];
569 $userparam = array($usertype['type'] => $usertype['value']);
572 if ($cohorttype['type'] != 'id' && $cohorttype['type'] != 'idnumber') {
574 $warning['warningcode'] = '1';
575 $warning['message'] = 'invalid parameter: cohortype='.$cohorttype['type'];
576 $warnings[] = $warning;
579 if ($usertype['type'] != 'id' && $usertype['type'] != 'username') {
581 $warning['warningcode'] = '1';
582 $warning['message'] = 'invalid parameter: usertype='.$usertype['type'];
583 $warnings[] = $warning;
586 // Extract parameters.
587 if (!$cohortid = $DB->get_field('cohort', 'id', $cohortparam)) {
589 $warning['warningcode'] = '2';
590 $warning['message'] = 'cohort '.$cohorttype['type'].'='.$cohorttype['value'].' not exists';
591 $warnings[] = $warning;
594 if (!$userid = $DB->get_field('user', 'id', array_merge($userparam, array('deleted' => 0,
595 'mnethostid' => $CFG->mnet_localhost_id
)))) {
597 $warning['warningcode'] = '2';
598 $warning['message'] = 'user '.$usertype['type'].'='.$usertype['value'].' not exists';
599 $warnings[] = $warning;
602 if ($DB->record_exists('cohort_members', array('cohortid' => $cohortid, 'userid' => $userid))) {
604 $warning['warningcode'] = '3';
605 $warning['message'] = 'record already exists: cohort('.$cohorttype['type'].'='.$cohorttype['value'].' '.
606 $usertype['type'].'='.$usertype['value'].')';
607 $warnings[] = $warning;
610 $cohort = $DB->get_record('cohort', array('id'=>$cohortid), '*', MUST_EXIST
);
611 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
612 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
614 $warning['warningcode'] = '1';
615 $warning['message'] = 'Invalid context: '.$context->contextlevel
;
616 $warnings[] = $warning;
619 self
::validate_context($context);
620 } catch (Exception
$e) {
621 throw new moodle_exception('Error', 'cohort', '', $e->getMessage());
623 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
624 throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
626 cohort_add_member($cohortid, $userid);
628 $transaction->allow_commit();
631 $result['warnings'] = $warnings;
636 * Returns description of method result value
641 public static function add_cohort_members_returns() {
642 return new external_single_structure(
644 'warnings' => new external_warnings()
650 * Returns description of method parameters
652 * @return external_function_parameters
655 public static function delete_cohort_members_parameters() {
656 return new external_function_parameters(
658 'members' => new external_multiple_structure(
659 new external_single_structure(
661 'cohortid' => new external_value(PARAM_INT
, 'cohort record id'),
662 'userid' => new external_value(PARAM_INT
, 'user id'),
671 * Delete cohort members
673 * @param array $members of arrays with keys userid, cohortid
676 public static function delete_cohort_members($members) {
678 require_once("$CFG->dirroot/cohort/lib.php");
680 // Validate parameters.
681 $params = self
::validate_parameters(self
::delete_cohort_members_parameters(), array('members' => $members));
683 $transaction = $DB->start_delegated_transaction();
685 foreach ($params['members'] as $member) {
686 $cohortid = $member['cohortid'];
687 $userid = $member['userid'];
689 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST
);
690 $user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0, 'mnethostid' => $CFG->mnet_localhost_id
),
693 // Now security checks.
694 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
695 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
696 throw new invalid_parameter_exception('Invalid context');
698 self
::validate_context($context);
699 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
700 throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
703 cohort_remove_member($cohort->id
, $user->id
);
705 $transaction->allow_commit();
709 * Returns description of method result value
714 public static function delete_cohort_members_returns() {
719 * Returns description of method parameters
721 * @return external_function_parameters
724 public static function get_cohort_members_parameters() {
725 return new external_function_parameters(
727 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT
, 'Cohort ID')),
733 * Return all members for a cohort
735 * @param array $cohortids array of cohort ids
736 * @return array with cohort id keys containing arrays of user ids
739 public static function get_cohort_members($cohortids) {
741 $params = self
::validate_parameters(self
::get_cohort_members_parameters(), array('cohortids' => $cohortids));
745 foreach ($params['cohortids'] as $cohortid) {
747 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST
);
748 // Now security checks.
749 $context = context
::instance_by_id($cohort->contextid
, MUST_EXIST
);
750 if ($context->contextlevel
!= CONTEXT_COURSECAT
and $context->contextlevel
!= CONTEXT_SYSTEM
) {
751 throw new invalid_parameter_exception('Invalid context');
753 self
::validate_context($context);
754 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
755 throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
758 $cohortmembers = $DB->get_records_sql("SELECT u.id FROM {user} u, {cohort_members} cm
759 WHERE u.id = cm.userid AND cm.cohortid = ?
760 ORDER BY lastname ASC, firstname ASC", array($cohort->id
));
761 $members[] = array('cohortid' => $cohortid, 'userids' => array_keys($cohortmembers));
767 * Returns description of method result value
769 * @return external_description
772 public static function get_cohort_members_returns() {
773 return new external_multiple_structure(
774 new external_single_structure(
776 'cohortid' => new external_value(PARAM_INT
, 'cohort record id'),
777 'userids' => new external_multiple_structure(new external_value(PARAM_INT
, 'user id')),