Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
  • Differences Between: [Versions 310 and 34] [Versions 34 and 310]

       1  <?php
       2  // This file is part of Moodle - http://moodle.org/
       3  //
       4  // Moodle is free software: you can redistribute it and/or modify
       5  // it under the terms of the GNU General Public License as published by
       6  // the Free Software Foundation, either version 3 of the License, or
       7  // (at your option) any later version.
       8  //
       9  // Moodle is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      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  
      17  /**
      18   * External cohort API
      19   *
      20   * @package    core_cohort
      21   * @category   external
      22   * @copyright  MediaTouch 2000 srl
      23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      24   */
      25  
      26  defined('MOODLE_INTERNAL') || die();
      27  
      28  require_once("$CFG->libdir/externallib.php");
      29  
      30  class core_cohort_external extends external_api {
      31  
      32      /**
      33       * Returns description of method parameters
      34       *
      35       * @return external_function_parameters
      36       * @since Moodle 2.5
      37       */
      38      public static function create_cohorts_parameters() {
      39          return new external_function_parameters(
      40              array(
      41                  'cohorts' => new external_multiple_structure(
      42                      new external_single_structure(
      43                          array(
      44                              'categorytype' => new external_single_structure(
      45                                  array(
      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')
      50                                  )
      51                              ),
      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),
      57                              'theme' => new external_value(PARAM_THEME,
      58                                  'the cohort theme. The allowcohortthemes setting must be enabled on Moodle',
      59                                  VALUE_OPTIONAL
      60                              ),
      61                          )
      62                      )
      63                  )
      64              )
      65          );
      66      }
      67  
      68      /**
      69       * Create one or more cohorts
      70       *
      71       * @param array $cohorts An array of cohorts to create.
      72       * @return array An array of arrays
      73       * @since Moodle 2.5
      74       */
      75      public static function create_cohorts($cohorts) {
      76          global $CFG, $DB;
      77          require_once("$CFG->dirroot/cohort/lib.php");
      78  
      79          $params = self::validate_parameters(self::create_cohorts_parameters(), array('cohorts' => $cohorts));
      80  
      81          $availablethemes = cohort_get_list_of_themes();
      82  
      83          $transaction = $DB->start_delegated_transaction();
      84  
      85          $syscontext = context_system::instance();
      86          $cohortids = array();
      87  
      88          foreach ($params['cohorts'] as $cohort) {
      89              $cohort = (object)$cohort;
      90  
      91              // Category type (context id).
      92              $categorytype = $cohort->categorytype;
      93              if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
      94                  throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
      95              }
      96              if ($categorytype['type'] === 'system') {
      97                  $cohort->contextid = $syscontext->id;
      98              } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
      99                  $catcontext = context_coursecat::instance($catid);
     100                  $cohort->contextid = $catcontext->id;
     101              } else {
     102                  throw new invalid_parameter_exception('category not exists: category '
     103                      .$categorytype['type'].' = '.$categorytype['value']);
     104              }
     105              // Make sure that the idnumber doesn't already exist.
     106              if ($DB->record_exists('cohort', array('idnumber' => $cohort->idnumber))) {
     107                  throw new invalid_parameter_exception('record already exists: idnumber='.$cohort->idnumber);
     108              }
     109              $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     110              if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     111                  throw new invalid_parameter_exception('Invalid context');
     112              }
     113              self::validate_context($context);
     114              require_capability('moodle/cohort:manage', $context);
     115  
     116              // Make sure theme is valid.
     117              if (isset($cohort->theme)) {
     118                  if (!empty($CFG->allowcohortthemes)) {
     119                      if (empty($availablethemes[$cohort->theme])) {
     120                          throw new moodle_exception('errorinvalidparam', 'webservice', '', 'theme');
     121                      }
     122                  }
     123              }
     124  
     125              // Validate format.
     126              $cohort->descriptionformat = external_validate_format($cohort->descriptionformat);
     127              $cohort->id = cohort_add_cohort($cohort);
     128  
     129              list($cohort->description, $cohort->descriptionformat) =
     130                  external_format_text($cohort->description, $cohort->descriptionformat,
     131                          $context->id, 'cohort', 'description', $cohort->id);
     132              $cohortids[] = (array)$cohort;
     133          }
     134          $transaction->allow_commit();
     135  
     136          return $cohortids;
     137      }
     138  
     139      /**
     140       * Returns description of method result value
     141       *
     142       * @return external_description
     143       * @since Moodle 2.5
     144       */
     145      public static function create_cohorts_returns() {
     146          return new external_multiple_structure(
     147              new external_single_structure(
     148                  array(
     149                      'id' => new external_value(PARAM_INT, 'cohort id'),
     150                      'name' => new external_value(PARAM_RAW, 'cohort name'),
     151                      'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
     152                      'description' => new external_value(PARAM_RAW, 'cohort description'),
     153                      'descriptionformat' => new external_format_value('description'),
     154                      'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
     155                      'theme' => new external_value(PARAM_THEME, 'cohort theme', VALUE_OPTIONAL),
     156                  )
     157              )
     158          );
     159      }
     160  
     161      /**
     162       * Returns description of method parameters
     163       *
     164       * @return external_function_parameters
     165       * @since Moodle 2.5
     166       */
     167      public static function delete_cohorts_parameters() {
     168          return new external_function_parameters(
     169              array(
     170                  'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'cohort ID')),
     171              )
     172          );
     173      }
     174  
     175      /**
     176       * Delete cohorts
     177       *
     178       * @param array $cohortids
     179       * @return null
     180       * @since Moodle 2.5
     181       */
     182      public static function delete_cohorts($cohortids) {
     183          global $CFG, $DB;
     184          require_once("$CFG->dirroot/cohort/lib.php");
     185  
     186          $params = self::validate_parameters(self::delete_cohorts_parameters(), array('cohortids' => $cohortids));
     187  
     188          $transaction = $DB->start_delegated_transaction();
     189  
     190          foreach ($params['cohortids'] as $cohortid) {
     191              // Validate params.
     192              $cohortid = validate_param($cohortid, PARAM_INT);
     193              $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
     194  
     195              // Now security checks.
     196              $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     197              if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     198                  throw new invalid_parameter_exception('Invalid context');
     199              }
     200              self::validate_context($context);
     201              require_capability('moodle/cohort:manage', $context);
     202              cohort_delete_cohort($cohort);
     203          }
     204          $transaction->allow_commit();
     205  
     206          return null;
     207      }
     208  
     209      /**
     210       * Returns description of method result value
     211       *
     212       * @return null
     213       * @since Moodle 2.5
     214       */
     215      public static function delete_cohorts_returns() {
     216          return null;
     217      }
     218  
     219      /**
     220       * Returns description of method parameters
     221       *
     222       * @return external_function_parameters
     223       * @since Moodle 2.5
     224       */
     225      public static function get_cohorts_parameters() {
     226          return new external_function_parameters(
     227              array(
     228                  'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'Cohort ID')
     229                      , 'List of cohort id. A cohort id is an integer.', VALUE_DEFAULT, array()),
     230              )
     231          );
     232      }
     233  
     234      /**
     235       * Get cohorts definition specified by ids
     236       *
     237       * @param array $cohortids array of cohort ids
     238       * @return array of cohort objects (id, courseid, name)
     239       * @since Moodle 2.5
     240       */
     241      public static function get_cohorts($cohortids = array()) {
     242          global $DB, $CFG;
     243  
     244          $params = self::validate_parameters(self::get_cohorts_parameters(), array('cohortids' => $cohortids));
     245  
     246          if (empty($cohortids)) {
     247              $cohorts = $DB->get_records('cohort');
     248          } else {
     249              $cohorts = $DB->get_records_list('cohort', 'id', $params['cohortids']);
     250          }
     251  
     252          $cohortsinfo = array();
     253          foreach ($cohorts as $cohort) {
     254              // Now security checks.
     255              $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     256              if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     257                  throw new invalid_parameter_exception('Invalid context');
     258              }
     259              self::validate_context($context);
     260              if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
     261                  throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
     262              }
     263  
     264              // Only return theme when $CFG->allowcohortthemes is enabled.
     265              if (!empty($cohort->theme) && empty($CFG->allowcohortthemes)) {
     266                  $cohort->theme = null;
     267              }
     268  
     269              list($cohort->description, $cohort->descriptionformat) =
     270                  external_format_text($cohort->description, $cohort->descriptionformat,
     271                          $context->id, 'cohort', 'description', $cohort->id);
     272  
     273              $cohortsinfo[] = (array) $cohort;
     274          }
     275          return $cohortsinfo;
     276      }
     277  
     278  
     279      /**
     280       * Returns description of method result value
     281       *
     282       * @return external_description
     283       * @since Moodle 2.5
     284       */
     285      public static function get_cohorts_returns() {
     286          return new external_multiple_structure(
     287              new external_single_structure(
     288                  array(
     289                      'id' => new external_value(PARAM_INT, 'ID of the cohort'),
     290                      'name' => new external_value(PARAM_RAW, 'cohort name'),
     291                      'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
     292                      'description' => new external_value(PARAM_RAW, 'cohort description'),
     293                      'descriptionformat' => new external_format_value('description'),
     294                      'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
     295                      'theme' => new external_value(PARAM_THEME, 'cohort theme', VALUE_OPTIONAL),
     296                  )
     297              )
     298          );
     299      }
     300  
     301      /**
     302       * Returns the description of external function parameters.
     303       *
     304       * @return external_function_parameters
     305       */
     306      public static function search_cohorts_parameters() {
     307          $query = new external_value(
     308              PARAM_RAW,
     309              'Query string'
     310          );
     311          $includes = new external_value(
     312              PARAM_ALPHA,
     313              'What other contexts to fetch the frameworks from. (all, parents, self)',
     314              VALUE_DEFAULT,
     315              'parents'
     316          );
     317          $limitfrom = new external_value(
     318              PARAM_INT,
     319              'limitfrom we are fetching the records from',
     320              VALUE_DEFAULT,
     321              0
     322          );
     323          $limitnum = new external_value(
     324              PARAM_INT,
     325              'Number of records to fetch',
     326              VALUE_DEFAULT,
     327              25
     328          );
     329          return new external_function_parameters(array(
     330              'query' => $query,
     331              'context' => self::get_context_parameters(),
     332              'includes' => $includes,
     333              'limitfrom' => $limitfrom,
     334              'limitnum' => $limitnum
     335          ));
     336      }
     337  
     338      /**
     339       * Search cohorts.
     340       *
     341       * @param string $query
     342       * @param array $context
     343       * @param string $includes
     344       * @param int $limitfrom
     345       * @param int $limitnum
     346       * @return array
     347       */
     348      public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
     349          global $CFG;
     350          require_once($CFG->dirroot . '/cohort/lib.php');
     351  
     352          $params = self::validate_parameters(self::search_cohorts_parameters(), array(
     353              'query' => $query,
     354              'context' => $context,
     355              'includes' => $includes,
     356              'limitfrom' => $limitfrom,
     357              'limitnum' => $limitnum,
     358          ));
     359          $query = $params['query'];
     360          $includes = $params['includes'];
     361          $context = self::get_context_from_params($params['context']);
     362          $limitfrom = $params['limitfrom'];
     363          $limitnum = $params['limitnum'];
     364  
     365          self::validate_context($context);
     366  
     367          $manager = has_capability('moodle/cohort:manage', $context);
     368          if (!$manager) {
     369              require_capability('moodle/cohort:view', $context);
     370          }
     371  
     372          // TODO Make this more efficient.
     373          if ($includes == 'self') {
     374              $results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
     375              $results = $results['cohorts'];
     376          } else if ($includes == 'parents') {
     377              $results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
     378              $results = $results['cohorts'];
     379              if (!$context instanceof context_system) {
     380                  $results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL, $limitfrom, $limitnum, $query));
     381              }
     382          } else if ($includes == 'all') {
     383              $results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
     384              $results = $results['cohorts'];
     385          } else {
     386              throw new coding_exception('Invalid parameter value for \'includes\'.');
     387          }
     388  
     389          $cohorts = array();
     390          foreach ($results as $key => $cohort) {
     391              $cohortcontext = context::instance_by_id($cohort->contextid);
     392  
     393              // Only return theme when $CFG->allowcohortthemes is enabled.
     394              if (!empty($cohort->theme) && empty($CFG->allowcohortthemes)) {
     395                  $cohort->theme = null;
     396              }
     397  
     398              if (!isset($cohort->description)) {
     399                  $cohort->description = '';
     400              }
     401              if (!isset($cohort->descriptionformat)) {
     402                  $cohort->descriptionformat = FORMAT_PLAIN;
     403              }
     404  
     405              list($cohort->description, $cohort->descriptionformat) =
     406                  external_format_text($cohort->description, $cohort->descriptionformat,
     407                          $cohortcontext->id, 'cohort', 'description', $cohort->id);
     408  
     409              $cohorts[$key] = $cohort;
     410          }
     411  
     412          return array('cohorts' => $cohorts);
     413      }
     414  
     415      /**
     416       * Returns description of external function result value.
     417       *
     418       * @return external_description
     419       */
     420      public static function search_cohorts_returns() {
     421          return new external_single_structure(array(
     422              'cohorts' => new external_multiple_structure(
     423                  new external_single_structure(array(
     424                      'id' => new external_value(PARAM_INT, 'ID of the cohort'),
     425                      'name' => new external_value(PARAM_RAW, 'cohort name'),
     426                      'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
     427                      'description' => new external_value(PARAM_RAW, 'cohort description'),
     428                      'descriptionformat' => new external_format_value('description'),
     429                      'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
     430                      'theme' => new external_value(PARAM_THEME, 'cohort theme', VALUE_OPTIONAL),
     431                  ))
     432              )
     433          ));
     434      }
     435  
     436  
     437  
     438      /**
     439       * Returns description of method parameters
     440       *
     441       * @return external_function_parameters
     442       * @since Moodle 2.5
     443       */
     444      public static function update_cohorts_parameters() {
     445          return new external_function_parameters(
     446              array(
     447                  'cohorts' => new external_multiple_structure(
     448                      new external_single_structure(
     449                          array(
     450                              'id' => new external_value(PARAM_INT, 'ID of the cohort'),
     451                              'categorytype' => new external_single_structure(
     452                                  array(
     453                                      'type' => new external_value(PARAM_TEXT, 'the name of the field: id (numeric value
     454                                          of course category id) or idnumber (alphanumeric value of idnumber course category)
     455                                          or system (value ignored)'),
     456                                      'value' => new external_value(PARAM_RAW, 'the value of the categorytype')
     457                                  )
     458                              ),
     459                              'name' => new external_value(PARAM_RAW, 'cohort name'),
     460                              'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
     461                              'description' => new external_value(PARAM_RAW, 'cohort description', VALUE_OPTIONAL),
     462                              'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
     463                              'visible' => new external_value(PARAM_BOOL, 'cohort visible', VALUE_OPTIONAL),
     464                              'theme' => new external_value(PARAM_THEME,
     465                                  'the cohort theme. The allowcohortthemes setting must be enabled on Moodle',
     466                                  VALUE_OPTIONAL
     467                              ),
     468                          )
     469                      )
     470                  )
     471              )
     472          );
     473      }
     474  
     475      /**
     476       * Update cohorts
     477       *
     478       * @param array $cohorts
     479       * @return null
     480       * @since Moodle 2.5
     481       */
     482      public static function update_cohorts($cohorts) {
     483          global $CFG, $DB;
     484          require_once("$CFG->dirroot/cohort/lib.php");
     485  
     486          $params = self::validate_parameters(self::update_cohorts_parameters(), array('cohorts' => $cohorts));
     487  
     488          $availablethemes = cohort_get_list_of_themes();
     489  
     490          $transaction = $DB->start_delegated_transaction();
     491          $syscontext = context_system::instance();
     492  
     493          foreach ($params['cohorts'] as $cohort) {
     494              $cohort = (object) $cohort;
     495  
     496              if (trim($cohort->name) == '') {
     497                  throw new invalid_parameter_exception('Invalid cohort name');
     498              }
     499  
     500              $oldcohort = $DB->get_record('cohort', array('id' => $cohort->id), '*', MUST_EXIST);
     501              $oldcontext = context::instance_by_id($oldcohort->contextid, MUST_EXIST);
     502              require_capability('moodle/cohort:manage', $oldcontext);
     503  
     504              // Category type (context id).
     505              $categorytype = $cohort->categorytype;
     506              if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
     507                  throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
     508              }
     509              if ($categorytype['type'] === 'system') {
     510                  $cohort->contextid = $syscontext->id;
     511              } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
     512                  $cohort->contextid = $DB->get_field('context', 'id', array('instanceid' => $catid,
     513                      'contextlevel' => CONTEXT_COURSECAT));
     514              } else {
     515                  throw new invalid_parameter_exception('category not exists: category='.$categorytype['value']);
     516              }
     517  
     518              if ($cohort->contextid != $oldcohort->contextid) {
     519                  $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     520                  if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     521                      throw new invalid_parameter_exception('Invalid context');
     522                  }
     523  
     524                  self::validate_context($context);
     525                  require_capability('moodle/cohort:manage', $context);
     526              }
     527  
     528              // Make sure theme is valid.
     529              if (!empty($cohort->theme) && !empty($CFG->allowcohortthemes)) {
     530                  if (empty($availablethemes[$cohort->theme])) {
     531                      $debuginfo = 'The following cohort theme is not installed on this site: '.$cohort->theme;
     532                      throw new moodle_exception('errorinvalidparam', 'webservice', '', 'theme', $debuginfo);
     533                  }
     534              }
     535  
     536              if (!empty($cohort->description)) {
     537                  $cohort->descriptionformat = external_validate_format($cohort->descriptionformat);
     538              }
     539  
     540              cohort_update_cohort($cohort);
     541          }
     542  
     543          $transaction->allow_commit();
     544  
     545          return null;
     546      }
     547  
     548      /**
     549       * Returns description of method result value
     550       *
     551       * @return null
     552       * @since Moodle 2.5
     553       */
     554      public static function update_cohorts_returns() {
     555          return null;
     556      }
     557  
     558      /**
     559       * Returns description of method parameters
     560       *
     561       * @return external_function_parameters
     562       * @since Moodle 2.5
     563       */
     564      public static function add_cohort_members_parameters() {
     565          return new external_function_parameters (
     566              array(
     567                  'members' => new external_multiple_structure (
     568                      new external_single_structure (
     569                          array (
     570                              'cohorttype' => new external_single_structure (
     571                                  array(
     572                                      'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the field: id
     573                                          (numeric value of cohortid) or idnumber (alphanumeric value of idnumber) '),
     574                                      'value' => new external_value(PARAM_RAW, 'The value of the cohort')
     575                                  )
     576                              ),
     577                              'usertype' => new external_single_structure (
     578                                  array(
     579                                      'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the field: id
     580                                          (numeric value of id) or username (alphanumeric value of username) '),
     581                                      'value' => new external_value(PARAM_RAW, 'The value of the cohort')
     582                                  )
     583                              )
     584                          )
     585                      )
     586                  )
     587              )
     588          );
     589      }
     590  
     591      /**
     592       * Add cohort members
     593       *
     594       * @param array $members of arrays with keys userid, cohortid
     595       * @since Moodle 2.5
     596       */
     597      public static function add_cohort_members($members) {
     598          global $CFG, $DB;
     599          require_once($CFG->dirroot."/cohort/lib.php");
     600  
     601          $params = self::validate_parameters(self::add_cohort_members_parameters(), array('members' => $members));
     602  
     603          $transaction = $DB->start_delegated_transaction();
     604          $warnings = array();
     605          foreach ($params['members'] as $member) {
     606              // Cohort parameters.
     607              $cohorttype = $member['cohorttype'];
     608              $cohortparam = array($cohorttype['type'] => $cohorttype['value']);
     609              // User parameters.
     610              $usertype = $member['usertype'];
     611              $userparam = array($usertype['type'] => $usertype['value']);
     612              try {
     613                  // Check parameters.
     614                  if ($cohorttype['type'] != 'id' && $cohorttype['type'] != 'idnumber') {
     615                      $warning = array();
     616                      $warning['warningcode'] = '1';
     617                      $warning['message'] = 'invalid parameter: cohortype='.$cohorttype['type'];
     618                      $warnings[] = $warning;
     619                      continue;
     620                  }
     621                  if ($usertype['type'] != 'id' && $usertype['type'] != 'username') {
     622                      $warning = array();
     623                      $warning['warningcode'] = '1';
     624                      $warning['message'] = 'invalid parameter: usertype='.$usertype['type'];
     625                      $warnings[] = $warning;
     626                      continue;
     627                  }
     628                  // Extract parameters.
     629                  if (!$cohortid = $DB->get_field('cohort', 'id', $cohortparam)) {
     630                      $warning = array();
     631                      $warning['warningcode'] = '2';
     632                      $warning['message'] = 'cohort '.$cohorttype['type'].'='.$cohorttype['value'].' not exists';
     633                      $warnings[] = $warning;
     634                      continue;
     635                  }
     636                  if (!$userid = $DB->get_field('user', 'id', array_merge($userparam, array('deleted' => 0,
     637                      'mnethostid' => $CFG->mnet_localhost_id)))) {
     638                      $warning = array();
     639                      $warning['warningcode'] = '2';
     640                      $warning['message'] = 'user '.$usertype['type'].'='.$usertype['value'].' not exists';
     641                      $warnings[] = $warning;
     642                      continue;
     643                  }
     644                  if ($DB->record_exists('cohort_members', array('cohortid' => $cohortid, 'userid' => $userid))) {
     645                      $warning = array();
     646                      $warning['warningcode'] = '3';
     647                      $warning['message'] = 'record already exists: cohort('.$cohorttype['type'].'='.$cohorttype['value'].' '.
     648                          $usertype['type'].'='.$usertype['value'].')';
     649                      $warnings[] = $warning;
     650                      continue;
     651                  }
     652                  $cohort = $DB->get_record('cohort', array('id'=>$cohortid), '*', MUST_EXIST);
     653                  $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     654                  if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     655                      $warning = array();
     656                      $warning['warningcode'] = '1';
     657                      $warning['message'] = 'Invalid context: '.$context->contextlevel;
     658                      $warnings[] = $warning;
     659                      continue;
     660                  }
     661                  self::validate_context($context);
     662              } catch (Exception $e) {
     663                  throw new moodle_exception('Error', 'cohort', '', $e->getMessage());
     664              }
     665              if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
     666                  throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
     667              }
     668              cohort_add_member($cohortid, $userid);
     669          }
     670          $transaction->allow_commit();
     671          // Return.
     672          $result = array();
     673          $result['warnings'] = $warnings;
     674          return $result;
     675      }
     676  
     677      /**
     678       * Returns description of method result value
     679       *
     680       * @return null
     681       * @since Moodle 2.5
     682       */
     683      public static function add_cohort_members_returns() {
     684          return new external_single_structure(
     685              array(
     686                  'warnings' => new external_warnings()
     687              )
     688          );
     689      }
     690  
     691      /**
     692       * Returns description of method parameters
     693       *
     694       * @return external_function_parameters
     695       * @since Moodle 2.5
     696       */
     697      public static function delete_cohort_members_parameters() {
     698          return new external_function_parameters(
     699              array(
     700                  'members' => new external_multiple_structure(
     701                      new external_single_structure(
     702                          array(
     703                              'cohortid' => new external_value(PARAM_INT, 'cohort record id'),
     704                              'userid' => new external_value(PARAM_INT, 'user id'),
     705                          )
     706                      )
     707                  )
     708              )
     709          );
     710      }
     711  
     712      /**
     713       * Delete cohort members
     714       *
     715       * @param array $members of arrays with keys userid, cohortid
     716       * @since Moodle 2.5
     717       */
     718      public static function delete_cohort_members($members) {
     719          global $CFG, $DB;
     720          require_once("$CFG->dirroot/cohort/lib.php");
     721  
     722          // Validate parameters.
     723          $params = self::validate_parameters(self::delete_cohort_members_parameters(), array('members' => $members));
     724  
     725          $transaction = $DB->start_delegated_transaction();
     726  
     727          foreach ($params['members'] as $member) {
     728              $cohortid = $member['cohortid'];
     729              $userid = $member['userid'];
     730  
     731              $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
     732              $user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0, 'mnethostid' => $CFG->mnet_localhost_id),
     733                  '*', MUST_EXIST);
     734  
     735              // Now security checks.
     736              $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     737              if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     738                  throw new invalid_parameter_exception('Invalid context');
     739              }
     740              self::validate_context($context);
     741              if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
     742                  throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
     743              }
     744  
     745              cohort_remove_member($cohort->id, $user->id);
     746          }
     747          $transaction->allow_commit();
     748      }
     749  
     750      /**
     751       * Returns description of method result value
     752       *
     753       * @return null
     754       * @since Moodle 2.5
     755       */
     756      public static function delete_cohort_members_returns() {
     757          return null;
     758      }
     759  
     760      /**
     761       * Returns description of method parameters
     762       *
     763       * @return external_function_parameters
     764       * @since Moodle 2.5
     765       */
     766      public static function get_cohort_members_parameters() {
     767          return new external_function_parameters(
     768              array(
     769                  'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'Cohort ID')),
     770              )
     771          );
     772      }
     773  
     774      /**
     775       * Return all members for a cohort
     776       *
     777       * @param array $cohortids array of cohort ids
     778       * @return array with cohort id keys containing arrays of user ids
     779       * @since Moodle 2.5
     780       */
     781      public static function get_cohort_members($cohortids) {
     782          global $DB;
     783          $params = self::validate_parameters(self::get_cohort_members_parameters(), array('cohortids' => $cohortids));
     784  
     785          $members = array();
     786  
     787          foreach ($params['cohortids'] as $cohortid) {
     788              // Validate params.
     789              $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
     790              // Now security checks.
     791              $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
     792              if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
     793                  throw new invalid_parameter_exception('Invalid context');
     794              }
     795              self::validate_context($context);
     796              if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
     797                  throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
     798              }
     799  
     800              $cohortmembers = $DB->get_records_sql("SELECT u.id FROM {user} u, {cohort_members} cm
     801                  WHERE u.id = cm.userid AND cm.cohortid = ?
     802                  ORDER BY lastname ASC, firstname ASC", array($cohort->id));
     803              $members[] = array('cohortid' => $cohortid, 'userids' => array_keys($cohortmembers));
     804          }
     805          return $members;
     806      }
     807  
     808      /**
     809       * Returns description of method result value
     810       *
     811       * @return external_description
     812       * @since Moodle 2.5
     813       */
     814      public static function get_cohort_members_returns() {
     815          return new external_multiple_structure(
     816              new external_single_structure(
     817                  array(
     818                      'cohortid' => new external_value(PARAM_INT, 'cohort record id'),
     819                      'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user id')),
     820                  )
     821              )
     822          );
     823      }
     824  }