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