Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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