2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
17 defined('MOODLE_INTERNAL') || die();
21 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
24 * External mod assign functions unit tests
28 * @copyright 2012 Paul Charsley
29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 class mod_assign_external_testcase extends externallib_advanced_testcase {
36 protected function setUp() {
38 require_once($CFG->dirroot . '/mod/assign/externallib.php');
44 public function test_get_grades() {
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);
55 $assigndata['course'] = $course->id;
56 $assigndata['name'] = 'lightwork assignment';
58 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
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);
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);
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);
78 // Create a student and give them 2 grades (for 2 attempts).
79 $student = self::getDataGenerator()->create_user();
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);
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;
99 $grade->attemptnumber = 0;
100 $DB->insert_record('assign_grades', $grade);
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);
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;
120 $grade->attemptnumber = 1;
121 $DB->insert_record('assign_grades', $grade);
123 $assignmentids[] = $assign->id;
124 $result = mod_assign_external::get_grades($assignmentids);
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);
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']);
142 * Test get_assignments
144 public function test_get_assignments() {
147 $this->resetAfterTest(true);
149 $category = self::getDataGenerator()->create_category(array(
150 'name' => 'Test category'
154 $course1 = self::getDataGenerator()->create_course(array(
155 'idnumber' => 'idnumbercourse1',
156 'fullname' => 'Lightwork Course 1',
157 'summary' => 'Lightwork Course 1 description',
158 'summaryformat' => FORMAT_MOODLE,
159 'category' => $category->id
162 // Create a second course, just for testing.
163 $course2 = self::getDataGenerator()->create_course(array(
164 'idnumber' => 'idnumbercourse2',
165 'fullname' => 'Lightwork Course 2',
166 'summary' => 'Lightwork Course 2 description',
167 'summaryformat' => FORMAT_MOODLE,
168 'category' => $category->id
171 // Create the assignment module.
172 $assign1 = self::getDataGenerator()->create_module('assign', array(
173 'course' => $course1->id,
174 'name' => 'lightwork assignment',
175 'intro' => 'the assignment intro text here',
176 'markingworkflow' => 1,
177 'markingallocation' => 1
180 // Create manual enrolment record.
181 $enrolid = $DB->insert_record('enrol', (object)array(
184 'courseid' => $course1->id
187 // Create the user and give them capabilities.
188 $context = context_course::instance($course1->id);
189 $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
190 $context = context_module::instance($assign1->cmid);
191 $this->assignUserCapability('mod/assign:view', $context->id, $roleid);
193 // Create the user enrolment record.
194 $DB->insert_record('user_enrolments', (object)array(
196 'enrolid' => $enrolid,
197 'userid' => $USER->id
200 // Add a file as assignment attachment.
201 $filerecord = array('component' => 'mod_assign', 'filearea' => ASSIGN_INTROATTACHMENT_FILEAREA,
202 'contextid' => $context->id, 'itemid' => 0,
203 'filename' => 'introattachment.txt', 'filepath' => '/');
204 $fs = get_file_storage();
205 $fs->create_file_from_string($filerecord, 'Test intro attachment file');
207 $result = mod_assign_external::get_assignments();
209 // We need to execute the return values cleaning process to simulate the web service server.
210 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
212 // Check the course and assignment are returned.
213 $this->assertEquals(1, count($result['courses']));
214 $course = $result['courses'][0];
215 $this->assertEquals('Lightwork Course 1', $course['fullname']);
216 $this->assertEquals(1, count($course['assignments']));
217 $assignment = $course['assignments'][0];
218 $this->assertEquals($assign1->id, $assignment['id']);
219 $this->assertEquals($course1->id, $assignment['course']);
220 $this->assertEquals('lightwork assignment', $assignment['name']);
221 $this->assertEquals('the assignment intro text here', $assignment['intro']);
222 $this->assertEquals(1, $assignment['markingworkflow']);
223 $this->assertEquals(1, $assignment['markingallocation']);
225 $this->assertCount(1, $assignment['introattachments']);
226 $this->assertEquals('introattachment.txt', $assignment['introattachments'][0]['filename']);
228 // Now, hide the descritption until the submission from date.
229 $DB->set_field('assign', 'alwaysshowdescription', 0, array('id' => $assign1->id));
230 $DB->set_field('assign', 'allowsubmissionsfromdate', time() + DAYSECS, array('id' => $assign1->id));
232 $result = mod_assign_external::get_assignments(array($course1->id));
234 // We need to execute the return values cleaning process to simulate the web service server.
235 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
237 $this->assertEquals(1, count($result['courses']));
238 $course = $result['courses'][0];
239 $this->assertEquals('Lightwork Course 1', $course['fullname']);
240 $this->assertEquals(1, count($course['assignments']));
241 $assignment = $course['assignments'][0];
242 $this->assertEquals($assign1->id, $assignment['id']);
243 $this->assertEquals($course1->id, $assignment['course']);
244 $this->assertEquals('lightwork assignment', $assignment['name']);
245 $this->assertArrayNotHasKey('intro', $assignment);
246 $this->assertArrayNotHasKey('introattachments', $assignment);
247 $this->assertEquals(1, $assignment['markingworkflow']);
248 $this->assertEquals(1, $assignment['markingallocation']);
250 $result = mod_assign_external::get_assignments(array($course2->id));
252 // We need to execute the return values cleaning process to simulate the web service server.
253 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
255 $this->assertEquals(0, count($result['courses']));
256 $this->assertEquals(1, count($result['warnings']));
258 // Test with non-enrolled user, but with view capabilities.
259 $this->setAdminUser();
260 $result = mod_assign_external::get_assignments();
261 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
262 $this->assertEquals(0, count($result['courses']));
263 $this->assertEquals(0, count($result['warnings']));
265 // Expect no courses, because we are not using the special flag.
266 $result = mod_assign_external::get_assignments(array($course1->id));
267 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
268 $this->assertCount(0, $result['courses']);
270 // Now use the special flag to return courses where you are not enroled in.
271 $result = mod_assign_external::get_assignments(array($course1->id), array(), true);
272 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
273 $this->assertCount(1, $result['courses']);
275 $course = $result['courses'][0];
276 $this->assertEquals('Lightwork Course 1', $course['fullname']);
277 $this->assertEquals(1, count($course['assignments']));
278 $assignment = $course['assignments'][0];
279 $this->assertEquals($assign1->id, $assignment['id']);
280 $this->assertEquals($course1->id, $assignment['course']);
281 $this->assertEquals('lightwork assignment', $assignment['name']);
282 $this->assertArrayNotHasKey('intro', $assignment);
283 $this->assertArrayNotHasKey('introattachments', $assignment);
284 $this->assertEquals(1, $assignment['markingworkflow']);
285 $this->assertEquals(1, $assignment['markingallocation']);
289 * Test get_submissions
291 public function test_get_submissions() {
294 $this->resetAfterTest(true);
295 // Create a course and assignment.
296 $coursedata['idnumber'] = 'idnumbercourse1';
297 $coursedata['fullname'] = 'Lightwork Course 1';
298 $coursedata['summary'] = 'Lightwork Course 1 description';
299 $coursedata['summaryformat'] = FORMAT_MOODLE;
300 $course1 = self::getDataGenerator()->create_course($coursedata);
302 $assigndata['course'] = $course1->id;
303 $assigndata['name'] = 'lightwork assignment';
305 $assign1 = self::getDataGenerator()->create_module('assign', $assigndata);
307 // Create a student with an online text submission.
309 $student = self::getDataGenerator()->create_user();
310 $submission = new stdClass();
311 $submission->assignment = $assign1->id;
312 $submission->userid = $student->id;
313 $submission->timecreated = time();
314 $submission->timemodified = $submission->timecreated;
315 $submission->status = 'draft';
316 $submission->attemptnumber = 0;
317 $submission->latest = 0;
318 $sid = $DB->insert_record('assign_submission', $submission);
321 $submission = new stdClass();
322 $submission->assignment = $assign1->id;
323 $submission->userid = $student->id;
324 $submission->timecreated = time();
325 $submission->timemodified = $submission->timecreated;
326 $submission->status = 'submitted';
327 $submission->attemptnumber = 1;
328 $submission->latest = 1;
329 $sid = $DB->insert_record('assign_submission', $submission);
330 $submission->id = $sid;
332 $onlinetextsubmission = new stdClass();
333 $onlinetextsubmission->onlinetext = "<p>online test text</p>";
334 $onlinetextsubmission->onlineformat = 1;
335 $onlinetextsubmission->submission = $submission->id;
336 $onlinetextsubmission->assignment = $assign1->id;
337 $DB->insert_record('assignsubmission_onlinetext', $onlinetextsubmission);
339 // Create manual enrolment record.
340 $manualenroldata['enrol'] = 'manual';
341 $manualenroldata['status'] = 0;
342 $manualenroldata['courseid'] = $course1->id;
343 $enrolid = $DB->insert_record('enrol', $manualenroldata);
345 // Create a teacher and give them capabilities.
346 $context = context_course::instance($course1->id);
347 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
348 $context = context_module::instance($assign1->cmid);
349 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
351 // Create the teacher's enrolment record.
352 $userenrolmentdata['status'] = 0;
353 $userenrolmentdata['enrolid'] = $enrolid;
354 $userenrolmentdata['userid'] = $USER->id;
355 $DB->insert_record('user_enrolments', $userenrolmentdata);
357 $assignmentids[] = $assign1->id;
358 $result = mod_assign_external::get_submissions($assignmentids);
359 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
361 // Check the online text submission is returned.
362 $this->assertEquals(1, count($result['assignments']));
363 $assignment = $result['assignments'][0];
364 $this->assertEquals($assign1->id, $assignment['assignmentid']);
365 $this->assertEquals(1, count($assignment['submissions']));
366 $submission = $assignment['submissions'][0];
367 $this->assertEquals($sid, $submission['id']);
368 $this->assertCount(1, $submission['plugins']);
372 * Test get_user_flags
374 public function test_get_user_flags() {
377 $this->resetAfterTest(true);
378 // Create a course and assignment.
379 $coursedata['idnumber'] = 'idnumbercourse';
380 $coursedata['fullname'] = 'Lightwork Course';
381 $coursedata['summary'] = 'Lightwork Course description';
382 $coursedata['summaryformat'] = FORMAT_MOODLE;
383 $course = self::getDataGenerator()->create_course($coursedata);
385 $assigndata['course'] = $course->id;
386 $assigndata['name'] = 'lightwork assignment';
388 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
390 // Create a manual enrolment record.
391 $manualenroldata['enrol'] = 'manual';
392 $manualenroldata['status'] = 0;
393 $manualenroldata['courseid'] = $course->id;
394 $enrolid = $DB->insert_record('enrol', $manualenroldata);
396 // Create a teacher and give them capabilities.
397 $context = context_course::instance($course->id);
398 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
399 $context = context_module::instance($assign->cmid);
400 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
402 // Create the teacher's enrolment record.
403 $userenrolmentdata['status'] = 0;
404 $userenrolmentdata['enrolid'] = $enrolid;
405 $userenrolmentdata['userid'] = $USER->id;
406 $DB->insert_record('user_enrolments', $userenrolmentdata);
408 // Create a student and give them a user flag record.
409 $student = self::getDataGenerator()->create_user();
410 $userflag = new stdClass();
411 $userflag->assignment = $assign->id;
412 $userflag->userid = $student->id;
413 $userflag->locked = 0;
414 $userflag->mailed = 0;
415 $userflag->extensionduedate = 0;
416 $userflag->workflowstate = 'inmarking';
417 $userflag->allocatedmarker = $USER->id;
419 $DB->insert_record('assign_user_flags', $userflag);
421 $assignmentids[] = $assign->id;
422 $result = mod_assign_external::get_user_flags($assignmentids);
424 // We need to execute the return values cleaning process to simulate the web service server.
425 $result = external_api::clean_returnvalue(mod_assign_external::get_user_flags_returns(), $result);
427 // Check that the correct user flag information for the student is returned.
428 $this->assertEquals(1, count($result['assignments']));
429 $assignment = $result['assignments'][0];
430 $this->assertEquals($assign->id, $assignment['assignmentid']);
431 // Should be one user flag record.
432 $this->assertEquals(1, count($assignment['userflags']));
433 $userflag = $assignment['userflags'][0];
434 $this->assertEquals($student->id, $userflag['userid']);
435 $this->assertEquals(0, $userflag['locked']);
436 $this->assertEquals(0, $userflag['mailed']);
437 $this->assertEquals(0, $userflag['extensionduedate']);
438 $this->assertEquals('inmarking', $userflag['workflowstate']);
439 $this->assertEquals($USER->id, $userflag['allocatedmarker']);
443 * Test get_user_mappings
445 public function test_get_user_mappings() {
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);
456 $assigndata['course'] = $course->id;
457 $assigndata['name'] = 'lightwork assignment';
459 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
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);
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:revealidentities', $context->id, $roleid);
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);
479 // Create a student and give them a user mapping record.
480 $student = self::getDataGenerator()->create_user();
481 $mapping = new stdClass();
482 $mapping->assignment = $assign->id;
483 $mapping->userid = $student->id;
485 $DB->insert_record('assign_user_mapping', $mapping);
487 $assignmentids[] = $assign->id;
488 $result = mod_assign_external::get_user_mappings($assignmentids);
490 // We need to execute the return values cleaning process to simulate the web service server.
491 $result = external_api::clean_returnvalue(mod_assign_external::get_user_mappings_returns(), $result);
493 // Check that the correct user mapping information for the student is returned.
494 $this->assertEquals(1, count($result['assignments']));
495 $assignment = $result['assignments'][0];
496 $this->assertEquals($assign->id, $assignment['assignmentid']);
497 // Should be one user mapping record.
498 $this->assertEquals(1, count($assignment['mappings']));
499 $mapping = $assignment['mappings'][0];
500 $this->assertEquals($student->id, $mapping['userid']);
504 * Test lock_submissions
506 public function test_lock_submissions() {
509 $this->resetAfterTest(true);
510 // Create a course and assignment and users.
511 $course = self::getDataGenerator()->create_course();
513 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
514 $params['course'] = $course->id;
515 $params['assignsubmission_onlinetext_enabled'] = 1;
516 $instance = $generator->create_instance($params);
517 $cm = get_coursemodule_from_instance('assign', $instance->id);
518 $context = context_module::instance($cm->id);
520 $assign = new assign($context, $cm, $course);
522 $student1 = self::getDataGenerator()->create_user();
523 $student2 = self::getDataGenerator()->create_user();
524 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
525 $this->getDataGenerator()->enrol_user($student1->id,
528 $this->getDataGenerator()->enrol_user($student2->id,
531 $teacher = self::getDataGenerator()->create_user();
532 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
533 $this->getDataGenerator()->enrol_user($teacher->id,
537 // Create a student1 with an online text submission.
538 // Simulate a submission.
539 $this->setUser($student1);
540 $submission = $assign->get_user_submission($student1->id, true);
541 $data = new stdClass();
542 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
543 'text'=>'Submission text',
544 'format'=>FORMAT_MOODLE);
545 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
546 $plugin->save($submission, $data);
549 $this->setUser($teacher);
550 $students = array($student1->id, $student2->id);
551 $result = mod_assign_external::lock_submissions($instance->id, $students);
552 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
554 // Check for 0 warnings.
555 $this->assertEquals(0, count($result));
557 $this->setUser($student2);
558 $submission = $assign->get_user_submission($student2->id, true);
559 $data = new stdClass();
560 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
561 'text'=>'Submission text',
562 'format'=>FORMAT_MOODLE);
564 $this->setExpectedException('moodle_exception');
565 $assign->save_submission($data, $notices);
569 * Test unlock_submissions
571 public function test_unlock_submissions() {
574 $this->resetAfterTest(true);
575 // Create a course and assignment and users.
576 $course = self::getDataGenerator()->create_course();
578 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
579 $params['course'] = $course->id;
580 $params['assignsubmission_onlinetext_enabled'] = 1;
581 $instance = $generator->create_instance($params);
582 $cm = get_coursemodule_from_instance('assign', $instance->id);
583 $context = context_module::instance($cm->id);
585 $assign = new assign($context, $cm, $course);
587 $student1 = self::getDataGenerator()->create_user();
588 $student2 = self::getDataGenerator()->create_user();
589 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
590 $this->getDataGenerator()->enrol_user($student1->id,
593 $this->getDataGenerator()->enrol_user($student2->id,
596 $teacher = self::getDataGenerator()->create_user();
597 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
598 $this->getDataGenerator()->enrol_user($teacher->id,
602 // Create a student1 with an online text submission.
603 // Simulate a submission.
604 $this->setUser($student1);
605 $submission = $assign->get_user_submission($student1->id, true);
606 $data = new stdClass();
607 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
608 'text'=>'Submission text',
609 'format'=>FORMAT_MOODLE);
610 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
611 $plugin->save($submission, $data);
614 $this->setUser($teacher);
615 $students = array($student1->id, $student2->id);
616 $result = mod_assign_external::lock_submissions($instance->id, $students);
617 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
619 // Check for 0 warnings.
620 $this->assertEquals(0, count($result));
622 $result = mod_assign_external::unlock_submissions($instance->id, $students);
623 $result = external_api::clean_returnvalue(mod_assign_external::unlock_submissions_returns(), $result);
625 // Check for 0 warnings.
626 $this->assertEquals(0, count($result));
628 $this->setUser($student2);
629 $submission = $assign->get_user_submission($student2->id, true);
630 $data = new stdClass();
631 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
632 'text'=>'Submission text',
633 'format'=>FORMAT_MOODLE);
635 $assign->save_submission($data, $notices);
639 * Test submit_for_grading
641 public function test_submit_for_grading() {
644 $this->resetAfterTest(true);
645 // Create a course and assignment and users.
646 $course = self::getDataGenerator()->create_course();
648 set_config('submissionreceipts', 0, 'assign');
649 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
650 $params['course'] = $course->id;
651 $params['assignsubmission_onlinetext_enabled'] = 1;
652 $params['submissiondrafts'] = 1;
653 $params['sendnotifications'] = 0;
654 $params['requiresubmissionstatement'] = 1;
655 $instance = $generator->create_instance($params);
656 $cm = get_coursemodule_from_instance('assign', $instance->id);
657 $context = context_module::instance($cm->id);
659 $assign = new assign($context, $cm, $course);
661 $student1 = self::getDataGenerator()->create_user();
662 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
663 $this->getDataGenerator()->enrol_user($student1->id,
667 // Create a student1 with an online text submission.
668 // Simulate a submission.
669 $this->setUser($student1);
670 $submission = $assign->get_user_submission($student1->id, true);
671 $data = new stdClass();
672 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
673 'text'=>'Submission text',
674 'format'=>FORMAT_MOODLE);
675 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
676 $plugin->save($submission, $data);
678 $result = mod_assign_external::submit_for_grading($instance->id, false);
679 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
681 // Should be 1 fail because the submission statement was not aceptted.
682 $this->assertEquals(1, count($result));
684 $result = mod_assign_external::submit_for_grading($instance->id, true);
685 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
687 // Check for 0 warnings.
688 $this->assertEquals(0, count($result));
690 $submission = $assign->get_user_submission($student1->id, false);
692 $this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
696 * Test save_user_extensions
698 public function test_save_user_extensions() {
701 $this->resetAfterTest(true);
702 // Create a course and assignment and users.
703 $course = self::getDataGenerator()->create_course();
705 $teacher = self::getDataGenerator()->create_user();
706 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
707 $this->getDataGenerator()->enrol_user($teacher->id,
710 $this->setUser($teacher);
713 $yesterday = $now - 24*60*60;
714 $tomorrow = $now + 24*60*60;
715 set_config('submissionreceipts', 0, 'assign');
716 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
717 $params['course'] = $course->id;
718 $params['submissiondrafts'] = 1;
719 $params['sendnotifications'] = 0;
720 $params['duedate'] = $yesterday;
721 $params['cutoffdate'] = $now - 10;
722 $instance = $generator->create_instance($params);
723 $cm = get_coursemodule_from_instance('assign', $instance->id);
724 $context = context_module::instance($cm->id);
726 $assign = new assign($context, $cm, $course);
728 $student1 = self::getDataGenerator()->create_user();
729 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
730 $this->getDataGenerator()->enrol_user($student1->id,
734 $this->setUser($student1);
735 $result = mod_assign_external::submit_for_grading($instance->id, true);
736 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
738 // Check for 0 warnings.
739 $this->assertEquals(1, count($result));
741 $this->setUser($teacher);
742 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
743 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
744 $this->assertEquals(1, count($result));
746 $this->setUser($teacher);
747 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
748 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
749 $this->assertEquals(1, count($result));
751 $this->setUser($teacher);
752 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
753 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
754 $this->assertEquals(0, count($result));
756 $this->setUser($student1);
757 $result = mod_assign_external::submit_for_grading($instance->id, true);
758 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
759 $this->assertEquals(0, count($result));
761 $this->setUser($student1);
762 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
763 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
768 * Test reveal_identities
770 public function test_reveal_identities() {
773 $this->resetAfterTest(true);
774 // Create a course and assignment and users.
775 $course = self::getDataGenerator()->create_course();
777 $teacher = self::getDataGenerator()->create_user();
778 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
779 $this->getDataGenerator()->enrol_user($teacher->id,
782 $this->setUser($teacher);
784 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
785 $params['course'] = $course->id;
786 $params['submissiondrafts'] = 1;
787 $params['sendnotifications'] = 0;
788 $params['blindmarking'] = 1;
789 $instance = $generator->create_instance($params);
790 $cm = get_coursemodule_from_instance('assign', $instance->id);
791 $context = context_module::instance($cm->id);
793 $assign = new assign($context, $cm, $course);
795 $student1 = self::getDataGenerator()->create_user();
796 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
797 $this->getDataGenerator()->enrol_user($student1->id,
801 $this->setUser($student1);
802 $this->setExpectedException('required_capability_exception');
803 $result = mod_assign_external::reveal_identities($instance->id);
804 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
805 $this->assertEquals(1, count($result));
806 $this->assertEquals(true, $assign->is_blind_marking());
808 $this->setUser($teacher);
809 $result = mod_assign_external::reveal_identities($instance->id);
810 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
811 $this->assertEquals(0, count($result));
812 $this->assertEquals(false, $assign->is_blind_marking());
814 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
815 $params['course'] = $course->id;
816 $params['submissiondrafts'] = 1;
817 $params['sendnotifications'] = 0;
818 $params['blindmarking'] = 0;
819 $instance = $generator->create_instance($params);
820 $cm = get_coursemodule_from_instance('assign', $instance->id);
821 $context = context_module::instance($cm->id);
823 $assign = new assign($context, $cm, $course);
824 $result = mod_assign_external::reveal_identities($instance->id);
825 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
826 $this->assertEquals(1, count($result));
827 $this->assertEquals(false, $assign->is_blind_marking());
832 * Test revert_submissions_to_draft
834 public function test_revert_submissions_to_draft() {
837 $this->resetAfterTest(true);
838 set_config('submissionreceipts', 0, 'assign');
839 // Create a course and assignment and users.
840 $course = self::getDataGenerator()->create_course();
842 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
843 $params['course'] = $course->id;
844 $params['sendnotifications'] = 0;
845 $params['submissiondrafts'] = 1;
846 $instance = $generator->create_instance($params);
847 $cm = get_coursemodule_from_instance('assign', $instance->id);
848 $context = context_module::instance($cm->id);
850 $assign = new assign($context, $cm, $course);
852 $student1 = self::getDataGenerator()->create_user();
853 $student2 = self::getDataGenerator()->create_user();
854 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
855 $this->getDataGenerator()->enrol_user($student1->id,
858 $this->getDataGenerator()->enrol_user($student2->id,
861 $teacher = self::getDataGenerator()->create_user();
862 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
863 $this->getDataGenerator()->enrol_user($teacher->id,
867 // Create a student1 with an online text submission.
868 // Simulate a submission.
869 $this->setUser($student1);
870 $result = mod_assign_external::submit_for_grading($instance->id, true);
871 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
872 $this->assertEquals(0, count($result));
875 $this->setUser($teacher);
876 $students = array($student1->id, $student2->id);
877 $result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
878 $result = external_api::clean_returnvalue(mod_assign_external::revert_submissions_to_draft_returns(), $result);
880 // Check for 0 warnings.
881 $this->assertEquals(0, count($result));
886 * Test save_submission
888 public function test_save_submission() {
891 $this->resetAfterTest(true);
892 // Create a course and assignment and users.
893 $course = self::getDataGenerator()->create_course();
895 $teacher = self::getDataGenerator()->create_user();
896 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
897 $this->getDataGenerator()->enrol_user($teacher->id,
900 $this->setUser($teacher);
902 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
903 $params['course'] = $course->id;
904 $params['assignsubmission_onlinetext_enabled'] = 1;
905 $params['assignsubmission_file_enabled'] = 1;
906 $params['assignsubmission_file_maxfiles'] = 5;
907 $params['assignsubmission_file_maxsizebytes'] = 1024*1024;
908 $instance = $generator->create_instance($params);
909 $cm = get_coursemodule_from_instance('assign', $instance->id);
910 $context = context_module::instance($cm->id);
912 $assign = new assign($context, $cm, $course);
914 $student1 = self::getDataGenerator()->create_user();
915 $student2 = self::getDataGenerator()->create_user();
916 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
917 $this->getDataGenerator()->enrol_user($student1->id,
920 $this->getDataGenerator()->enrol_user($student2->id,
923 // Create a student1 with an online text submission.
924 // Simulate a submission.
925 $this->setUser($student1);
927 // Create a file in a draft area.
928 $draftidfile = file_get_unused_draft_itemid();
930 $usercontext = context_user::instance($student1->id);
932 'contextid' => $usercontext->id,
933 'component' => 'user',
934 'filearea' => 'draft',
935 'itemid' => $draftidfile,
937 'filename' => 'testtext.txt',
940 $fs = get_file_storage();
941 $fs->create_file_from_string($filerecord, 'text contents');
943 // Create another file in a different draft area.
944 $draftidonlinetext = file_get_unused_draft_itemid();
947 'contextid' => $usercontext->id,
948 'component' => 'user',
949 'filearea' => 'draft',
950 'itemid' => $draftidonlinetext,
952 'filename' => 'shouldbeanimage.txt',
955 $fs->create_file_from_string($filerecord, 'image contents (not really)');
957 // Now try a submission.
958 $submissionpluginparams = array();
959 $submissionpluginparams['files_filemanager'] = $draftidfile;
960 $onlinetexteditorparams = array('text'=>'Yeeha!',
962 'itemid'=>$draftidonlinetext);
963 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
964 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
965 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
967 $this->assertEquals(0, count($result));
969 // Set up a due and cutoff passed date.
970 $instance->duedate = time() - WEEKSECS;
971 $instance->cutoffdate = time() - WEEKSECS;
972 $DB->update_record('assign', $instance);
974 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
975 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
977 $this->assertCount(1, $result);
978 $this->assertEquals(get_string('duedatereached', 'assign'), $result[0]['item']);
984 public function test_save_grade() {
987 $this->resetAfterTest(true);
988 // Create a course and assignment and users.
989 $course = self::getDataGenerator()->create_course();
991 $teacher = self::getDataGenerator()->create_user();
992 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
993 $this->getDataGenerator()->enrol_user($teacher->id,
996 $this->setUser($teacher);
998 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
999 $params['course'] = $course->id;
1000 $params['assignfeedback_file_enabled'] = 1;
1001 $params['assignfeedback_comments_enabled'] = 1;
1002 $instance = $generator->create_instance($params);
1003 $cm = get_coursemodule_from_instance('assign', $instance->id);
1004 $context = context_module::instance($cm->id);
1006 $assign = new assign($context, $cm, $course);
1008 $student1 = self::getDataGenerator()->create_user();
1009 $student2 = self::getDataGenerator()->create_user();
1010 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1011 $this->getDataGenerator()->enrol_user($student1->id,
1014 $this->getDataGenerator()->enrol_user($student2->id,
1017 // Simulate a grade.
1018 $this->setUser($teacher);
1020 // Create a file in a draft area.
1021 $draftidfile = file_get_unused_draft_itemid();
1023 $usercontext = context_user::instance($teacher->id);
1024 $filerecord = array(
1025 'contextid' => $usercontext->id,
1026 'component' => 'user',
1027 'filearea' => 'draft',
1028 'itemid' => $draftidfile,
1030 'filename' => 'testtext.txt',
1033 $fs = get_file_storage();
1034 $fs->create_file_from_string($filerecord, 'text contents');
1037 $feedbackpluginparams = array();
1038 $feedbackpluginparams['files_filemanager'] = $draftidfile;
1039 $feedbackeditorparams = array('text' => 'Yeeha!',
1041 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1042 $result = mod_assign_external::save_grade($instance->id,
1049 $feedbackpluginparams);
1051 $this->assertNull($result);
1053 $result = mod_assign_external::get_grades(array($instance->id));
1054 $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
1056 $this->assertEquals($result['assignments'][0]['grades'][0]['grade'], '50.0');
1060 * Test save grades with advanced grading data
1062 public function test_save_grades_with_advanced_grading() {
1065 $this->resetAfterTest(true);
1066 // Create a course and assignment and users.
1067 $course = self::getDataGenerator()->create_course();
1069 $teacher = self::getDataGenerator()->create_user();
1070 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1071 $this->getDataGenerator()->enrol_user($teacher->id,
1075 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1076 $params['course'] = $course->id;
1077 $params['assignfeedback_file_enabled'] = 0;
1078 $params['assignfeedback_comments_enabled'] = 0;
1079 $instance = $generator->create_instance($params);
1080 $cm = get_coursemodule_from_instance('assign', $instance->id);
1081 $context = context_module::instance($cm->id);
1083 $assign = new assign($context, $cm, $course);
1085 $student1 = self::getDataGenerator()->create_user();
1086 $student2 = self::getDataGenerator()->create_user();
1087 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1088 $this->getDataGenerator()->enrol_user($student1->id,
1091 $this->getDataGenerator()->enrol_user($student2->id,
1095 $this->setUser($teacher);
1097 $feedbackpluginparams = array();
1098 $feedbackpluginparams['files_filemanager'] = 0;
1099 $feedbackeditorparams = array('text' => '', 'format' => 1);
1100 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1102 // Create advanced grading data.
1103 // Create grading area.
1104 $gradingarea = array(
1105 'contextid' => $context->id,
1106 'component' => 'mod_assign',
1107 'areaname' => 'submissions',
1108 'activemethod' => 'rubric'
1110 $areaid = $DB->insert_record('grading_areas', $gradingarea);
1112 // Create a rubric grading definition.
1113 $rubricdefinition = array (
1114 'areaid' => $areaid,
1115 'method' => 'rubric',
1118 'copiedfromid' => 1,
1120 'usercreated' => $teacher->id,
1121 'timemodified' => 1,
1122 'usermodified' => $teacher->id,
1125 $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
1127 // Create a criterion with a level.
1128 $rubriccriteria = array (
1129 'definitionid' => $definitionid,
1131 'description' => 'Demonstrate an understanding of disease control',
1132 'descriptionformat' => 0
1134 $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
1135 $rubriclevel1 = array (
1136 'criterionid' => $criterionid,
1138 'definition' => 'pass',
1139 'definitionformat' => 0
1141 $rubriclevel2 = array (
1142 'criterionid' => $criterionid,
1144 'definition' => 'excellent',
1145 'definitionformat' => 0
1147 $rubriclevel3 = array (
1148 'criterionid' => $criterionid,
1150 'definition' => 'fail',
1151 'definitionformat' => 0
1153 $levelid1 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
1154 $levelid2 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
1155 $levelid3 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel3);
1157 // Create the filling.
1158 $student1filling = array (
1159 'criterionid' => $criterionid,
1160 'levelid' => $levelid1,
1161 'remark' => 'well done you passed',
1165 $student2filling = array (
1166 'criterionid' => $criterionid,
1167 'levelid' => $levelid2,
1168 'remark' => 'Excellent work',
1172 $student1criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student1filling)));
1173 $student1advancedgradingdata = array('rubric' => array('criteria' => $student1criteria));
1175 $student2criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student2filling)));
1176 $student2advancedgradingdata = array('rubric' => array('criteria' => $student2criteria));
1179 $student1gradeinfo = array();
1180 $student1gradeinfo['userid'] = $student1->id;
1181 $student1gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1182 $student1gradeinfo['attemptnumber'] = -1;
1183 $student1gradeinfo['addattempt'] = true;
1184 $student1gradeinfo['workflowstate'] = 'released';
1185 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1186 $student1gradeinfo['advancedgradingdata'] = $student1advancedgradingdata;
1187 $grades[] = $student1gradeinfo;
1189 $student2gradeinfo = array();
1190 $student2gradeinfo['userid'] = $student2->id;
1191 $student2gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1192 $student2gradeinfo['attemptnumber'] = -1;
1193 $student2gradeinfo['addattempt'] = true;
1194 $student2gradeinfo['workflowstate'] = 'released';
1195 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1196 $student2gradeinfo['advancedgradingdata'] = $student2advancedgradingdata;
1197 $grades[] = $student2gradeinfo;
1199 $result = mod_assign_external::save_grades($instance->id, false, $grades);
1200 $this->assertNull($result);
1202 $student1grade = $DB->get_record('assign_grades',
1203 array('userid' => $student1->id, 'assignment' => $instance->id),
1206 $this->assertEquals($student1grade->grade, '50.0');
1208 $student2grade = $DB->get_record('assign_grades',
1209 array('userid' => $student2->id, 'assignment' => $instance->id),
1212 $this->assertEquals($student2grade->grade, '100.0');
1216 * Test save grades for a team submission
1218 public function test_save_grades_with_group_submission() {
1219 global $DB, $USER, $CFG;
1220 require_once($CFG->dirroot . '/group/lib.php');
1222 $this->resetAfterTest(true);
1223 // Create a course and assignment and users.
1224 $course = self::getDataGenerator()->create_course();
1226 $teacher = self::getDataGenerator()->create_user();
1227 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1228 $this->getDataGenerator()->enrol_user($teacher->id,
1232 $groupingdata = array();
1233 $groupingdata['courseid'] = $course->id;
1234 $groupingdata['name'] = 'Group assignment grouping';
1236 $grouping = self::getDataGenerator()->create_grouping($groupingdata);
1238 $group1data = array();
1239 $group1data['courseid'] = $course->id;
1240 $group1data['name'] = 'Team 1';
1241 $group2data = array();
1242 $group2data['courseid'] = $course->id;
1243 $group2data['name'] = 'Team 2';
1245 $group1 = self::getDataGenerator()->create_group($group1data);
1246 $group2 = self::getDataGenerator()->create_group($group2data);
1248 groups_assign_grouping($grouping->id, $group1->id);
1249 groups_assign_grouping($grouping->id, $group2->id);
1251 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1252 $params['course'] = $course->id;
1253 $params['teamsubmission'] = 1;
1254 $params['teamsubmissiongroupingid'] = $grouping->id;
1255 $instance = $generator->create_instance($params);
1256 $cm = get_coursemodule_from_instance('assign', $instance->id);
1257 $context = context_module::instance($cm->id);
1259 $assign = new assign($context, $cm, $course);
1261 $student1 = self::getDataGenerator()->create_user();
1262 $student2 = self::getDataGenerator()->create_user();
1263 $student3 = self::getDataGenerator()->create_user();
1264 $student4 = self::getDataGenerator()->create_user();
1265 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1266 $this->getDataGenerator()->enrol_user($student1->id,
1269 $this->getDataGenerator()->enrol_user($student2->id,
1272 $this->getDataGenerator()->enrol_user($student3->id,
1275 $this->getDataGenerator()->enrol_user($student4->id,
1279 groups_add_member($group1->id, $student1->id);
1280 groups_add_member($group1->id, $student2->id);
1281 groups_add_member($group1->id, $student3->id);
1282 groups_add_member($group2->id, $student4->id);
1283 $this->setUser($teacher);
1285 $feedbackpluginparams = array();
1286 $feedbackpluginparams['files_filemanager'] = 0;
1287 $feedbackeditorparams = array('text' => '', 'format' => 1);
1288 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1291 $student1gradeinfo = array();
1292 $student1gradeinfo['userid'] = $student1->id;
1293 $student1gradeinfo['grade'] = 50;
1294 $student1gradeinfo['attemptnumber'] = -1;
1295 $student1gradeinfo['addattempt'] = true;
1296 $student1gradeinfo['workflowstate'] = 'released';
1297 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1298 $grades1[] = $student1gradeinfo;
1300 $student2gradeinfo = array();
1301 $student2gradeinfo['userid'] = $student2->id;
1302 $student2gradeinfo['grade'] = 75;
1303 $student2gradeinfo['attemptnumber'] = -1;
1304 $student2gradeinfo['addattempt'] = true;
1305 $student2gradeinfo['workflowstate'] = 'released';
1306 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1307 $grades1[] = $student2gradeinfo;
1309 $this->setExpectedException('invalid_parameter_exception');
1310 // Expect an exception since 2 grades have been submitted for the same team.
1311 $result = mod_assign_external::save_grades($instance->id, true, $grades1);
1312 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
1315 $student3gradeinfo = array();
1316 $student3gradeinfo['userid'] = $student3->id;
1317 $student3gradeinfo['grade'] = 50;
1318 $student3gradeinfo['attemptnumber'] = -1;
1319 $student3gradeinfo['addattempt'] = true;
1320 $student3gradeinfo['workflowstate'] = 'released';
1321 $student3gradeinfo['plugindata'] = $feedbackpluginparams;
1322 $grades2[] = $student3gradeinfo;
1324 $student4gradeinfo = array();
1325 $student4gradeinfo['userid'] = $student4->id;
1326 $student4gradeinfo['grade'] = 75;
1327 $student4gradeinfo['attemptnumber'] = -1;
1328 $student4gradeinfo['addattempt'] = true;
1329 $student4gradeinfo['workflowstate'] = 'released';
1330 $student4gradeinfo['plugindata'] = $feedbackpluginparams;
1331 $grades2[] = $student4gradeinfo;
1332 $result = mod_assign_external::save_grades($instance->id, true, $grades2);
1333 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
1334 // There should be no warnings.
1335 $this->assertEquals(0, count($result));
1337 $student3grade = $DB->get_record('assign_grades',
1338 array('userid' => $student3->id, 'assignment' => $instance->id),
1341 $this->assertEquals($student3grade->grade, '50.0');
1343 $student4grade = $DB->get_record('assign_grades',
1344 array('userid' => $student4->id, 'assignment' => $instance->id),
1347 $this->assertEquals($student4grade->grade, '75.0');
1351 * Test copy_previous_attempt
1353 public function test_copy_previous_attempt() {
1356 $this->resetAfterTest(true);
1357 // Create a course and assignment and users.
1358 $course = self::getDataGenerator()->create_course();
1360 $teacher = self::getDataGenerator()->create_user();
1361 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1362 $this->getDataGenerator()->enrol_user($teacher->id,
1365 $this->setUser($teacher);
1367 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1368 $params['course'] = $course->id;
1369 $params['assignsubmission_onlinetext_enabled'] = 1;
1370 $params['assignsubmission_file_enabled'] = 0;
1371 $params['assignfeedback_file_enabled'] = 0;
1372 $params['attemptreopenmethod'] = 'manual';
1373 $params['maxattempts'] = 5;
1374 $instance = $generator->create_instance($params);
1375 $cm = get_coursemodule_from_instance('assign', $instance->id);
1376 $context = context_module::instance($cm->id);
1378 $assign = new assign($context, $cm, $course);
1380 $student1 = self::getDataGenerator()->create_user();
1381 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
1382 $this->getDataGenerator()->enrol_user($student1->id,
1385 // Now try a submission.
1386 $this->setUser($student1);
1387 $draftidonlinetext = file_get_unused_draft_itemid();
1388 $submissionpluginparams = array();
1389 $onlinetexteditorparams = array('text'=>'Yeeha!',
1391 'itemid'=>$draftidonlinetext);
1392 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1393 $submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1394 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
1395 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
1397 $this->setUser($teacher);
1398 // Add a grade and reopen the attempt.
1400 $feedbackpluginparams = array();
1401 $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1402 $feedbackeditorparams = array('text'=>'Yeeha!',
1404 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1405 $result = mod_assign_external::save_grade($instance->id,
1412 $feedbackpluginparams);
1413 $this->assertNull($result);
1415 $this->setUser($student1);
1416 // Now copy the previous attempt.
1417 $result = mod_assign_external::copy_previous_attempt($instance->id);
1418 $result = external_api::clean_returnvalue(mod_assign_external::copy_previous_attempt_returns(), $result);
1420 $this->assertEquals(0, count($result));
1422 $this->setUser($teacher);
1423 $result = mod_assign_external::get_submissions(array($instance->id));
1424 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
1426 // Check we are now on the second attempt.
1427 $this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
1428 // Check the plugins data is not empty.
1429 $this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
1434 * Test set_user_flags
1436 public function test_set_user_flags() {
1439 $this->resetAfterTest(true);
1440 // Create a course and assignment.
1441 $coursedata['idnumber'] = 'idnumbercourse';
1442 $coursedata['fullname'] = 'Lightwork Course';
1443 $coursedata['summary'] = 'Lightwork Course description';
1444 $coursedata['summaryformat'] = FORMAT_MOODLE;
1445 $course = self::getDataGenerator()->create_course($coursedata);
1447 $assigndata['course'] = $course->id;
1448 $assigndata['name'] = 'lightwork assignment';
1450 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
1452 // Create a manual enrolment record.
1453 $manualenroldata['enrol'] = 'manual';
1454 $manualenroldata['status'] = 0;
1455 $manualenroldata['courseid'] = $course->id;
1456 $enrolid = $DB->insert_record('enrol', $manualenroldata);
1458 // Create a teacher and give them capabilities.
1459 $context = context_course::instance($course->id);
1460 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
1461 $context = context_module::instance($assign->cmid);
1462 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
1464 // Create the teacher's enrolment record.
1465 $userenrolmentdata['status'] = 0;
1466 $userenrolmentdata['enrolid'] = $enrolid;
1467 $userenrolmentdata['userid'] = $USER->id;
1468 $DB->insert_record('user_enrolments', $userenrolmentdata);
1470 // Create a student.
1471 $student = self::getDataGenerator()->create_user();
1473 // Create test user flags record.
1474 $userflags = array();
1475 $userflag['userid'] = $student->id;
1476 $userflag['workflowstate'] = 'inmarking';
1477 $userflag['allocatedmarker'] = $USER->id;
1478 $userflags = array($userflag);
1480 $createduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1481 // We need to execute the return values cleaning process to simulate the web service server.
1482 $createduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $createduserflags);
1484 $this->assertEquals($student->id, $createduserflags[0]['userid']);
1485 $createduserflag = $DB->get_record('assign_user_flags', array('id' => $createduserflags[0]['id']));
1487 // Confirm that all data was inserted correctly.
1488 $this->assertEquals($student->id, $createduserflag->userid);
1489 $this->assertEquals($assign->id, $createduserflag->assignment);
1490 $this->assertEquals(0, $createduserflag->locked);
1491 $this->assertEquals(2, $createduserflag->mailed);
1492 $this->assertEquals(0, $createduserflag->extensionduedate);
1493 $this->assertEquals('inmarking', $createduserflag->workflowstate);
1494 $this->assertEquals($USER->id, $createduserflag->allocatedmarker);
1496 // Create update data.
1497 $userflags = array();
1498 $userflag['userid'] = $createduserflag->userid;
1499 $userflag['workflowstate'] = 'readyforreview';
1500 $userflags = array($userflag);
1502 $updateduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1503 // We need to execute the return values cleaning process to simulate the web service server.
1504 $updateduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $updateduserflags);
1506 $this->assertEquals($student->id, $updateduserflags[0]['userid']);
1507 $updateduserflag = $DB->get_record('assign_user_flags', array('id' => $updateduserflags[0]['id']));
1509 // Confirm that all data was updated correctly.
1510 $this->assertEquals($student->id, $updateduserflag->userid);
1511 $this->assertEquals($assign->id, $updateduserflag->assignment);
1512 $this->assertEquals(0, $updateduserflag->locked);
1513 $this->assertEquals(2, $updateduserflag->mailed);
1514 $this->assertEquals(0, $updateduserflag->extensionduedate);
1515 $this->assertEquals('readyforreview', $updateduserflag->workflowstate);
1516 $this->assertEquals($USER->id, $updateduserflag->allocatedmarker);
1520 * Test view_grading_table
1522 public function test_view_grading_table_invalid_instance() {
1525 $this->resetAfterTest(true);
1528 $course = $this->getDataGenerator()->create_course();
1529 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1530 $context = context_module::instance($assign->cmid);
1531 $cm = get_coursemodule_from_instance('assign', $assign->id);
1533 // Test invalid instance id.
1534 $this->setExpectedExceptionRegexp('dml_missing_record_exception');
1535 mod_assign_external::view_grading_table(0);
1539 * Test view_grading_table
1541 public function test_view_grading_table_not_enrolled() {
1544 $this->resetAfterTest(true);
1547 $course = $this->getDataGenerator()->create_course();
1548 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1549 $context = context_module::instance($assign->cmid);
1550 $cm = get_coursemodule_from_instance('assign', $assign->id);
1552 // Test not-enrolled user.
1553 $user = self::getDataGenerator()->create_user();
1554 $this->setUser($user);
1556 $this->setExpectedException('require_login_exception');
1557 mod_assign_external::view_grading_table($assign->id);
1561 * Test view_grading_table
1563 public function test_view_grading_table_correct() {
1566 $this->resetAfterTest(true);
1569 $course = $this->getDataGenerator()->create_course();
1570 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1571 $context = context_module::instance($assign->cmid);
1572 $cm = get_coursemodule_from_instance('assign', $assign->id);
1574 // Test user with full capabilities.
1575 $user = self::getDataGenerator()->create_user();
1576 $this->setUser($user);
1577 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1578 $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1580 // Trigger and capture the event.
1581 $sink = $this->redirectEvents();
1583 $result = mod_assign_external::view_grading_table($assign->id);
1584 $result = external_api::clean_returnvalue(mod_assign_external::view_grading_table_returns(), $result);
1586 $events = $sink->get_events();
1587 $this->assertCount(1, $events);
1588 $event = array_shift($events);
1590 // Checking that the event contains the expected values.
1591 $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
1592 $this->assertEquals($context, $event->get_context());
1593 $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1594 $this->assertEquals($moodleurl, $event->get_url());
1595 $this->assertEventContextNotUsed($event);
1596 $this->assertNotEmpty($event->get_name());
1600 * Test view_grading_table
1602 public function test_view_grading_table_without_capability() {
1605 $this->resetAfterTest(true);
1608 $course = $this->getDataGenerator()->create_course();
1609 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1610 $context = context_module::instance($assign->cmid);
1611 $cm = get_coursemodule_from_instance('assign', $assign->id);
1613 // Test user with no capabilities.
1614 $user = self::getDataGenerator()->create_user();
1615 $this->setUser($user);
1616 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1617 $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1619 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1620 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1621 assign_capability('mod/assign:view', CAP_PROHIBIT, $teacherrole->id, $context->id);
1622 // Empty all the caches that may be affected by this change.
1623 accesslib_clear_all_caches_for_unit_testing();
1624 course_modinfo::clear_instance_cache();
1626 $this->setExpectedException('require_login_exception', 'Course or activity not accessible. (Activity is hidden)');
1627 mod_assign_external::view_grading_table($assign->id);
1631 * Test subplugins availability
1633 public function test_subplugins_availability() {
1636 require_once($CFG->dirroot . '/mod/assign/adminlib.php');
1637 $this->resetAfterTest(true);
1639 // Hide assignment file submissiong plugin.
1640 $pluginmanager = new assign_plugin_manager('assignsubmission');
1641 $pluginmanager->hide_plugin('file');
1642 $parameters = mod_assign_external::save_submission_parameters();
1644 $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1646 // Show it again and check that the value is returned as optional.
1647 $pluginmanager->show_plugin('file');
1648 $parameters = mod_assign_external::save_submission_parameters();
1649 $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1650 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1652 // Hide feedback file submissiong plugin.
1653 $pluginmanager = new assign_plugin_manager('assignfeedback');
1654 $pluginmanager->hide_plugin('file');
1656 $parameters = mod_assign_external::save_grade_parameters();
1658 $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1660 // Show it again and check that the value is returned as optional.
1661 $pluginmanager->show_plugin('file');
1662 $parameters = mod_assign_external::save_grade_parameters();
1664 $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1665 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1667 // Check a different one.
1668 $pluginmanager->show_plugin('comments');
1669 $this->assertTrue(isset($parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']));
1670 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']->required);
1674 * Test test_view_submission_status
1676 public function test_view_submission_status() {
1679 $this->resetAfterTest(true);
1681 $this->setAdminUser();
1683 $course = $this->getDataGenerator()->create_course();
1684 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1685 $context = context_module::instance($assign->cmid);
1686 $cm = get_coursemodule_from_instance('assign', $assign->id);
1688 // Test invalid instance id.
1690 mod_assign_external::view_submission_status(0);
1691 $this->fail('Exception expected due to invalid mod_assign instance id.');
1692 } catch (moodle_exception $e) {
1693 $this->assertEquals('invalidrecord', $e->errorcode);
1696 // Test not-enrolled user.
1697 $user = self::getDataGenerator()->create_user();
1698 $this->setUser($user);
1700 mod_assign_external::view_submission_status($assign->id);
1701 $this->fail('Exception expected due to not enrolled user.');
1702 } catch (moodle_exception $e) {
1703 $this->assertEquals('requireloginerror', $e->errorcode);
1706 // Test user with full capabilities.
1707 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1708 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
1710 // Trigger and capture the event.
1711 $sink = $this->redirectEvents();
1713 $result = mod_assign_external::view_submission_status($assign->id);
1714 $result = external_api::clean_returnvalue(mod_assign_external::view_submission_status_returns(), $result);
1716 $events = $sink->get_events();
1717 $this->assertCount(1, $events);
1718 $event = array_shift($events);
1720 // Checking that the event contains the expected values.
1721 $this->assertInstanceOf('\mod_assign\event\submission_status_viewed', $event);
1722 $this->assertEquals($context, $event->get_context());
1723 $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1724 $this->assertEquals($moodleurl, $event->get_url());
1725 $this->assertEventContextNotUsed($event);
1726 $this->assertNotEmpty($event->get_name());
1728 // Test user with no capabilities.
1729 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1730 assign_capability('mod/assign:view', CAP_PROHIBIT, $studentrole->id, $context->id);
1731 accesslib_clear_all_caches_for_unit_testing();
1732 course_modinfo::clear_instance_cache();
1735 mod_assign_external::view_submission_status($assign->id);
1736 $this->fail('Exception expected due to missing capability.');
1737 } catch (moodle_exception $e) {
1738 $this->assertEquals('requireloginerror', $e->errorcode);
1743 * Create a submission for testing the get_submission_status function.
1744 * @param boolean $submitforgrading whether to submit for grading the submission
1745 * @return array an array containing all the required data for testing
1747 private function create_submission_for_testing_status($submitforgrading = false) {
1749 require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
1751 // Create a course and assignment and users.
1752 $course = self::getDataGenerator()->create_course();
1754 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1756 'course' => $course->id,
1757 'assignsubmission_file_maxfiles' => 1,
1758 'assignsubmission_file_maxsizebytes' => 1024 * 1024,
1759 'assignsubmission_onlinetext_enabled' => 1,
1760 'assignsubmission_file_enabled' => 1,
1761 'submissiondrafts' => 1,
1762 'assignfeedback_file_enabled' => 1,
1763 'assignfeedback_comments_enabled' => 1,
1764 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1765 'sendnotifications' => 0
1768 set_config('submissionreceipts', 0, 'assign');
1770 $instance = $generator->create_instance($params);
1771 $cm = get_coursemodule_from_instance('assign', $instance->id);
1772 $context = context_module::instance($cm->id);
1774 $assign = new testable_assign($context, $cm, $course);
1776 $student1 = self::getDataGenerator()->create_user();
1777 $student2 = self::getDataGenerator()->create_user();
1778 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1779 $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
1780 $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
1781 $teacher = self::getDataGenerator()->create_user();
1782 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1783 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
1785 $this->setUser($student1);
1787 // Create a student1 with an online text submission.
1788 // Simulate a submission.
1789 $submission = $assign->get_user_submission($student1->id, true);
1791 $data = new stdClass();
1792 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1793 'text' => 'Submission text',
1794 'format' => FORMAT_MOODLE);
1796 $draftidfile = file_get_unused_draft_itemid();
1797 $usercontext = context_user::instance($student1->id);
1798 $filerecord = array(
1799 'contextid' => $usercontext->id,
1800 'component' => 'user',
1801 'filearea' => 'draft',
1802 'itemid' => $draftidfile,
1804 'filename' => 't.txt',
1806 $fs = get_file_storage();
1807 $fs->create_file_from_string($filerecord, 'text contents');
1809 $data->files_filemanager = $draftidfile;
1812 $assign->save_submission($data, $notices);
1814 if ($submitforgrading) {
1815 // Now, submit the draft for grading.
1818 $data = new stdClass;
1819 $data->userid = $student1->id;
1820 $assign->submit_for_grading($data, $notices);
1823 return array($assign, $instance, $student1, $student2, $teacher);
1827 * Test get_submission_status for a draft submission.
1829 public function test_get_submission_status_in_draft_status() {
1830 $this->resetAfterTest(true);
1832 list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
1834 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1835 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1836 $this->assertDebuggingCalled();
1838 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1840 // The submission is now in draft mode.
1841 $this->assertCount(0, $result['warnings']);
1842 $this->assertFalse(isset($result['gradingsummary']));
1843 $this->assertFalse(isset($result['feedback']));
1844 $this->assertFalse(isset($result['previousattempts']));
1846 $this->assertTrue($result['lastattempt']['submissionsenabled']);
1847 $this->assertTrue($result['lastattempt']['canedit']);
1848 $this->assertTrue($result['lastattempt']['cansubmit']);
1849 $this->assertFalse($result['lastattempt']['locked']);
1850 $this->assertFalse($result['lastattempt']['graded']);
1851 $this->assertEmpty($result['lastattempt']['extensionduedate']);
1852 $this->assertFalse($result['lastattempt']['blindmarking']);
1853 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1854 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1856 $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
1857 $this->assertEquals(0, $result['lastattempt']['submission']['attemptnumber']);
1858 $this->assertEquals('draft', $result['lastattempt']['submission']['status']);
1859 $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
1860 $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
1861 $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
1862 $this->assertEquals('Submission text', $result['lastattempt']['submission']['plugins'][0]['editorfields'][0]['text']);
1863 $this->assertEquals('/t.txt', $result['lastattempt']['submission']['plugins'][1]['fileareas'][0]['files'][0]['filepath']);
1867 * Test get_submission_status for a submitted submission.
1869 public function test_get_submission_status_in_submission_status() {
1870 $this->resetAfterTest(true);
1872 list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
1874 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1875 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1876 $this->assertDebuggingCalled();
1877 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1879 $this->assertCount(0, $result['warnings']);
1880 $this->assertFalse(isset($result['gradingsummary']));
1881 $this->assertFalse(isset($result['feedback']));
1882 $this->assertFalse(isset($result['previousattempts']));
1884 $this->assertTrue($result['lastattempt']['submissionsenabled']);
1885 $this->assertFalse($result['lastattempt']['canedit']);
1886 $this->assertFalse($result['lastattempt']['cansubmit']);
1887 $this->assertFalse($result['lastattempt']['locked']);
1888 $this->assertFalse($result['lastattempt']['graded']);
1889 $this->assertEmpty($result['lastattempt']['extensionduedate']);
1890 $this->assertFalse($result['lastattempt']['blindmarking']);
1891 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1892 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1897 * Test get_submission_status using the teacher role.
1899 public function test_get_submission_status_in_submission_status_for_teacher() {
1900 $this->resetAfterTest(true);
1902 list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
1904 // Now, as teacher, see the grading summary.
1905 $this->setUser($teacher);
1906 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1907 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1908 $this->assertDebuggingCalled();
1909 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1911 $this->assertCount(0, $result['warnings']);
1912 $this->assertFalse(isset($result['lastattempt']));
1913 $this->assertFalse(isset($result['feedback']));
1914 $this->assertFalse(isset($result['previousattempts']));
1916 $this->assertEquals(2, $result['gradingsummary']['participantcount']);
1917 $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
1918 $this->assertEquals(1, $result['gradingsummary']['submissionsenabled']);
1919 $this->assertEquals(1, $result['gradingsummary']['submissionssubmittedcount']);
1920 $this->assertEquals(1, $result['gradingsummary']['submissionsneedgradingcount']);
1921 $this->assertFalse($result['gradingsummary']['warnofungroupedusers']);
1925 * Test get_submission_status for a reopened submission.
1927 public function test_get_submission_status_in_reopened_status() {
1930 $this->resetAfterTest(true);
1932 list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
1934 $this->setUser($teacher);
1935 // Grade and reopen.
1936 $feedbackpluginparams = array();
1937 $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1938 $feedbackeditorparams = array('text' => 'Yeeha!',
1940 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1941 $result = mod_assign_external::save_grade($instance->id,
1948 $feedbackpluginparams);
1949 $USER->ignoresesskey = true;
1950 $assign->testable_process_add_attempt($student1->id);
1952 $this->setUser($student1);
1954 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1955 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1956 $this->assertDebuggingCalled();
1957 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1959 $this->assertCount(0, $result['warnings']);
1960 $this->assertFalse(isset($result['gradingsummary']));
1962 $this->assertTrue($result['lastattempt']['submissionsenabled']);
1963 $this->assertTrue($result['lastattempt']['canedit']);
1964 $this->assertFalse($result['lastattempt']['cansubmit']);
1965 $this->assertFalse($result['lastattempt']['locked']);
1966 $this->assertFalse($result['lastattempt']['graded']);
1967 $this->assertEmpty($result['lastattempt']['extensionduedate']);
1968 $this->assertFalse($result['lastattempt']['blindmarking']);
1969 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1970 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1972 // Check new attempt reopened.
1973 $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
1974 $this->assertEquals(1, $result['lastattempt']['submission']['attemptnumber']);
1975 $this->assertEquals('reopened', $result['lastattempt']['submission']['status']);
1976 $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
1977 $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
1978 $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
1979 $this->assertCount(3, $result['lastattempt']['submission']['plugins']);
1981 // Now see feedback and the attempts history (remember, is a submission reopened).
1982 // Only 2 fields (no grade, no plugins data).
1983 $this->assertCount(2, $result['feedback']);
1985 // One previous attempt.
1986 $this->assertCount(1, $result['previousattempts']);
1987 $this->assertEquals(0, $result['previousattempts'][0]['attemptnumber']);
1988 $this->assertEquals(50, $result['previousattempts'][0]['grade']['grade']);
1989 $this->assertEquals($teacher->id, $result['previousattempts'][0]['grade']['grader']);
1990 $this->assertEquals($student1->id, $result['previousattempts'][0]['grade']['userid']);
1991 $this->assertEquals('Yeeha!', $result['previousattempts'][0]['feedbackplugins'][0]['editorfields'][0]['text']);
1992 $submissionplugins = $result['previousattempts'][0]['submission']['plugins'];
1993 $this->assertEquals('Submission text', $submissionplugins[0]['editorfields'][0]['text']);
1994 $this->assertEquals('/t.txt', $submissionplugins[1]['fileareas'][0]['files'][0]['filepath']);
1998 * Test access control for get_submission_status.
2000 public function test_get_submission_status_access_control() {
2001 $this->resetAfterTest(true);
2003 list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
2005 $this->setUser($student2);
2007 // Access control test.
2008 $this->setExpectedException('required_capability_exception');
2009 mod_assign_external::get_submission_status($assign->get_instance()->id, $student1->id);