[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/assign/tests/ -> externallib_test.php (source)

   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  defined('MOODLE_INTERNAL') || die();
  18  
  19  global $CFG;
  20  
  21  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  22  
  23  /**
  24   * External mod assign functions unit tests
  25   *
  26   * @package mod_assign
  27   * @category external
  28   * @copyright 2012 Paul Charsley
  29   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class mod_assign_external_testcase extends externallib_advanced_testcase {
  32  
  33      /**
  34       * Tests set up
  35       */
  36      protected function setUp() {
  37          global $CFG;
  38          require_once($CFG->dirroot . '/mod/assign/externallib.php');
  39      }
  40  
  41      /**
  42       * Test get_grades
  43       */
  44      public function test_get_grades() {
  45          global $DB, $USER;
  46  
  47          $this->resetAfterTest(true);
  48          // Create a course and assignment.
  49          $coursedata['idnumber'] = 'idnumbercourse';
  50          $coursedata['fullname'] = 'Lightwork Course';
  51          $coursedata['summary'] = 'Lightwork Course description';
  52          $coursedata['summaryformat'] = FORMAT_MOODLE;
  53          $course = self::getDataGenerator()->create_course($coursedata);
  54  
  55          $assigndata['course'] = $course->id;
  56          $assigndata['name'] = 'lightwork assignment';
  57  
  58          $assign = self::getDataGenerator()->create_module('assign', $assigndata);
  59  
  60          // Create a manual enrolment record.
  61          $manualenroldata['enrol'] = 'manual';
  62          $manualenroldata['status'] = 0;
  63          $manualenroldata['courseid'] = $course->id;
  64          $enrolid = $DB->insert_record('enrol', $manualenroldata);
  65  
  66          // Create a teacher and give them capabilities.
  67          $context = context_course::instance($course->id);
  68          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
  69          $context = context_module::instance($assign->cmid);
  70          $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
  71  
  72          // Create the teacher's enrolment record.
  73          $userenrolmentdata['status'] = 0;
  74          $userenrolmentdata['enrolid'] = $enrolid;
  75          $userenrolmentdata['userid'] = $USER->id;
  76          $DB->insert_record('user_enrolments', $userenrolmentdata);
  77  
  78          // Create a student and give them 2 grades (for 2 attempts).
  79          $student = self::getDataGenerator()->create_user();
  80  
  81          $submission = new stdClass();
  82          $submission->assignment = $assign->id;
  83          $submission->userid = $student->id;
  84          $submission->status = ASSIGN_SUBMISSION_STATUS_NEW;
  85          $submission->latest = 0;
  86          $submission->attemptnumber = 0;
  87          $submission->groupid = 0;
  88          $submission->timecreated = time();
  89          $submission->timemodified = time();
  90          $DB->insert_record('assign_submission', $submission);
  91  
  92          $grade = new stdClass();
  93          $grade->assignment = $assign->id;
  94          $grade->userid = $student->id;
  95          $grade->timecreated = time();
  96          $grade->timemodified = $grade->timecreated;
  97          $grade->grader = $USER->id;
  98          $grade->grade = 50;
  99          $grade->attemptnumber = 0;
 100          $DB->insert_record('assign_grades', $grade);
 101  
 102          $submission = new stdClass();
 103          $submission->assignment = $assign->id;
 104          $submission->userid = $student->id;
 105          $submission->status = ASSIGN_SUBMISSION_STATUS_NEW;
 106          $submission->latest = 1;
 107          $submission->attemptnumber = 1;
 108          $submission->groupid = 0;
 109          $submission->timecreated = time();
 110          $submission->timemodified = time();
 111          $DB->insert_record('assign_submission', $submission);
 112  
 113          $grade = new stdClass();
 114          $grade->assignment = $assign->id;
 115          $grade->userid = $student->id;
 116          $grade->timecreated = time();
 117          $grade->timemodified = $grade->timecreated;
 118          $grade->grader = $USER->id;
 119          $grade->grade = 75;
 120          $grade->attemptnumber = 1;
 121          $DB->insert_record('assign_grades', $grade);
 122  
 123          $assignmentids[] = $assign->id;
 124          $result = mod_assign_external::get_grades($assignmentids);
 125  
 126          // We need to execute the return values cleaning process to simulate the web service server.
 127          $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
 128  
 129          // Check that the correct grade information for the student is returned.
 130          $this->assertEquals(1, count($result['assignments']));
 131          $assignment = $result['assignments'][0];
 132          $this->assertEquals($assign->id, $assignment['assignmentid']);
 133          // Should only get the last grade for this student.
 134          $this->assertEquals(1, count($assignment['grades']));
 135          $grade = $assignment['grades'][0];
 136          $this->assertEquals($student->id, $grade['userid']);
 137          // Should be the last grade (not the first).
 138          $this->assertEquals(75, $grade['grade']);
 139      }
 140  
 141      /**
 142       * Test get_assignments
 143       */
 144      public function test_get_assignments() {
 145          global $DB, $USER, $CFG;
 146  
 147          $this->resetAfterTest(true);
 148  
 149          $category = self::getDataGenerator()->create_category(array(
 150              'name' => 'Test category'
 151          ));
 152  
 153          // Create a course.
 154          $course1 = self::getDataGenerator()->create_course(array(
 155              'idnumber' => 'idnumbercourse1',
 156              'fullname' => '<b>Lightwork Course 1</b>',      // Adding tags here to check that external_format_string works.
 157              'shortname' => '<b>Lightwork Course 1</b>',     // Adding tags here to check that external_format_string works.
 158              'summary' => 'Lightwork Course 1 description',
 159              'summaryformat' => FORMAT_MOODLE,
 160              'category' => $category->id
 161          ));
 162  
 163          // Create a second course, just for testing.
 164          $course2 = self::getDataGenerator()->create_course(array(
 165              'idnumber' => 'idnumbercourse2',
 166              'fullname' => 'Lightwork Course 2',
 167              'summary' => 'Lightwork Course 2 description',
 168              'summaryformat' => FORMAT_MOODLE,
 169              'category' => $category->id
 170          ));
 171  
 172          // Create the assignment module with links to a filerecord.
 173          $assign1 = self::getDataGenerator()->create_module('assign', array(
 174              'course' => $course1->id,
 175              'name' => 'lightwork assignment',
 176              'intro' => 'the assignment intro text here <a href="@@PLUGINFILE@@/intro.txt">link</a>',
 177              'introformat' => FORMAT_HTML,
 178              'markingworkflow' => 1,
 179              'markingallocation' => 1
 180          ));
 181  
 182          // Add a file as assignment attachment.
 183          $context = context_module::instance($assign1->cmid);
 184          $filerecord = array('component' => 'mod_assign', 'filearea' => 'intro', 'contextid' => $context->id, 'itemid' => 0,
 185                  'filename' => 'intro.txt', 'filepath' => '/');
 186          $fs = get_file_storage();
 187          $fs->create_file_from_string($filerecord, 'Test intro file');
 188  
 189          // Create manual enrolment record.
 190          $enrolid = $DB->insert_record('enrol', (object)array(
 191              'enrol' => 'manual',
 192              'status' => 0,
 193              'courseid' => $course1->id
 194          ));
 195  
 196          // Create the user and give them capabilities.
 197          $context = context_course::instance($course1->id);
 198          $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
 199          $context = context_module::instance($assign1->cmid);
 200          $this->assignUserCapability('mod/assign:view', $context->id, $roleid);
 201  
 202          // Create the user enrolment record.
 203          $DB->insert_record('user_enrolments', (object)array(
 204              'status' => 0,
 205              'enrolid' => $enrolid,
 206              'userid' => $USER->id
 207          ));
 208  
 209          // Add a file as assignment attachment.
 210          $filerecord = array('component' => 'mod_assign', 'filearea' => ASSIGN_INTROATTACHMENT_FILEAREA,
 211                  'contextid' => $context->id, 'itemid' => 0,
 212                  'filename' => 'introattachment.txt', 'filepath' => '/');
 213          $fs = get_file_storage();
 214          $fs->create_file_from_string($filerecord, 'Test intro attachment file');
 215  
 216          $result = mod_assign_external::get_assignments();
 217  
 218          // We need to execute the return values cleaning process to simulate the web service server.
 219          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 220  
 221          // Check the course and assignment are returned.
 222          $this->assertEquals(1, count($result['courses']));
 223          $course = $result['courses'][0];
 224          $this->assertEquals('Lightwork Course 1', $course['fullname']);
 225          $this->assertEquals('Lightwork Course 1', $course['shortname']);
 226          $this->assertEquals(1, count($course['assignments']));
 227          $assignment = $course['assignments'][0];
 228          $this->assertEquals($assign1->id, $assignment['id']);
 229          $this->assertEquals($course1->id, $assignment['course']);
 230          $this->assertEquals('lightwork assignment', $assignment['name']);
 231          $this->assertContains('the assignment intro text here', $assignment['intro']);
 232          // Check the url of the file attatched.
 233          $this->assertRegExp('@"' . $CFG->wwwroot . '/webservice/pluginfile.php/\d+/mod_assign/intro/intro\.txt"@', $assignment['intro']);
 234          $this->assertEquals(1, $assignment['markingworkflow']);
 235          $this->assertEquals(1, $assignment['markingallocation']);
 236          $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
 237  
 238          $this->assertCount(1, $assignment['introattachments']);
 239          $this->assertEquals('introattachment.txt', $assignment['introattachments'][0]['filename']);
 240  
 241          // Now, hide the descritption until the submission from date.
 242          $DB->set_field('assign', 'alwaysshowdescription', 0, array('id' => $assign1->id));
 243          $DB->set_field('assign', 'allowsubmissionsfromdate', time() + DAYSECS, array('id' => $assign1->id));
 244  
 245          $result = mod_assign_external::get_assignments(array($course1->id));
 246  
 247          // We need to execute the return values cleaning process to simulate the web service server.
 248          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 249  
 250          $this->assertEquals(1, count($result['courses']));
 251          $course = $result['courses'][0];
 252          $this->assertEquals('Lightwork Course 1', $course['fullname']);
 253          $this->assertEquals(1, count($course['assignments']));
 254          $assignment = $course['assignments'][0];
 255          $this->assertEquals($assign1->id, $assignment['id']);
 256          $this->assertEquals($course1->id, $assignment['course']);
 257          $this->assertEquals('lightwork assignment', $assignment['name']);
 258          $this->assertArrayNotHasKey('intro', $assignment);
 259          $this->assertArrayNotHasKey('introattachments', $assignment);
 260          $this->assertEquals(1, $assignment['markingworkflow']);
 261          $this->assertEquals(1, $assignment['markingallocation']);
 262          $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
 263  
 264          $result = mod_assign_external::get_assignments(array($course2->id));
 265  
 266          // We need to execute the return values cleaning process to simulate the web service server.
 267          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 268  
 269          $this->assertEquals(0, count($result['courses']));
 270          $this->assertEquals(1, count($result['warnings']));
 271  
 272          // Test with non-enrolled user, but with view capabilities.
 273          $this->setAdminUser();
 274          $result = mod_assign_external::get_assignments();
 275          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 276          $this->assertEquals(0, count($result['courses']));
 277          $this->assertEquals(0, count($result['warnings']));
 278  
 279          // Expect no courses, because we are not using the special flag.
 280          $result = mod_assign_external::get_assignments(array($course1->id));
 281          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 282          $this->assertCount(0, $result['courses']);
 283  
 284          // Now use the special flag to return courses where you are not enroled in.
 285          $result = mod_assign_external::get_assignments(array($course1->id), array(), true);
 286          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 287          $this->assertCount(1, $result['courses']);
 288  
 289          $course = $result['courses'][0];
 290          $this->assertEquals('Lightwork Course 1', $course['fullname']);
 291          $this->assertEquals(1, count($course['assignments']));
 292          $assignment = $course['assignments'][0];
 293          $this->assertEquals($assign1->id, $assignment['id']);
 294          $this->assertEquals($course1->id, $assignment['course']);
 295          $this->assertEquals('lightwork assignment', $assignment['name']);
 296          $this->assertArrayNotHasKey('intro', $assignment);
 297          $this->assertArrayNotHasKey('introattachments', $assignment);
 298          $this->assertEquals(1, $assignment['markingworkflow']);
 299          $this->assertEquals(1, $assignment['markingallocation']);
 300          $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
 301      }
 302  
 303      /**
 304       * Test get_assignments with submissionstatement.
 305       */
 306      public function test_get_assignments_with_submissionstatement() {
 307          global $DB, $USER, $CFG;
 308  
 309          $this->resetAfterTest(true);
 310  
 311          // Setup test data. Create 2 assigns, one with requiresubmissionstatement and the other without it.
 312          $course = $this->getDataGenerator()->create_course();
 313          $assign = $this->getDataGenerator()->create_module('assign', array(
 314              'course' => $course->id,
 315              'requiresubmissionstatement' => 1
 316          ));
 317          $assign2 = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
 318  
 319          // Create student.
 320          $student = self::getDataGenerator()->create_user();
 321  
 322          // Users enrolments.
 323          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 324          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 325  
 326          // Update the submissionstatement.
 327          $submissionstatement = 'This is a fake submission statement.';
 328          set_config('submissionstatement', $submissionstatement, 'assign');
 329  
 330          $this->setUser($student);
 331  
 332          $result = mod_assign_external::get_assignments();
 333          // We need to execute the return values cleaning process to simulate the web service server.
 334          $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
 335  
 336          // Check that the amount of courses and assignments is right.
 337          $this->assertCount(1, $result['courses']);
 338          $assignmentsret = $result['courses'][0]['assignments'];
 339          $this->assertCount(2, $assignmentsret);
 340  
 341          // Order the returned assignments by ID.
 342          usort($assignmentsret, function($a, $b) {
 343              return strcmp($a['id'], $b['id']);
 344          });
 345  
 346          // Check that the first assign contains the submission statement.
 347          $assignmentret = $assignmentsret[0];
 348          $this->assertEquals($assign->id, $assignmentret['id']);
 349          $this->assertEquals(1, $assignmentret['requiresubmissionstatement']);
 350          $this->assertEquals($submissionstatement, $assignmentret['submissionstatement']);
 351  
 352          // Check that the second assign does NOT contain the submission statement.
 353          $assignmentret = $assignmentsret[1];
 354          $this->assertEquals($assign2->id, $assignmentret['id']);
 355          $this->assertEquals(0, $assignmentret['requiresubmissionstatement']);
 356          $this->assertArrayNotHasKey('submissionstatement', $assignmentret);
 357      }
 358  
 359      /**
 360       * Test get_submissions
 361       */
 362      public function test_get_submissions() {
 363          global $DB, $USER;
 364  
 365          $this->resetAfterTest(true);
 366          // Create a course and assignment.
 367          $coursedata['idnumber'] = 'idnumbercourse1';
 368          $coursedata['fullname'] = 'Lightwork Course 1';
 369          $coursedata['summary'] = 'Lightwork Course 1 description';
 370          $coursedata['summaryformat'] = FORMAT_MOODLE;
 371          $course1 = self::getDataGenerator()->create_course($coursedata);
 372  
 373          $assigndata['course'] = $course1->id;
 374          $assigndata['name'] = 'lightwork assignment';
 375  
 376          $assign1 = self::getDataGenerator()->create_module('assign', $assigndata);
 377  
 378          // Create a student with an online text submission.
 379          // First attempt.
 380          $student = self::getDataGenerator()->create_user();
 381          $submission = new stdClass();
 382          $submission->assignment = $assign1->id;
 383          $submission->userid = $student->id;
 384          $submission->timecreated = time();
 385          $submission->timemodified = $submission->timecreated;
 386          $submission->status = 'draft';
 387          $submission->attemptnumber = 0;
 388          $submission->latest = 0;
 389          $sid = $DB->insert_record('assign_submission', $submission);
 390  
 391          // Second attempt.
 392          $submission = new stdClass();
 393          $submission->assignment = $assign1->id;
 394          $submission->userid = $student->id;
 395          $submission->timecreated = time();
 396          $submission->timemodified = $submission->timecreated;
 397          $submission->status = 'submitted';
 398          $submission->attemptnumber = 1;
 399          $submission->latest = 1;
 400          $sid = $DB->insert_record('assign_submission', $submission);
 401          $submission->id = $sid;
 402  
 403          $onlinetextsubmission = new stdClass();
 404          $onlinetextsubmission->onlinetext = "<p>online test text</p>";
 405          $onlinetextsubmission->onlineformat = 1;
 406          $onlinetextsubmission->submission = $submission->id;
 407          $onlinetextsubmission->assignment = $assign1->id;
 408          $DB->insert_record('assignsubmission_onlinetext', $onlinetextsubmission);
 409  
 410          // Create manual enrolment record.
 411          $manualenroldata['enrol'] = 'manual';
 412          $manualenroldata['status'] = 0;
 413          $manualenroldata['courseid'] = $course1->id;
 414          $enrolid = $DB->insert_record('enrol', $manualenroldata);
 415  
 416          // Create a teacher and give them capabilities.
 417          $context = context_course::instance($course1->id);
 418          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
 419          $context = context_module::instance($assign1->cmid);
 420          $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
 421  
 422          // Create the teacher's enrolment record.
 423          $userenrolmentdata['status'] = 0;
 424          $userenrolmentdata['enrolid'] = $enrolid;
 425          $userenrolmentdata['userid'] = $USER->id;
 426          $DB->insert_record('user_enrolments', $userenrolmentdata);
 427  
 428          $assignmentids[] = $assign1->id;
 429          $result = mod_assign_external::get_submissions($assignmentids);
 430          $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
 431  
 432          // Check the online text submission is returned.
 433          $this->assertEquals(1, count($result['assignments']));
 434          $assignment = $result['assignments'][0];
 435          $this->assertEquals($assign1->id, $assignment['assignmentid']);
 436          $this->assertEquals(1, count($assignment['submissions']));
 437          $submission = $assignment['submissions'][0];
 438          $this->assertEquals($sid, $submission['id']);
 439          $this->assertCount(1, $submission['plugins']);
 440      }
 441  
 442      /**
 443       * Test get_user_flags
 444       */
 445      public function test_get_user_flags() {
 446          global $DB, $USER;
 447  
 448          $this->resetAfterTest(true);
 449          // Create a course and assignment.
 450          $coursedata['idnumber'] = 'idnumbercourse';
 451          $coursedata['fullname'] = 'Lightwork Course';
 452          $coursedata['summary'] = 'Lightwork Course description';
 453          $coursedata['summaryformat'] = FORMAT_MOODLE;
 454          $course = self::getDataGenerator()->create_course($coursedata);
 455  
 456          $assigndata['course'] = $course->id;
 457          $assigndata['name'] = 'lightwork assignment';
 458  
 459          $assign = self::getDataGenerator()->create_module('assign', $assigndata);
 460  
 461          // Create a manual enrolment record.
 462          $manualenroldata['enrol'] = 'manual';
 463          $manualenroldata['status'] = 0;
 464          $manualenroldata['courseid'] = $course->id;
 465          $enrolid = $DB->insert_record('enrol', $manualenroldata);
 466  
 467          // Create a teacher and give them capabilities.
 468          $context = context_course::instance($course->id);
 469          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
 470          $context = context_module::instance($assign->cmid);
 471          $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
 472  
 473          // Create the teacher's enrolment record.
 474          $userenrolmentdata['status'] = 0;
 475          $userenrolmentdata['enrolid'] = $enrolid;
 476          $userenrolmentdata['userid'] = $USER->id;
 477          $DB->insert_record('user_enrolments', $userenrolmentdata);
 478  
 479          // Create a student and give them a user flag record.
 480          $student = self::getDataGenerator()->create_user();
 481          $userflag = new stdClass();
 482          $userflag->assignment = $assign->id;
 483          $userflag->userid = $student->id;
 484          $userflag->locked = 0;
 485          $userflag->mailed = 0;
 486          $userflag->extensionduedate = 0;
 487          $userflag->workflowstate = 'inmarking';
 488          $userflag->allocatedmarker = $USER->id;
 489  
 490          $DB->insert_record('assign_user_flags', $userflag);
 491  
 492          $assignmentids[] = $assign->id;
 493          $result = mod_assign_external::get_user_flags($assignmentids);
 494  
 495          // We need to execute the return values cleaning process to simulate the web service server.
 496          $result = external_api::clean_returnvalue(mod_assign_external::get_user_flags_returns(), $result);
 497  
 498          // Check that the correct user flag information for the student is returned.
 499          $this->assertEquals(1, count($result['assignments']));
 500          $assignment = $result['assignments'][0];
 501          $this->assertEquals($assign->id, $assignment['assignmentid']);
 502          // Should be one user flag record.
 503          $this->assertEquals(1, count($assignment['userflags']));
 504          $userflag = $assignment['userflags'][0];
 505          $this->assertEquals($student->id, $userflag['userid']);
 506          $this->assertEquals(0, $userflag['locked']);
 507          $this->assertEquals(0, $userflag['mailed']);
 508          $this->assertEquals(0, $userflag['extensionduedate']);
 509          $this->assertEquals('inmarking', $userflag['workflowstate']);
 510          $this->assertEquals($USER->id, $userflag['allocatedmarker']);
 511      }
 512  
 513      /**
 514       * Test get_user_mappings
 515       */
 516      public function test_get_user_mappings() {
 517          global $DB, $USER;
 518  
 519          $this->resetAfterTest(true);
 520          // Create a course and assignment.
 521          $coursedata['idnumber'] = 'idnumbercourse';
 522          $coursedata['fullname'] = 'Lightwork Course';
 523          $coursedata['summary'] = 'Lightwork Course description';
 524          $coursedata['summaryformat'] = FORMAT_MOODLE;
 525          $course = self::getDataGenerator()->create_course($coursedata);
 526  
 527          $assigndata['course'] = $course->id;
 528          $assigndata['name'] = 'lightwork assignment';
 529  
 530          $assign = self::getDataGenerator()->create_module('assign', $assigndata);
 531  
 532          // Create a manual enrolment record.
 533          $manualenroldata['enrol'] = 'manual';
 534          $manualenroldata['status'] = 0;
 535          $manualenroldata['courseid'] = $course->id;
 536          $enrolid = $DB->insert_record('enrol', $manualenroldata);
 537  
 538          // Create a teacher and give them capabilities.
 539          $context = context_course::instance($course->id);
 540          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
 541          $context = context_module::instance($assign->cmid);
 542          $this->assignUserCapability('mod/assign:revealidentities', $context->id, $roleid);
 543  
 544          // Create the teacher's enrolment record.
 545          $userenrolmentdata['status'] = 0;
 546          $userenrolmentdata['enrolid'] = $enrolid;
 547          $userenrolmentdata['userid'] = $USER->id;
 548          $DB->insert_record('user_enrolments', $userenrolmentdata);
 549  
 550          // Create a student and give them a user mapping record.
 551          $student = self::getDataGenerator()->create_user();
 552          $mapping = new stdClass();
 553          $mapping->assignment = $assign->id;
 554          $mapping->userid = $student->id;
 555  
 556          $DB->insert_record('assign_user_mapping', $mapping);
 557  
 558          $assignmentids[] = $assign->id;
 559          $result = mod_assign_external::get_user_mappings($assignmentids);
 560  
 561          // We need to execute the return values cleaning process to simulate the web service server.
 562          $result = external_api::clean_returnvalue(mod_assign_external::get_user_mappings_returns(), $result);
 563  
 564          // Check that the correct user mapping information for the student is returned.
 565          $this->assertEquals(1, count($result['assignments']));
 566          $assignment = $result['assignments'][0];
 567          $this->assertEquals($assign->id, $assignment['assignmentid']);
 568          // Should be one user mapping record.
 569          $this->assertEquals(1, count($assignment['mappings']));
 570          $mapping = $assignment['mappings'][0];
 571          $this->assertEquals($student->id, $mapping['userid']);
 572      }
 573  
 574      /**
 575       * Test lock_submissions
 576       *
 577       * @expectedException moodle_exception
 578       */
 579      public function test_lock_submissions() {
 580          global $DB, $USER;
 581  
 582          $this->resetAfterTest(true);
 583          // Create a course and assignment and users.
 584          $course = self::getDataGenerator()->create_course();
 585  
 586          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 587          $params['course'] = $course->id;
 588          $params['assignsubmission_onlinetext_enabled'] = 1;
 589          $instance = $generator->create_instance($params);
 590          $cm = get_coursemodule_from_instance('assign', $instance->id);
 591          $context = context_module::instance($cm->id);
 592  
 593          $assign = new assign($context, $cm, $course);
 594  
 595          $student1 = self::getDataGenerator()->create_user();
 596          $student2 = self::getDataGenerator()->create_user();
 597          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 598          $this->getDataGenerator()->enrol_user($student1->id,
 599                                                $course->id,
 600                                                $studentrole->id);
 601          $this->getDataGenerator()->enrol_user($student2->id,
 602                                                $course->id,
 603                                                $studentrole->id);
 604          $teacher = self::getDataGenerator()->create_user();
 605          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 606          $this->getDataGenerator()->enrol_user($teacher->id,
 607                                                $course->id,
 608                                                $teacherrole->id);
 609  
 610          // Create a student1 with an online text submission.
 611          // Simulate a submission.
 612          $this->setUser($student1);
 613          $submission = $assign->get_user_submission($student1->id, true);
 614          $data = new stdClass();
 615          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 616                                           'text'=>'Submission text',
 617                                           'format'=>FORMAT_MOODLE);
 618          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 619          $plugin->save($submission, $data);
 620  
 621          // Ready to test.
 622          $this->setUser($teacher);
 623          $students = array($student1->id, $student2->id);
 624          $result = mod_assign_external::lock_submissions($instance->id, $students);
 625          $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
 626  
 627          // Check for 0 warnings.
 628          $this->assertEquals(0, count($result));
 629  
 630          $this->setUser($student2);
 631          $submission = $assign->get_user_submission($student2->id, true);
 632          $data = new stdClass();
 633          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 634                                           'text'=>'Submission text',
 635                                           'format'=>FORMAT_MOODLE);
 636          $notices = array();
 637          $assign->save_submission($data, $notices);
 638      }
 639  
 640      /**
 641       * Test unlock_submissions
 642       */
 643      public function test_unlock_submissions() {
 644          global $DB, $USER;
 645  
 646          $this->resetAfterTest(true);
 647          // Create a course and assignment and users.
 648          $course = self::getDataGenerator()->create_course();
 649  
 650          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 651          $params['course'] = $course->id;
 652          $params['assignsubmission_onlinetext_enabled'] = 1;
 653          $instance = $generator->create_instance($params);
 654          $cm = get_coursemodule_from_instance('assign', $instance->id);
 655          $context = context_module::instance($cm->id);
 656  
 657          $assign = new assign($context, $cm, $course);
 658  
 659          $student1 = self::getDataGenerator()->create_user();
 660          $student2 = self::getDataGenerator()->create_user();
 661          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 662          $this->getDataGenerator()->enrol_user($student1->id,
 663                                                $course->id,
 664                                                $studentrole->id);
 665          $this->getDataGenerator()->enrol_user($student2->id,
 666                                                $course->id,
 667                                                $studentrole->id);
 668          $teacher = self::getDataGenerator()->create_user();
 669          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 670          $this->getDataGenerator()->enrol_user($teacher->id,
 671                                                $course->id,
 672                                                $teacherrole->id);
 673  
 674          // Create a student1 with an online text submission.
 675          // Simulate a submission.
 676          $this->setUser($student1);
 677          $submission = $assign->get_user_submission($student1->id, true);
 678          $data = new stdClass();
 679          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 680                                           'text'=>'Submission text',
 681                                           'format'=>FORMAT_MOODLE);
 682          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 683          $plugin->save($submission, $data);
 684  
 685          // Ready to test.
 686          $this->setUser($teacher);
 687          $students = array($student1->id, $student2->id);
 688          $result = mod_assign_external::lock_submissions($instance->id, $students);
 689          $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
 690  
 691          // Check for 0 warnings.
 692          $this->assertEquals(0, count($result));
 693  
 694          $result = mod_assign_external::unlock_submissions($instance->id, $students);
 695          $result = external_api::clean_returnvalue(mod_assign_external::unlock_submissions_returns(), $result);
 696  
 697          // Check for 0 warnings.
 698          $this->assertEquals(0, count($result));
 699  
 700          $this->setUser($student2);
 701          $submission = $assign->get_user_submission($student2->id, true);
 702          $data = new stdClass();
 703          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 704                                           'text'=>'Submission text',
 705                                           'format'=>FORMAT_MOODLE);
 706          $notices = array();
 707          $assign->save_submission($data, $notices);
 708      }
 709  
 710      /**
 711       * Test submit_for_grading
 712       */
 713      public function test_submit_for_grading() {
 714          global $DB, $USER;
 715  
 716          $this->resetAfterTest(true);
 717          // Create a course and assignment and users.
 718          $course = self::getDataGenerator()->create_course();
 719  
 720          set_config('submissionreceipts', 0, 'assign');
 721          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 722          $params['course'] = $course->id;
 723          $params['assignsubmission_onlinetext_enabled'] = 1;
 724          $params['submissiondrafts'] = 1;
 725          $params['sendnotifications'] = 0;
 726          $params['requiresubmissionstatement'] = 1;
 727          $instance = $generator->create_instance($params);
 728          $cm = get_coursemodule_from_instance('assign', $instance->id);
 729          $context = context_module::instance($cm->id);
 730  
 731          $assign = new assign($context, $cm, $course);
 732  
 733          $student1 = self::getDataGenerator()->create_user();
 734          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 735          $this->getDataGenerator()->enrol_user($student1->id,
 736                                                $course->id,
 737                                                $studentrole->id);
 738  
 739          // Create a student1 with an online text submission.
 740          // Simulate a submission.
 741          $this->setUser($student1);
 742          $submission = $assign->get_user_submission($student1->id, true);
 743          $data = new stdClass();
 744          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 745                                           'text'=>'Submission text',
 746                                           'format'=>FORMAT_MOODLE);
 747          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 748          $plugin->save($submission, $data);
 749  
 750          $result = mod_assign_external::submit_for_grading($instance->id, false);
 751          $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
 752  
 753          // Should be 1 fail because the submission statement was not aceptted.
 754          $this->assertEquals(1, count($result));
 755  
 756          $result = mod_assign_external::submit_for_grading($instance->id, true);
 757          $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
 758  
 759          // Check for 0 warnings.
 760          $this->assertEquals(0, count($result));
 761  
 762          $submission = $assign->get_user_submission($student1->id, false);
 763  
 764          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
 765      }
 766  
 767      /**
 768       * Test save_user_extensions
 769       */
 770      public function test_save_user_extensions() {
 771          global $DB, $USER;
 772  
 773          $this->resetAfterTest(true);
 774          // Create a course and assignment and users.
 775          $course = self::getDataGenerator()->create_course();
 776  
 777          $teacher = self::getDataGenerator()->create_user();
 778          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 779          $this->getDataGenerator()->enrol_user($teacher->id,
 780                                                $course->id,
 781                                                $teacherrole->id);
 782          $this->setUser($teacher);
 783  
 784          $now = time();
 785          $yesterday = $now - 24*60*60;
 786          $tomorrow = $now + 24*60*60;
 787          set_config('submissionreceipts', 0, 'assign');
 788          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 789          $params['course'] = $course->id;
 790          $params['submissiondrafts'] = 1;
 791          $params['sendnotifications'] = 0;
 792          $params['duedate'] = $yesterday;
 793          $params['cutoffdate'] = $now - 10;
 794          $instance = $generator->create_instance($params);
 795          $cm = get_coursemodule_from_instance('assign', $instance->id);
 796          $context = context_module::instance($cm->id);
 797  
 798          $assign = new assign($context, $cm, $course);
 799  
 800          $student1 = self::getDataGenerator()->create_user();
 801          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 802          $this->getDataGenerator()->enrol_user($student1->id,
 803                                                $course->id,
 804                                                $studentrole->id);
 805  
 806          $this->setUser($student1);
 807          $result = mod_assign_external::submit_for_grading($instance->id, true);
 808          $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
 809  
 810          // Check for 0 warnings.
 811          $this->assertEquals(1, count($result));
 812  
 813          $this->setUser($teacher);
 814          $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
 815          $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
 816          $this->assertEquals(1, count($result));
 817  
 818          $this->setUser($teacher);
 819          $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
 820          $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
 821          $this->assertEquals(1, count($result));
 822  
 823          $this->setUser($teacher);
 824          $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
 825          $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
 826          $this->assertEquals(0, count($result));
 827  
 828          $this->setUser($student1);
 829          $result = mod_assign_external::submit_for_grading($instance->id, true);
 830          $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
 831          $this->assertEquals(0, count($result));
 832  
 833          $this->setUser($student1);
 834          $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
 835          $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
 836  
 837      }
 838  
 839      /**
 840       * Test reveal_identities
 841       *
 842       * @expectedException required_capability_exception
 843       */
 844      public function test_reveal_identities() {
 845          global $DB, $USER;
 846  
 847          $this->resetAfterTest(true);
 848          // Create a course and assignment and users.
 849          $course = self::getDataGenerator()->create_course();
 850  
 851          $teacher = self::getDataGenerator()->create_user();
 852          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 853          $this->getDataGenerator()->enrol_user($teacher->id,
 854                                                $course->id,
 855                                                $teacherrole->id);
 856          $this->setUser($teacher);
 857  
 858          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 859          $params['course'] = $course->id;
 860          $params['submissiondrafts'] = 1;
 861          $params['sendnotifications'] = 0;
 862          $params['blindmarking'] = 1;
 863          $instance = $generator->create_instance($params);
 864          $cm = get_coursemodule_from_instance('assign', $instance->id);
 865          $context = context_module::instance($cm->id);
 866  
 867          $assign = new assign($context, $cm, $course);
 868  
 869          $student1 = self::getDataGenerator()->create_user();
 870          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 871          $this->getDataGenerator()->enrol_user($student1->id,
 872                                                $course->id,
 873                                                $studentrole->id);
 874  
 875          $this->setUser($student1);
 876          $result = mod_assign_external::reveal_identities($instance->id);
 877          $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
 878          $this->assertEquals(1, count($result));
 879          $this->assertEquals(true, $assign->is_blind_marking());
 880  
 881          $this->setUser($teacher);
 882          $result = mod_assign_external::reveal_identities($instance->id);
 883          $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
 884          $this->assertEquals(0, count($result));
 885          $this->assertEquals(false, $assign->is_blind_marking());
 886  
 887          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 888          $params['course'] = $course->id;
 889          $params['submissiondrafts'] = 1;
 890          $params['sendnotifications'] = 0;
 891          $params['blindmarking'] = 0;
 892          $instance = $generator->create_instance($params);
 893          $cm = get_coursemodule_from_instance('assign', $instance->id);
 894          $context = context_module::instance($cm->id);
 895  
 896          $assign = new assign($context, $cm, $course);
 897          $result = mod_assign_external::reveal_identities($instance->id);
 898          $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
 899          $this->assertEquals(1, count($result));
 900          $this->assertEquals(false, $assign->is_blind_marking());
 901  
 902      }
 903  
 904      /**
 905       * Test revert_submissions_to_draft
 906       */
 907      public function test_revert_submissions_to_draft() {
 908          global $DB, $USER;
 909  
 910          $this->resetAfterTest(true);
 911          set_config('submissionreceipts', 0, 'assign');
 912          // Create a course and assignment and users.
 913          $course = self::getDataGenerator()->create_course();
 914  
 915          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 916          $params['course'] = $course->id;
 917          $params['sendnotifications'] = 0;
 918          $params['submissiondrafts'] = 1;
 919          $instance = $generator->create_instance($params);
 920          $cm = get_coursemodule_from_instance('assign', $instance->id);
 921          $context = context_module::instance($cm->id);
 922  
 923          $assign = new assign($context, $cm, $course);
 924  
 925          $student1 = self::getDataGenerator()->create_user();
 926          $student2 = self::getDataGenerator()->create_user();
 927          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 928          $this->getDataGenerator()->enrol_user($student1->id,
 929                                                $course->id,
 930                                                $studentrole->id);
 931          $this->getDataGenerator()->enrol_user($student2->id,
 932                                                $course->id,
 933                                                $studentrole->id);
 934          $teacher = self::getDataGenerator()->create_user();
 935          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 936          $this->getDataGenerator()->enrol_user($teacher->id,
 937                                                $course->id,
 938                                                $teacherrole->id);
 939  
 940          // Create a student1 with an online text submission.
 941          // Simulate a submission.
 942          $this->setUser($student1);
 943          $result = mod_assign_external::submit_for_grading($instance->id, true);
 944          $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
 945          $this->assertEquals(0, count($result));
 946  
 947          // Ready to test.
 948          $this->setUser($teacher);
 949          $students = array($student1->id, $student2->id);
 950          $result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
 951          $result = external_api::clean_returnvalue(mod_assign_external::revert_submissions_to_draft_returns(), $result);
 952  
 953          // Check for 0 warnings.
 954          $this->assertEquals(0, count($result));
 955  
 956      }
 957  
 958      /**
 959       * Test save_submission
 960       */
 961      public function test_save_submission() {
 962          global $DB, $USER;
 963  
 964          $this->resetAfterTest(true);
 965          // Create a course and assignment and users.
 966          $course = self::getDataGenerator()->create_course();
 967  
 968          $teacher = self::getDataGenerator()->create_user();
 969          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 970          $this->getDataGenerator()->enrol_user($teacher->id,
 971                                                $course->id,
 972                                                $teacherrole->id);
 973          $this->setUser($teacher);
 974  
 975          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 976          $params['course'] = $course->id;
 977          $params['assignsubmission_onlinetext_enabled'] = 1;
 978          $params['assignsubmission_file_enabled'] = 1;
 979          $params['assignsubmission_file_maxfiles'] = 5;
 980          $params['assignsubmission_file_maxsizebytes'] = 1024*1024;
 981          $instance = $generator->create_instance($params);
 982          $cm = get_coursemodule_from_instance('assign', $instance->id);
 983          $context = context_module::instance($cm->id);
 984  
 985          $assign = new assign($context, $cm, $course);
 986  
 987          $student1 = self::getDataGenerator()->create_user();
 988          $student2 = self::getDataGenerator()->create_user();
 989          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 990          $this->getDataGenerator()->enrol_user($student1->id,
 991                                                $course->id,
 992                                                $studentrole->id);
 993          $this->getDataGenerator()->enrol_user($student2->id,
 994                                                $course->id,
 995                                                $studentrole->id);
 996          // Create a student1 with an online text submission.
 997          // Simulate a submission.
 998          $this->setUser($student1);
 999  
1000          // Create a file in a draft area.
1001          $draftidfile = file_get_unused_draft_itemid();
1002  
1003          $usercontext = context_user::instance($student1->id);
1004          $filerecord = array(
1005              'contextid' => $usercontext->id,
1006              'component' => 'user',
1007              'filearea'  => 'draft',
1008              'itemid'    => $draftidfile,
1009              'filepath'  => '/',
1010              'filename'  => 'testtext.txt',
1011          );
1012  
1013          $fs = get_file_storage();
1014          $fs->create_file_from_string($filerecord, 'text contents');
1015  
1016          // Create another file in a different draft area.
1017          $draftidonlinetext = file_get_unused_draft_itemid();
1018  
1019          $filerecord = array(
1020              'contextid' => $usercontext->id,
1021              'component' => 'user',
1022              'filearea'  => 'draft',
1023              'itemid'    => $draftidonlinetext,
1024              'filepath'  => '/',
1025              'filename'  => 'shouldbeanimage.txt',
1026          );
1027  
1028          $fs->create_file_from_string($filerecord, 'image contents (not really)');
1029  
1030          // Now try a submission.
1031          $submissionpluginparams = array();
1032          $submissionpluginparams['files_filemanager'] = $draftidfile;
1033          $onlinetexteditorparams = array('text' => '<p>Yeeha!</p>',
1034                                          'format'=>1,
1035                                          'itemid'=>$draftidonlinetext);
1036          $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1037          $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
1038          $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
1039  
1040          $this->assertEquals(0, count($result));
1041  
1042          // Set up a due and cutoff passed date.
1043          $instance->duedate = time() - WEEKSECS;
1044          $instance->cutoffdate = time() - WEEKSECS;
1045          $DB->update_record('assign', $instance);
1046  
1047          $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
1048          $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
1049  
1050          $this->assertCount(1, $result);
1051          $this->assertEquals(get_string('duedatereached', 'assign'), $result[0]['item']);
1052      }
1053  
1054      /**
1055       * Test save_grade
1056       */
1057      public function test_save_grade() {
1058          global $DB, $USER;
1059  
1060          $this->resetAfterTest(true);
1061          // Create a course and assignment and users.
1062          $course = self::getDataGenerator()->create_course();
1063  
1064          $teacher = self::getDataGenerator()->create_user();
1065          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1066          $this->getDataGenerator()->enrol_user($teacher->id,
1067                                                $course->id,
1068                                                $teacherrole->id);
1069          $this->setUser($teacher);
1070  
1071          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1072          $params['course'] = $course->id;
1073          $params['assignfeedback_file_enabled'] = 1;
1074          $params['assignfeedback_comments_enabled'] = 1;
1075          $instance = $generator->create_instance($params);
1076          $cm = get_coursemodule_from_instance('assign', $instance->id);
1077          $context = context_module::instance($cm->id);
1078  
1079          $assign = new assign($context, $cm, $course);
1080  
1081          $student1 = self::getDataGenerator()->create_user();
1082          $student2 = self::getDataGenerator()->create_user();
1083          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1084          $this->getDataGenerator()->enrol_user($student1->id,
1085                                                $course->id,
1086                                                $studentrole->id);
1087          $this->getDataGenerator()->enrol_user($student2->id,
1088                                                $course->id,
1089                                                $studentrole->id);
1090          // Simulate a grade.
1091          $this->setUser($teacher);
1092  
1093          // Create a file in a draft area.
1094          $draftidfile = file_get_unused_draft_itemid();
1095  
1096          $usercontext = context_user::instance($teacher->id);
1097          $filerecord = array(
1098              'contextid' => $usercontext->id,
1099              'component' => 'user',
1100              'filearea'  => 'draft',
1101              'itemid'    => $draftidfile,
1102              'filepath'  => '/',
1103              'filename'  => 'testtext.txt',
1104          );
1105  
1106          $fs = get_file_storage();
1107          $fs->create_file_from_string($filerecord, 'text contents');
1108  
1109          // Now try a grade.
1110          $feedbackpluginparams = array();
1111          $feedbackpluginparams['files_filemanager'] = $draftidfile;
1112          $feedbackeditorparams = array('text' => 'Yeeha!',
1113                                          'format' => 1);
1114          $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1115          $result = mod_assign_external::save_grade($instance->id,
1116                                                    $student1->id,
1117                                                    50.0,
1118                                                    -1,
1119                                                    true,
1120                                                    'released',
1121                                                    false,
1122                                                    $feedbackpluginparams);
1123          // No warnings.
1124          $this->assertNull($result);
1125  
1126          $result = mod_assign_external::get_grades(array($instance->id));
1127          $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
1128  
1129          $this->assertEquals($result['assignments'][0]['grades'][0]['grade'], '50.0');
1130      }
1131  
1132      /**
1133       * Test save grades with advanced grading data
1134       */
1135      public function test_save_grades_with_advanced_grading() {
1136          global $DB, $USER;
1137  
1138          $this->resetAfterTest(true);
1139          // Create a course and assignment and users.
1140          $course = self::getDataGenerator()->create_course();
1141  
1142          $teacher = self::getDataGenerator()->create_user();
1143          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1144          $this->getDataGenerator()->enrol_user($teacher->id,
1145                                                $course->id,
1146                                                $teacherrole->id);
1147  
1148          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1149          $params['course'] = $course->id;
1150          $params['assignfeedback_file_enabled'] = 0;
1151          $params['assignfeedback_comments_enabled'] = 0;
1152          $instance = $generator->create_instance($params);
1153          $cm = get_coursemodule_from_instance('assign', $instance->id);
1154          $context = context_module::instance($cm->id);
1155  
1156          $assign = new assign($context, $cm, $course);
1157  
1158          $student1 = self::getDataGenerator()->create_user();
1159          $student2 = self::getDataGenerator()->create_user();
1160          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1161          $this->getDataGenerator()->enrol_user($student1->id,
1162                                                $course->id,
1163                                                $studentrole->id);
1164          $this->getDataGenerator()->enrol_user($student2->id,
1165                                                $course->id,
1166                                                $studentrole->id);
1167  
1168          $this->setUser($teacher);
1169  
1170          $feedbackpluginparams = array();
1171          $feedbackpluginparams['files_filemanager'] = 0;
1172          $feedbackeditorparams = array('text' => '', 'format' => 1);
1173          $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1174  
1175          // Create advanced grading data.
1176          // Create grading area.
1177          $gradingarea = array(
1178              'contextid' => $context->id,
1179              'component' => 'mod_assign',
1180              'areaname' => 'submissions',
1181              'activemethod' => 'rubric'
1182          );
1183          $areaid = $DB->insert_record('grading_areas', $gradingarea);
1184  
1185          // Create a rubric grading definition.
1186          $rubricdefinition = array (
1187              'areaid' => $areaid,
1188              'method' => 'rubric',
1189              'name' => 'test',
1190              'status' => 20,
1191              'copiedfromid' => 1,
1192              'timecreated' => 1,
1193              'usercreated' => $teacher->id,
1194              'timemodified' => 1,
1195              'usermodified' => $teacher->id,
1196              'timecopied' => 0
1197          );
1198          $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
1199  
1200          // Create a criterion with a level.
1201          $rubriccriteria = array (
1202               'definitionid' => $definitionid,
1203               'sortorder' => 1,
1204               'description' => 'Demonstrate an understanding of disease control',
1205               'descriptionformat' => 0
1206          );
1207          $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
1208          $rubriclevel1 = array (
1209              'criterionid' => $criterionid,
1210              'score' => 50,
1211              'definition' => 'pass',
1212              'definitionformat' => 0
1213          );
1214          $rubriclevel2 = array (
1215              'criterionid' => $criterionid,
1216              'score' => 100,
1217              'definition' => 'excellent',
1218              'definitionformat' => 0
1219          );
1220          $rubriclevel3 = array (
1221              'criterionid' => $criterionid,
1222              'score' => 0,
1223              'definition' => 'fail',
1224              'definitionformat' => 0
1225          );
1226          $levelid1 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
1227          $levelid2 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
1228          $levelid3 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel3);
1229  
1230          // Create the filling.
1231          $student1filling = array (
1232              'criterionid' => $criterionid,
1233              'levelid' => $levelid1,
1234              'remark' => 'well done you passed',
1235              'remarkformat' => 0
1236          );
1237  
1238          $student2filling = array (
1239              'criterionid' => $criterionid,
1240              'levelid' => $levelid2,
1241              'remark' => 'Excellent work',
1242              'remarkformat' => 0
1243          );
1244  
1245          $student1criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student1filling)));
1246          $student1advancedgradingdata = array('rubric' => array('criteria' => $student1criteria));
1247  
1248          $student2criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student2filling)));
1249          $student2advancedgradingdata = array('rubric' => array('criteria' => $student2criteria));
1250  
1251          $grades = array();
1252          $student1gradeinfo = array();
1253          $student1gradeinfo['userid'] = $student1->id;
1254          $student1gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1255          $student1gradeinfo['attemptnumber'] = -1;
1256          $student1gradeinfo['addattempt'] = true;
1257          $student1gradeinfo['workflowstate'] = 'released';
1258          $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1259          $student1gradeinfo['advancedgradingdata'] = $student1advancedgradingdata;
1260          $grades[] = $student1gradeinfo;
1261  
1262          $student2gradeinfo = array();
1263          $student2gradeinfo['userid'] = $student2->id;
1264          $student2gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1265          $student2gradeinfo['attemptnumber'] = -1;
1266          $student2gradeinfo['addattempt'] = true;
1267          $student2gradeinfo['workflowstate'] = 'released';
1268          $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1269          $student2gradeinfo['advancedgradingdata'] = $student2advancedgradingdata;
1270          $grades[] = $student2gradeinfo;
1271  
1272          $result = mod_assign_external::save_grades($instance->id, false, $grades);
1273          $this->assertNull($result);
1274  
1275          $student1grade = $DB->get_record('assign_grades',
1276                                           array('userid' => $student1->id, 'assignment' => $instance->id),
1277                                           '*',
1278                                           MUST_EXIST);
1279          $this->assertEquals($student1grade->grade, '50.0');
1280  
1281          $student2grade = $DB->get_record('assign_grades',
1282                                           array('userid' => $student2->id, 'assignment' => $instance->id),
1283                                           '*',
1284                                           MUST_EXIST);
1285          $this->assertEquals($student2grade->grade, '100.0');
1286      }
1287  
1288      /**
1289       * Test save grades for a team submission
1290       *
1291       * @expectedException invalid_parameter_exception
1292       */
1293      public function test_save_grades_with_group_submission() {
1294          global $DB, $USER, $CFG;
1295          require_once($CFG->dirroot . '/group/lib.php');
1296  
1297          $this->resetAfterTest(true);
1298          // Create a course and assignment and users.
1299          $course = self::getDataGenerator()->create_course();
1300  
1301          $teacher = self::getDataGenerator()->create_user();
1302          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1303          $this->getDataGenerator()->enrol_user($teacher->id,
1304                                                $course->id,
1305                                                $teacherrole->id);
1306  
1307          $groupingdata = array();
1308          $groupingdata['courseid'] = $course->id;
1309          $groupingdata['name'] = 'Group assignment grouping';
1310  
1311          $grouping = self::getDataGenerator()->create_grouping($groupingdata);
1312  
1313          $group1data = array();
1314          $group1data['courseid'] = $course->id;
1315          $group1data['name'] = 'Team 1';
1316          $group2data = array();
1317          $group2data['courseid'] = $course->id;
1318          $group2data['name'] = 'Team 2';
1319  
1320          $group1 = self::getDataGenerator()->create_group($group1data);
1321          $group2 = self::getDataGenerator()->create_group($group2data);
1322  
1323          groups_assign_grouping($grouping->id, $group1->id);
1324          groups_assign_grouping($grouping->id, $group2->id);
1325  
1326          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1327          $params['course'] = $course->id;
1328          $params['teamsubmission'] = 1;
1329          $params['teamsubmissiongroupingid'] = $grouping->id;
1330          $instance = $generator->create_instance($params);
1331          $cm = get_coursemodule_from_instance('assign', $instance->id);
1332          $context = context_module::instance($cm->id);
1333  
1334          $assign = new assign($context, $cm, $course);
1335  
1336          $student1 = self::getDataGenerator()->create_user();
1337          $student2 = self::getDataGenerator()->create_user();
1338          $student3 = self::getDataGenerator()->create_user();
1339          $student4 = self::getDataGenerator()->create_user();
1340          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1341          $this->getDataGenerator()->enrol_user($student1->id,
1342                                                $course->id,
1343                                                $studentrole->id);
1344          $this->getDataGenerator()->enrol_user($student2->id,
1345                                                $course->id,
1346                                                $studentrole->id);
1347          $this->getDataGenerator()->enrol_user($student3->id,
1348                                                $course->id,
1349                                                $studentrole->id);
1350          $this->getDataGenerator()->enrol_user($student4->id,
1351                                                $course->id,
1352                                                $studentrole->id);
1353  
1354          groups_add_member($group1->id, $student1->id);
1355          groups_add_member($group1->id, $student2->id);
1356          groups_add_member($group1->id, $student3->id);
1357          groups_add_member($group2->id, $student4->id);
1358          $this->setUser($teacher);
1359  
1360          $feedbackpluginparams = array();
1361          $feedbackpluginparams['files_filemanager'] = 0;
1362          $feedbackeditorparams = array('text' => '', 'format' => 1);
1363          $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1364  
1365          $grades1 = array();
1366          $student1gradeinfo = array();
1367          $student1gradeinfo['userid'] = $student1->id;
1368          $student1gradeinfo['grade'] = 50;
1369          $student1gradeinfo['attemptnumber'] = -1;
1370          $student1gradeinfo['addattempt'] = true;
1371          $student1gradeinfo['workflowstate'] = 'released';
1372          $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1373          $grades1[] = $student1gradeinfo;
1374  
1375          $student2gradeinfo = array();
1376          $student2gradeinfo['userid'] = $student2->id;
1377          $student2gradeinfo['grade'] = 75;
1378          $student2gradeinfo['attemptnumber'] = -1;
1379          $student2gradeinfo['addattempt'] = true;
1380          $student2gradeinfo['workflowstate'] = 'released';
1381          $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1382          $grades1[] = $student2gradeinfo;
1383  
1384          // Expect an exception since 2 grades have been submitted for the same team.
1385          $result = mod_assign_external::save_grades($instance->id, true, $grades1);
1386          $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
1387  
1388          $grades2 = array();
1389          $student3gradeinfo = array();
1390          $student3gradeinfo['userid'] = $student3->id;
1391          $student3gradeinfo['grade'] = 50;
1392          $student3gradeinfo['attemptnumber'] = -1;
1393          $student3gradeinfo['addattempt'] = true;
1394          $student3gradeinfo['workflowstate'] = 'released';
1395          $student3gradeinfo['plugindata'] = $feedbackpluginparams;
1396          $grades2[] = $student3gradeinfo;
1397  
1398          $student4gradeinfo = array();
1399          $student4gradeinfo['userid'] = $student4->id;
1400          $student4gradeinfo['grade'] = 75;
1401          $student4gradeinfo['attemptnumber'] = -1;
1402          $student4gradeinfo['addattempt'] = true;
1403          $student4gradeinfo['workflowstate'] = 'released';
1404          $student4gradeinfo['plugindata'] = $feedbackpluginparams;
1405          $grades2[] = $student4gradeinfo;
1406          $result = mod_assign_external::save_grades($instance->id, true, $grades2);
1407          $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
1408          // There should be no warnings.
1409          $this->assertEquals(0, count($result));
1410  
1411          $student3grade = $DB->get_record('assign_grades',
1412                                           array('userid' => $student3->id, 'assignment' => $instance->id),
1413                                           '*',
1414                                           MUST_EXIST);
1415          $this->assertEquals($student3grade->grade, '50.0');
1416  
1417          $student4grade = $DB->get_record('assign_grades',
1418                                           array('userid' => $student4->id, 'assignment' => $instance->id),
1419                                           '*',
1420                                           MUST_EXIST);
1421          $this->assertEquals($student4grade->grade, '75.0');
1422      }
1423  
1424      /**
1425       * Test copy_previous_attempt
1426       */
1427      public function test_copy_previous_attempt() {
1428          global $DB, $USER;
1429  
1430          $this->resetAfterTest(true);
1431          // Create a course and assignment and users.
1432          $course = self::getDataGenerator()->create_course();
1433  
1434          $teacher = self::getDataGenerator()->create_user();
1435          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1436          $this->getDataGenerator()->enrol_user($teacher->id,
1437                                                $course->id,
1438                                                $teacherrole->id);
1439          $this->setUser($teacher);
1440  
1441          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1442          $params['course'] = $course->id;
1443          $params['assignsubmission_onlinetext_enabled'] = 1;
1444          $params['assignsubmission_file_enabled'] = 0;
1445          $params['assignfeedback_file_enabled'] = 0;
1446          $params['attemptreopenmethod'] = 'manual';
1447          $params['maxattempts'] = 5;
1448          $instance = $generator->create_instance($params);
1449          $cm = get_coursemodule_from_instance('assign', $instance->id);
1450          $context = context_module::instance($cm->id);
1451  
1452          $assign = new assign($context, $cm, $course);
1453  
1454          $student1 = self::getDataGenerator()->create_user();
1455          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
1456          $this->getDataGenerator()->enrol_user($student1->id,
1457                                                $course->id,
1458                                                $studentrole->id);
1459          // Now try a submission.
1460          $this->setUser($student1);
1461          $draftidonlinetext = file_get_unused_draft_itemid();
1462          $submissionpluginparams = array();
1463          $onlinetexteditorparams = array('text'=>'Yeeha!',
1464                                          'format'=>1,
1465                                          'itemid'=>$draftidonlinetext);
1466          $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1467          $submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1468          $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
1469          $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
1470  
1471          $this->setUser($teacher);
1472          // Add a grade and reopen the attempt.
1473          // Now try a grade.
1474          $feedbackpluginparams = array();
1475          $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1476          $feedbackeditorparams = array('text'=>'Yeeha!',
1477                                          'format'=>1);
1478          $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1479          $result = mod_assign_external::save_grade($instance->id,
1480                                                    $student1->id,
1481                                                    50.0,
1482                                                    -1,
1483                                                    true,
1484                                                    'released',
1485                                                    false,
1486                                                    $feedbackpluginparams);
1487          $this->assertNull($result);
1488  
1489          $this->setUser($student1);
1490          // Now copy the previous attempt.
1491          $result = mod_assign_external::copy_previous_attempt($instance->id);
1492          $result = external_api::clean_returnvalue(mod_assign_external::copy_previous_attempt_returns(), $result);
1493          // No warnings.
1494          $this->assertEquals(0, count($result));
1495  
1496          $this->setUser($teacher);
1497          $result = mod_assign_external::get_submissions(array($instance->id));
1498          $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
1499  
1500          // Check we are now on the second attempt.
1501          $this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
1502          // Check the plugins data is not empty.
1503          $this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
1504  
1505      }
1506  
1507      /**
1508       * Test set_user_flags
1509       */
1510      public function test_set_user_flags() {
1511          global $DB, $USER;
1512  
1513          $this->resetAfterTest(true);
1514          // Create a course and assignment.
1515          $coursedata['idnumber'] = 'idnumbercourse';
1516          $coursedata['fullname'] = 'Lightwork Course';
1517          $coursedata['summary'] = 'Lightwork Course description';
1518          $coursedata['summaryformat'] = FORMAT_MOODLE;
1519          $course = self::getDataGenerator()->create_course($coursedata);
1520  
1521          $assigndata['course'] = $course->id;
1522          $assigndata['name'] = 'lightwork assignment';
1523  
1524          $assign = self::getDataGenerator()->create_module('assign', $assigndata);
1525  
1526          // Create a manual enrolment record.
1527          $manualenroldata['enrol'] = 'manual';
1528          $manualenroldata['status'] = 0;
1529          $manualenroldata['courseid'] = $course->id;
1530          $enrolid = $DB->insert_record('enrol', $manualenroldata);
1531  
1532          // Create a teacher and give them capabilities.
1533          $context = context_course::instance($course->id);
1534          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
1535          $context = context_module::instance($assign->cmid);
1536          $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
1537  
1538          // Create the teacher's enrolment record.
1539          $userenrolmentdata['status'] = 0;
1540          $userenrolmentdata['enrolid'] = $enrolid;
1541          $userenrolmentdata['userid'] = $USER->id;
1542          $DB->insert_record('user_enrolments', $userenrolmentdata);
1543  
1544          // Create a student.
1545          $student = self::getDataGenerator()->create_user();
1546  
1547          // Create test user flags record.
1548          $userflags = array();
1549          $userflag['userid'] = $student->id;
1550          $userflag['workflowstate'] = 'inmarking';
1551          $userflag['allocatedmarker'] = $USER->id;
1552          $userflags = array($userflag);
1553  
1554          $createduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1555          // We need to execute the return values cleaning process to simulate the web service server.
1556          $createduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $createduserflags);
1557  
1558          $this->assertEquals($student->id, $createduserflags[0]['userid']);
1559          $createduserflag = $DB->get_record('assign_user_flags', array('id' => $createduserflags[0]['id']));
1560  
1561          // Confirm that all data was inserted correctly.
1562          $this->assertEquals($student->id,  $createduserflag->userid);
1563          $this->assertEquals($assign->id, $createduserflag->assignment);
1564          $this->assertEquals(0, $createduserflag->locked);
1565          $this->assertEquals(2, $createduserflag->mailed);
1566          $this->assertEquals(0, $createduserflag->extensionduedate);
1567          $this->assertEquals('inmarking', $createduserflag->workflowstate);
1568          $this->assertEquals($USER->id, $createduserflag->allocatedmarker);
1569  
1570          // Create update data.
1571          $userflags = array();
1572          $userflag['userid'] = $createduserflag->userid;
1573          $userflag['workflowstate'] = 'readyforreview';
1574          $userflags = array($userflag);
1575  
1576          $updateduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1577          // We need to execute the return values cleaning process to simulate the web service server.
1578          $updateduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $updateduserflags);
1579  
1580          $this->assertEquals($student->id, $updateduserflags[0]['userid']);
1581          $updateduserflag = $DB->get_record('assign_user_flags', array('id' => $updateduserflags[0]['id']));
1582  
1583          // Confirm that all data was updated correctly.
1584          $this->assertEquals($student->id,  $updateduserflag->userid);
1585          $this->assertEquals($assign->id, $updateduserflag->assignment);
1586          $this->assertEquals(0, $updateduserflag->locked);
1587          $this->assertEquals(2, $updateduserflag->mailed);
1588          $this->assertEquals(0, $updateduserflag->extensionduedate);
1589          $this->assertEquals('readyforreview', $updateduserflag->workflowstate);
1590          $this->assertEquals($USER->id, $updateduserflag->allocatedmarker);
1591      }
1592  
1593      /**
1594       * Test view_grading_table
1595       *
1596       * @expectedException dml_missing_record_exception
1597       */
1598      public function test_view_grading_table_invalid_instance() {
1599          global $DB;
1600  
1601          $this->resetAfterTest(true);
1602  
1603          // Setup test data.
1604          $course = $this->getDataGenerator()->create_course();
1605          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1606          $context = context_module::instance($assign->cmid);
1607          $cm = get_coursemodule_from_instance('assign', $assign->id);
1608  
1609          // Test invalid instance id.
1610          mod_assign_external::view_grading_table(0);
1611      }
1612  
1613      /**
1614       * Test view_grading_table
1615       *
1616       * @expectedException require_login_exception
1617       */
1618      public function test_view_grading_table_not_enrolled() {
1619          global $DB;
1620  
1621          $this->resetAfterTest(true);
1622  
1623          // Setup test data.
1624          $course = $this->getDataGenerator()->create_course();
1625          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1626          $context = context_module::instance($assign->cmid);
1627          $cm = get_coursemodule_from_instance('assign', $assign->id);
1628  
1629          // Test not-enrolled user.
1630          $user = self::getDataGenerator()->create_user();
1631          $this->setUser($user);
1632  
1633          mod_assign_external::view_grading_table($assign->id);
1634      }
1635  
1636      /**
1637       * Test view_grading_table
1638       */
1639      public function test_view_grading_table_correct() {
1640          global $DB;
1641  
1642          $this->resetAfterTest(true);
1643  
1644          // Setup test data.
1645          $course = $this->getDataGenerator()->create_course();
1646          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1647          $context = context_module::instance($assign->cmid);
1648          $cm = get_coursemodule_from_instance('assign', $assign->id);
1649  
1650          // Test user with full capabilities.
1651          $user = self::getDataGenerator()->create_user();
1652          $this->setUser($user);
1653          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1654          $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1655  
1656          // Trigger and capture the event.
1657          $sink = $this->redirectEvents();
1658  
1659          $result = mod_assign_external::view_grading_table($assign->id);
1660          $result = external_api::clean_returnvalue(mod_assign_external::view_grading_table_returns(), $result);
1661  
1662          $events = $sink->get_events();
1663          $this->assertCount(1, $events);
1664          $event = array_shift($events);
1665  
1666          // Checking that the event contains the expected values.
1667          $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
1668          $this->assertEquals($context, $event->get_context());
1669          $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1670          $this->assertEquals($moodleurl, $event->get_url());
1671          $this->assertEventContextNotUsed($event);
1672          $this->assertNotEmpty($event->get_name());
1673      }
1674  
1675      /**
1676       * Test view_grading_table
1677       *
1678       * @expectedException        require_login_exception
1679       * @expectedExceptionMessage Course or activity not accessible. (Activity is hidden)
1680       */
1681      public function test_view_grading_table_without_capability() {
1682          global $DB;
1683  
1684          $this->resetAfterTest(true);
1685  
1686          // Setup test data.
1687          $course = $this->getDataGenerator()->create_course();
1688          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1689          $context = context_module::instance($assign->cmid);
1690          $cm = get_coursemodule_from_instance('assign', $assign->id);
1691  
1692          // Test user with no capabilities.
1693          $user = self::getDataGenerator()->create_user();
1694          $this->setUser($user);
1695          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1696          $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1697  
1698          // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1699          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1700          assign_capability('mod/assign:view', CAP_PROHIBIT, $teacherrole->id, $context->id);
1701          // Empty all the caches that may be affected by this change.
1702          accesslib_clear_all_caches_for_unit_testing();
1703          course_modinfo::clear_instance_cache();
1704  
1705          mod_assign_external::view_grading_table($assign->id);
1706      }
1707  
1708      /**
1709       * Test subplugins availability
1710       */
1711      public function test_subplugins_availability() {
1712          global $CFG;
1713  
1714          require_once($CFG->dirroot . '/mod/assign/adminlib.php');
1715          $this->resetAfterTest(true);
1716  
1717          // Hide assignment file submissiong plugin.
1718          $pluginmanager = new assign_plugin_manager('assignsubmission');
1719          $pluginmanager->hide_plugin('file');
1720          $parameters = mod_assign_external::save_submission_parameters();
1721  
1722          $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1723  
1724          // Show it again and check that the value is returned as optional.
1725          $pluginmanager->show_plugin('file');
1726          $parameters = mod_assign_external::save_submission_parameters();
1727          $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1728          $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1729  
1730          // Hide feedback file submissiong plugin.
1731          $pluginmanager = new assign_plugin_manager('assignfeedback');
1732          $pluginmanager->hide_plugin('file');
1733  
1734          $parameters = mod_assign_external::save_grade_parameters();
1735  
1736          $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1737  
1738          // Show it again and check that the value is returned as optional.
1739          $pluginmanager->show_plugin('file');
1740          $parameters = mod_assign_external::save_grade_parameters();
1741  
1742          $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1743          $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1744  
1745          // Check a different one.
1746          $pluginmanager->show_plugin('comments');
1747          $this->assertTrue(isset($parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']));
1748          $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']->required);
1749      }
1750  
1751      /**
1752       * Test test_view_submission_status
1753       */
1754      public function test_view_submission_status() {
1755          global $DB;
1756  
1757          $this->resetAfterTest(true);
1758  
1759          $this->setAdminUser();
1760          // Setup test data.
1761          $course = $this->getDataGenerator()->create_course();
1762          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1763          $context = context_module::instance($assign->cmid);
1764          $cm = get_coursemodule_from_instance('assign', $assign->id);
1765  
1766          // Test invalid instance id.
1767          try {
1768              mod_assign_external::view_submission_status(0);
1769              $this->fail('Exception expected due to invalid mod_assign instance id.');
1770          } catch (moodle_exception $e) {
1771              $this->assertEquals('invalidrecord', $e->errorcode);
1772          }
1773  
1774          // Test not-enrolled user.
1775          $user = self::getDataGenerator()->create_user();
1776          $this->setUser($user);
1777          try {
1778              mod_assign_external::view_submission_status($assign->id);
1779              $this->fail('Exception expected due to not enrolled user.');
1780          } catch (moodle_exception $e) {
1781              $this->assertEquals('requireloginerror', $e->errorcode);
1782          }
1783  
1784          // Test user with full capabilities.
1785          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1786          $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
1787  
1788          // Trigger and capture the event.
1789          $sink = $this->redirectEvents();
1790  
1791          $result = mod_assign_external::view_submission_status($assign->id);
1792          $result = external_api::clean_returnvalue(mod_assign_external::view_submission_status_returns(), $result);
1793  
1794          $events = $sink->get_events();
1795          $this->assertCount(1, $events);
1796          $event = array_shift($events);
1797  
1798          // Checking that the event contains the expected values.
1799          $this->assertInstanceOf('\mod_assign\event\submission_status_viewed', $event);
1800          $this->assertEquals($context, $event->get_context());
1801          $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1802          $this->assertEquals($moodleurl, $event->get_url());
1803          $this->assertEventContextNotUsed($event);
1804          $this->assertNotEmpty($event->get_name());
1805  
1806          // Test user with no capabilities.
1807          // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1808          assign_capability('mod/assign:view', CAP_PROHIBIT, $studentrole->id, $context->id);
1809          accesslib_clear_all_caches_for_unit_testing();
1810          course_modinfo::clear_instance_cache();
1811  
1812          try {
1813              mod_assign_external::view_submission_status($assign->id);
1814              $this->fail('Exception expected due to missing capability.');
1815          } catch (moodle_exception $e) {
1816              $this->assertEquals('requireloginerror', $e->errorcode);
1817          }
1818      }
1819  
1820      /**
1821       * Create a submission for testing the get_submission_status function.
1822       * @param  boolean $submitforgrading whether to submit for grading the submission
1823       * @return array an array containing all the required data for testing
1824       */
1825      private function create_submission_for_testing_status($submitforgrading = false) {
1826          global $DB, $CFG;
1827          require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
1828  
1829          // Create a course and assignment and users.
1830          $course = self::getDataGenerator()->create_course();
1831  
1832          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1833          $params = array(
1834              'course' => $course->id,
1835              'assignsubmission_file_maxfiles' => 1,
1836              'assignsubmission_file_maxsizebytes' => 1024 * 1024,
1837              'assignsubmission_onlinetext_enabled' => 1,
1838              'assignsubmission_file_enabled' => 1,
1839              'submissiondrafts' => 1,
1840              'assignfeedback_file_enabled' => 1,
1841              'assignfeedback_comments_enabled' => 1,
1842              'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1843              'sendnotifications' => 0
1844          );
1845  
1846          set_config('submissionreceipts', 0, 'assign');
1847  
1848          $instance = $generator->create_instance($params);
1849          $cm = get_coursemodule_from_instance('assign', $instance->id);
1850          $context = context_module::instance($cm->id);
1851  
1852          $assign = new testable_assign($context, $cm, $course);
1853  
1854          $student1 = self::getDataGenerator()->create_user();
1855          $student2 = self::getDataGenerator()->create_user();
1856          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1857          $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
1858          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
1859          $teacher = self::getDataGenerator()->create_user();
1860          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1861          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
1862  
1863          $this->setUser($student1);
1864  
1865          // Create a student1 with an online text submission.
1866          // Simulate a submission.
1867          $submission = $assign->get_user_submission($student1->id, true);
1868  
1869          $data = new stdClass();
1870          $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1871                                           'text' => 'Submission text',
1872                                           'format' => FORMAT_MOODLE);
1873  
1874          $draftidfile = file_get_unused_draft_itemid();
1875          $usercontext = context_user::instance($student1->id);
1876          $filerecord = array(
1877              'contextid' => $usercontext->id,
1878              'component' => 'user',
1879              'filearea'  => 'draft',
1880              'itemid'    => $draftidfile,
1881              'filepath'  => '/',
1882              'filename'  => 't.txt',
1883          );
1884          $fs = get_file_storage();
1885          $fs->create_file_from_string($filerecord, 'text contents');
1886  
1887          $data->files_filemanager = $draftidfile;
1888  
1889          $notices = array();
1890          $assign->save_submission($data, $notices);
1891  
1892          if ($submitforgrading) {
1893              // Now, submit the draft for grading.
1894              $notices = array();
1895  
1896              $data = new stdClass;
1897              $data->userid = $student1->id;
1898              $assign->submit_for_grading($data, $notices);
1899          }
1900  
1901          return array($assign, $instance, $student1, $student2, $teacher);
1902      }
1903  
1904      /**
1905       * Test get_submission_status for a draft submission.
1906       */
1907      public function test_get_submission_status_in_draft_status() {
1908          $this->resetAfterTest(true);
1909  
1910          list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
1911  
1912          $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1913          // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1914          $this->assertDebuggingCalled();
1915  
1916          $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1917  
1918          // The submission is now in draft mode.
1919          $this->assertCount(0, $result['warnings']);
1920          $this->assertFalse(isset($result['gradingsummary']));
1921          $this->assertFalse(isset($result['feedback']));
1922          $this->assertFalse(isset($result['previousattempts']));
1923  
1924          $this->assertTrue($result['lastattempt']['submissionsenabled']);
1925          $this->assertTrue($result['lastattempt']['canedit']);
1926          $this->assertTrue($result['lastattempt']['cansubmit']);
1927          $this->assertFalse($result['lastattempt']['locked']);
1928          $this->assertFalse($result['lastattempt']['graded']);
1929          $this->assertEmpty($result['lastattempt']['extensionduedate']);
1930          $this->assertFalse($result['lastattempt']['blindmarking']);
1931          $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1932          $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1933  
1934          $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
1935          $this->assertEquals(0, $result['lastattempt']['submission']['attemptnumber']);
1936          $this->assertEquals('draft', $result['lastattempt']['submission']['status']);
1937          $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
1938          $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
1939          $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
1940  
1941          // Map plugins based on their type - we can't rely on them being in a
1942          // particular order, especially if 3rd party plugins are installed.
1943          $submissionplugins = array();
1944          foreach ($result['lastattempt']['submission']['plugins'] as $plugin) {
1945              $submissionplugins[$plugin['type']] = $plugin;
1946          }
1947          $this->assertEquals('Submission text', $submissionplugins['onlinetext']['editorfields'][0]['text']);
1948          $this->assertEquals('/', $submissionplugins['file']['fileareas'][0]['files'][0]['filepath']);
1949          $this->assertEquals('t.txt', $submissionplugins['file']['fileareas'][0]['files'][0]['filename']);
1950      }
1951  
1952      /**
1953       * Test get_submission_status for a submitted submission.
1954       */
1955      public function test_get_submission_status_in_submission_status() {
1956          $this->resetAfterTest(true);
1957  
1958          list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
1959  
1960          $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1961          // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1962          $this->assertDebuggingCalled();
1963          $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1964  
1965          $this->assertCount(0, $result['warnings']);
1966          $this->assertFalse(isset($result['gradingsummary']));
1967          $this->assertFalse(isset($result['feedback']));
1968          $this->assertFalse(isset($result['previousattempts']));
1969  
1970          $this->assertTrue($result['lastattempt']['submissionsenabled']);
1971          $this->assertFalse($result['lastattempt']['canedit']);
1972          $this->assertFalse($result['lastattempt']['cansubmit']);
1973          $this->assertFalse($result['lastattempt']['locked']);
1974          $this->assertFalse($result['lastattempt']['graded']);
1975          $this->assertEmpty($result['lastattempt']['extensionduedate']);
1976          $this->assertFalse($result['lastattempt']['blindmarking']);
1977          $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1978          $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1979  
1980      }
1981  
1982      /**
1983       * Test get_submission_status using the teacher role.
1984       */
1985      public function test_get_submission_status_in_submission_status_for_teacher() {
1986          $this->resetAfterTest(true);
1987  
1988          list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
1989  
1990          // Now, as teacher, see the grading summary.
1991          $this->setUser($teacher);
1992          $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1993          // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1994          $this->assertDebuggingCalled();
1995          $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1996  
1997          $this->assertCount(0, $result['warnings']);
1998          $this->assertFalse(isset($result['lastattempt']));
1999          $this->assertFalse(isset($result['feedback']));
2000          $this->assertFalse(isset($result['previousattempts']));
2001  
2002          $this->assertEquals(2, $result['gradingsummary']['participantcount']);
2003          $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
2004          $this->assertEquals(1, $result['gradingsummary']['submissionsenabled']);
2005          $this->assertEquals(1, $result['gradingsummary']['submissionssubmittedcount']);
2006          $this->assertEquals(1, $result['gradingsummary']['submissionsneedgradingcount']);
2007          $this->assertFalse($result['gradingsummary']['warnofungroupedusers']);
2008      }
2009  
2010      /**
2011       * Test get_submission_status for a reopened submission.
2012       */
2013      public function test_get_submission_status_in_reopened_status() {
2014          global $USER;
2015  
2016          $this->resetAfterTest(true);
2017  
2018          list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
2019  
2020          $this->setUser($teacher);
2021          // Grade and reopen.
2022          $feedbackpluginparams = array();
2023          $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
2024          $feedbackeditorparams = array('text' => 'Yeeha!',
2025                                          'format' => 1);
2026          $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
2027          $result = mod_assign_external::save_grade($instance->id,
2028                                                    $student1->id,
2029                                                    50.0,
2030                                                    -1,
2031                                                    false,
2032                                                    'released',
2033                                                    false,
2034                                                    $feedbackpluginparams);
2035          $USER->ignoresesskey = true;
2036          $assign->testable_process_add_attempt($student1->id);
2037  
2038          $this->setUser($student1);
2039  
2040          $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
2041          // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
2042          $this->assertDebuggingCalled();
2043          $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2044  
2045          $this->assertCount(0, $result['warnings']);
2046          $this->assertFalse(isset($result['gradingsummary']));
2047  
2048          $this->assertTrue($result['lastattempt']['submissionsenabled']);
2049          $this->assertTrue($result['lastattempt']['canedit']);
2050          $this->assertFalse($result['lastattempt']['cansubmit']);
2051          $this->assertFalse($result['lastattempt']['locked']);
2052          $this->assertFalse($result['lastattempt']['graded']);
2053          $this->assertEmpty($result['lastattempt']['extensionduedate']);
2054          $this->assertFalse($result['lastattempt']['blindmarking']);
2055          $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
2056          $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
2057  
2058          // Check new attempt reopened.
2059          $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
2060          $this->assertEquals(1, $result['lastattempt']['submission']['attemptnumber']);
2061          $this->assertEquals('reopened', $result['lastattempt']['submission']['status']);
2062          $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
2063          $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
2064          $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
2065          $this->assertCount(3, $result['lastattempt']['submission']['plugins']);
2066  
2067          // Now see feedback and the attempts history (remember, is a submission reopened).
2068          // Only 2 fields (no grade, no plugins data).
2069          $this->assertCount(2, $result['feedback']);
2070  
2071          // One previous attempt.
2072          $this->assertCount(1, $result['previousattempts']);
2073          $this->assertEquals(0, $result['previousattempts'][0]['attemptnumber']);
2074          $this->assertEquals(50, $result['previousattempts'][0]['grade']['grade']);
2075          $this->assertEquals($teacher->id, $result['previousattempts'][0]['grade']['grader']);
2076          $this->assertEquals($student1->id, $result['previousattempts'][0]['grade']['userid']);
2077  
2078          // Map plugins based on their type - we can't rely on them being in a
2079          // particular order, especially if 3rd party plugins are installed.
2080          $feedbackplugins = array();
2081          foreach ($result['previousattempts'][0]['feedbackplugins'] as $plugin) {
2082              $feedbackplugins[$plugin['type']] = $plugin;
2083          }
2084          $this->assertEquals('Yeeha!', $feedbackplugins['comments']['editorfields'][0]['text']);
2085  
2086          $submissionplugins = array();
2087          foreach ($result['previousattempts'][0]['submission']['plugins'] as $plugin) {
2088              $submissionplugins[$plugin['type']] = $plugin;
2089          }
2090          $this->assertEquals('Submission text', $submissionplugins['onlinetext']['editorfields'][0]['text']);
2091          $this->assertEquals('/', $submissionplugins['file']['fileareas'][0]['files'][0]['filepath']);
2092          $this->assertEquals('t.txt', $submissionplugins['file']['fileareas'][0]['files'][0]['filename']);
2093      }
2094  
2095      /**
2096       * Test access control for get_submission_status.
2097       *
2098       * @expectedException required_capability_exception
2099       */
2100      public function test_get_submission_status_access_control() {
2101          $this->resetAfterTest(true);
2102  
2103          list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
2104  
2105          $this->setUser($student2);
2106  
2107          // Access control test.
2108          mod_assign_external::get_submission_status($assign->get_instance()->id, $student1->id);
2109  
2110      }
2111  
2112      /**
2113       * get_participant should throw an excaption if the requested assignment doesn't exist.
2114       *
2115       * @expectedException moodle_exception
2116       */
2117      public function test_get_participant_no_assignment() {
2118          $this->resetAfterTest(true);
2119          mod_assign_external::get_participant('-1', '-1', false);
2120      }
2121  
2122      /**
2123       * get_participant should throw a require_login_exception if the user doesn't have access
2124       * to view assignments.
2125       *
2126       * @expectedException require_login_exception
2127       */
2128      public function test_get_participant_no_view_capability() {
2129          global $DB;
2130          $this->resetAfterTest(true);
2131  
2132          $result = $this->create_assign_with_student_and_teacher();
2133          $assign = $result['assign'];
2134          $student = $result['student'];
2135          $course = $result['course'];
2136          $context = context_course::instance($course->id);
2137          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
2138  
2139          $this->setUser($student);
2140          assign_capability('mod/assign:view', CAP_PROHIBIT, $studentrole->id, $context->id, true);
2141  
2142          mod_assign_external::get_participant($assign->id, $student->id, false);
2143      }
2144  
2145      /**
2146       * get_participant should throw a required_capability_exception if the user doesn't have access
2147       * to view assignment grades.
2148       *
2149       * @expectedException required_capability_exception
2150       */
2151      public function test_get_participant_no_grade_capability() {
2152          global $DB;
2153          $this->resetAfterTest(true);
2154  
2155          $result = $this->create_assign_with_student_and_teacher();
2156          $assign = $result['assign'];
2157          $student = $result['student'];
2158          $teacher = $result['teacher'];
2159          $course = $result['course'];
2160          $context = context_course::instance($course->id);
2161          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2162  
2163          $this->setUser($teacher);
2164          assign_capability('mod/assign:viewgrades', CAP_PROHIBIT, $teacherrole->id, $context->id, true);
2165          assign_capability('mod/assign:grade', CAP_PROHIBIT, $teacherrole->id, $context->id, true);
2166          accesslib_clear_all_caches_for_unit_testing();
2167  
2168          mod_assign_external::get_participant($assign->id, $student->id, false);
2169      }
2170  
2171      /**
2172       * get_participant should throw an exception if the user isn't enrolled in the course.
2173       *
2174       * @expectedException moodle_exception
2175       */
2176      public function test_get_participant_no_participant() {
2177          global $DB;
2178          $this->resetAfterTest(true);
2179  
2180          $result = $this->create_assign_with_student_and_teacher(array('blindmarking' => true));
2181          $student = $this->getDataGenerator()->create_user();
2182          $assign = $result['assign'];
2183          $teacher = $result['teacher'];
2184  
2185          $this->setUser($teacher);
2186  
2187          $result = mod_assign_external::get_participant($assign->id, $student->id, false);
2188      }
2189  
2190      /**
2191       * get_participant should return a summarised list of details with a different fullname if blind
2192       * marking is on for the requested assignment.
2193       */
2194      public function test_get_participant_blind_marking() {
2195          global $DB;
2196          $this->resetAfterTest(true);
2197  
2198          $result = $this->create_assign_with_student_and_teacher(array('blindmarking' => true));
2199          $assign = $result['assign'];
2200          $student = $result['student'];
2201          $teacher = $result['teacher'];
2202          $course = $result['course'];
2203          $context = context_course::instance($course->id);
2204          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2205  
2206          $this->setUser($teacher);
2207  
2208          $result = mod_assign_external::get_participant($assign->id, $student->id, true);
2209          $this->assertEquals($student->id, $result['id']);
2210          $this->assertFalse(fullname($student) == $result['fullname']);
2211          $this->assertFalse($result['submitted']);
2212          $this->assertFalse($result['requiregrading']);
2213          $this->assertTrue($result['blindmarking']);
2214          // Make sure we don't get any additional info.
2215          $this->assertTrue(empty($result['user']));
2216      }
2217  
2218      /**
2219       * get_participant should return a summarised list of details if requested.
2220       */
2221      public function test_get_participant_no_user() {
2222          global $DB;
2223          $this->resetAfterTest(true);
2224  
2225          $result = $this->create_assign_with_student_and_teacher();
2226          $assignmodule = $result['assign'];
2227          $student = $result['student'];
2228          $teacher = $result['teacher'];
2229          $course = $result['course'];
2230          $context = context_course::instance($course->id);
2231          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2232  
2233          // Create an assign instance to save a submission.
2234          set_config('submissionreceipts', 0, 'assign');
2235  
2236          $cm = get_coursemodule_from_instance('assign', $assignmodule->id);
2237          $context = context_module::instance($cm->id);
2238  
2239          $assign = new assign($context, $cm, $course);
2240  
2241          $this->setUser($student);
2242  
2243          // Simulate a submission.
2244          $data = new stdClass();
2245          $data->onlinetext_editor = array(
2246              'itemid' => file_get_unused_draft_itemid(),
2247              'text' => 'Student submission text',
2248              'format' => FORMAT_MOODLE
2249          );
2250  
2251          $notices = array();
2252          $assign->save_submission($data, $notices);
2253  
2254          $data = new stdClass;
2255          $data->userid = $student->id;
2256          $assign->submit_for_grading($data, array());
2257  
2258          $this->setUser($teacher);
2259  
2260          $result = mod_assign_external::get_participant($assignmodule->id, $student->id, false);
2261          $this->assertEquals($student->id, $result['id']);
2262          $this->assertEquals(fullname($student), $result['fullname']);
2263          $this->assertTrue($result['submitted']);
2264          $this->assertTrue($result['requiregrading']);
2265          $this->assertFalse($result['blindmarking']);
2266          // Make sure we don't get any additional info.
2267          $this->assertTrue(empty($result['user']));
2268      }
2269  
2270      /**
2271       * get_participant should return user details if requested.
2272       */
2273      public function test_get_participant_full_details() {
2274          global $DB;
2275          $this->resetAfterTest(true);
2276  
2277          $result = $this->create_assign_with_student_and_teacher();
2278          $assign = $result['assign'];
2279          $student = $result['student'];
2280          $teacher = $result['teacher'];
2281          $course = $result['course'];
2282          $context = context_course::instance($course->id);
2283          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2284  
2285          $this->setUser($teacher);
2286  
2287          $result = mod_assign_external::get_participant($assign->id, $student->id, true);
2288          // Check some of the extended properties we get when requesting the user.
2289          $this->assertEquals($student->id, $result['id']);
2290          // We should get user infomation back.
2291          $user = $result['user'];
2292          $this->assertFalse(empty($user));
2293          $this->assertEquals($student->firstname, $user['firstname']);
2294          $this->assertEquals($student->lastname, $user['lastname']);
2295          $this->assertEquals($student->email, $user['email']);
2296      }
2297  
2298      /**
2299       * get_participant should return group details if a group submission was
2300       * submitted.
2301       */
2302      public function test_get_participant_group_submission() {
2303          global $DB, $CFG;
2304          require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
2305  
2306          $this->resetAfterTest(true);
2307  
2308          $result = $this->create_assign_with_student_and_teacher(array(
2309              'assignsubmission_onlinetext_enabled' => 1,
2310              'teamsubmission' => 1
2311          ));
2312          $assignmodule = $result['assign'];
2313          $student = $result['student'];
2314          $teacher = $result['teacher'];
2315          $course = $result['course'];
2316          $context = context_course::instance($course->id);
2317          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2318          $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
2319          $cm = get_coursemodule_from_instance('assign', $assignmodule->id);
2320          $context = context_module::instance($cm->id);
2321          $assign = new testable_assign($context, $cm, $course);
2322  
2323          groups_add_member($group, $student);
2324  
2325          $this->setUser($student);
2326          $submission = $assign->get_group_submission($student->id, $group->id, true);
2327          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2328          $assign->testable_update_submission($submission, $student->id, true, false);
2329          $data = new stdClass();
2330          $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
2331                                           'text' => 'Submission text',
2332                                           'format' => FORMAT_MOODLE);
2333          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2334          $plugin->save($submission, $data);
2335  
2336          $this->setUser($teacher);
2337  
2338          $result = mod_assign_external::get_participant($assignmodule->id, $student->id, false);
2339          // Check some of the extended properties we get when not requesting a summary.
2340          $this->assertEquals($student->id, $result['id']);
2341          $this->assertEquals($group->id, $result['groupid']);
2342          $this->assertEquals($group->name, $result['groupname']);
2343      }
2344  
2345      /**
2346       * Test for mod_assign_external::list_participants().
2347       *
2348       * @throws coding_exception
2349       */
2350      public function test_list_participants_user_info_with_special_characters() {
2351          global $CFG, $DB;
2352          $this->resetAfterTest(true);
2353          $CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
2354  
2355          $data = $this->create_assign_with_student_and_teacher();
2356          $assignment = $data['assign'];
2357          $teacher = $data['teacher'];
2358  
2359          // Set data for student info that contain special characters.
2360          $student = $data['student'];
2361          $student->idnumber = '<\'"1am@wesome&c00l"\'>';
2362          $student->phone1 = '+63 (999) 888-7777';
2363          $student->phone2 = '(011) [15]4-123-4567';
2364          $student->department = 'Arts & Sciences & \' " ¢ £ © € ¥ ® < >';
2365          $student->institution = 'University of Awesome People & \' " ¢ £ © € ¥ ® < >';
2366          // Assert that we have valid user data.
2367          $this->assertTrue(core_user::validate($student));
2368          // Update the user record.
2369          $DB->update_record('user', $student);
2370  
2371          $this->setUser($teacher);
2372          $participants = mod_assign_external::list_participants($assignment->id, 0, '', 0, 0, false);
2373          $this->assertCount(1, $participants);
2374  
2375          // Asser that we have a valid response data.
2376          $response = external_api::clean_returnvalue(mod_assign_external::list_participants_returns(), $participants);
2377          $this->assertEquals($response, $participants);
2378  
2379          // Check participant data.
2380          $participant = $participants[0];
2381          $this->assertEquals($student->idnumber, $participant['idnumber']);
2382          $this->assertEquals($student->email, $participant['email']);
2383          $this->assertEquals($student->phone1, $participant['phone1']);
2384          $this->assertEquals($student->phone2, $participant['phone2']);
2385          $this->assertEquals($student->department, $participant['department']);
2386          $this->assertEquals($student->institution, $participant['institution']);
2387      }
2388  
2389      /**
2390       * Test for the type of the user-related properties in mod_assign_external::list_participants_returns().
2391       */
2392      public function test_list_participants_returns_user_property_types() {
2393          // Get user properties.
2394          $userdesc = core_user_external::user_description();
2395          $this->assertTrue(isset($userdesc->keys));
2396          $userproperties = array_keys($userdesc->keys);
2397  
2398          // Get returns description for mod_assign_external::list_participants_returns().
2399          $listreturns = mod_assign_external::list_participants_returns();
2400          $this->assertTrue(isset($listreturns->content));
2401          $listreturnsdesc = $listreturns->content->keys;
2402  
2403          // Iterate over list returns description's keys.
2404          foreach ($listreturnsdesc as $key => $desc) {
2405              // Check if key exists in user properties and the description has a type attribute.
2406              if (in_array($key, $userproperties) && isset($desc->type)) {
2407                  try {
2408                      // The core_user::get_property_type() method might throw a coding_exception since
2409                      // core_user_external::user_description() might contain properties that are not yet included in
2410                      // core_user's $propertiescache.
2411                      $propertytype = core_user::get_property_type($key);
2412  
2413                      // Assert that user-related property types match those of the defined in core_user.
2414                      $this->assertEquals($propertytype, $desc->type);
2415                  } catch (coding_exception $e) {
2416                      // All good.
2417                  }
2418              }
2419          }
2420      }
2421  
2422      /**
2423       * Create a a course, assignment module instance, student and teacher and enrol them in
2424       * the course.
2425       *
2426       * @param array $params parameters to be provided to the assignment module creation
2427       * @return array containing the course, assignment module, student and teacher
2428       */
2429      private function create_assign_with_student_and_teacher($params = array()) {
2430          global $DB;
2431  
2432          $course = $this->getDataGenerator()->create_course();
2433          $params = array_merge(array(
2434              'course' => $course->id,
2435              'name' => 'assignment',
2436              'intro' => 'assignment intro text',
2437          ), $params);
2438  
2439          // Create a course and assignment and users.
2440          $assign = $this->getDataGenerator()->create_module('assign', $params);
2441  
2442          $cm = get_coursemodule_from_instance('assign', $assign->id);
2443          $context = context_module::instance($cm->id);
2444  
2445          $student = $this->getDataGenerator()->create_user();
2446          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
2447          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
2448          $teacher = $this->getDataGenerator()->create_user();
2449          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2450          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
2451  
2452          assign_capability('mod/assign:view', CAP_ALLOW, $teacherrole->id, $context->id, true);
2453          assign_capability('mod/assign:viewgrades', CAP_ALLOW, $teacherrole->id, $context->id, true);
2454          assign_capability('mod/assign:grade', CAP_ALLOW, $teacherrole->id, $context->id, true);
2455          accesslib_clear_all_caches_for_unit_testing();
2456  
2457          return array(
2458              'course' => $course,
2459              'assign' => $assign,
2460              'student' => $student,
2461              'teacher' => $teacher
2462          );
2463      }
2464  
2465      /**
2466       * Test test_view_assign
2467       */
2468      public function test_view_assign() {
2469          global $CFG;
2470  
2471          $CFG->enablecompletion = 1;
2472          $this->resetAfterTest();
2473  
2474          $this->setAdminUser();
2475          // Setup test data.
2476          $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
2477          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id),
2478                                                              array('completion' => 2, 'completionview' => 1));
2479          $context = context_module::instance($assign->cmid);
2480          $cm = get_coursemodule_from_instance('assign', $assign->id);
2481  
2482          $result = mod_assign_external::view_assign($assign->id);
2483          $result = external_api::clean_returnvalue(mod_assign_external::view_assign_returns(), $result);
2484          $this->assertTrue($result['status']);
2485          $this->assertEmpty($result['warnings']);
2486  
2487          // Check completion status.
2488          $completion = new completion_info($course);
2489          $completiondata = $completion->get_data($cm);
2490          $this->assertEquals(1, $completiondata->completionstate);
2491      }
2492  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1