Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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   * External choice functions unit tests
  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   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  
  30  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  31  require_once($CFG->dirroot . '/mod/choice/lib.php');
  32  
  33  /**
  34   * External choice functions unit tests
  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   */
  41  class mod_choice_externallib_testcase extends externallib_advanced_testcase {
  42  
  43      /**
  44       * Test get_choice_results
  45       */
  46      public function test_get_choice_results() {
  47          global $DB;
  48  
  49          $this->resetAfterTest(true);
  50  
  51          $course = self::getDataGenerator()->create_course();
  52          $params = new stdClass();
  53          $params->course = $course->id;
  54          $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
  55          $params->name = 'First Choice Activity';
  56          $params->showresults = CHOICE_SHOWRESULTS_AFTER_ANSWER;
  57          $params->publish = 1;
  58          $params->allowmultiple = 1;
  59          $params->showunanswered = 1;
  60          $choice = self::getDataGenerator()->create_module('choice', $params);
  61  
  62          $cm = get_coursemodule_from_id('choice', $choice->cmid);
  63          $choiceinstance = choice_get_choice($cm->instance);
  64          $options = array_keys($choiceinstance->option);
  65          $student1 = $this->getDataGenerator()->create_user();
  66          $student2 = $this->getDataGenerator()->create_user();
  67          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  68  
  69          // Enroll Students in Course1.
  70          self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
  71          self::getDataGenerator()->enrol_user($student2->id,  $course->id, $studentrole->id);
  72  
  73          $this->setUser($student1);
  74          $myanswer = $options[2];
  75          choice_user_submit_response($myanswer, $choice, $student1->id, $course, $cm);
  76          $results = mod_choice_external::get_choice_results($choice->id);
  77          // We need to execute the return values cleaning process to simulate the web service server.
  78          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
  79  
  80          // Create an array with optionID as Key.
  81          $resultsarr = array();
  82          foreach ($results['options'] as $option) {
  83              $resultsarr[$option['id']] = $option['userresponses'];
  84          }
  85          // The stundent1 is the userid who choosed the myanswer(option 3).
  86          $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
  87          // The stundent2 is the userid who didn't answered yet.
  88          $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
  89  
  90          // As Stundent2 we cannot see results (until we answered).
  91          $this->setUser($student2);
  92          $results = mod_choice_external::get_choice_results($choice->id);
  93          // We need to execute the return values cleaning process to simulate the web service server.
  94          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
  95          // We do not retrieve any response!
  96          foreach ($results['options'] as $option) {
  97              $this->assertCount(0, $option['userresponses']);
  98          }
  99  
 100          $timenow = time();
 101          // We can see results only after activity close (even if we didn't answered).
 102          $choice->showresults = CHOICE_SHOWRESULTS_AFTER_CLOSE;
 103          // Set timeopen and timeclose in the past.
 104          $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
 105          $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
 106          $DB->update_record('choice', $choice);
 107  
 108          $results = mod_choice_external::get_choice_results($choice->id);
 109          // We need to execute the return values cleaning process to simulate the web service server.
 110          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
 111          // We do not retrieve any response (activity is still open).
 112          foreach ($results['options'] as $option) {
 113              $this->assertCount(0, $option['userresponses']);
 114          }
 115  
 116          // We close the activity (setting timeclose in the past).
 117          $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
 118          $DB->update_record('choice', $choice);
 119          // Now as Stundent2 we will see results!
 120          $results = mod_choice_external::get_choice_results($choice->id);
 121          // We need to execute the return values cleaning process to simulate the web service server.
 122          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
 123          // Create an array with optionID as Key.
 124          $resultsarr = array();
 125          foreach ($results['options'] as $option) {
 126              $resultsarr[$option['id']] = $option['userresponses'];
 127          }
 128          // The stundent1 is the userid who choosed the myanswer(option 3).
 129          $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
 130          // The stundent2 is the userid who didn't answered yet.
 131          $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
 132  
 133          // Do not publish user names!
 134          $choice->publish = 0;
 135          $DB->update_record('choice', $choice);
 136          $results = mod_choice_external::get_choice_results($choice->id);
 137          // We need to execute the return values cleaning process to simulate the web service server.
 138          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
 139          // Create an array with optionID as Key.
 140          $resultsarr = array();
 141          // Does not show any user response!
 142          foreach ($results['options'] as $option) {
 143              $this->assertCount(0, $option['userresponses']);
 144              $resultsarr[$option['id']] = $option;
 145          }
 146          // But we can see totals and percentages.
 147          $this->assertEquals(1, $resultsarr[$myanswer]['numberofuser']);
 148      }
 149  
 150      /**
 151       * Test get_choice_options
 152       */
 153      public function test_get_choice_options() {
 154          global $DB;
 155  
 156          // Warningcodes.
 157          $notopenyet = 1;
 158          $previewonly = 2;
 159          $expired = 3;
 160  
 161          $this->resetAfterTest(true);
 162          $timenow = time();
 163          $timeopen = $timenow + (60 * 60 * 24 * 2);
 164          $timeclose = $timenow + (60 * 60 * 24 * 7);
 165          $course = self::getDataGenerator()->create_course();
 166          $possibleoptions = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
 167          $params = array();
 168          $params['course'] = $course->id;
 169          $params['option'] = $possibleoptions;
 170          $params['name'] = 'First Choice Activity';
 171          $params['showpreview'] = 0;
 172  
 173          $generator = $this->getDataGenerator()->get_plugin_generator('mod_choice');
 174          $choice = $generator->create_instance($params);
 175  
 176          $student1 = $this->getDataGenerator()->create_user();
 177          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 178          // Enroll Students in Course.
 179          self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
 180          $this->setUser($student1);
 181  
 182          $results = mod_choice_external::get_choice_options($choice->id);
 183          // We need to execute the return values cleaning process to simulate the web service server.
 184          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
 185          // We should retrieve all options.
 186          $this->assertCount(count($possibleoptions), $results['options']);
 187  
 188          // Here we force timeopen/close in the future.
 189          $choice->timeopen = $timeopen;
 190          $choice->timeclose = $timeclose;
 191          $DB->update_record('choice', $choice);
 192  
 193          $results = mod_choice_external::get_choice_options($choice->id);
 194          // We need to execute the return values cleaning process to simulate the web service server.
 195          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
 196          // We should retrieve no options.
 197          $this->assertCount(0, $results['options']);
 198          $this->assertEquals($notopenyet, $results['warnings'][0]['warningcode']);
 199  
 200          // Here we see the options because of preview!
 201          $choice->showpreview = 1;
 202          $DB->update_record('choice', $choice);
 203          $results = mod_choice_external::get_choice_options($choice->id);
 204          // We need to execute the return values cleaning process to simulate the web service server.
 205          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
 206          // We should retrieve all options.
 207          $this->assertCount(count($possibleoptions), $results['options']);
 208  
 209          foreach ($results['options'] as $option) {
 210              // Each option is disabled as this is only the preview!
 211              $this->assertEquals(1, $option['disabled']);
 212          }
 213          $warnings = array();
 214          foreach ($results['warnings'] as $warning) {
 215              $warnings[$warning['warningcode']] = $warning['message'];
 216          }
 217          $this->assertTrue(isset($warnings[$previewonly]));
 218          $this->assertTrue(isset($warnings[$notopenyet]));
 219  
 220          // Simulate activity as opened!
 221          $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
 222          $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
 223          $DB->update_record('choice', $choice);
 224          $cm = get_coursemodule_from_id('choice', $choice->cmid);
 225          $choiceinstance = choice_get_choice($cm->instance);
 226          $optionsids = array_keys($choiceinstance->option);
 227          $myanswerid = $optionsids[2];
 228          choice_user_submit_response($myanswerid, $choice, $student1->id, $course, $cm);
 229  
 230          $results = mod_choice_external::get_choice_options($choice->id);
 231          // We need to execute the return values cleaning process to simulate the web service server.
 232          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
 233          // We should retrieve all options.
 234          $this->assertCount(count($possibleoptions), $results['options']);
 235          foreach ($results['options'] as $option) {
 236              // When we answered and we cannot update our choice.
 237              if ($option['id'] == $myanswerid and !$choice->allowupdate) {
 238                  $this->assertEquals(1, $option['disabled']);
 239                  $this->assertEquals(1, $option['checked']);
 240              } else {
 241                  $this->assertEquals(0, $option['disabled']);
 242              }
 243          }
 244  
 245          // Set timeopen and timeclose as older than today!
 246          // We simulate what happens when the activity is closed.
 247          $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
 248          $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
 249          $DB->update_record('choice', $choice);
 250          $results = mod_choice_external::get_choice_options($choice->id);
 251          // We need to execute the return values cleaning process to simulate the web service server.
 252          $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
 253          // We should retrieve no options.
 254          $this->assertCount(0, $results['options']);
 255          $this->assertEquals($expired, $results['warnings'][0]['warningcode']);
 256  
 257      }
 258  
 259      /**
 260       * Test submit_choice_response
 261       */
 262      public function test_submit_choice_response() {
 263          global $DB;
 264  
 265          $this->resetAfterTest(true);
 266  
 267          $course = self::getDataGenerator()->create_course();
 268          $params = new stdClass();
 269          $params->course = $course->id;
 270          $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
 271          $params->name = 'First Choice Activity';
 272          $params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
 273          $params->allowmultiple = 1;
 274          $params->showunanswered = 1;
 275          $choice = self::getDataGenerator()->create_module('choice', $params);
 276          $cm = get_coursemodule_from_id('choice', $choice->cmid);
 277          $choiceinstance = choice_get_choice($cm->instance);
 278          $options = array_keys($choiceinstance->option);
 279          $student1 = $this->getDataGenerator()->create_user();
 280          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 281  
 282          // Enroll Students in Course1.
 283          self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
 284  
 285          $this->setUser($student1);
 286          $myresponse = $options[2];
 287          $results = mod_choice_external::submit_choice_response($choice->id, array($myresponse));
 288          // We need to execute the return values cleaning process to simulate the web service server.
 289          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 290          $myanswers = $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $student1->id));
 291          $myanswer = reset($myanswers);
 292          $this->assertEquals($results['answers'][0]['id'], $myanswer->id);
 293          $this->assertEquals($results['answers'][0]['choiceid'], $myanswer->choiceid);
 294          $this->assertEquals($results['answers'][0]['userid'], $myanswer->userid);
 295          $this->assertEquals($results['answers'][0]['timemodified'], $myanswer->timemodified);
 296      }
 297  
 298      /**
 299       * Test view_choice
 300       */
 301      public function test_view_choice() {
 302          global $DB;
 303  
 304          $this->resetAfterTest(true);
 305  
 306          // Setup test data.
 307          $course = $this->getDataGenerator()->create_course();
 308          $choice = $this->getDataGenerator()->create_module('choice', array('course' => $course->id));
 309          $context = context_module::instance($choice->cmid);
 310          $cm = get_coursemodule_from_instance('choice', $choice->id);
 311  
 312          // Test invalid instance id.
 313          try {
 314              mod_choice_external::view_choice(0);
 315              $this->fail('Exception expected due to invalid mod_choice instance id.');
 316          } catch (moodle_exception $e) {
 317              $this->assertEquals('invalidcoursemodule', $e->errorcode);
 318          }
 319  
 320          // Test not-enrolled user.
 321          $user = self::getDataGenerator()->create_user();
 322          $this->setUser($user);
 323          try {
 324              mod_choice_external::view_choice($choice->id);
 325              $this->fail('Exception expected due to not enrolled user.');
 326          } catch (moodle_exception $e) {
 327              $this->assertEquals('requireloginerror', $e->errorcode);
 328          }
 329  
 330          // Test user with full capabilities.
 331          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 332          $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
 333  
 334          // Trigger and capture the event.
 335          $sink = $this->redirectEvents();
 336  
 337          $result = mod_choice_external::view_choice($choice->id);
 338          $result = external_api::clean_returnvalue(mod_choice_external::view_choice_returns(), $result);
 339  
 340          $events = $sink->get_events();
 341          $this->assertCount(1, $events);
 342          $event = array_shift($events);
 343  
 344          // Checking that the event contains the expected values.
 345          $this->assertInstanceOf('\mod_choice\event\course_module_viewed', $event);
 346          $this->assertEquals($context, $event->get_context());
 347          $moodlechoice = new \moodle_url('/mod/choice/view.php', array('id' => $cm->id));
 348          $this->assertEquals($moodlechoice, $event->get_url());
 349          $this->assertEventContextNotUsed($event);
 350          $this->assertNotEmpty($event->get_name());
 351  
 352      }
 353  
 354      /**
 355       * Test get_choices_by_courses
 356       */
 357      public function test_get_choices_by_courses() {
 358          global $DB;
 359          $this->resetAfterTest(true);
 360          // As admin.
 361          $this->setAdminUser();
 362          $course1 = self::getDataGenerator()->create_course();
 363          $choiceoptions1 = array(
 364            'course' => $course1->id,
 365            'name' => 'First IMSCP'
 366          );
 367          $choice1 = self::getDataGenerator()->create_module('choice', $choiceoptions1);
 368          $course2 = self::getDataGenerator()->create_course();
 369  
 370          $choiceoptions2 = array(
 371            'course' => $course2->id,
 372            'name' => 'Second IMSCP'
 373          );
 374          $choice2 = self::getDataGenerator()->create_module('choice', $choiceoptions2);
 375          $student1 = $this->getDataGenerator()->create_user();
 376  
 377          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 378  
 379          // Enroll Student1 in Course1.
 380          self::getDataGenerator()->enrol_user($student1->id,  $course1->id, $studentrole->id);
 381  
 382          $this->setUser($student1);
 383          $choices = mod_choice_external::get_choices_by_courses(array());
 384          $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
 385          $this->assertCount(1, $choices['choices']);
 386          $this->assertEquals('First IMSCP', $choices['choices'][0]['name']);
 387          // As Student you cannot see some IMSCP properties like 'section'.
 388          $this->assertFalse(isset($choices['choices'][0]['section']));
 389  
 390          // Student1 is not enrolled in this Course.
 391          // The webservice will give a warning!
 392          $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
 393          $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
 394          $this->assertCount(0, $choices['choices']);
 395          $this->assertEquals(1, $choices['warnings'][0]['warningcode']);
 396  
 397          // Now as admin.
 398          $this->setAdminUser();
 399          // As Admin we can see this IMSCP.
 400          $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
 401          $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
 402          $this->assertCount(1, $choices['choices']);
 403          $this->assertEquals('Second IMSCP', $choices['choices'][0]['name']);
 404          // As an Admin you can see some IMSCP properties like 'section'.
 405          $this->assertEquals(0, $choices['choices'][0]['section']);
 406  
 407          // Now, prohibit capabilities.
 408          $this->setUser($student1);
 409          $contextcourse1 = context_course::instance($course1->id);
 410          // Prohibit capability = mod:choice:choose on Course1 for students.
 411          assign_capability('mod/choice:choose', CAP_PROHIBIT, $studentrole->id, $contextcourse1->id);
 412          accesslib_clear_all_caches_for_unit_testing();
 413  
 414          $choices = mod_choice_external::get_choices_by_courses(array($course1->id));
 415          $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
 416          $this->assertFalse(isset($choices['choices'][0]['timeopen']));
 417      }
 418  
 419      /**
 420       * Test delete_choice_responses
 421       */
 422      public function test_delete_choice_responses() {
 423          global $DB;
 424  
 425          $this->resetAfterTest(true);
 426  
 427          $course = self::getDataGenerator()->create_course();
 428          $params = new stdClass();
 429          $params->course = $course->id;
 430          $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
 431          $params->name = 'First Choice Activity';
 432          $params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
 433          $params->allowmultiple = 1;
 434          $params->showunanswered = 1;
 435          $choice = self::getDataGenerator()->create_module('choice', $params);
 436          $cm = get_coursemodule_from_id('choice', $choice->cmid);
 437  
 438          $choiceinstance = choice_get_choice($cm->instance);
 439          $options = array_keys($choiceinstance->option);
 440  
 441          $student = $this->getDataGenerator()->create_user();
 442          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 443  
 444          // Enroll student in Course1.
 445          self::getDataGenerator()->enrol_user($student->id,  $course->id, $studentrole->id);
 446  
 447          $this->setUser($student);
 448          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 449          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 450  
 451          $myresponses = array_keys(choice_get_my_response($choice));
 452  
 453          // Try to delete responses when allow update is false.
 454          try {
 455              mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[0]));
 456              $this->fail('Exception expected due to missing permissions.');
 457          } catch (required_capability_exception $e) {
 458              $this->assertEquals('nopermissions', $e->errorcode);
 459          }
 460  
 461          // Set allow update to true, and a passed time close.
 462          $DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
 463          $DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
 464          try {
 465              mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
 466              $this->fail('Exception expected due to expired choice.');
 467          } catch (moodle_exception $e) {
 468              $this->assertEquals('expired', $e->errorcode);
 469          }
 470  
 471          // Reset time close. We should be able now to delete all the responses.
 472          $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
 473          $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
 474          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 475  
 476          $this->assertTrue($results['status']);
 477          $this->assertCount(0, $results['warnings']);
 478          // Now, in the DB 0 responses.
 479          $this->assertCount(0, choice_get_my_response($choice));
 480  
 481          // Submit again the responses.
 482          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 483          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 484  
 485          $myresponses = array_keys(choice_get_my_response($choice));
 486          // Delete only one response.
 487          $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0]));
 488          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 489          $this->assertTrue($results['status']);
 490          $this->assertCount(0, $results['warnings']);
 491          // Now, in the DB 1 response still.
 492          $this->assertCount(1, choice_get_my_response($choice));
 493  
 494          // Delete the remaining response, passing 2 invalid responses ids.
 495          $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[1], $myresponses[0] + 2,
 496                                                                  $myresponses[0] + 3));
 497          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 498          $this->assertTrue($results['status']);
 499          // 2 warnings, 2 invalid responses.
 500          $this->assertCount(2, $results['warnings']);
 501          // Now, in the DB 0 responses.
 502          $this->assertCount(0, choice_get_my_response($choice));
 503  
 504          // Now, as an admin we must be able to delete all the responses under any condition.
 505          $this->setUser($student);
 506          // Submit again the responses.
 507          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 508          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 509          $studentresponses = array_keys(choice_get_my_response($choice));
 510  
 511          $this->setAdminUser();
 512          $DB->set_field('choice', 'allowupdate', 0, array('id' => $choice->id));
 513          $DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
 514  
 515          $results = mod_choice_external::delete_choice_responses($choice->id, array($studentresponses[0], $studentresponses[1]));
 516          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 517  
 518          $this->assertTrue($results['status']);
 519          $this->assertCount(0, $results['warnings']);
 520  
 521          // Submit again the responses.
 522          $this->setUser($student);
 523          $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
 524          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 525          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 526  
 527          // Test admin try to delete his own responses (he didn't respond so nothing should be deleted).
 528          $this->setAdminUser();
 529          $results = mod_choice_external::delete_choice_responses($choice->id);
 530          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 531          $this->assertFalse($results['status']);
 532          $this->assertCount(0, $results['warnings']);
 533          $allresponses = choice_get_all_responses($choice);
 534          $this->assertCount(2, $allresponses);   // No responses deleted (admin didn't submit any).
 535  
 536          // Now admin submit a couple of responses more.
 537          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 538          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 539          $allresponses = choice_get_all_responses($choice);
 540          $this->assertCount(4, $allresponses);
 541          // Admin responses are deleted when passing an empty array.
 542          $results = mod_choice_external::delete_choice_responses($choice->id);
 543          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 544          $this->assertTrue($results['status']);
 545          $this->assertCount(0, $results['warnings']);
 546          $allresponses = choice_get_all_responses($choice);
 547          $this->assertCount(2, $allresponses);
 548  
 549          // Now admin will delete all the other users responses.
 550          $results = mod_choice_external::delete_choice_responses($choice->id, array_keys($allresponses));
 551          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 552  
 553          $this->assertTrue($results['status']);
 554          $this->assertCount(0, $results['warnings']);
 555          $allresponses = choice_get_all_responses($choice);
 556          $this->assertCount(0, $allresponses);   // Now all the responses were deleted.
 557  
 558          // Admin try do delete an invalid response.
 559          $results = mod_choice_external::delete_choice_responses($choice->id, array(-1));
 560          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 561  
 562          $this->assertFalse($results['status']);
 563          $this->assertCount(1, $results['warnings']);
 564  
 565          // Now, in the DB 0 responses.
 566          $this->setUser($student);
 567  
 568          // Submit again respones.
 569          $DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
 570          $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
 571          $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
 572          $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
 573  
 574          // Delete all responses.
 575          $results = mod_choice_external::delete_choice_responses($choice->id);
 576          $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
 577  
 578          $this->assertTrue($results['status']);
 579          $this->assertCount(0, $results['warnings']);
 580          $this->assertCount(0, choice_get_my_response($choice));
 581  
 582      }
 583  }