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