MDL-52999 mod_assign: Fix subplugins handling in external functions
[moodle.git] / mod / assign / tests / externallib_test.php
CommitLineData
1f8c8f61
PC
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
17defined('MOODLE_INTERNAL') || die();
18
19global $CFG;
20
21require_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 */
31class 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 */
05a6445a 44 public function test_get_grades() {
1f8c8f61
PC
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.
07df8c38
PC
61 $manualenroldata['enrol'] = 'manual';
62 $manualenroldata['status'] = 0;
63 $manualenroldata['courseid'] = $course->id;
64 $enrolid = $DB->insert_record('enrol', $manualenroldata);
1f8c8f61
PC
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);
780cf0a7 69 $context = context_module::instance($assign->cmid);
1f8c8f61
PC
70 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
71
72 // Create the teacher's enrolment record.
07df8c38
PC
73 $userenrolmentdata['status'] = 0;
74 $userenrolmentdata['enrolid'] = $enrolid;
75 $userenrolmentdata['userid'] = $USER->id;
76 $DB->insert_record('user_enrolments', $userenrolmentdata);
1f8c8f61 77
a13fbf5f 78 // Create a student and give them 2 grades (for 2 attempts).
1f8c8f61 79 $student = self::getDataGenerator()->create_user();
9e3eee67
DW
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
a13fbf5f
DW
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;
a13fbf5f
DW
99 $grade->attemptnumber = 0;
100 $DB->insert_record('assign_grades', $grade);
101
9e3eee67
DW
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
1f8c8f61
PC
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;
a13fbf5f 120 $grade->attemptnumber = 1;
1f8c8f61
PC
121 $DB->insert_record('assign_grades', $grade);
122
123 $assignmentids[] = $assign->id;
124 $result = mod_assign_external::get_grades($assignmentids);
125
fb695f6e
JM
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
1f8c8f61
PC
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']);
a13fbf5f 133 // Should only get the last grade for this student.
1f8c8f61
PC
134 $this->assertEquals(1, count($assignment['grades']));
135 $grade = $assignment['grades'][0];
136 $this->assertEquals($student->id, $grade['userid']);
13e82f1c 137 // Should be the last grade (not the first).
1f8c8f61
PC
138 $this->assertEquals(75, $grade['grade']);
139 }
140
1378838e
PC
141 /**
142 * Test get_assignments
143 */
05a6445a 144 public function test_get_assignments() {
1378838e
PC
145 global $DB, $USER;
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' => 'Lightwork Course 1',
157 'summary' => 'Lightwork Course 1 description',
158 'summaryformat' => FORMAT_MOODLE,
159 'category' => $category->id
160 ));
161
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
169 ));
170
171 // Create the assignment module.
172 $assign1 = self::getDataGenerator()->create_module('assign', array(
173 'course' => $course1->id,
d1ec5c83 174 'name' => 'lightwork assignment',
0be81772 175 'intro' => 'the assignment intro text here',
d1ec5c83
PC
176 'markingworkflow' => 1,
177 'markingallocation' => 1
1378838e
PC
178 ));
179
180 // Create manual enrolment record.
181 $enrolid = $DB->insert_record('enrol', (object)array(
182 'enrol' => 'manual',
183 'status' => 0,
184 'courseid' => $course1->id
185 ));
186
187 // Create the user and give them capabilities.
188 $context = context_course::instance($course1->id);
189 $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
74b63eae 190 $context = context_module::instance($assign1->cmid);
1378838e
PC
191 $this->assignUserCapability('mod/assign:view', $context->id, $roleid);
192
193 // Create the user enrolment record.
194 $DB->insert_record('user_enrolments', (object)array(
195 'status' => 0,
196 'enrolid' => $enrolid,
197 'userid' => $USER->id
198 ));
199
0be81772
JL
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');
206
1378838e 207 $result = mod_assign_external::get_assignments();
fb695f6e
JM
208
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);
211
1378838e
PC
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']);
0be81772 221 $this->assertEquals('the assignment intro text here', $assignment['intro']);
d1ec5c83
PC
222 $this->assertEquals(1, $assignment['markingworkflow']);
223 $this->assertEquals(1, $assignment['markingallocation']);
1378838e 224
0be81772
JL
225 $this->assertCount(1, $assignment['introattachments']);
226 $this->assertEquals('introattachment.txt', $assignment['introattachments'][0]['filename']);
227
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));
231
1378838e 232 $result = mod_assign_external::get_assignments(array($course1->id));
fb695f6e
JM
233
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);
236
1378838e
PC
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']);
0be81772
JL
245 $this->assertArrayNotHasKey('intro', $assignment);
246 $this->assertArrayNotHasKey('introattachments', $assignment);
d1ec5c83
PC
247 $this->assertEquals(1, $assignment['markingworkflow']);
248 $this->assertEquals(1, $assignment['markingallocation']);
1378838e
PC
249
250 $result = mod_assign_external::get_assignments(array($course2->id));
fb695f6e
JM
251
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);
254
1378838e
PC
255 $this->assertEquals(0, count($result['courses']));
256 $this->assertEquals(1, count($result['warnings']));
257 }
c144959c
PC
258
259 /**
260 * Test get_submissions
261 */
05a6445a 262 public function test_get_submissions() {
c144959c
PC
263 global $DB, $USER;
264
265 $this->resetAfterTest(true);
266 // Create a course and assignment.
267 $coursedata['idnumber'] = 'idnumbercourse1';
268 $coursedata['fullname'] = 'Lightwork Course 1';
269 $coursedata['summary'] = 'Lightwork Course 1 description';
270 $coursedata['summaryformat'] = FORMAT_MOODLE;
271 $course1 = self::getDataGenerator()->create_course($coursedata);
272
273 $assigndata['course'] = $course1->id;
274 $assigndata['name'] = 'lightwork assignment';
275
276 $assign1 = self::getDataGenerator()->create_module('assign', $assigndata);
277
278 // Create a student with an online text submission.
a13fbf5f 279 // First attempt.
c144959c
PC
280 $student = self::getDataGenerator()->create_user();
281 $submission = new stdClass();
282 $submission->assignment = $assign1->id;
283 $submission->userid = $student->id;
284 $submission->timecreated = time();
285 $submission->timemodified = $submission->timecreated;
a13fbf5f
DW
286 $submission->status = 'draft';
287 $submission->attemptnumber = 0;
1523f9e0 288 $submission->latest = 0;
a13fbf5f
DW
289 $sid = $DB->insert_record('assign_submission', $submission);
290
291 // Second attempt.
292 $submission = new stdClass();
293 $submission->assignment = $assign1->id;
294 $submission->userid = $student->id;
295 $submission->timecreated = time();
296 $submission->timemodified = $submission->timecreated;
c144959c 297 $submission->status = 'submitted';
a13fbf5f 298 $submission->attemptnumber = 1;
1523f9e0 299 $submission->latest = 1;
c144959c
PC
300 $sid = $DB->insert_record('assign_submission', $submission);
301 $submission->id = $sid;
302
303 $onlinetextsubmission = new stdClass();
9f780282 304 $onlinetextsubmission->onlinetext = "<p>online test text</p>";
c144959c
PC
305 $onlinetextsubmission->onlineformat = 1;
306 $onlinetextsubmission->submission = $submission->id;
307 $onlinetextsubmission->assignment = $assign1->id;
308 $DB->insert_record('assignsubmission_onlinetext', $onlinetextsubmission);
309
310 // Create manual enrolment record.
07df8c38
PC
311 $manualenroldata['enrol'] = 'manual';
312 $manualenroldata['status'] = 0;
313 $manualenroldata['courseid'] = $course1->id;
314 $enrolid = $DB->insert_record('enrol', $manualenroldata);
c144959c
PC
315
316 // Create a teacher and give them capabilities.
317 $context = context_course::instance($course1->id);
318 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
d2c58b95 319 $context = context_module::instance($assign1->cmid);
c144959c
PC
320 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
321
322 // Create the teacher's enrolment record.
07df8c38
PC
323 $userenrolmentdata['status'] = 0;
324 $userenrolmentdata['enrolid'] = $enrolid;
325 $userenrolmentdata['userid'] = $USER->id;
326 $DB->insert_record('user_enrolments', $userenrolmentdata);
c144959c
PC
327
328 $assignmentids[] = $assign1->id;
329 $result = mod_assign_external::get_submissions($assignmentids);
7f45111e 330 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
c144959c
PC
331
332 // Check the online text submission is returned.
333 $this->assertEquals(1, count($result['assignments']));
334 $assignment = $result['assignments'][0];
335 $this->assertEquals($assign1->id, $assignment['assignmentid']);
336 $this->assertEquals(1, count($assignment['submissions']));
337 $submission = $assignment['submissions'][0];
338 $this->assertEquals($sid, $submission['id']);
339 $this->assertGreaterThanOrEqual(3, count($submission['plugins']));
340 $plugins = $submission['plugins'];
341 foreach ($plugins as $plugin) {
342 $foundonlinetext = false;
343 if ($plugin['type'] == 'onlinetext') {
344 $foundonlinetext = true;
345 break;
346 }
347 }
348 $this->assertTrue($foundonlinetext);
349 }
07df8c38
PC
350
351 /**
352 * Test get_user_flags
353 */
05a6445a 354 public function test_get_user_flags() {
07df8c38
PC
355 global $DB, $USER;
356
357 $this->resetAfterTest(true);
358 // Create a course and assignment.
359 $coursedata['idnumber'] = 'idnumbercourse';
360 $coursedata['fullname'] = 'Lightwork Course';
361 $coursedata['summary'] = 'Lightwork Course description';
362 $coursedata['summaryformat'] = FORMAT_MOODLE;
363 $course = self::getDataGenerator()->create_course($coursedata);
364
365 $assigndata['course'] = $course->id;
366 $assigndata['name'] = 'lightwork assignment';
367
368 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
369
370 // Create a manual enrolment record.
371 $manualenroldata['enrol'] = 'manual';
372 $manualenroldata['status'] = 0;
373 $manualenroldata['courseid'] = $course->id;
374 $enrolid = $DB->insert_record('enrol', $manualenroldata);
375
376 // Create a teacher and give them capabilities.
377 $context = context_course::instance($course->id);
378 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 379 $context = context_module::instance($assign->cmid);
07df8c38
PC
380 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
381
382 // Create the teacher's enrolment record.
383 $userenrolmentdata['status'] = 0;
384 $userenrolmentdata['enrolid'] = $enrolid;
385 $userenrolmentdata['userid'] = $USER->id;
386 $DB->insert_record('user_enrolments', $userenrolmentdata);
387
388 // Create a student and give them a user flag record.
389 $student = self::getDataGenerator()->create_user();
390 $userflag = new stdClass();
391 $userflag->assignment = $assign->id;
392 $userflag->userid = $student->id;
393 $userflag->locked = 0;
394 $userflag->mailed = 0;
395 $userflag->extensionduedate = 0;
396 $userflag->workflowstate = 'inmarking';
397 $userflag->allocatedmarker = $USER->id;
398
399 $DB->insert_record('assign_user_flags', $userflag);
400
401 $assignmentids[] = $assign->id;
402 $result = mod_assign_external::get_user_flags($assignmentids);
403
404 // We need to execute the return values cleaning process to simulate the web service server.
405 $result = external_api::clean_returnvalue(mod_assign_external::get_user_flags_returns(), $result);
406
407 // Check that the correct user flag information for the student is returned.
408 $this->assertEquals(1, count($result['assignments']));
409 $assignment = $result['assignments'][0];
410 $this->assertEquals($assign->id, $assignment['assignmentid']);
411 // Should be one user flag record.
412 $this->assertEquals(1, count($assignment['userflags']));
413 $userflag = $assignment['userflags'][0];
414 $this->assertEquals($student->id, $userflag['userid']);
415 $this->assertEquals(0, $userflag['locked']);
416 $this->assertEquals(0, $userflag['mailed']);
417 $this->assertEquals(0, $userflag['extensionduedate']);
418 $this->assertEquals('inmarking', $userflag['workflowstate']);
419 $this->assertEquals($USER->id, $userflag['allocatedmarker']);
420 }
421
422 /**
423 * Test get_user_mappings
424 */
05a6445a 425 public function test_get_user_mappings() {
07df8c38
PC
426 global $DB, $USER;
427
428 $this->resetAfterTest(true);
429 // Create a course and assignment.
430 $coursedata['idnumber'] = 'idnumbercourse';
431 $coursedata['fullname'] = 'Lightwork Course';
432 $coursedata['summary'] = 'Lightwork Course description';
433 $coursedata['summaryformat'] = FORMAT_MOODLE;
434 $course = self::getDataGenerator()->create_course($coursedata);
435
436 $assigndata['course'] = $course->id;
437 $assigndata['name'] = 'lightwork assignment';
438
439 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
440
441 // Create a manual enrolment record.
442 $manualenroldata['enrol'] = 'manual';
443 $manualenroldata['status'] = 0;
444 $manualenroldata['courseid'] = $course->id;
445 $enrolid = $DB->insert_record('enrol', $manualenroldata);
446
447 // Create a teacher and give them capabilities.
448 $context = context_course::instance($course->id);
449 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 450 $context = context_module::instance($assign->cmid);
07df8c38
PC
451 $this->assignUserCapability('mod/assign:revealidentities', $context->id, $roleid);
452
453 // Create the teacher's enrolment record.
454 $userenrolmentdata['status'] = 0;
455 $userenrolmentdata['enrolid'] = $enrolid;
456 $userenrolmentdata['userid'] = $USER->id;
457 $DB->insert_record('user_enrolments', $userenrolmentdata);
458
459 // Create a student and give them a user mapping record.
460 $student = self::getDataGenerator()->create_user();
461 $mapping = new stdClass();
462 $mapping->assignment = $assign->id;
463 $mapping->userid = $student->id;
464
465 $DB->insert_record('assign_user_mapping', $mapping);
466
467 $assignmentids[] = $assign->id;
468 $result = mod_assign_external::get_user_mappings($assignmentids);
469
470 // We need to execute the return values cleaning process to simulate the web service server.
471 $result = external_api::clean_returnvalue(mod_assign_external::get_user_mappings_returns(), $result);
472
473 // Check that the correct user mapping information for the student is returned.
474 $this->assertEquals(1, count($result['assignments']));
475 $assignment = $result['assignments'][0];
476 $this->assertEquals($assign->id, $assignment['assignmentid']);
477 // Should be one user mapping record.
478 $this->assertEquals(1, count($assignment['mappings']));
479 $mapping = $assignment['mappings'][0];
480 $this->assertEquals($student->id, $mapping['userid']);
481 }
482
05a6445a
DW
483 /**
484 * Test lock_submissions
485 */
486 public function test_lock_submissions() {
487 global $DB, $USER;
488
489 $this->resetAfterTest(true);
490 // Create a course and assignment and users.
491 $course = self::getDataGenerator()->create_course();
492
493 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
494 $params['course'] = $course->id;
495 $params['assignsubmission_onlinetext_enabled'] = 1;
496 $instance = $generator->create_instance($params);
497 $cm = get_coursemodule_from_instance('assign', $instance->id);
498 $context = context_module::instance($cm->id);
499
500 $assign = new assign($context, $cm, $course);
501
502 $student1 = self::getDataGenerator()->create_user();
503 $student2 = self::getDataGenerator()->create_user();
504 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
505 $this->getDataGenerator()->enrol_user($student1->id,
506 $course->id,
507 $studentrole->id);
508 $this->getDataGenerator()->enrol_user($student2->id,
509 $course->id,
510 $studentrole->id);
511 $teacher = self::getDataGenerator()->create_user();
512 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
513 $this->getDataGenerator()->enrol_user($teacher->id,
514 $course->id,
515 $teacherrole->id);
516
6d90ef2b 517 // Create a student1 with an online text submission.
05a6445a
DW
518 // Simulate a submission.
519 $this->setUser($student1);
520 $submission = $assign->get_user_submission($student1->id, true);
521 $data = new stdClass();
522 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
523 'text'=>'Submission text',
524 'format'=>FORMAT_MOODLE);
525 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
526 $plugin->save($submission, $data);
527
539af602 528 // Ready to test.
05a6445a
DW
529 $this->setUser($teacher);
530 $students = array($student1->id, $student2->id);
531 $result = mod_assign_external::lock_submissions($instance->id, $students);
7f45111e 532 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
05a6445a
DW
533
534 // Check for 0 warnings.
535 $this->assertEquals(0, count($result));
536
537 $this->setUser($student2);
538 $submission = $assign->get_user_submission($student2->id, true);
539 $data = new stdClass();
540 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
541 'text'=>'Submission text',
542 'format'=>FORMAT_MOODLE);
543 $notices = array();
544 $this->setExpectedException('moodle_exception');
545 $assign->save_submission($data, $notices);
546 }
547
548 /**
549 * Test unlock_submissions
550 */
551 public function test_unlock_submissions() {
552 global $DB, $USER;
553
554 $this->resetAfterTest(true);
555 // Create a course and assignment and users.
556 $course = self::getDataGenerator()->create_course();
557
558 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
559 $params['course'] = $course->id;
560 $params['assignsubmission_onlinetext_enabled'] = 1;
561 $instance = $generator->create_instance($params);
562 $cm = get_coursemodule_from_instance('assign', $instance->id);
563 $context = context_module::instance($cm->id);
564
565 $assign = new assign($context, $cm, $course);
566
567 $student1 = self::getDataGenerator()->create_user();
568 $student2 = self::getDataGenerator()->create_user();
569 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
570 $this->getDataGenerator()->enrol_user($student1->id,
571 $course->id,
572 $studentrole->id);
573 $this->getDataGenerator()->enrol_user($student2->id,
574 $course->id,
575 $studentrole->id);
576 $teacher = self::getDataGenerator()->create_user();
577 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
578 $this->getDataGenerator()->enrol_user($teacher->id,
579 $course->id,
580 $teacherrole->id);
581
6d90ef2b 582 // Create a student1 with an online text submission.
05a6445a
DW
583 // Simulate a submission.
584 $this->setUser($student1);
585 $submission = $assign->get_user_submission($student1->id, true);
586 $data = new stdClass();
587 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
588 'text'=>'Submission text',
589 'format'=>FORMAT_MOODLE);
590 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
591 $plugin->save($submission, $data);
592
539af602 593 // Ready to test.
05a6445a
DW
594 $this->setUser($teacher);
595 $students = array($student1->id, $student2->id);
596 $result = mod_assign_external::lock_submissions($instance->id, $students);
7f45111e 597 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
05a6445a
DW
598
599 // Check for 0 warnings.
600 $this->assertEquals(0, count($result));
601
602 $result = mod_assign_external::unlock_submissions($instance->id, $students);
7f45111e 603 $result = external_api::clean_returnvalue(mod_assign_external::unlock_submissions_returns(), $result);
05a6445a
DW
604
605 // Check for 0 warnings.
606 $this->assertEquals(0, count($result));
607
608 $this->setUser($student2);
609 $submission = $assign->get_user_submission($student2->id, true);
610 $data = new stdClass();
611 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
612 'text'=>'Submission text',
613 'format'=>FORMAT_MOODLE);
614 $notices = array();
615 $assign->save_submission($data, $notices);
616 }
617
618 /**
619 * Test submit_for_grading
620 */
621 public function test_submit_for_grading() {
622 global $DB, $USER;
623
624 $this->resetAfterTest(true);
625 // Create a course and assignment and users.
626 $course = self::getDataGenerator()->create_course();
627
628 set_config('submissionreceipts', 0, 'assign');
629 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
630 $params['course'] = $course->id;
631 $params['assignsubmission_onlinetext_enabled'] = 1;
632 $params['submissiondrafts'] = 1;
633 $params['sendnotifications'] = 0;
91327d96 634 $params['requiresubmissionstatement'] = 1;
05a6445a
DW
635 $instance = $generator->create_instance($params);
636 $cm = get_coursemodule_from_instance('assign', $instance->id);
637 $context = context_module::instance($cm->id);
638
639 $assign = new assign($context, $cm, $course);
640
641 $student1 = self::getDataGenerator()->create_user();
642 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
643 $this->getDataGenerator()->enrol_user($student1->id,
644 $course->id,
645 $studentrole->id);
646
647 // Create a student1 with an online text submission.
648 // Simulate a submission.
649 $this->setUser($student1);
650 $submission = $assign->get_user_submission($student1->id, true);
651 $data = new stdClass();
652 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
653 'text'=>'Submission text',
654 'format'=>FORMAT_MOODLE);
655 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
656 $plugin->save($submission, $data);
657
91327d96 658 $result = mod_assign_external::submit_for_grading($instance->id, false);
7f45111e 659 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
91327d96
DW
660
661 // Should be 1 fail because the submission statement was not aceptted.
662 $this->assertEquals(1, count($result));
663
664 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 665 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
666
667 // Check for 0 warnings.
668 $this->assertEquals(0, count($result));
669
670 $submission = $assign->get_user_submission($student1->id, false);
671
672 $this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
673 }
674
675 /**
676 * Test save_user_extensions
677 */
678 public function test_save_user_extensions() {
679 global $DB, $USER;
680
681 $this->resetAfterTest(true);
682 // Create a course and assignment and users.
683 $course = self::getDataGenerator()->create_course();
684
685 $teacher = self::getDataGenerator()->create_user();
686 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
687 $this->getDataGenerator()->enrol_user($teacher->id,
688 $course->id,
689 $teacherrole->id);
690 $this->setUser($teacher);
691
692 $now = time();
693 $yesterday = $now - 24*60*60;
694 $tomorrow = $now + 24*60*60;
695 set_config('submissionreceipts', 0, 'assign');
696 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
697 $params['course'] = $course->id;
698 $params['submissiondrafts'] = 1;
699 $params['sendnotifications'] = 0;
700 $params['duedate'] = $yesterday;
701 $params['cutoffdate'] = $now - 10;
702 $instance = $generator->create_instance($params);
703 $cm = get_coursemodule_from_instance('assign', $instance->id);
704 $context = context_module::instance($cm->id);
705
706 $assign = new assign($context, $cm, $course);
707
708 $student1 = self::getDataGenerator()->create_user();
709 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
710 $this->getDataGenerator()->enrol_user($student1->id,
711 $course->id,
712 $studentrole->id);
713
714 $this->setUser($student1);
91327d96 715 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 716 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
717
718 // Check for 0 warnings.
719 $this->assertEquals(1, count($result));
720
721 $this->setUser($teacher);
722 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
7f45111e 723 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
724 $this->assertEquals(1, count($result));
725
726 $this->setUser($teacher);
727 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
7f45111e 728 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
729 $this->assertEquals(1, count($result));
730
731 $this->setUser($teacher);
732 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
7f45111e 733 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
734 $this->assertEquals(0, count($result));
735
736 $this->setUser($student1);
91327d96 737 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 738 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
739 $this->assertEquals(0, count($result));
740
741 $this->setUser($student1);
742 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
7f45111e 743 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
744
745 }
746
747 /**
748 * Test reveal_identities
749 */
750 public function test_reveal_identities() {
751 global $DB, $USER;
752
753 $this->resetAfterTest(true);
754 // Create a course and assignment and users.
755 $course = self::getDataGenerator()->create_course();
756
757 $teacher = self::getDataGenerator()->create_user();
758 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
759 $this->getDataGenerator()->enrol_user($teacher->id,
760 $course->id,
761 $teacherrole->id);
762 $this->setUser($teacher);
763
764 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
765 $params['course'] = $course->id;
766 $params['submissiondrafts'] = 1;
767 $params['sendnotifications'] = 0;
768 $params['blindmarking'] = 1;
769 $instance = $generator->create_instance($params);
770 $cm = get_coursemodule_from_instance('assign', $instance->id);
771 $context = context_module::instance($cm->id);
772
773 $assign = new assign($context, $cm, $course);
774
775 $student1 = self::getDataGenerator()->create_user();
776 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
777 $this->getDataGenerator()->enrol_user($student1->id,
778 $course->id,
779 $studentrole->id);
780
781 $this->setUser($student1);
782 $this->setExpectedException('required_capability_exception');
783 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 784 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
785 $this->assertEquals(1, count($result));
786 $this->assertEquals(true, $assign->is_blind_marking());
787
788 $this->setUser($teacher);
789 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 790 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
791 $this->assertEquals(0, count($result));
792 $this->assertEquals(false, $assign->is_blind_marking());
793
794 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
795 $params['course'] = $course->id;
796 $params['submissiondrafts'] = 1;
797 $params['sendnotifications'] = 0;
798 $params['blindmarking'] = 0;
799 $instance = $generator->create_instance($params);
800 $cm = get_coursemodule_from_instance('assign', $instance->id);
801 $context = context_module::instance($cm->id);
802
803 $assign = new assign($context, $cm, $course);
804 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 805 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
806 $this->assertEquals(1, count($result));
807 $this->assertEquals(false, $assign->is_blind_marking());
808
809 }
810
811 /**
812 * Test revert_submissions_to_draft
813 */
814 public function test_revert_submissions_to_draft() {
815 global $DB, $USER;
816
817 $this->resetAfterTest(true);
818 set_config('submissionreceipts', 0, 'assign');
819 // Create a course and assignment and users.
820 $course = self::getDataGenerator()->create_course();
821
822 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
823 $params['course'] = $course->id;
824 $params['sendnotifications'] = 0;
825 $params['submissiondrafts'] = 1;
826 $instance = $generator->create_instance($params);
827 $cm = get_coursemodule_from_instance('assign', $instance->id);
828 $context = context_module::instance($cm->id);
829
830 $assign = new assign($context, $cm, $course);
831
832 $student1 = self::getDataGenerator()->create_user();
833 $student2 = self::getDataGenerator()->create_user();
834 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
835 $this->getDataGenerator()->enrol_user($student1->id,
836 $course->id,
837 $studentrole->id);
838 $this->getDataGenerator()->enrol_user($student2->id,
839 $course->id,
840 $studentrole->id);
841 $teacher = self::getDataGenerator()->create_user();
842 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
843 $this->getDataGenerator()->enrol_user($teacher->id,
844 $course->id,
845 $teacherrole->id);
846
847 // Create a student1 with an online text submission.
848 // Simulate a submission.
849 $this->setUser($student1);
91327d96 850 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 851 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
852 $this->assertEquals(0, count($result));
853
539af602 854 // Ready to test.
05a6445a
DW
855 $this->setUser($teacher);
856 $students = array($student1->id, $student2->id);
857 $result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
7f45111e 858 $result = external_api::clean_returnvalue(mod_assign_external::revert_submissions_to_draft_returns(), $result);
05a6445a
DW
859
860 // Check for 0 warnings.
861 $this->assertEquals(0, count($result));
862
863 }
864
865 /**
866 * Test save_submission
867 */
868 public function test_save_submission() {
869 global $DB, $USER;
870
871 $this->resetAfterTest(true);
872 // Create a course and assignment and users.
873 $course = self::getDataGenerator()->create_course();
874
875 $teacher = self::getDataGenerator()->create_user();
876 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
877 $this->getDataGenerator()->enrol_user($teacher->id,
878 $course->id,
879 $teacherrole->id);
880 $this->setUser($teacher);
881
882 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
883 $params['course'] = $course->id;
884 $params['assignsubmission_onlinetext_enabled'] = 1;
885 $params['assignsubmission_file_enabled'] = 1;
886 $params['assignsubmission_file_maxfiles'] = 5;
887 $params['assignsubmission_file_maxsizebytes'] = 1024*1024;
888 $instance = $generator->create_instance($params);
889 $cm = get_coursemodule_from_instance('assign', $instance->id);
890 $context = context_module::instance($cm->id);
891
892 $assign = new assign($context, $cm, $course);
893
894 $student1 = self::getDataGenerator()->create_user();
895 $student2 = self::getDataGenerator()->create_user();
896 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
897 $this->getDataGenerator()->enrol_user($student1->id,
898 $course->id,
899 $studentrole->id);
900 $this->getDataGenerator()->enrol_user($student2->id,
901 $course->id,
902 $studentrole->id);
903 // Create a student1 with an online text submission.
904 // Simulate a submission.
905 $this->setUser($student1);
906
907 // Create a file in a draft area.
908 $draftidfile = file_get_unused_draft_itemid();
909
910 $usercontext = context_user::instance($student1->id);
911 $filerecord = array(
912 'contextid' => $usercontext->id,
913 'component' => 'user',
914 'filearea' => 'draft',
915 'itemid' => $draftidfile,
916 'filepath' => '/',
917 'filename' => 'testtext.txt',
918 );
919
920 $fs = get_file_storage();
921 $fs->create_file_from_string($filerecord, 'text contents');
922
923 // Create another file in a different draft area.
924 $draftidonlinetext = file_get_unused_draft_itemid();
925
926 $filerecord = array(
927 'contextid' => $usercontext->id,
928 'component' => 'user',
929 'filearea' => 'draft',
930 'itemid' => $draftidonlinetext,
931 'filepath' => '/',
932 'filename' => 'shouldbeanimage.txt',
933 );
934
935 $fs->create_file_from_string($filerecord, 'image contents (not really)');
936
539af602 937 // Now try a submission.
05a6445a
DW
938 $submissionpluginparams = array();
939 $submissionpluginparams['files_filemanager'] = $draftidfile;
940 $onlinetexteditorparams = array('text'=>'Yeeha!',
941 'format'=>1,
942 'itemid'=>$draftidonlinetext);
943 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
944 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
7f45111e 945 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
05a6445a
DW
946
947 $this->assertEquals(0, count($result));
948
949 }
950
951 /**
952 * Test save_grade
953 */
954 public function test_save_grade() {
955 global $DB, $USER;
956
957 $this->resetAfterTest(true);
958 // Create a course and assignment and users.
959 $course = self::getDataGenerator()->create_course();
960
961 $teacher = self::getDataGenerator()->create_user();
962 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
963 $this->getDataGenerator()->enrol_user($teacher->id,
964 $course->id,
965 $teacherrole->id);
966 $this->setUser($teacher);
967
968 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
969 $params['course'] = $course->id;
970 $params['assignfeedback_file_enabled'] = 1;
971 $params['assignfeedback_comments_enabled'] = 1;
972 $instance = $generator->create_instance($params);
973 $cm = get_coursemodule_from_instance('assign', $instance->id);
974 $context = context_module::instance($cm->id);
975
976 $assign = new assign($context, $cm, $course);
977
978 $student1 = self::getDataGenerator()->create_user();
979 $student2 = self::getDataGenerator()->create_user();
40c3dacf 980 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
05a6445a
DW
981 $this->getDataGenerator()->enrol_user($student1->id,
982 $course->id,
983 $studentrole->id);
984 $this->getDataGenerator()->enrol_user($student2->id,
985 $course->id,
986 $studentrole->id);
987 // Simulate a grade.
988 $this->setUser($teacher);
989
990 // Create a file in a draft area.
991 $draftidfile = file_get_unused_draft_itemid();
992
993 $usercontext = context_user::instance($teacher->id);
994 $filerecord = array(
995 'contextid' => $usercontext->id,
996 'component' => 'user',
997 'filearea' => 'draft',
998 'itemid' => $draftidfile,
999 'filepath' => '/',
1000 'filename' => 'testtext.txt',
1001 );
1002
1003 $fs = get_file_storage();
1004 $fs->create_file_from_string($filerecord, 'text contents');
1005
539af602 1006 // Now try a grade.
05a6445a
DW
1007 $feedbackpluginparams = array();
1008 $feedbackpluginparams['files_filemanager'] = $draftidfile;
40c3dacf
PC
1009 $feedbackeditorparams = array('text' => 'Yeeha!',
1010 'format' => 1);
05a6445a 1011 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
539af602
DW
1012 $result = mod_assign_external::save_grade($instance->id,
1013 $student1->id,
1014 50.0,
1015 -1,
1016 true,
1017 'released',
1018 false,
1019 $feedbackpluginparams);
05a6445a 1020 // No warnings.
7f45111e 1021 $this->assertNull($result);
05a6445a
DW
1022
1023 $result = mod_assign_external::get_grades(array($instance->id));
7f45111e 1024 $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
05a6445a
DW
1025
1026 $this->assertEquals($result['assignments'][0]['grades'][0]['grade'], '50.0');
05a6445a
DW
1027 }
1028
40c3dacf
PC
1029 /**
1030 * Test save grades with advanced grading data
1031 */
1032 public function test_save_grades_with_advanced_grading() {
1033 global $DB, $USER;
1034
1035 $this->resetAfterTest(true);
1036 // Create a course and assignment and users.
1037 $course = self::getDataGenerator()->create_course();
1038
1039 $teacher = self::getDataGenerator()->create_user();
1040 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1041 $this->getDataGenerator()->enrol_user($teacher->id,
1042 $course->id,
1043 $teacherrole->id);
1044
1045 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1046 $params['course'] = $course->id;
1047 $params['assignfeedback_file_enabled'] = 0;
1048 $params['assignfeedback_comments_enabled'] = 0;
1049 $instance = $generator->create_instance($params);
1050 $cm = get_coursemodule_from_instance('assign', $instance->id);
1051 $context = context_module::instance($cm->id);
1052
1053 $assign = new assign($context, $cm, $course);
1054
1055 $student1 = self::getDataGenerator()->create_user();
1056 $student2 = self::getDataGenerator()->create_user();
1057 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1058 $this->getDataGenerator()->enrol_user($student1->id,
1059 $course->id,
1060 $studentrole->id);
1061 $this->getDataGenerator()->enrol_user($student2->id,
1062 $course->id,
1063 $studentrole->id);
1064
1065 $this->setUser($teacher);
1066
1067 $feedbackpluginparams = array();
1068 $feedbackpluginparams['files_filemanager'] = 0;
1069 $feedbackeditorparams = array('text' => '', 'format' => 1);
1070 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1071
1072 // Create advanced grading data.
1073 // Create grading area.
1074 $gradingarea = array(
1075 'contextid' => $context->id,
1076 'component' => 'mod_assign',
1077 'areaname' => 'submissions',
1078 'activemethod' => 'rubric'
1079 );
1080 $areaid = $DB->insert_record('grading_areas', $gradingarea);
1081
1082 // Create a rubric grading definition.
1083 $rubricdefinition = array (
1084 'areaid' => $areaid,
1085 'method' => 'rubric',
1086 'name' => 'test',
1087 'status' => 20,
1088 'copiedfromid' => 1,
1089 'timecreated' => 1,
1090 'usercreated' => $teacher->id,
1091 'timemodified' => 1,
1092 'usermodified' => $teacher->id,
1093 'timecopied' => 0
1094 );
1095 $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
1096
1097 // Create a criterion with a level.
1098 $rubriccriteria = array (
1099 'definitionid' => $definitionid,
1100 'sortorder' => 1,
1101 'description' => 'Demonstrate an understanding of disease control',
1102 'descriptionformat' => 0
1103 );
1104 $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
1105 $rubriclevel1 = array (
1106 'criterionid' => $criterionid,
1107 'score' => 50,
1108 'definition' => 'pass',
1109 'definitionformat' => 0
1110 );
1111 $rubriclevel2 = array (
1112 'criterionid' => $criterionid,
1113 'score' => 100,
1114 'definition' => 'excellent',
1115 'definitionformat' => 0
1116 );
1117 $rubriclevel3 = array (
1118 'criterionid' => $criterionid,
1119 'score' => 0,
1120 'definition' => 'fail',
1121 'definitionformat' => 0
1122 );
1123 $levelid1 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
1124 $levelid2 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
1125 $levelid3 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel3);
1126
1127 // Create the filling.
1128 $student1filling = array (
1129 'criterionid' => $criterionid,
1130 'levelid' => $levelid1,
1131 'remark' => 'well done you passed',
1132 'remarkformat' => 0
1133 );
1134
1135 $student2filling = array (
1136 'criterionid' => $criterionid,
1137 'levelid' => $levelid2,
1138 'remark' => 'Excellent work',
1139 'remarkformat' => 0
1140 );
1141
1142 $student1criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student1filling)));
1143 $student1advancedgradingdata = array('rubric' => array('criteria' => $student1criteria));
1144
1145 $student2criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student2filling)));
1146 $student2advancedgradingdata = array('rubric' => array('criteria' => $student2criteria));
1147
1148 $grades = array();
1149 $student1gradeinfo = array();
1150 $student1gradeinfo['userid'] = $student1->id;
1151 $student1gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1152 $student1gradeinfo['attemptnumber'] = -1;
1153 $student1gradeinfo['addattempt'] = true;
1154 $student1gradeinfo['workflowstate'] = 'released';
1155 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1156 $student1gradeinfo['advancedgradingdata'] = $student1advancedgradingdata;
1157 $grades[] = $student1gradeinfo;
1158
1159 $student2gradeinfo = array();
1160 $student2gradeinfo['userid'] = $student2->id;
1161 $student2gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1162 $student2gradeinfo['attemptnumber'] = -1;
1163 $student2gradeinfo['addattempt'] = true;
1164 $student2gradeinfo['workflowstate'] = 'released';
1165 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1166 $student2gradeinfo['advancedgradingdata'] = $student2advancedgradingdata;
1167 $grades[] = $student2gradeinfo;
1168
1169 $result = mod_assign_external::save_grades($instance->id, false, $grades);
7f45111e 1170 $this->assertNull($result);
40c3dacf
PC
1171
1172 $student1grade = $DB->get_record('assign_grades',
1173 array('userid' => $student1->id, 'assignment' => $instance->id),
1174 '*',
1175 MUST_EXIST);
1176 $this->assertEquals($student1grade->grade, '50.0');
1177
1178 $student2grade = $DB->get_record('assign_grades',
1179 array('userid' => $student2->id, 'assignment' => $instance->id),
1180 '*',
1181 MUST_EXIST);
1182 $this->assertEquals($student2grade->grade, '100.0');
1183 }
1184
1185 /**
1186 * Test save grades for a team submission
1187 */
1188 public function test_save_grades_with_group_submission() {
1189 global $DB, $USER, $CFG;
1190 require_once($CFG->dirroot . '/group/lib.php');
1191
1192 $this->resetAfterTest(true);
1193 // Create a course and assignment and users.
1194 $course = self::getDataGenerator()->create_course();
1195
1196 $teacher = self::getDataGenerator()->create_user();
1197 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1198 $this->getDataGenerator()->enrol_user($teacher->id,
1199 $course->id,
1200 $teacherrole->id);
1201
1202 $groupingdata = array();
1203 $groupingdata['courseid'] = $course->id;
1204 $groupingdata['name'] = 'Group assignment grouping';
1205
1206 $grouping = self::getDataGenerator()->create_grouping($groupingdata);
1207
1208 $group1data = array();
1209 $group1data['courseid'] = $course->id;
1210 $group1data['name'] = 'Team 1';
1211 $group2data = array();
1212 $group2data['courseid'] = $course->id;
1213 $group2data['name'] = 'Team 2';
1214
1215 $group1 = self::getDataGenerator()->create_group($group1data);
1216 $group2 = self::getDataGenerator()->create_group($group2data);
1217
1218 groups_assign_grouping($grouping->id, $group1->id);
1219 groups_assign_grouping($grouping->id, $group2->id);
1220
1221 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1222 $params['course'] = $course->id;
1223 $params['teamsubmission'] = 1;
1224 $params['teamsubmissiongroupingid'] = $grouping->id;
1225 $instance = $generator->create_instance($params);
1226 $cm = get_coursemodule_from_instance('assign', $instance->id);
1227 $context = context_module::instance($cm->id);
1228
1229 $assign = new assign($context, $cm, $course);
1230
1231 $student1 = self::getDataGenerator()->create_user();
1232 $student2 = self::getDataGenerator()->create_user();
1233 $student3 = self::getDataGenerator()->create_user();
1234 $student4 = self::getDataGenerator()->create_user();
1235 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1236 $this->getDataGenerator()->enrol_user($student1->id,
1237 $course->id,
1238 $studentrole->id);
1239 $this->getDataGenerator()->enrol_user($student2->id,
1240 $course->id,
1241 $studentrole->id);
1242 $this->getDataGenerator()->enrol_user($student3->id,
1243 $course->id,
1244 $studentrole->id);
1245 $this->getDataGenerator()->enrol_user($student4->id,
1246 $course->id,
1247 $studentrole->id);
1248
1249 groups_add_member($group1->id, $student1->id);
1250 groups_add_member($group1->id, $student2->id);
1251 groups_add_member($group1->id, $student3->id);
1252 groups_add_member($group2->id, $student4->id);
1253 $this->setUser($teacher);
1254
1255 $feedbackpluginparams = array();
1256 $feedbackpluginparams['files_filemanager'] = 0;
1257 $feedbackeditorparams = array('text' => '', 'format' => 1);
1258 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1259
1260 $grades1 = array();
1261 $student1gradeinfo = array();
1262 $student1gradeinfo['userid'] = $student1->id;
1263 $student1gradeinfo['grade'] = 50;
1264 $student1gradeinfo['attemptnumber'] = -1;
1265 $student1gradeinfo['addattempt'] = true;
1266 $student1gradeinfo['workflowstate'] = 'released';
1267 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1268 $grades1[] = $student1gradeinfo;
1269
1270 $student2gradeinfo = array();
1271 $student2gradeinfo['userid'] = $student2->id;
1272 $student2gradeinfo['grade'] = 75;
1273 $student2gradeinfo['attemptnumber'] = -1;
1274 $student2gradeinfo['addattempt'] = true;
1275 $student2gradeinfo['workflowstate'] = 'released';
1276 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1277 $grades1[] = $student2gradeinfo;
1278
1279 $this->setExpectedException('invalid_parameter_exception');
1280 // Expect an exception since 2 grades have been submitted for the same team.
1281 $result = mod_assign_external::save_grades($instance->id, true, $grades1);
7f45111e 1282 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
40c3dacf
PC
1283
1284 $grades2 = array();
1285 $student3gradeinfo = array();
1286 $student3gradeinfo['userid'] = $student3->id;
1287 $student3gradeinfo['grade'] = 50;
1288 $student3gradeinfo['attemptnumber'] = -1;
1289 $student3gradeinfo['addattempt'] = true;
1290 $student3gradeinfo['workflowstate'] = 'released';
1291 $student3gradeinfo['plugindata'] = $feedbackpluginparams;
1292 $grades2[] = $student3gradeinfo;
1293
1294 $student4gradeinfo = array();
1295 $student4gradeinfo['userid'] = $student4->id;
1296 $student4gradeinfo['grade'] = 75;
1297 $student4gradeinfo['attemptnumber'] = -1;
1298 $student4gradeinfo['addattempt'] = true;
1299 $student4gradeinfo['workflowstate'] = 'released';
1300 $student4gradeinfo['plugindata'] = $feedbackpluginparams;
1301 $grades2[] = $student4gradeinfo;
1302 $result = mod_assign_external::save_grades($instance->id, true, $grades2);
7f45111e 1303 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
40c3dacf
PC
1304 // There should be no warnings.
1305 $this->assertEquals(0, count($result));
1306
1307 $student3grade = $DB->get_record('assign_grades',
1308 array('userid' => $student3->id, 'assignment' => $instance->id),
1309 '*',
1310 MUST_EXIST);
1311 $this->assertEquals($student3grade->grade, '50.0');
1312
1313 $student4grade = $DB->get_record('assign_grades',
1314 array('userid' => $student4->id, 'assignment' => $instance->id),
1315 '*',
1316 MUST_EXIST);
1317 $this->assertEquals($student4grade->grade, '75.0');
1318 }
1319
05a6445a
DW
1320 /**
1321 * Test copy_previous_attempt
1322 */
1323 public function test_copy_previous_attempt() {
1324 global $DB, $USER;
1325
1326 $this->resetAfterTest(true);
1327 // Create a course and assignment and users.
1328 $course = self::getDataGenerator()->create_course();
1329
1330 $teacher = self::getDataGenerator()->create_user();
1331 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1332 $this->getDataGenerator()->enrol_user($teacher->id,
1333 $course->id,
1334 $teacherrole->id);
1335 $this->setUser($teacher);
1336
1337 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1338 $params['course'] = $course->id;
1339 $params['assignsubmission_onlinetext_enabled'] = 1;
1340 $params['assignsubmission_file_enabled'] = 0;
1341 $params['assignfeedback_file_enabled'] = 0;
1342 $params['attemptreopenmethod'] = 'manual';
1343 $params['maxattempts'] = 5;
1344 $instance = $generator->create_instance($params);
1345 $cm = get_coursemodule_from_instance('assign', $instance->id);
1346 $context = context_module::instance($cm->id);
1347
1348 $assign = new assign($context, $cm, $course);
1349
1350 $student1 = self::getDataGenerator()->create_user();
1351 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
1352 $this->getDataGenerator()->enrol_user($student1->id,
1353 $course->id,
1354 $studentrole->id);
539af602 1355 // Now try a submission.
05a6445a
DW
1356 $this->setUser($student1);
1357 $draftidonlinetext = file_get_unused_draft_itemid();
1358 $submissionpluginparams = array();
1359 $onlinetexteditorparams = array('text'=>'Yeeha!',
1360 'format'=>1,
1361 'itemid'=>$draftidonlinetext);
1362 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1363 $submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1364 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
7f45111e 1365 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
05a6445a
DW
1366
1367 $this->setUser($teacher);
1368 // Add a grade and reopen the attempt.
539af602 1369 // Now try a grade.
05a6445a
DW
1370 $feedbackpluginparams = array();
1371 $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1372 $feedbackeditorparams = array('text'=>'Yeeha!',
1373 'format'=>1);
1374 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
539af602
DW
1375 $result = mod_assign_external::save_grade($instance->id,
1376 $student1->id,
1377 50.0,
1378 -1,
1379 true,
1380 'released',
1381 false,
1382 $feedbackpluginparams);
7f45111e 1383 $this->assertNull($result);
05a6445a
DW
1384
1385 $this->setUser($student1);
1386 // Now copy the previous attempt.
1387 $result = mod_assign_external::copy_previous_attempt($instance->id);
7f45111e 1388 $result = external_api::clean_returnvalue(mod_assign_external::copy_previous_attempt_returns(), $result);
05a6445a
DW
1389 // No warnings.
1390 $this->assertEquals(0, count($result));
1391
1392 $this->setUser($teacher);
1393 $result = mod_assign_external::get_submissions(array($instance->id));
7f45111e 1394 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
05a6445a
DW
1395
1396 // Check we are now on the second attempt.
1397 $this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
1398 // Check the plugins data is not empty.
1399 $this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
1400
1401 }
e8b443df
PC
1402
1403 /**
1404 * Test set_user_flags
1405 */
1406 public function test_set_user_flags() {
1407 global $DB, $USER;
1408
1409 $this->resetAfterTest(true);
1410 // Create a course and assignment.
1411 $coursedata['idnumber'] = 'idnumbercourse';
1412 $coursedata['fullname'] = 'Lightwork Course';
1413 $coursedata['summary'] = 'Lightwork Course description';
1414 $coursedata['summaryformat'] = FORMAT_MOODLE;
1415 $course = self::getDataGenerator()->create_course($coursedata);
1416
1417 $assigndata['course'] = $course->id;
1418 $assigndata['name'] = 'lightwork assignment';
1419
1420 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
1421
1422 // Create a manual enrolment record.
1423 $manualenroldata['enrol'] = 'manual';
1424 $manualenroldata['status'] = 0;
1425 $manualenroldata['courseid'] = $course->id;
1426 $enrolid = $DB->insert_record('enrol', $manualenroldata);
1427
1428 // Create a teacher and give them capabilities.
1429 $context = context_course::instance($course->id);
1430 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 1431 $context = context_module::instance($assign->cmid);
e8b443df
PC
1432 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
1433
1434 // Create the teacher's enrolment record.
1435 $userenrolmentdata['status'] = 0;
1436 $userenrolmentdata['enrolid'] = $enrolid;
1437 $userenrolmentdata['userid'] = $USER->id;
1438 $DB->insert_record('user_enrolments', $userenrolmentdata);
1439
1440 // Create a student.
1441 $student = self::getDataGenerator()->create_user();
1442
1443 // Create test user flags record.
1444 $userflags = array();
1445 $userflag['userid'] = $student->id;
1446 $userflag['workflowstate'] = 'inmarking';
1447 $userflag['allocatedmarker'] = $USER->id;
1448 $userflags = array($userflag);
1449
1450 $createduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1451 // We need to execute the return values cleaning process to simulate the web service server.
1452 $createduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $createduserflags);
1453
1454 $this->assertEquals($student->id, $createduserflags[0]['userid']);
1455 $createduserflag = $DB->get_record('assign_user_flags', array('id' => $createduserflags[0]['id']));
1456
1457 // Confirm that all data was inserted correctly.
1458 $this->assertEquals($student->id, $createduserflag->userid);
1459 $this->assertEquals($assign->id, $createduserflag->assignment);
1460 $this->assertEquals(0, $createduserflag->locked);
1461 $this->assertEquals(2, $createduserflag->mailed);
1462 $this->assertEquals(0, $createduserflag->extensionduedate);
1463 $this->assertEquals('inmarking', $createduserflag->workflowstate);
1464 $this->assertEquals($USER->id, $createduserflag->allocatedmarker);
1465
1466 // Create update data.
1467 $userflags = array();
1468 $userflag['userid'] = $createduserflag->userid;
1469 $userflag['workflowstate'] = 'readyforreview';
1470 $userflags = array($userflag);
1471
1472 $updateduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1473 // We need to execute the return values cleaning process to simulate the web service server.
1474 $updateduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $updateduserflags);
1475
1476 $this->assertEquals($student->id, $updateduserflags[0]['userid']);
1477 $updateduserflag = $DB->get_record('assign_user_flags', array('id' => $updateduserflags[0]['id']));
1478
1479 // Confirm that all data was updated correctly.
1480 $this->assertEquals($student->id, $updateduserflag->userid);
1481 $this->assertEquals($assign->id, $updateduserflag->assignment);
1482 $this->assertEquals(0, $updateduserflag->locked);
1483 $this->assertEquals(2, $updateduserflag->mailed);
1484 $this->assertEquals(0, $updateduserflag->extensionduedate);
1485 $this->assertEquals('readyforreview', $updateduserflag->workflowstate);
1486 $this->assertEquals($USER->id, $updateduserflag->allocatedmarker);
1487 }
1488
91a12bc6
JL
1489 /**
1490 * Test view_grading_table
1491 */
1492 public function test_view_grading_table() {
1493 global $DB;
1494
1495 $this->resetAfterTest(true);
1496
1497 $this->setAdminUser();
1498 // Setup test data.
1499 $course = $this->getDataGenerator()->create_course();
1500 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1501 $context = context_module::instance($assign->cmid);
1502 $cm = get_coursemodule_from_instance('assign', $assign->id);
1503
1504 // Test invalid instance id.
1505 try {
1506 mod_assign_external::view_grading_table(0);
1507 $this->fail('Exception expected due to invalid mod_assign instance id.');
1508 } catch (moodle_exception $e) {
1509 $this->assertEquals('invalidrecord', $e->errorcode);
1510 }
1511
1512 // Test not-enrolled user.
1513 $user = self::getDataGenerator()->create_user();
1514 $this->setUser($user);
1515 try {
1516 mod_assign_external::view_grading_table($assign->id);
1517 $this->fail('Exception expected due to not enrolled user.');
1518 } catch (moodle_exception $e) {
1519 $this->assertEquals('requireloginerror', $e->errorcode);
1520 }
1521
1522 // Test user with full capabilities.
1523 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1524 $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1525
1526 // Trigger and capture the event.
1527 $sink = $this->redirectEvents();
1528
1529 $result = mod_assign_external::view_grading_table($assign->id);
1530 $result = external_api::clean_returnvalue(mod_assign_external::view_grading_table_returns(), $result);
1531
1532 $events = $sink->get_events();
1533 $this->assertCount(1, $events);
1534 $event = array_shift($events);
1535
1536 // Checking that the event contains the expected values.
1537 $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
1538 $this->assertEquals($context, $event->get_context());
1539 $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1540 $this->assertEquals($moodleurl, $event->get_url());
1541 $this->assertEventContextNotUsed($event);
1542 $this->assertNotEmpty($event->get_name());
1543
1544 // Test user with no capabilities.
1545 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1546 assign_capability('mod/assign:view', CAP_PROHIBIT, $teacherrole->id, $context->id);
1547 accesslib_clear_all_caches_for_unit_testing();
1548
1549 try {
1550 mod_assign_external::view_grading_table($assign->id);
1551 $this->fail('Exception expected due to missing capability.');
1552 } catch (moodle_exception $e) {
1553 $this->assertEquals('nopermissions', $e->errorcode);
1554 }
1555
1556 }
1557
1f8c8f61 1558}