Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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   * Choice module external API
  19   *
  20   * @package    mod_choice
  21   * @category   external
  22   * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @since      Moodle 3.0
  25   */
  26  
  27  use core_course\external\helper_for_get_mods_by_courses;
  28  
  29  defined('MOODLE_INTERNAL') || die;
  30  require_once($CFG->libdir . '/externallib.php');
  31  require_once($CFG->dirroot . '/mod/choice/lib.php');
  32  
  33  /**
  34   * Choice module external functions
  35   *
  36   * @package    mod_choice
  37   * @category   external
  38   * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
  39   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   * @since      Moodle 3.0
  41   */
  42  class mod_choice_external extends external_api {
  43  
  44      /**
  45       * Describes the parameters for get_choices_by_courses.
  46       *
  47       * @return external_function_parameters
  48       * @since Moodle 3.0
  49       */
  50      public static function get_choice_results_parameters() {
  51          return new external_function_parameters (array('choiceid' => new external_value(PARAM_INT, 'choice instance id')));
  52      }
  53      /**
  54       * Returns user's results for a specific choice
  55       * and a list of those users that did not answered yet.
  56       *
  57       * @param int $choiceid the choice instance id
  58       * @return array of responses details
  59       * @since Moodle 3.0
  60       */
  61      public static function get_choice_results($choiceid) {
  62          global $USER, $PAGE;
  63  
  64          $params = self::validate_parameters(self::get_choice_results_parameters(), array('choiceid' => $choiceid));
  65  
  66          if (!$choice = choice_get_choice($params['choiceid'])) {
  67              throw new moodle_exception("invalidcoursemodule", "error");
  68          }
  69          list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
  70  
  71          $context = context_module::instance($cm->id);
  72          self::validate_context($context);
  73  
  74          $groupmode = groups_get_activity_groupmode($cm);
  75          // Check if we have to include responses from inactive users.
  76          $onlyactive = $choice->includeinactive ? false : true;
  77          $users = choice_get_response_data($choice, $cm, $groupmode, $onlyactive);
  78          // Show those who haven't answered the question.
  79          if (!empty($choice->showunanswered)) {
  80              $choice->option[0] = get_string('notanswered', 'choice');
  81              $choice->maxanswers[0] = 0;
  82          }
  83          $results = prepare_choice_show_results($choice, $course, $cm, $users);
  84  
  85          $options = array();
  86          $fullnamecap = has_capability('moodle/site:viewfullnames', $context);
  87          foreach ($results->options as $optionid => $option) {
  88  
  89              $userresponses = array();
  90              $numberofuser = 0;
  91              $percentageamount = 0;
  92              if (property_exists($option, 'user') and
  93                  (has_capability('mod/choice:readresponses', $context) or choice_can_view_results($choice))) {
  94                  $numberofuser = count($option->user);
  95                  $percentageamount = ((float)$numberofuser / (float)$results->numberofuser) * 100.0;
  96                  if ($choice->publish) {
  97                      foreach ($option->user as $userresponse) {
  98                          $response = array();
  99                          $response['userid'] = $userresponse->id;
 100                          $response['fullname'] = fullname($userresponse, $fullnamecap);
 101  
 102                          $userpicture = new user_picture($userresponse);
 103                          $userpicture->size = 1; // Size f1.
 104                          $response['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
 105  
 106                          // Add optional properties.
 107                          foreach (array('answerid', 'timemodified') as $field) {
 108                              if (property_exists($userresponse, 'answerid')) {
 109                                  $response[$field] = $userresponse->$field;
 110                              }
 111                          }
 112                          $userresponses[] = $response;
 113                      }
 114                  }
 115              }
 116  
 117              $options[] = array('id'               => $optionid,
 118                                 'text'             => external_format_string($option->text, $context->id),
 119                                 'maxanswer'        => $option->maxanswer,
 120                                 'userresponses'    => $userresponses,
 121                                 'numberofuser'     => $numberofuser,
 122                                 'percentageamount' => $percentageamount
 123                                );
 124          }
 125  
 126          $warnings = array();
 127          return array(
 128              'options' => $options,
 129              'warnings' => $warnings
 130          );
 131      }
 132  
 133      /**
 134       * Describes the get_choice_results return value.
 135       *
 136       * @return external_single_structure
 137       * @since Moodle 3.0
 138       */
 139      public static function get_choice_results_returns() {
 140          return new external_single_structure(
 141              array(
 142                  'options' => new external_multiple_structure(
 143                      new external_single_structure(
 144                          array(
 145                              'id' => new external_value(PARAM_INT, 'choice instance id'),
 146                              'text' => new external_value(PARAM_RAW, 'text of the choice'),
 147                              'maxanswer' => new external_value(PARAM_INT, 'maximum number of answers'),
 148                              'userresponses' => new external_multiple_structure(
 149                                   new external_single_structure(
 150                                       array(
 151                                          'userid' => new external_value(PARAM_INT, 'user id'),
 152                                          'fullname' => new external_value(PARAM_NOTAGS, 'user full name'),
 153                                          'profileimageurl' => new external_value(PARAM_URL, 'profile user image url'),
 154                                          'answerid' => new external_value(PARAM_INT, 'answer id', VALUE_OPTIONAL),
 155                                          'timemodified' => new external_value(PARAM_INT, 'time of modification', VALUE_OPTIONAL),
 156                                       ), 'User responses'
 157                                   )
 158                              ),
 159                              'numberofuser' => new external_value(PARAM_INT, 'number of users answers'),
 160                              'percentageamount' => new external_value(PARAM_FLOAT, 'percentage of users answers')
 161                          ), 'Options'
 162                      )
 163                  ),
 164                  'warnings' => new external_warnings(),
 165              )
 166          );
 167      }
 168  
 169      /**
 170       * Describes the parameters for mod_choice_get_choice_options.
 171       *
 172       * @return external_function_parameters
 173       * @since Moodle 3.0
 174       */
 175      public static function get_choice_options_parameters() {
 176          return new external_function_parameters (array('choiceid' => new external_value(PARAM_INT, 'choice instance id')));
 177      }
 178  
 179      /**
 180       * Returns options for a specific choice
 181       *
 182       * @param int $choiceid the choice instance id
 183       * @return array of options details
 184       * @since Moodle 3.0
 185       */
 186      public static function get_choice_options($choiceid) {
 187          global $USER;
 188          $warnings = array();
 189          $params = self::validate_parameters(self::get_choice_options_parameters(), array('choiceid' => $choiceid));
 190  
 191          if (!$choice = choice_get_choice($params['choiceid'])) {
 192              throw new moodle_exception("invalidcoursemodule", "error");
 193          }
 194          list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
 195  
 196          $context = context_module::instance($cm->id);
 197          self::validate_context($context);
 198  
 199          require_capability('mod/choice:choose', $context);
 200  
 201          $groupmode = groups_get_activity_groupmode($cm);
 202          $onlyactive = $choice->includeinactive ? false : true;
 203          $allresponses = choice_get_response_data($choice, $cm, $groupmode, $onlyactive);
 204  
 205          $timenow = time();
 206          $choiceopen = true;
 207          $showpreview = false;
 208  
 209          if (!empty($choice->timeopen) && ($choice->timeopen > $timenow)) {
 210              $choiceopen = false;
 211              $warnings[1] = get_string("notopenyet", "choice", userdate($choice->timeopen));
 212              if ($choice->showpreview) {
 213                  $warnings[2] = get_string('previewonly', 'choice', userdate($choice->timeopen));
 214                  $showpreview = true;
 215              }
 216          }
 217          if (!empty($choice->timeclose) && ($timenow > $choice->timeclose)) {
 218              $choiceopen = false;
 219              $warnings[3] = get_string("expired", "choice", userdate($choice->timeclose));
 220          }
 221  
 222          $optionsarray = array();
 223  
 224          if ($choiceopen or $showpreview) {
 225  
 226              $options = choice_prepare_options($choice, $USER, $cm, $allresponses);
 227  
 228              foreach ($options['options'] as $option) {
 229                  $optionarr = array();
 230                  $optionarr['id']            = $option->attributes->value;
 231                  $optionarr['text']          = external_format_string($option->text, $context->id);
 232                  $optionarr['maxanswers']    = $option->maxanswers;
 233                  $optionarr['displaylayout'] = $option->displaylayout;
 234                  $optionarr['countanswers']  = $option->countanswers;
 235                  foreach (array('checked', 'disabled') as $field) {
 236                      if (property_exists($option->attributes, $field) and $option->attributes->$field == 1) {
 237                          $optionarr[$field] = 1;
 238                      } else {
 239                          $optionarr[$field] = 0;
 240                      }
 241                  }
 242                  // When showpreview is active, we show options as disabled.
 243                  if ($showpreview or ($optionarr['checked'] == 1 and !$choice->allowupdate)) {
 244                      $optionarr['disabled'] = 1;
 245                  }
 246                  $optionsarray[] = $optionarr;
 247              }
 248          }
 249          foreach ($warnings as $key => $message) {
 250              $warnings[$key] = array(
 251                  'item' => 'choice',
 252                  'itemid' => $cm->id,
 253                  'warningcode' => $key,
 254                  'message' => $message
 255              );
 256          }
 257          return array(
 258              'options' => $optionsarray,
 259              'warnings' => $warnings
 260          );
 261      }
 262  
 263      /**
 264       * Describes the get_choice_results return value.
 265       *
 266       * @return external_multiple_structure
 267       * @since Moodle 3.0
 268       */
 269      public static function get_choice_options_returns() {
 270          return new external_single_structure(
 271              array(
 272                  'options' => new external_multiple_structure(
 273                      new external_single_structure(
 274                          array(
 275                              'id' => new external_value(PARAM_INT, 'option id'),
 276                              'text' => new external_value(PARAM_RAW, 'text of the choice'),
 277                              'maxanswers' => new external_value(PARAM_INT, 'maximum number of answers'),
 278                              'displaylayout' => new external_value(PARAM_BOOL, 'true for orizontal, otherwise vertical'),
 279                              'countanswers' => new external_value(PARAM_INT, 'number of answers'),
 280                              'checked' => new external_value(PARAM_BOOL, 'we already answered'),
 281                              'disabled' => new external_value(PARAM_BOOL, 'option disabled'),
 282                              )
 283                      ), 'Options'
 284                  ),
 285                  'warnings' => new external_warnings(),
 286              )
 287          );
 288      }
 289  
 290      /**
 291       * Describes the parameters for submit_choice_response.
 292       *
 293       * @return external_function_parameters
 294       * @since Moodle 3.0
 295       */
 296      public static function submit_choice_response_parameters() {
 297          return new external_function_parameters (
 298              array(
 299                  'choiceid' => new external_value(PARAM_INT, 'choice instance id'),
 300                  'responses' => new external_multiple_structure(
 301                      new external_value(PARAM_INT, 'answer id'),
 302                      'Array of response ids'
 303                  ),
 304              )
 305          );
 306      }
 307  
 308      /**
 309       * Submit choice responses
 310       *
 311       * @param int $choiceid the choice instance id
 312       * @param array $responses the response ids
 313       * @return array answers information and warnings
 314       * @since Moodle 3.0
 315       */
 316      public static function submit_choice_response($choiceid, $responses) {
 317          global $USER;
 318  
 319          $warnings = array();
 320          $params = self::validate_parameters(self::submit_choice_response_parameters(),
 321                                              array(
 322                                                  'choiceid' => $choiceid,
 323                                                  'responses' => $responses
 324                                              ));
 325  
 326          if (!$choice = choice_get_choice($params['choiceid'])) {
 327              throw new moodle_exception("invalidcoursemodule", "error");
 328          }
 329          list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
 330  
 331          $context = context_module::instance($cm->id);
 332          self::validate_context($context);
 333  
 334          require_capability('mod/choice:choose', $context);
 335  
 336          $timenow = time();
 337          if (!empty($choice->timeopen) && ($choice->timeopen > $timenow)) {
 338              throw new moodle_exception("notopenyet", "choice", '', userdate($choice->timeopen));
 339          } else if (!empty($choice->timeclose) && ($timenow > $choice->timeclose)) {
 340              throw new moodle_exception("expired", "choice", '', userdate($choice->timeclose));
 341          }
 342  
 343          if (!choice_get_my_response($choice) or $choice->allowupdate) {
 344              // When a single response is given, we convert the array to a simple variable
 345              // in order to avoid choice_user_submit_response to check with allowmultiple even
 346              // for a single response.
 347              if (count($params['responses']) == 1) {
 348                  $params['responses'] = reset($params['responses']);
 349              }
 350              choice_user_submit_response($params['responses'], $choice, $USER->id, $course, $cm);
 351          } else {
 352              throw new moodle_exception('missingrequiredcapability', 'webservice', '', 'allowupdate');
 353          }
 354          $answers = choice_get_my_response($choice);
 355  
 356          return array(
 357              'answers' => $answers,
 358              'warnings' => $warnings
 359          );
 360      }
 361  
 362      /**
 363       * Describes the submit_choice_response return value.
 364       *
 365       * @return external_multiple_structure
 366       * @since Moodle 3.0
 367       */
 368      public static function submit_choice_response_returns() {
 369          return new external_single_structure(
 370              array(
 371                  'answers' => new external_multiple_structure(
 372                       new external_single_structure(
 373                           array(
 374                               'id'           => new external_value(PARAM_INT, 'answer id'),
 375                               'choiceid'     => new external_value(PARAM_INT, 'choiceid'),
 376                               'userid'       => new external_value(PARAM_INT, 'user id'),
 377                               'optionid'     => new external_value(PARAM_INT, 'optionid'),
 378                               'timemodified' => new external_value(PARAM_INT, 'time of last modification')
 379                           ), 'Answers'
 380                       )
 381                  ),
 382                  'warnings' => new external_warnings(),
 383              )
 384          );
 385      }
 386  
 387      /**
 388       * Returns description of method parameters
 389       *
 390       * @return external_function_parameters
 391       * @since Moodle 3.0
 392       */
 393      public static function view_choice_parameters() {
 394          return new external_function_parameters(
 395              array(
 396                  'choiceid' => new external_value(PARAM_INT, 'choice instance id')
 397              )
 398          );
 399      }
 400  
 401      /**
 402       * Trigger the course module viewed event and update the module completion status.
 403       *
 404       * @param int $choiceid the choice instance id
 405       * @return array of warnings and status result
 406       * @since Moodle 3.0
 407       * @throws moodle_exception
 408       */
 409      public static function view_choice($choiceid) {
 410          global $CFG;
 411  
 412          $params = self::validate_parameters(self::view_choice_parameters(),
 413                                              array(
 414                                                  'choiceid' => $choiceid
 415                                              ));
 416          $warnings = array();
 417  
 418          // Request and permission validation.
 419          if (!$choice = choice_get_choice($params['choiceid'])) {
 420              throw new moodle_exception("invalidcoursemodule", "error");
 421          }
 422          list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
 423  
 424          $context = context_module::instance($cm->id);
 425          self::validate_context($context);
 426  
 427          // Trigger course_module_viewed event and completion.
 428          choice_view($choice, $course, $cm, $context);
 429  
 430          $result = array();
 431          $result['status'] = true;
 432          $result['warnings'] = $warnings;
 433          return $result;
 434      }
 435  
 436      /**
 437       * Returns description of method result value
 438       *
 439       * @return external_description
 440       * @since Moodle 3.0
 441       */
 442      public static function view_choice_returns() {
 443          return new external_single_structure(
 444              array(
 445                  'status' => new external_value(PARAM_BOOL, 'status: true if success'),
 446                  'warnings' => new external_warnings()
 447              )
 448          );
 449      }
 450  
 451      /**
 452       * Describes the parameters for get_choices_by_courses.
 453       *
 454       * @return external_function_parameters
 455       * @since Moodle 3.0
 456       */
 457      public static function get_choices_by_courses_parameters() {
 458          return new external_function_parameters (
 459              array(
 460                  'courseids' => new external_multiple_structure(
 461                      new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array()
 462                  ),
 463              )
 464          );
 465      }
 466  
 467      /**
 468       * Returns a list of choices in a provided list of courses,
 469       * if no list is provided all choices that the user can view will be returned.
 470       *
 471       * @param array $courseids the course ids
 472       * @return array of choices details
 473       * @since Moodle 3.0
 474       */
 475      public static function get_choices_by_courses($courseids = array()) {
 476          $returnedchoices = array();
 477          $warnings = array();
 478  
 479          $params = self::validate_parameters(self::get_choices_by_courses_parameters(), array('courseids' => $courseids));
 480  
 481          $courses = array();
 482          if (empty($params['courseids'])) {
 483              $courses = enrol_get_my_courses();
 484              $params['courseids'] = array_keys($courses);
 485          }
 486  
 487          // Ensure there are courseids to loop through.
 488          if (!empty($params['courseids'])) {
 489  
 490              list($courses, $warnings) = external_util::validate_courses($params['courseids'], $courses);
 491  
 492              // Get the choices in this course, this function checks users visibility permissions.
 493              // We can avoid then additional validate_context calls.
 494              $choices = get_all_instances_in_courses("choice", $courses);
 495              foreach ($choices as $choice) {
 496                  $context = context_module::instance($choice->coursemodule);
 497  
 498                  $choicedetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values($choice, 'mod_choice');
 499  
 500                  if (has_capability('mod/choice:choose', $context)) {
 501                      $choicedetails['publish']  = $choice->publish;
 502                      $choicedetails['showresults']  = $choice->showresults;
 503                      $choicedetails['showpreview']  = $choice->showpreview;
 504                      $choicedetails['timeopen']  = $choice->timeopen;
 505                      $choicedetails['timeclose']  = $choice->timeclose;
 506                      $choicedetails['display']  = $choice->display;
 507                      $choicedetails['allowupdate']  = $choice->allowupdate;
 508                      $choicedetails['allowmultiple']  = $choice->allowmultiple;
 509                      $choicedetails['limitanswers']  = $choice->limitanswers;
 510                      $choicedetails['showunanswered']  = $choice->showunanswered;
 511                      $choicedetails['includeinactive']  = $choice->includeinactive;
 512                      $choicedetails['showavailable']  = $choice->showavailable;
 513                  }
 514  
 515                  if (has_capability('moodle/course:manageactivities', $context)) {
 516                      $choicedetails['timemodified']  = $choice->timemodified;
 517                      $choicedetails['completionsubmit']  = $choice->completionsubmit;
 518                  }
 519                  $returnedchoices[] = $choicedetails;
 520              }
 521          }
 522          $result = array();
 523          $result['choices'] = $returnedchoices;
 524          $result['warnings'] = $warnings;
 525          return $result;
 526      }
 527  
 528      /**
 529       * Describes the mod_choice_get_choices_by_courses return value.
 530       *
 531       * @return external_single_structure
 532       * @since Moodle 3.0
 533       */
 534      public static function get_choices_by_courses_returns() {
 535          return new external_single_structure(
 536              array(
 537                  'choices' => new external_multiple_structure(
 538                      new external_single_structure(array_merge(
 539                          helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(),
 540                          [
 541                              'publish' => new external_value(PARAM_BOOL, 'If choice is published', VALUE_OPTIONAL),
 542                              'showresults' => new external_value(PARAM_INT, '0 never, 1 after answer, 2 after close, 3 always',
 543                                                                  VALUE_OPTIONAL),
 544                              'display' => new external_value(PARAM_INT, 'Display mode (vertical, horizontal)', VALUE_OPTIONAL),
 545                              'allowupdate' => new external_value(PARAM_BOOL, 'Allow update', VALUE_OPTIONAL),
 546                              'allowmultiple' => new external_value(PARAM_BOOL, 'Allow multiple choices', VALUE_OPTIONAL),
 547                              'showunanswered' => new external_value(PARAM_BOOL, 'Show users who not answered yet', VALUE_OPTIONAL),
 548                              'includeinactive' => new external_value(PARAM_BOOL, 'Include inactive users', VALUE_OPTIONAL),
 549                              'limitanswers' => new external_value(PARAM_BOOL, 'Limit unswers', VALUE_OPTIONAL),
 550                              'timeopen' => new external_value(PARAM_INT, 'Date of opening validity', VALUE_OPTIONAL),
 551                              'timeclose' => new external_value(PARAM_INT, 'Date of closing validity', VALUE_OPTIONAL),
 552                              'showpreview' => new external_value(PARAM_BOOL, 'Show preview before timeopen', VALUE_OPTIONAL),
 553                              'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL),
 554                              'completionsubmit' => new external_value(PARAM_BOOL, 'Completion on user submission', VALUE_OPTIONAL),
 555                              'showavailable' => new external_value(PARAM_BOOL, 'Show available spaces', VALUE_OPTIONAL),
 556                          ]
 557                      ), 'Choices')
 558                  ),
 559                  'warnings' => new external_warnings(),
 560              )
 561          );
 562      }
 563  
 564      /**
 565       * Describes the parameters for delete_choice_responses.
 566       *
 567       * @return external_function_parameters
 568       * @since Moodle 3.0
 569       */
 570      public static function delete_choice_responses_parameters() {
 571          return new external_function_parameters (
 572              array(
 573                  'choiceid' => new external_value(PARAM_INT, 'choice instance id'),
 574                  'responses' => new external_multiple_structure(
 575                      new external_value(PARAM_INT, 'response id'),
 576                      'Array of response ids, empty for deleting all the current user responses.',
 577                      VALUE_DEFAULT,
 578                      array()
 579                  ),
 580              )
 581          );
 582      }
 583  
 584      /**
 585       * Delete the given submitted responses in a choice
 586       *
 587       * @param int $choiceid the choice instance id
 588       * @param array $responses the response ids,  empty for deleting all the current user responses
 589       * @return array status information and warnings
 590       * @throws moodle_exception
 591       * @since Moodle 3.0
 592       */
 593      public static function delete_choice_responses($choiceid, $responses = array()) {
 594  
 595          $status = false;
 596          $warnings = array();
 597          $params = self::validate_parameters(self::delete_choice_responses_parameters(),
 598                                              array(
 599                                                  'choiceid' => $choiceid,
 600                                                  'responses' => $responses
 601                                              ));
 602  
 603          if (!$choice = choice_get_choice($params['choiceid'])) {
 604              throw new moodle_exception("invalidcoursemodule", "error");
 605          }
 606          list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
 607  
 608          $context = context_module::instance($cm->id);
 609          self::validate_context($context);
 610  
 611          require_capability('mod/choice:choose', $context);
 612  
 613          $candeleteall = has_capability('mod/choice:deleteresponses', $context);
 614          if ($candeleteall || $choice->allowupdate) {
 615  
 616              // Check if we can delete our own responses.
 617              if (!$candeleteall) {
 618                  $timenow = time();
 619                  if (!empty($choice->timeclose) && ($timenow > $choice->timeclose)) {
 620                      throw new moodle_exception("expired", "choice", '', userdate($choice->timeclose));
 621                  }
 622              }
 623  
 624              if (empty($params['responses'])) {
 625                  // No responses indicated so delete only my responses.
 626                  $todelete = array_keys(choice_get_my_response($choice));
 627              } else {
 628                  // Fill an array with the responses that can be deleted for this choice.
 629                  if ($candeleteall) {
 630                      // Teacher/managers can delete any.
 631                      $allowedresponses = array_keys(choice_get_all_responses($choice));
 632                  } else {
 633                      // Students can delete only their own responses.
 634                      $allowedresponses = array_keys(choice_get_my_response($choice));
 635                  }
 636  
 637                  $todelete = array();
 638                  foreach ($params['responses'] as $response) {
 639                      if (!in_array($response, $allowedresponses)) {
 640                          $warnings[] = array(
 641                              'item' => 'response',
 642                              'itemid' => $response,
 643                              'warningcode' => 'nopermissions',
 644                              'message' => 'Invalid response id, the response does not exist or you are not allowed to delete it.'
 645                          );
 646                      } else {
 647                          $todelete[] = $response;
 648                      }
 649                  }
 650              }
 651  
 652              $status = choice_delete_responses($todelete, $choice, $cm, $course);
 653          } else {
 654              // The user requires the capability to delete responses.
 655              throw new required_capability_exception($context, 'mod/choice:deleteresponses', 'nopermissions', '');
 656          }
 657  
 658          return array(
 659              'status' => $status,
 660              'warnings' => $warnings
 661          );
 662      }
 663  
 664      /**
 665       * Describes the delete_choice_responses return value.
 666       *
 667       * @return external_multiple_structure
 668       * @since Moodle 3.0
 669       */
 670      public static function delete_choice_responses_returns() {
 671          return new external_single_structure(
 672              array(
 673                  'status' => new external_value(PARAM_BOOL, 'status, true if everything went right'),
 674                  'warnings' => new external_warnings(),
 675              )
 676          );
 677      }
 678  
 679  }