Done, changing some files with DOS linefeeds to Unix linefeeds. Bug 4763.
[moodle.git] / mod / assignment / lib.php
CommitLineData
5c6b657a 1<?PHP // $Id$
b0f2597e 2/**
3 * assignment_base is the base class for assignment types
4 *
5 * This class provides all the functionality for an assignment
6 */
04eba58f 7
1884f2a6 8DEFINE ('ASSIGNMENT_COUNT_WORDS', 1);
9DEFINE ('ASSIGNMENT_COUNT_LETTERS', 2);
d699cd1e 10
4909e176 11if (!isset($CFG->assignment_maxbytes)) {
12 set_config("assignment_maxbytes", 1024000); // Default maximum size for all assignments
04eba58f 13}
1884f2a6 14if (!isset($CFG->assignment_itemstocount)) {
15 set_config("assignment_itemstocount", ASSIGNMENT_COUNT_WORDS); // Default item to count
16}
04eba58f 17
b0f2597e 18/*
19 * Standard base class for all assignment submodules (assignment types).
20 *
21 *
22 */
23class assignment_base {
24
25 var $cm;
26 var $course;
27 var $assignment;
28
29 /**
30 * Constructor for the base assignment class
31 *
32 * Constructor for the base assignment class.
33 * If cmid is set create the cm, course, assignment objects.
34 *
35 * @param cmid integer, the current course module id - not set for new assignments
73097f07 36 * @param assignment object, usually null, but if we have it we pass it to save db access
b0f2597e 37 */
73097f07 38 function assignment_base($cmid=0, $assignment=NULL, $cm=NULL, $course=NULL) {
b0f2597e 39
40 global $CFG;
41
42 if ($cmid) {
73097f07 43 if ($cm) {
44 $this->cm = $cm;
45 } else if (! $this->cm = get_record('course_modules', 'id', $cmid)) {
46 error('Course Module ID was incorrect');
b0f2597e 47 }
04eba58f 48
73097f07 49 if ($course) {
50 $this->course = $course;
51 } else if (! $this->course = get_record('course', 'id', $this->cm->course)) {
52 error('Course is misconfigured');
b0f2597e 53 }
04eba58f 54
73097f07 55 if ($assignment) {
56 $this->assignment = $assignment;
57 } else if (! $this->assignment = get_record('assignment', 'id', $this->cm->instance)) {
58 error('assignment ID was incorrect');
b0f2597e 59 }
e6a4906b 60
b0f2597e 61 $this->strassignment = get_string('modulename', 'assignment');
62 $this->strassignments = get_string('modulenameplural', 'assignment');
63 $this->strsubmissions = get_string('submissions', 'assignment');
64 $this->strlastmodified = get_string('lastmodified');
e6a4906b 65
b0f2597e 66 if ($this->course->category) {
67 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname}</a> -> ".
68 "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
69 } else {
70 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
71 }
e6a4906b 72
3898bc33 73 $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.format_string($this->assignment->name,true));
e6a4906b 74
b0f2597e 75 if (!$this->cm->visible and !isteacher($this->course->id)) {
76 $pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment);
77 print_header($pagetitle, $this->course->fullname, "$this->navigation $this->strassignment",
78 "", "", true, '', navmenu($this->course, $this->cm));
79 notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}");
80 }
b0f2597e 81 $this->currentgroup = get_current_group($this->course->id);
73097f07 82 }
e6a4906b 83
73097f07 84 /// Set up things for a HTML editor if it's needed
85 if ($this->usehtmleditor = can_use_html_editor()) {
86 $this->defaultformat = FORMAT_HTML;
87 } else {
88 $this->defaultformat = FORMAT_MOODLE;
e6a4906b 89 }
90 }
91
b0f2597e 92 /*
93 * Display the assignment to students (sub-modules will most likely override this)
94 */
04eba58f 95
b0f2597e 96 function view() {
04eba58f 97
b0f2597e 98 add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}",
99 $this->assignment->id, $this->cm->id);
04eba58f 100
73097f07 101 $this->view_header();
04eba58f 102
f77cfb73 103 $this->view_intro();
04eba58f 104
f77cfb73 105 $this->view_dates();
04eba58f 106
b0f2597e 107 $this->view_feedback();
108
f77cfb73 109 $this->view_footer();
36eb856f 110 }
111
73097f07 112 /*
113 * Display the top of the view.php page, this doesn't change much for submodules
114 */
115 function view_header($subpage='') {
116
117 global $CFG;
118
119 if ($subpage) {
120 $extranav = '<a target="'.$CFG->framename.'" href="view.php?id='.$this->cm->id.'">'.
3898bc33 121 format_string($this->assignment->name,true).'</a> -> '.$subpage;
73097f07 122 } else {
3898bc33 123 $extranav = ' '.format_string($this->assignment->name,true);
73097f07 124 }
125
126 print_header($this->pagetitle, $this->course->fullname, $this->navigation.$extranav, '', '',
127 true, update_module_button($this->cm->id, $this->course->id, $this->strassignment),
128 navmenu($this->course, $this->cm));
129
130 echo '<div class="reportlink">'.$this->submittedlink().'</div>';
131 }
132
133
f77cfb73 134 /*
135 * Display the assignment intro
136 */
137 function view_intro() {
138 print_simple_box_start('center', '', '', '', 'generalbox', 'intro');
1e4343a0 139 $formatoptions = new stdClass;
140 $formatoptions->noclean = true;
141 echo format_text($this->assignment->description, $this->assignment->format, $formatoptions);
f77cfb73 142 print_simple_box_end();
143 }
144
145 /*
146 * Display the assignment dates
147 */
148 function view_dates() {
149 if (!$this->assignment->timeavailable && !$this->assignment->timedue) {
150 return;
151 }
152
153 print_simple_box_start('center', '', '', '', 'generalbox', 'dates');
154 echo '<table>';
155 if ($this->assignment->timeavailable) {
156 echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
157 echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
158 }
159 if ($this->assignment->timedue) {
160 echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
161 echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
162 }
163 echo '</table>';
164 print_simple_box_end();
165 }
166
167
73097f07 168 /*
169 * Display the bottom of the view.php page, this doesn't change much for submodules
170 */
171 function view_footer() {
172 print_footer($this->course);
173 }
174
73097f07 175 function view_feedback($submission=NULL) {
b0f2597e 176 global $USER;
e6a4906b 177
73097f07 178 if (!$submission) { /// Get submission for this assignment
179 $submission = $this->get_submission($USER->id);
70b2c772 180 }
181
182 if (empty($submission->timemarked)) { /// Nothing to show, so print nothing
183 return;
9c48354d 184 }
e6a4906b 185
b0f2597e 186 /// We need the teacher info
187 if (! $teacher = get_record('user', 'id', $submission->teacher)) {
b0f2597e 188 error('Could not find the teacher');
189 }
e6a4906b 190
b0f2597e 191 /// Print the feedback
6d4ecaec 192 print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher));
193
b0f2597e 194 echo '<table cellspacing="0" class="feedback">';
195
196 echo '<tr>';
197 echo '<td class="left picture">';
198 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
199 echo '</td>';
6d4ecaec 200 echo '<td class="topic">';
70b2c772 201 echo '<div class="from">';
73097f07 202 echo '<div class="fullname">'.fullname($teacher).'</div>';
6d4ecaec 203 echo '<div class="time">'.userdate($submission->timemarked).'</div>';
70b2c772 204 echo '</div>';
205 $this->print_user_files($submission->userid);
206 echo '</td>';
b0f2597e 207 echo '</td>';
208 echo '</tr>';
209
210 echo '<tr>';
211 echo '<td class="left side">&nbsp;</td>';
6d4ecaec 212 echo '<td class="content">';
b0f2597e 213 if ($this->assignment->grade) {
6d4ecaec 214 echo '<div class="grade">';
70b2c772 215 echo get_string("grade").': '.$this->display_grade($submission->grade);
6d4ecaec 216 echo '</div>';
52436fe1 217 echo '<div class="clearer"></div>';
e6a4906b 218 }
dcd338ff 219
6d4ecaec 220 echo '<div class="comment">';
ff8f7015 221 echo format_text($submission->comment, $submission->format);
6d4ecaec 222 echo '</div>';
b0f2597e 223 echo '</tr>';
224
225 echo '</table>';
e6a4906b 226 }
e6a4906b 227
ba16713f 228 /*
229 * Returns a link with info about the state of the assignment submissions
230 */
231 function submittedlink() {
232 global $USER;
233
234 $submitted = '';
235
236 if (isteacher($this->course->id)) {
237 if (!isteacheredit($this->course->id) and user_group($this->course->id, $USER->id)) {
238 $count = $this->count_real_submissions($this->currentgroup); // Only their group
239 } else {
240 $count = $this->count_real_submissions(); // Everyone
241 }
242 $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
243 get_string('viewsubmissions', 'assignment', $count).'</a>';
244 } else {
245 if (isset($USER->id)) {
246 if ($submission = $this->get_submission($USER->id)) {
247 if ($submission->timemodified) {
1e4343a0 248 if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
ba16713f 249 $submitted = '<span class="early">'.userdate($submission->timemodified).'</span>';
250 } else {
251 $submitted = '<span class="late">'.userdate($submission->timemodified).'</span>';
252 }
253 }
254 }
255 }
256 }
257
258 return $submitted;
259 }
260
261
b0f2597e 262 /*
263 * Print the start of the setup form for the current assignment type
264 */
265 function setup(&$form, $action='') {
266 global $CFG, $THEME;
267
268 if (empty($this->course)) {
269 if (! $this->course = get_record("course", "id", $form->course)) {
270 error("Course is misconfigured");
77db7e4c 271 }
272 }
b0f2597e 273 if (empty($action)) { // Default destination for this form
274 $action = $CFG->wwwroot.'/course/mod.php';
275 }
77db7e4c 276
b0f2597e 277 if (empty($form->name)) {
278 $form->name = "";
279 }
280 if (empty($form->assignmenttype)) {
281 $form->assignmenttype = "";
1e4343a0 282 } else {
283 $form->assignmenttype = clean_param($form->assignmenttype, PARAM_SAFEDIR);
b0f2597e 284 }
285 if (empty($form->description)) {
286 $form->description = "";
287 }
77db7e4c 288
b0f2597e 289 $strname = get_string('name');
290 $strassignments = get_string('modulenameplural', 'assignment');
3898bc33 291 $strheading = empty($form->name) ? get_string("type$form->assignmenttype",'assignment') : s(format_string(stripslashes($form->name),true));
77db7e4c 292
b0f2597e 293 print_header($this->course->shortname.': '.$strheading, "$strheading",
294 "<a href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname} </a> -> ".
295 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading");
77db7e4c 296
f77cfb73 297 print_simple_box_start('center', '70%');
298 print_heading(get_string('type'.$form->assignmenttype,'assignment'));
299 print_simple_box(get_string('help'.$form->assignmenttype, 'assignment'), 'center');
b0f2597e 300 include("$CFG->dirroot/mod/assignment/type/common.html");
f77cfb73 301
302 include("$CFG->dirroot/mod/assignment/type/".$form->assignmenttype."/mod.html");
303 $this->setup_end();
b0f2597e 304 }
305
306 /*
307 * Print the end of the setup form for the current assignment type
308 */
309 function setup_end() {
73097f07 310 global $CFG;
b0f2597e 311
312 include($CFG->dirroot.'/mod/assignment/type/common_end.html');
77db7e4c 313
314 print_simple_box_end();
315
73097f07 316 if ($this->usehtmleditor) {
b0f2597e 317 use_html_editor();
318 }
319
320 print_footer($this->course);
77db7e4c 321 }
77db7e4c 322
323
b0f2597e 324 function add_instance($assignment) {
325 // Given an object containing all the necessary data,
326 // (defined by the form in mod.html) this function
327 // will create a new instance and return the id number
328 // of the new instance.
329
330 $assignment->timemodified = time();
38147229 331 if (empty($assignment->dueenable)) {
332 $assignment->timedue = 0;
f00da052 333 $assignment->preventlate = 0;
38147229 334 } else {
335 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
336 $assignment->dueday, $assignment->duehour,
337 $assignment->dueminute);
338 }
339 if (empty($assignment->availableenable)) {
340 $assignment->timeavailable = 0;
38147229 341 } else {
342 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
343 $assignment->availableday, $assignment->availablehour,
344 $assignment->availableminute);
345 }
346
736f191c 347 if ($returnid = insert_record("assignment", $assignment)) {
348
1e4343a0 349 if ($assignment->timedue) {
350 $event = NULL;
351 $event->name = $assignment->name;
352 $event->description = $assignment->description;
353 $event->courseid = $assignment->course;
354 $event->groupid = 0;
355 $event->userid = 0;
356 $event->modulename = 'assignment';
357 $event->instance = $returnid;
358 $event->eventtype = 'due';
359 $event->timestart = $assignment->timedue;
360 $event->timeduration = 0;
736f191c 361
1e4343a0 362 add_event($event);
363 }
736f191c 364 }
365
366 return $returnid;
b0f2597e 367 }
d699cd1e 368
b0f2597e 369 function delete_instance($assignment) {
736f191c 370 $result = true;
371
372 if (! delete_records('assignment_submissions', 'assignment', $assignment->id)) {
373 $result = false;
374 }
375
376 if (! delete_records('assignment', 'id', $assignment->id)) {
377 $result = false;
378 }
379
380 if (! delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id)) {
381 $result = false;
382 }
383
384 return $result;
b0f2597e 385 }
d699cd1e 386
b0f2597e 387 function update_instance($assignment) {
388 // Given an object containing all the necessary data,
389 // (defined by the form in mod.html) this function
390 // will create a new instance and return the id number
391 // of the new instance.
392
38147229 393 $assignment->timemodified = time();
394 if (empty($assignment->dueenable)) {
395 $assignment->timedue = 0;
5c6b657a 396 $assignment->preventlate = 0;
38147229 397 } else {
398 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
399 $assignment->dueday, $assignment->duehour,
400 $assignment->dueminute);
401 }
402 if (empty($assignment->availableenable)) {
403 $assignment->timeavailable = 0;
38147229 404 } else {
405 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
406 $assignment->availableday, $assignment->availablehour,
407 $assignment->availableminute);
408 }
409
b0f2597e 410 $assignment->id = $assignment->instance;
736f191c 411
412 if ($returnid = update_record('assignment', $assignment)) {
413
1e4343a0 414 if ($assignment->timedue) {
415 $event = NULL;
736f191c 416
1e4343a0 417 if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) {
736f191c 418
1e4343a0 419 $event->name = $assignment->name;
420 $event->description = $assignment->description;
421 $event->timestart = $assignment->timedue;
736f191c 422
1e4343a0 423 update_event($event);
47263937 424 } else {
425 $event = NULL;
426 $event->name = $assignment->name;
427 $event->description = $assignment->description;
428 $event->courseid = $assignment->course;
429 $event->groupid = 0;
430 $event->userid = 0;
431 $event->modulename = 'assignment';
432 $event->instance = $assignment->id;
433 $event->eventtype = 'due';
434 $event->timestart = $assignment->timedue;
435 $event->timeduration = 0;
436
437 add_event($event);
1e4343a0 438 }
47263937 439 } else {
440 delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id);
736f191c 441 }
442 }
443
444 return $returnid;
b0f2597e 445 }
446
b0f2597e 447 /*
448 * Top-level function for handling of submissions called by submissions.php
449 *
450 */
451 function submissions($mode) {
9bf660b3 452 ///The main switch is changed to facilitate
453 ///1) Batch fast grading
454 ///2) Skip to the next one on the popup
455 ///3) Save and Skip to the next one on the popup
456
457 //make user global so we can use the id
458 global $USER;
459
b0f2597e 460 switch ($mode) {
461 case 'grade': // We are in a popup window grading
462 if ($submission = $this->process_feedback()) {
5a36be8c 463 //IE needs proper header with encoding
464 print_header(get_string('feedback', 'assignment').':'.format_string($this->assignment->name));
b0f2597e 465 print_heading(get_string('changessaved'));
be86672d 466 $this->update_main_listing($submission);
b0f2597e 467 }
468 close_window();
469 break;
9cc9b7c1 470
b0f2597e 471 case 'single': // We are in a popup window displaying submission
472 $this->display_submission();
473 break;
a56d79cd 474
b0f2597e 475 case 'all': // Main window, display everything
476 $this->display_submissions();
477 break;
082215e6 478
9bf660b3 479 case 'fastgrade':
082215e6 480 ///do the fast grading stuff - this process should work for all 3 subclasses
39e11905 481 $grading = false;
16907e53 482 $commenting = false;
39e11905 483 $col = false;
16907e53 484 if (isset($_POST['comment'])) {
39e11905 485 $col = 'comment';
16907e53 486 $commenting = true;
487 }
488 if (isset($_POST['menu'])) {
39e11905 489 $col = 'menu';
16907e53 490 $grading = true;
491 }
39e11905 492 if (!$col) {
493 //both comment and grade columns collapsed..
494 $this->display_submissions();
16907e53 495 break;
496 }
39e11905 497 foreach ($_POST[$col] as $id => $unusedvalue){
77f4b17b 498
499 $id = (int)$id; //clean parameter name
39e11905 500 if (!$submission = $this->get_submission($id)) {
501 $submission = $this->prepare_new_submission($id);
502 $newsubmission = true;
503 } else {
504 $newsubmission = false;
505 }
506 unset($submission->data1); // Don't need to update this.
507 unset($submission->data2); // Don't need to update this.
16907e53 508
9bf660b3 509 //for fast grade, we need to check if any changes take place
16907e53 510 $updatedb = false;
511
512 if ($grading) {
513 $grade = $_POST['menu'][$id];
39e11905 514 $updatedb = $updatedb || ($submission->grade != $grade);
515 $submission->grade = $grade;
16907e53 516 } else {
39e11905 517 if (!$newsubmission) {
518 unset($submission->grade); // Don't need to update this.
519 }
16907e53 520 }
521 if ($commenting) {
39e11905 522 $commentvalue = trim($_POST['comment'][$id]);
523 $updatedb = $updatedb || ($submission->comment != stripslashes($commentvalue));
524 $submission->comment = $commentvalue;
16907e53 525 } else {
39e11905 526 unset($submission->comment); // Don't need to update this.
9bf660b3 527 }
528
39e11905 529 $submission->teacher = $USER->id;
530 $submission->mailed = $updatedb?0:$submission->mailed;//only change if it's an update
531 $submission->timemarked = time();
532
533 //if it is not an update, we don't change the last modified time etc.
9bf660b3 534 //this will also not write into database if no comment and grade is entered.
39e11905 535
16907e53 536 if ($updatedb){
39e11905 537 if ($newsubmission) {
538 if (!insert_record('assignment_submissions', $submission)) {
539 return false;
540 }
541 } else {
542 if (!update_record('assignment_submissions', $submission)) {
543 return false;
544 }
9bf660b3 545 }
39e11905 546 //add to log only if updating
9bf660b3 547 add_to_log($this->course->id, 'assignment', 'update grades',
39e11905 548 'submissions.php?id='.$this->assignment->id.'&user='.$submission->userid,
549 $submission->userid, $this->cm->id);
9bf660b3 550 }
551
e11dd872 552 }
553 print_heading(get_string('changessaved'));
9bf660b3 554 $this->display_submissions();
555 break;
39e11905 556
557
9bf660b3 558 case 'next':
559 /// We are currently in pop up, but we want to skip to next one without saving.
560 /// This turns out to be similar to a single case
561 /// The URL used is for the next submission.
562
563 $this->display_submission();
564 break;
565
566 case 'saveandnext':
567 ///We are in pop up. save the current one and go to the next one.
568 //first we save the current changes
569 if ($submission = $this->process_feedback()) {
570 //print_heading(get_string('changessaved'));
571 $this->update_main_listing($submission);
572 }
573
574 //then we display the next submission
575 $this->display_submission();
576 break;
577
578 default:
579 echo "something seriously is wrong!!";
580 break;
a56d79cd 581 }
b0f2597e 582 }
9bf660b3 583
584 //function that updates the listing on the main script from popup using javascript
be86672d 585 function update_main_listing($submission) {
586 global $SESSION;
9bf660b3 587
588 $perpage = get_user_preferences('assignment_perpage', 10);
be86672d 589
9bf660b3 590 $quickgrade = get_user_preferences('assignment_quickgrade', 0);
591
be86672d 592 /// Run some Javascript to try and update the parent page
593 echo '<script type="text/javascript">'."\n<!--\n";
be86672d 594 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['comment'])) {
9bf660b3 595 if ($quickgrade){
596 echo 'opener.document.getElementById("comment['.$submission->userid.']").value="'
597 .trim($submission->comment).'";'."\n";
598 } else {
599 echo 'opener.document.getElementById("com'.$submission->userid.
600 '").innerHTML="'.shorten_text(trim(strip_tags($submission->comment)), 15)."\";\n";
601 }
be86672d 602 }
9bf660b3 603
604 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['grade'])) {
605 //echo optional_param('menuindex');
606 if ($quickgrade){
607 echo 'opener.document.getElementById("menumenu['.$submission->userid.
16907e53 608 ']").selectedIndex="'.optional_param('menuindex', 0, PARAM_INT).'";'."\n";
9bf660b3 609 } else {
610 echo 'opener.document.getElementById("g'.$submission->userid.'").innerHTML="'.
611 $this->display_grade($submission->grade)."\";\n";
612 }
613 }
614 //need to add student's assignments in there too.
73097f07 615 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemodified']) &&
616 $submission->timemodified) {
be86672d 617 echo 'opener.document.getElementById("ts'.$submission->userid.
9bf660b3 618 '").innerHTML="'.addslashes($this->print_student_answer($submission->userid)).userdate($submission->timemodified)."\";\n";
be86672d 619 }
9bf660b3 620
73097f07 621 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemarked']) &&
622 $submission->timemarked) {
be86672d 623 echo 'opener.document.getElementById("tt'.$submission->userid.
624 '").innerHTML="'.userdate($submission->timemarked)."\";\n";
625 }
9bf660b3 626
be86672d 627 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['status'])) {
9bf660b3 628 echo 'opener.document.getElementById("up'.$submission->userid.'").className="s1";';
629 $buttontext = get_string('update');
16907e53 630 $button = link_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;userid='.$submission->userid.'&amp;mode=single'.'&amp;offset='.optional_param('offset', '', PARAM_INT),
9bf660b3 631 'grade'.$submission->userid, $buttontext, 450, 700, $buttontext, 'none', true, 'button'.$submission->userid);
632 echo 'opener.document.getElementById("up'.$submission->userid.'").innerHTML="'.addslashes($button).'";';
633 }
be86672d 634 echo "\n-->\n</script>";
3262ee10 635 flush();
be86672d 636 }
d699cd1e 637
d59269cf 638 /*
639 * Display a grade in user-friendly form, whether it's a scale or not
640 *
641 */
642 function display_grade($grade) {
643
c86aa2a4 644 static $scalegrades = array(); // Cache scales for each assignment - they might have different scales!!
d59269cf 645
646 if ($this->assignment->grade >= 0) { // Normal number
082215e6 647 if ($grade == -1) {
648 return '-';
649 } else {
650 return $grade.' / '.$this->assignment->grade;
651 }
d59269cf 652
653 } else { // Scale
c86aa2a4 654 if (empty($scalegrades[$this->assignment->id])) {
d59269cf 655 if ($scale = get_record('scale', 'id', -($this->assignment->grade))) {
c86aa2a4 656 $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale);
d59269cf 657 } else {
658 return '-';
659 }
660 }
c86aa2a4 661 if (isset($scalegrades[$this->assignment->id][$grade])) {
662 return $scalegrades[$this->assignment->id][$grade];
0f7d4e5e 663 }
39e11905 664 return '-';
d59269cf 665 }
666 }
667
b0f2597e 668 /*
669 * Display a single submission, ready for grading on a popup window
670 *
671 */
672 function display_submission() {
9bf660b3 673
082215e6 674 global $CFG;
b0f2597e 675
4fdabdc3 676 $userid = required_param('userid', PARAM_INT);
677 $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student.
d699cd1e 678
b0f2597e 679 if (!$user = get_record('user', 'id', $userid)) {
680 error('No such user!');
681 }
d699cd1e 682
39e11905 683 if (!$submission = $this->get_submission($user->id)) {
684 $submission = $this->prepare_new_submission($userid);
b0f2597e 685 }
a5a4cd60 686
b0f2597e 687 if ($submission->timemodified > $submission->timemarked) {
688 $subtype = 'assignmentnew';
689 } else {
690 $subtype = 'assignmentold';
691 }
d699cd1e 692
9bf660b3 693 ///construct SQL, using current offset to find the data of the next student
694 $course = $this->course;
695 $assignment = $this->assignment;
696 $cm = $this->cm;
697
698 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
699 $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
700 } else {
701 $currentgroup = false;
702 }
d699cd1e 703
9bf660b3 704 /// Get all teachers and students
705 if ($currentgroup) {
706 $users = get_group_users($currentgroup);
707 } else {
708 $users = get_course_users($course->id);
709 }
5b48244f 710
082215e6 711 $select = 'SELECT u.id, u.id, u.firstname, u.lastname, u.picture,'.
712 's.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) AND (s.timemarked >= s.timemodified)) AS status ';
9bf660b3 713 $sql = 'FROM '.$CFG->prefix.'user u '.
714 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment->id.' '.
082215e6 715 'WHERE u.id IN ('.implode(',', array_keys($users)).') ';
02828119 716
717 require_once($CFG->libdir.'/tablelib.php');
718 if($sort = flexible_table::get_sql_sort('mod-assignment-submissions')) {
719 $sort = 'ORDER BY '.$sort.' ';
720 }
721
722 $limit = sql_paging_limit($offset+1, 1);
723
082215e6 724 $nextid = 0;
81532b92 725 if (($auser = get_record_sql($select.$sql.$sort.$limit, false, true)) !== false) {
5b48244f 726 $nextid = $auser->id;
9bf660b3 727 }
81532b92 728
9bf660b3 729 print_header(get_string('feedback', 'assignment').':'.fullname($user, true).':'.format_string($this->assignment->name));
d699cd1e 730
9bf660b3 731 ///SOme javascript to help with setting up >.>
732
c9977d05 733 echo '<script type="text/javascript">'."\n";
9bf660b3 734 echo 'function setNext(){'."\n";
735 echo 'document.submitform.mode.value=\'next\';'."\n";
736 echo 'document.submitform.userid.value="'.$nextid.'";'."\n";
737 echo '}'."\n";
738
739 echo 'function saveNext(){'."\n";
740 echo 'document.submitform.mode.value=\'saveandnext\';'."\n";
741 echo 'document.submitform.userid.value="'.$nextid.'";'."\n";
742 echo 'document.submitform.saveuserid.value="'.$userid.'";'."\n";
743 echo 'document.submitform.menuindex.value = document.submitform.grade.selectedIndex;'."\n";
744 echo '}'."\n";
745
746 echo '</script>'."\n";
52436fe1 747 echo '<table cellspacing="0" class="feedback '.$subtype.'" >';
d699cd1e 748
9bf660b3 749 ///Start of teacher info row
c69cb506 750
b0f2597e 751 echo '<tr>';
752 echo '<td width="35" valign="top" class="picture teacher">';
753 if ($submission->teacher) {
754 $teacher = get_record('user', 'id', $submission->teacher);
755 } else {
756 global $USER;
757 $teacher = $USER;
758 }
759 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
760 echo '</td>';
761 echo '<td class="content">';
9894b824 762 echo '<form name="submitform" action="submissions.php" method="post">';
763 echo '<input type="hidden" name="offset" value="'.++$offset.'">';
c9977d05 764 echo '<input type="hidden" name="userid" value="'.$userid.'" />';
765 echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
766 echo '<input type="hidden" name="mode" value="grade" />';
767 echo '<input type="hidden" name="menuindex" value="0" />';//selected menu index
9bf660b3 768
769 //new hidden field, initialized to -1.
c9977d05 770 echo '<input type="hidden" name="saveuserid" value="-1" />';
52436fe1 771 if ($submission->timemarked) {
772 echo '<div class="from">';
773 echo '<div class="fullname">'.fullname($teacher, true).'</div>';
774 echo '<div class="time">'.userdate($submission->timemarked).'</div>';
775 echo '</div>';
776 }
777 echo '<div class="grade">'.get_string('grade').':';
082215e6 778 choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', $submission->grade, get_string('nograde'), '', -1);
52436fe1 779 echo '</div>';
780 echo '<div class="clearer"></div>';
b0f2597e 781
01e2fdfe 782 $this->preprocess_submission($submission);
783
b0f2597e 784 echo '<br />';
a8166227 785 print_textarea($this->usehtmleditor, 14, 58, 0, 0, 'comment', $submission->comment, $this->course->id);
ff8f7015 786
ff8f7015 787 if ($this->usehtmleditor) {
ff8f7015 788 echo '<input type="hidden" name="format" value="'.FORMAT_HTML.'" />';
789 } else {
f77cfb73 790 echo '<div align="right" class="format">';
ff8f7015 791 choose_from_menu(format_text_menu(), "format", $submission->format, "");
f77cfb73 792 helpbutton("textformat", get_string("helpformatting"));
793 echo '</div>';
ff8f7015 794 }
b0f2597e 795
9bf660b3 796 ///Print Buttons in Single View
73097f07 797 echo '<div class="buttons" align="center">';
c9977d05 798 echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" onclick = "document.submitform.menuindex.value = document.submitform.grade.selectedIndex" />';
b0f2597e 799 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
9bf660b3 800 //if there are more to be graded.
082215e6 801 if ($nextid) {
5b48244f 802 echo '<input type="submit" name="saveandnext" value="'.get_string('saveandnext').'" onclick="saveNext()" />';
803 echo '<input type="submit" name="next" value="'.get_string('next').'" onclick="setNext();" />';
9bf660b3 804 }
73097f07 805 echo '</div>';
b0f2597e 806 echo '</form>';
73097f07 807 echo '</td></tr>';
9bf660b3 808
809 ///End of teacher info row, Start of student info row
810 echo '<tr>';
811 echo '<td width="35" valign="top" class="picture user">';
812 print_user_picture($user->id, $this->course->id, $user->picture);
813 echo '</td>';
814 echo '<td class="topic">';
815 echo '<div class="from">';
816 echo '<div class="fullname">'.fullname($user, true).'</div>';
817 if ($submission->timemodified) {
818 echo '<div class="time">'.userdate($submission->timemodified).
819 $this->display_lateness($submission->timemodified).'</div>';
820 }
821 echo '</div>';
822 $this->print_user_files($user->id);
823 echo '</td>';
824 echo '</tr>';
825
826 ///End of student info row
827
73097f07 828 echo '</table>';
829
73097f07 830 if ($this->usehtmleditor) {
831 use_html_editor();
832 }
833
b0f2597e 834 print_footer('none');
d699cd1e 835 }
836
01e2fdfe 837 /*
838 * Preprocess submission before grading
839 */
840 function preprocess_submission(&$submission) {
841 }
d699cd1e 842
b0f2597e 843 /*
844 * Display all the submissions ready for grading
845 */
846 function display_submissions() {
3446205d 847
9bf660b3 848 global $CFG, $db, $USER;
3446205d 849
9bf660b3 850 /* first we check to see if the form has just been submitted
851 * to request user_preference updates
852 */
853
854 if (isset($_POST['updatepref'])){
16907e53 855 $perpage = optional_param('perpage', 10, PARAM_INT);
9bf660b3 856 $perpage = ($perpage <= 0) ? 10 : $perpage ;
857 set_user_preference('assignment_perpage', $perpage);
16907e53 858 set_user_preference('assignment_quickgrade', optional_param('quickgrade',0, PARAM_BOOL));
9bf660b3 859 }
1b5910c4 860
9bf660b3 861 /* next we get perpage and quickgrade (allow quick grade) params
862 * from database
863 */
864 $perpage = get_user_preferences('assignment_perpage', 10);
865 $quickgrade = get_user_preferences('assignment_quickgrade', 0);
866
867 $teacherattempts = true; /// Temporary measure
16907e53 868 $page = optional_param('page', 0, PARAM_INT);
b0f2597e 869 $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
d0ac6bc2 870
b0f2597e 871 /// Some shortcuts to make the code read better
872
873 $course = $this->course;
874 $assignment = $this->assignment;
875 $cm = $this->cm;
9bf660b3 876
877 $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
91719320 878
b0f2597e 879 add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id);
880
3898bc33 881 print_header_simple(format_string($this->assignment->name,true), "", '<a href="index.php?id='.$course->id.'">'.$this->strassignments.'</a> -> <a href="view.php?a='.$this->assignment->id.'">'.format_string($this->assignment->name,true).'</a> -> '. $this->strsubmissions, '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm));
fa22fd5f 882
883 ///Position swapped
884 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
885 $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
886 } else {
887 $currentgroup = false;
888 }
889
890 /// Get all teachers and students
891 if ($currentgroup) {
892 $users = get_group_users($currentgroup);
893 } else {
894 $users = get_course_users($course->id);
895 }
91719320 896
9437c854 897 $tablecolumns = array('picture', 'fullname', 'grade', 'comment', 'timemodified', 'timemarked', 'status');
898 $tableheaders = array('', get_string('fullname'), get_string('grade'), get_string('comment', 'assignment'), get_string('lastmodified').' ('.$course->student.')', get_string('lastmodified').' ('.$course->teacher.')', get_string('status'));
91719320 899
b0f2597e 900 require_once($CFG->libdir.'/tablelib.php');
901 $table = new flexible_table('mod-assignment-submissions');
902
903 $table->define_columns($tablecolumns);
904 $table->define_headers($tableheaders);
fa22fd5f 905 $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;currentgroup='.$currentgroup);
b0f2597e 906
907 $table->sortable(true);
908 $table->collapsible(true);
909 $table->initialbars(true);
910
911 $table->column_suppress('picture');
912 $table->column_suppress('fullname');
913
914 $table->column_class('picture', 'picture');
9437c854 915 $table->column_class('fullname', 'fullname');
916 $table->column_class('grade', 'grade');
917 $table->column_class('comment', 'comment');
918 $table->column_class('timemodified', 'timemodified');
919 $table->column_class('timemarked', 'timemarked');
920 $table->column_class('status', 'status');
b0f2597e 921
922 $table->set_attribute('cellspacing', '0');
923 $table->set_attribute('id', 'attempts');
9437c854 924 $table->set_attribute('class', 'submissions');
b0f2597e 925 $table->set_attribute('width', '90%');
926 $table->set_attribute('align', 'center');
927
928 // Start working -- this is necessary as soon as the niceties are over
929 $table->setup();
930
b0f2597e 931 /// Check to see if groups are being used in this assignment
05855091 932
b0f2597e 933 if (!$teacherattempts) {
934 $teachers = get_course_teachers($course->id);
935 if (!empty($teachers)) {
936 $keys = array_keys($teachers);
937 }
938 foreach ($keys as $key) {
939 unset($users[$key]);
940 }
941 }
942
943 if (empty($users)) {
c8dbfa5c 944 print_heading(get_string('noattempts','assignment'));
b0f2597e 945 return true;
946 }
0f1a97c2 947
b0f2597e 948 /// Construct the SQL
0f1a97c2 949
b0f2597e 950 if ($where = $table->get_sql_where()) {
b0f2597e 951 $where .= ' AND ';
952 }
0f1a97c2 953
b0f2597e 954 if ($sort = $table->get_sql_sort()) {
86f65395 955 $sort = ' ORDER BY '.$sort;
b0f2597e 956 }
9fa49e22 957
042311a9 958 $select = 'SELECT u.id, u.id, u.firstname, u.lastname, u.picture, s.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) AND (s.timemarked >= s.timemodified)) AS status ';
b0f2597e 959 $sql = 'FROM '.$CFG->prefix.'user u '.
306dc7e5 960 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment->id.' '.
961 'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') ';
9bf660b3 962
c5d36203 963 $table->pagesize($perpage, count($users));
b0f2597e 964
965 if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
966 $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
967 }
968 else {
969 $limit = '';
970 }
9bf660b3 971
9bf660b3 972 ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
973 $offset = $page * $perpage;
974
b0f2597e 975 $strupdate = get_string('update');
9437c854 976 $strgrade = get_string('grade');
b0f2597e 977 $grademenu = make_grades_menu($this->assignment->grade);
978
c5d36203 979 if (($ausers = get_records_sql($select.$sql.$sort.$limit)) !== false) {
d59269cf 980
d59269cf 981 foreach ($ausers as $auser) {
982 $picture = print_user_picture($auser->id, $course->id, $auser->picture, false, true);
9bf660b3 983
39e11905 984 if (empty($auser->submissionid)) {
985 $auser->grade = -1; //no submission yet
9bf660b3 986 }
987
d59269cf 988 if (!empty($auser->submissionid)) {
9bf660b3 989 ///Prints student answer and student modified date
990 ///attach file or print link to student answer, depending on the type of the assignment.
991 ///Refer to print_student_answer in inherited classes.
992 if ($auser->timemodified > 0) {
993 $studentmodified = '<div id="ts'.$auser->id.'">'.$this->print_student_answer($auser->id).userdate($auser->timemodified).'</div>';
d59269cf 994 } else {
9437c854 995 $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
d59269cf 996 }
9bf660b3 997 ///Print grade, dropdown or text
d59269cf 998 if ($auser->timemarked > 0) {
999 $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
9bf660b3 1000
1001 if ($quickgrade) {
1002 $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade),
082215e6 1003 'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
9bf660b3 1004 } else {
1005 $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
1006 }
1007
b0f2597e 1008 } else {
9437c854 1009 $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
9bf660b3 1010 if ($quickgrade){
1011 $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade),
082215e6 1012 'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
9bf660b3 1013 } else {
1014 $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
1015 }
1016 }
1017 ///Print Comment
1018 if ($quickgrade){
1019 $comment = '<div id="com'.$auser->id.'"><textarea tabindex="'.$tabindex++.'" name="comment['.$auser->id.']" id="comment['.$auser->id.']">'.($auser->comment).'</textarea></div>';
1020 } else {
1021 $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->comment),15).'</div>';
b0f2597e 1022 }
1023 } else {
9437c854 1024 $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
1025 $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
9bf660b3 1026 $status = '<div id="st'.$auser->id.'">&nbsp;</div>';
1027 if ($quickgrade){ // allow editing
1028 $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade),
082215e6 1029 'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
9bf660b3 1030 } else {
39e11905 1031 $grade = '<div id="g'.$auser->id.'">-</div>';
9bf660b3 1032 }
1033 if ($quickgrade){
1034 $comment = '<div id="com'.$auser->id.'"><textarea tabindex="'.$tabindex++.'" name="comment['.$auser->id.']" id="comment['.$auser->id.']">'.($auser->comment).'</textarea></div>';
1035 } else {
1036 $comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
1037 }
b0f2597e 1038 }
9fa49e22 1039
0f7d4e5e 1040 if ($auser->status === NULL) {
1041 $auser->status = 0;
1042 }
1043
9437c854 1044 $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
9bf660b3 1045
1046 ///No more buttons, we use popups ;-).
9894b824 1047 $button = link_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;offset='.$offset++,
a8166227 1048 'grade'.$auser->id, $buttontext, 500, 780, $buttontext, 'none', true, 'button'.$auser->id);
0f7d4e5e 1049
9437c854 1050 $status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
9bf660b3 1051
9437c854 1052 $row = array($picture, fullname($auser), $grade, $comment, $studentmodified, $teachermodified, $status);
d59269cf 1053 $table->add_data($row);
1054 }
b0f2597e 1055 }
9bf660b3 1056
082215e6 1057 /// Print quickgrade form around the table
1058 if ($quickgrade){
1059 echo '<form action="submissions.php" name="fastg" method="post">';
1060 echo '<input type="hidden" name="id" value="'.$this->cm->id.'">';
1061 echo '<input type="hidden" name="mode" value="fastgrade">';
16907e53 1062 echo '<input type="hidden" name="page" value="'.$page.'">';
082215e6 1063 }
1064
1065 $table->print_html(); /// Print the whole table
1066
9bf660b3 1067 if ($quickgrade){
1068 echo '<p align="center"><input type="submit" name="fastg" value="'.get_string('saveallfeedback', 'assignment').'" /></p>';
082215e6 1069 echo '</form>';
9bf660b3 1070 }
082215e6 1071 /// End of fast grading form
9bf660b3 1072
082215e6 1073 /// Mini form for setting user preference
9bf660b3 1074 echo '<br />';
1075 echo '<form name="options" action="submissions.php?id='.$this->cm->id.'" method="post">';
c9977d05 1076 echo '<input type="hidden" id="updatepref" name="updatepref" value="1" />';
9bf660b3 1077 echo '<table id="optiontable" align="center">';
1078 echo '<tr align="right"><td>';
1079 echo '<label for="perpage">'.get_string('pagesize','assignment').'</label>';
1080 echo ':</td>';
9bf660b3 1081 echo '<td align="left">';
1082 echo '<input type="text" id="perpage" name="perpage" size="1" value="'.$perpage.'" />';
1083 helpbutton('pagesize', get_string('pagesize','assignment'), 'assignment');
1084 echo '</td></tr>';
1085 echo '<tr align="right">';
1086 echo '<td>';
1087 print_string('quickgrade','assignment');
1088 echo ':</td>';
1089 echo '<td align="left">';
1090 if ($quickgrade){
1091 echo '<input type="checkbox" name="quickgrade" value="1" checked="checked" />';
1092 } else {
1093 echo '<input type="checkbox" name="quickgrade" value="1" />';
1094 }
1095 helpbutton('quickgrade', get_string('quickgrade', 'assignment'), 'assignment').'</p></div>';
1096 echo '</td></tr>';
1097 echo '<tr>';
1098 echo '<td colspan="2" align="right">';
1099 echo '<input type="submit" value="'.get_string('savepreferences').'" />';
1100 echo '</td></tr></table>';
1101 echo '</form>';
1102 ///End of mini form
b0f2597e 1103 print_footer($this->course);
8e340cb0 1104 }
d699cd1e 1105
b0f2597e 1106 /*
1107 * Display and process the submissions
1108 */
1109 function process_feedback() {
d699cd1e 1110
b0f2597e 1111 global $USER;
d699cd1e 1112
9894b824 1113 if (!$feedback = data_submitted()) { // No incoming data?
b0f2597e 1114 return false;
d699cd1e 1115 }
b7b42874 1116
9bf660b3 1117 ///For save and next, we need to know the userid to save, and the userid to go
1118 ///We use a new hidden field in the form, and set it to -1. If it's set, we use this
1119 ///as the userid to store
1120 if ((int)$feedback->saveuserid !== -1){
1121 $feedback->userid = $feedback->saveuserid;
1122 }
1123
b0f2597e 1124 if (!empty($feedback->cancel)) { // User hit cancel button
1125 return false;
1126 }
d699cd1e 1127
0f7d4e5e 1128 $newsubmission = $this->get_submission($feedback->userid, true); // Get or make one
d699cd1e 1129
b0f2597e 1130 $newsubmission->grade = $feedback->grade;
1131 $newsubmission->comment = $feedback->comment;
ff8f7015 1132 $newsubmission->format = $feedback->format;
b0f2597e 1133 $newsubmission->teacher = $USER->id;
1134 $newsubmission->mailed = 0; // Make sure mail goes out (again, even)
1135 $newsubmission->timemarked = time();
d699cd1e 1136
d4156e80 1137 unset($newsubmission->data1); // Don't need to update this.
1138 unset($newsubmission->data2); // Don't need to update this.
1139
b0f2597e 1140 if (empty($submission->timemodified)) { // eg for offline assignments
1141 $newsubmission->timemodified = time();
1142 }
d699cd1e 1143
b0f2597e 1144 if (! update_record('assignment_submissions', $newsubmission)) {
1145 return false;
1146 }
d699cd1e 1147
b0f2597e 1148 add_to_log($this->course->id, 'assignment', 'update grades',
1149 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
1150
1151 return $newsubmission;
d699cd1e 1152
d699cd1e 1153 }
d699cd1e 1154
f77cfb73 1155 function get_submission($userid=0, $createnew=false) {
1156 global $USER;
1157
1158 if (empty($userid)) {
1159 $userid = $USER->id;
1160 }
1161
b0f2597e 1162 $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
d699cd1e 1163
b0f2597e 1164 if ($submission || !$createnew) {
1165 return $submission;
1166 }
39e11905 1167 $newsubmission = $this->prepare_new_submission($userid);
b0f2597e 1168 if (!insert_record("assignment_submissions", $newsubmission)) {
1169 error("Could not insert a new empty submission");
1170 }
d699cd1e 1171
b0f2597e 1172 return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
1173 }
d699cd1e 1174
39e11905 1175
1176 function prepare_new_submission($userid) {
1177 $submission = new Object;
1178 $submission->assignment = $this->assignment->id;
1179 $submission->userid = $userid;
1180 $submission->timecreated = time();
1181 $submission->timemodified = $submission->timecreated;
1182 $submission->numfiles = 0;
1183 $submission->data1 = '';
1184 $submission->data2 = '';
1185 $submission->grade = -1;
1186 $submission->comment = '';
1187 $submission->format = 0;
1188 $submission->teacher = 0;
1189 $submission->timemarked = 0;
1190 $submission->mailed = 0;
1191 return $submission;
1192 }
1193
3f8247c2 1194
b0f2597e 1195 function get_submissions($sort='', $dir='DESC') {
1196 /// Return all assignment submissions by ENROLLED students (even empty)
1197 global $CFG;
1198
1199 if ($sort == "lastname" or $sort == "firstname") {
1200 $sort = "u.$sort $dir";
1201 } else if (empty($sort)) {
1202 $sort = "a.timemodified DESC";
1203 } else {
1204 $sort = "a.$sort $dir";
d699cd1e 1205 }
d699cd1e 1206
b0f2597e 1207 $select = "s.course = '$this->assignment->course' AND";
1208 $site = get_site();
1209 if ($this->assignment->course == $site->id) {
1210 $select = '';
1211 }
1212 return get_records_sql("SELECT a.*
1213 FROM {$CFG->prefix}assignment_submissions a,
1214 {$CFG->prefix}user_students s,
1215 {$CFG->prefix}user u
1216 WHERE a.userid = s.userid
1217 AND u.id = a.userid
1218 AND $select a.assignment = '$this->assignment->id'
1219 ORDER BY $sort");
1220 }
1221
1222
1223 function count_real_submissions($groupid=0) {
1224 /// Return all real assignment submissions by ENROLLED students (not empty ones)
1225 global $CFG;
1226
1227 if ($groupid) { /// How many in a particular group?
1228 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
1229 FROM {$CFG->prefix}assignment_submissions a,
1230 {$CFG->prefix}groups_members g
1231 WHERE a.assignment = {$this->assignment->id}
1232 AND a.timemodified > 0
1233 AND g.groupid = '$groupid'
1234 AND a.userid = g.userid ");
1235 } else {
1236 $select = "s.course = '{$this->assignment->course}' AND";
1237 if ($this->assignment->course == SITEID) {
1238 $select = '';
d699cd1e 1239 }
b0f2597e 1240 return count_records_sql("SELECT COUNT(*)
1241 FROM {$CFG->prefix}assignment_submissions a,
1242 {$CFG->prefix}user_students s
1243 WHERE a.assignment = '{$this->assignment->id}'
1244 AND a.timemodified > 0
1245 AND $select a.userid = s.userid ");
1246 }
d59269cf 1247 }
d699cd1e 1248
73097f07 1249 function email_teachers($submission) {
1250 /// Alerts teachers by email of new or changed assignments that need grading
1251
1252 global $CFG;
1253
d8199f1d 1254 if (empty($this->assignment->emailteachers)) { // No need to do anything
73097f07 1255 return;
1256 }
1257
1258 $user = get_record('user', 'id', $submission->userid);
1259
d8199f1d 1260 if (groupmode($this->course, $this->cm) == SEPARATEGROUPS) { // Separate groups are being used
1261 if (!$group = user_group($this->course->id, $user->id)) { // Try to find a group
73097f07 1262 $group->id = 0; // Not in a group, never mind
1263 }
d8199f1d 1264 $teachers = get_group_teachers($this->course->id, $group->id); // Works even if not in group
73097f07 1265 } else {
d8199f1d 1266 $teachers = get_course_teachers($this->course->id);
73097f07 1267 }
1268
1269 if ($teachers) {
1270
1271 $strassignments = get_string('modulenameplural', 'assignment');
1272 $strassignment = get_string('modulename', 'assignment');
1273 $strsubmitted = get_string('submitted', 'assignment');
1274
1275 foreach ($teachers as $teacher) {
1276 unset($info);
1277 $info->username = fullname($user);
d8199f1d 1278 $info->assignment = format_string($this->assignment->name,true);
1279 $info->url = $CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id;
1280
1281 $postsubject = $strsubmitted.': '.$info->username.' -> '.$this->assignment->name;
1282 $posttext = $this->email_teachers_text($info);
1283 $posthtml = ($teacher->mailformat == 1) ? $this->email_teachers_html($info) : '';
73097f07 1284
1285 @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
1286 }
1287 }
1288 }
1289
d8199f1d 1290 function email_teachers_text($info) {
1291 $posttext = $this->course->shortname.' -> '.$this->strassignments.' -> '.
1292 format_string($this->assignment->name, true)."\n";
1293 $posttext .= '---------------------------------------------------------------------'."\n";
1294 $posttext .= get_string("emailteachermail", "assignment", $info)."\n";
1295 $posttext .= '---------------------------------------------------------------------'."\n";
1296 return $posttext;
1297 }
1298
d8199f1d 1299 function email_teachers_html($info) {
3554b5c2 1300 global $CFG;
d8199f1d 1301 $posthtml = '<p><font face="sans-serif">'.
3554b5c2 1302 '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$this->course->id.'">'.$this->course->shortname.'</a> ->'.
d8199f1d 1303 '<a href="'.$CFG->wwwroot.'/mod/assignment/index.php?id='.$this->course->id.'">'.$this->strassignments.'</a> ->'.
3554b5c2 1304 '<a href="'.$CFG->wwwroot.'/mod/assignment/view.php?id='.$this->cm->id.'">'.format_string($this->assignment->name,true).'</a></font></p>';
d8199f1d 1305 $posthtml .= '<hr /><font face="sans-serif">';
1306 $posthtml .= '<p>'.get_string('emailteachermailhtml', 'assignment', $info).'</p>';
1307 $posthtml .= '</font><hr />';
815b5ca6 1308 return $posthtml;
d8199f1d 1309 }
1310
d8199f1d 1311 function print_user_files($userid=0, $return=false) {
d8199f1d 1312 global $CFG, $USER;
9bf660b3 1313
d8199f1d 1314 if (!$userid) {
1315 if (!isloggedin()) {
1316 return '';
1317 }
1318 $userid = $USER->id;
1319 }
73097f07 1320
70b2c772 1321 $filearea = $this->file_area_name($userid);
73097f07 1322
1323 $output = '';
1324
70b2c772 1325 if ($basedir = $this->file_area($userid)) {
73097f07 1326 if ($files = get_directory_list($basedir)) {
1ef048ae 1327 require_once($CFG->libdir.'/filelib.php');
73097f07 1328 foreach ($files as $key => $file) {
9bf660b3 1329
73097f07 1330 $icon = mimeinfo('icon', $file);
9bf660b3 1331
73097f07 1332 if ($CFG->slasharguments) {
d4156e80 1333 $ffurl = "$CFG->wwwroot/file.php/$filearea/$file";
73097f07 1334 } else {
d4156e80 1335 $ffurl = "$CFG->wwwroot/file.php?file=/$filearea/$file";
73097f07 1336 }
9bf660b3 1337
1ef048ae 1338 $output .= '<img align="middle" src="'.$CFG->pixpath.'/f/'.$icon.'" height="16" width="16" alt="'.$icon.'" />'.
9bf660b3 1339 '<a href="'.$ffurl.'" >'.$file.'</a><br />';
73097f07 1340 }
1341 }
1342 }
1343
1344 $output = '<div class="files">'.$output.'</div>';
1345
1346 if ($return) {
1347 return $output;
1348 }
1349 echo $output;
1350 }
1351
70b2c772 1352 function count_user_files($userid) {
1353 global $CFG;
1354
1355 $filearea = $this->file_area_name($userid);
1356
1357 if ($basedir = $this->file_area($userid)) {
1358 if ($files = get_directory_list($basedir)) {
1359 return count($files);
1360 }
1361 }
1362 return 0;
1363 }
73097f07 1364
70b2c772 1365 function file_area_name($userid) {
73097f07 1366 // Creates a directory file name, suitable for make_upload_directory()
1367 global $CFG;
1368
70b2c772 1369 return $this->course->id.'/'.$CFG->moddata.'/assignment/'.$this->assignment->id.'/'.$userid;
73097f07 1370 }
1371
70b2c772 1372 function file_area($userid) {
1373 return make_upload_directory( $this->file_area_name($userid) );
73097f07 1374 }
1375
f77cfb73 1376 function isopen() {
1377 $time = time();
1e4343a0 1378 if ($this->assignment->preventlate && $this->assignment->timedue) {
f77cfb73 1379 return ($this->assignment->timeavailable <= $time && $time <= $this->assignment->timedue);
1380 } else {
1381 return ($this->assignment->timeavailable <= $time);
1382 }
1383 }
1384
73097f07 1385 function user_outline($user) {
1386 if ($submission = $this->get_submission($user->id)) {
39e11905 1387
1388 $result->info = get_string('grade').': '.$this->display_grade($submission->grade);
73097f07 1389 $result->time = $submission->timemodified;
1390 return $result;
1391 }
1392 return NULL;
1393 }
1394
1395 function user_complete($user) {
1396 if ($submission = $this->get_submission($user->id)) {
70b2c772 1397 if ($basedir = $this->file_area($user->id)) {
73097f07 1398 if ($files = get_directory_list($basedir)) {
1399 $countfiles = count($files)." ".get_string("uploadedfiles", "assignment");
1400 foreach ($files as $file) {
1401 $countfiles .= "; $file";
1402 }
1403 }
1404 }
1405
1406 print_simple_box_start();
1407 echo get_string("lastmodified").": ";
9bf660b3 1408 echo userdate($submission->timemodified);
1409 echo $this->display_lateness($submission->timemodified);
73097f07 1410
70b2c772 1411 $this->print_user_files($user->id);
73097f07 1412
1413 echo '<br />';
1414
1415 if (empty($submission->timemarked)) {
1416 print_string("notgradedyet", "assignment");
1417 } else {
1418 $this->view_feedback($submission);
1419 }
1420
1421 print_simple_box_end();
1422
1423 } else {
1424 print_string("notsubmittedyet", "assignment");
1425 }
1426 }
1427
70b2c772 1428 function display_lateness($timesubmitted) {
1e4343a0 1429 if (!$this->assignment->timedue) {
1430 return '';
1431 }
70b2c772 1432 $time = $this->assignment->timedue - $timesubmitted;
73097f07 1433 if ($time < 0) {
1434 $timetext = get_string('late', 'assignment', format_time($time));
70b2c772 1435 return ' (<span class="late">'.$timetext.'</span>)';
73097f07 1436 } else {
1437 $timetext = get_string('early', 'assignment', format_time($time));
70b2c772 1438 return ' (<span class="early">'.$timetext.'</span>)';
73097f07 1439 }
1440 }
1441
1442
b0f2597e 1443} ////// End of the assignment_base class
d699cd1e 1444
18b8fbfa 1445
04eba58f 1446
b0f2597e 1447/// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////
1448
1449
1450function assignment_delete_instance($id){
26b90e70 1451 global $CFG;
1452
b0f2597e 1453 if (! $assignment = get_record('assignment', 'id', $id)) {
1454 return false;
26b90e70 1455 }
1456
b0f2597e 1457 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1458 $assignmentclass = "assignment_$assignment->assignmenttype";
1459 $ass = new $assignmentclass();
1460 return $ass->delete_instance($assignment);
1461}
f466c9ed 1462
ac21ad39 1463
b0f2597e 1464function assignment_update_instance($assignment){
1465 global $CFG;
26b90e70 1466
200c19fb 1467 $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR);
1468
b0f2597e 1469 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1470 $assignmentclass = "assignment_$assignment->assignmenttype";
1471 $ass = new $assignmentclass();
1472 return $ass->update_instance($assignment);
1473}
26b90e70 1474
26b90e70 1475
b0f2597e 1476function assignment_add_instance($assignment) {
1477 global $CFG;
f466c9ed 1478
200c19fb 1479 $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR);
1480
b0f2597e 1481 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1482 $assignmentclass = "assignment_$assignment->assignmenttype";
1483 $ass = new $assignmentclass();
1484 return $ass->add_instance($assignment);
1485}
f466c9ed 1486
73097f07 1487
1488function assignment_user_outline($course, $user, $mod, $assignment) {
1489 global $CFG;
1490
1491 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1492 $assignmentclass = "assignment_$assignment->assignmenttype";
1493 $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
1494 return $ass->user_outline($user);
1495}
1496
1497function assignment_user_complete($course, $user, $mod, $assignment) {
1498 global $CFG;
1499
1500 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1501 $assignmentclass = "assignment_$assignment->assignmenttype";
1502 $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
1503 return $ass->user_complete($user);
1504}
1505
1506
1507function assignment_cron () {
1508// Function to be run periodically according to the moodle cron
1509// Finds all assignment notifications that have yet to be mailed out, and mails them
1510
1511 global $CFG, $USER;
1512
1513 /// Notices older than 1 day will not be mailed. This is to avoid the problem where
1514 /// cron has not been running for a long time, and then suddenly people are flooded
1515 /// with mail from the past few weeks or months
1516
1517 $timenow = time();
1518 $endtime = $timenow - $CFG->maxeditingtime;
1519 $starttime = $endtime - 24 * 3600; /// One day earlier
1520
1521 if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) {
1522
1523 foreach ($submissions as $key => $submission) {
1524 if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) {
1525 echo "Could not update the mailed field for id $submission->id. Not mailed.\n";
1526 unset($submissions[$key]);
1527 }
1528 }
1529
1530 $timenow = time();
1531
1532 foreach ($submissions as $submission) {
1533
1534 echo "Processing assignment submission $submission->id\n";
1535
1536 if (! $user = get_record("user", "id", "$submission->userid")) {
1537 echo "Could not find user $post->userid\n";
1538 continue;
1539 }
1540
1541 $USER->lang = $user->lang;
1542
1543 if (! $course = get_record("course", "id", "$submission->course")) {
1544 echo "Could not find course $submission->course\n";
1545 continue;
1546 }
1547
1548 if (! isstudent($course->id, $user->id) and !isteacher($course->id, $user->id)) {
1549 echo fullname($user)." not an active participant in $course->shortname\n";
1550 continue;
1551 }
1552
1553 if (! $teacher = get_record("user", "id", "$submission->teacher")) {
1554 echo "Could not find teacher $submission->teacher\n";
1555 continue;
1556 }
1557
1558 if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment, $course->id)) {
1559 echo "Could not find course module for assignment id $submission->assignment\n";
1560 continue;
1561 }
1562
1563 if (! $mod->visible) { /// Hold mail notification for hidden assignments until later
1564 continue;
1565 }
1566
1567 $strassignments = get_string("modulenameplural", "assignment");
1568 $strassignment = get_string("modulename", "assignment");
1569
1570 unset($assignmentinfo);
1571 $assignmentinfo->teacher = fullname($teacher);
1572 $assignmentinfo->assignment = format_string($submission->name,true);
1573 $assignmentinfo->url = "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id";
1574
1575 $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true);
1576 $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n";
1577 $posttext .= "---------------------------------------------------------------------\n";
1578 $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo);
1579 $posttext .= "---------------------------------------------------------------------\n";
1580
1581 if ($user->mailformat == 1) { // HTML
1582 $posthtml = "<p><font face=\"sans-serif\">".
1583 "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
1584 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
1585 "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."</a></font></p>";
1586 $posthtml .= "<hr /><font face=\"sans-serif\">";
1587 $posthtml .= "<p>".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."</p>";
1588 $posthtml .= "</font><hr />";
1589 } else {
1590 $posthtml = "";
1591 }
1592
1593 if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) {
1594 echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n";
1595 }
1596 }
1597 }
1598
1599 return true;
1600}
1601
082215e6 1602
73097f07 1603function assignment_grades($assignmentid) {
1604/// Must return an array of grades, indexed by user, and a max grade.
1605
082215e6 1606 if (!$assignment = get_record('assignment', 'id', $assignmentid)) {
73097f07 1607 return NULL;
1608 }
3262ee10 1609 if ($assignment->grade == 0) { // No grading
1610 return NULL;
1611 }
73097f07 1612
082215e6 1613 $grades = get_records_menu('assignment_submissions', 'assignment',
1614 $assignment->id, '', 'userid,grade');
73097f07 1615
3262ee10 1616 if ($assignment->grade > 0) {
fa22fd5f 1617 if ($grades) {
1618 foreach ($grades as $userid => $grade) {
1619 if ($grade == -1) {
1620 $grades[$userid] = '-';
1621 }
082215e6 1622 }
1623 }
73097f07 1624 $return->grades = $grades;
1625 $return->maxgrade = $assignment->grade;
1626
1627 } else { // Scale
1628 if ($grades) {
1629 $scaleid = - ($assignment->grade);
1630 if ($scale = get_record('scale', 'id', $scaleid)) {
1631 $scalegrades = make_menu_from_list($scale->scale);
082215e6 1632 foreach ($grades as $userid => $grade) {
de4564ee 1633 if (empty($scalegrades[$grade])) {
39e11905 1634 $grades[$userid] = '-';
0a3f66a2 1635 } else {
082215e6 1636 $grades[$userid] = $scalegrades[$grade];
0a3f66a2 1637 }
73097f07 1638 }
1639 }
1640 }
1641 $return->grades = $grades;
1642 $return->maxgrade = "";
1643 }
1644
1645 return $return;
1646}
1647
1648function assignment_get_participants($assignmentid) {
1649//Returns the users with data in one assignment
1650//(users with records in assignment_submissions, students and teachers)
1651
1652 global $CFG;
1653
1654 //Get students
1655 $students = get_records_sql("SELECT DISTINCT u.id, u.id
1656 FROM {$CFG->prefix}user u,
1657 {$CFG->prefix}assignment_submissions a
1658 WHERE a.assignment = '$assignmentid' and
1659 u.id = a.userid");
1660 //Get teachers
1661 $teachers = get_records_sql("SELECT DISTINCT u.id, u.id
1662 FROM {$CFG->prefix}user u,
1663 {$CFG->prefix}assignment_submissions a
1664 WHERE a.assignment = '$assignmentid' and
1665 u.id = a.teacher");
1666
1667 //Add teachers to students
1668 if ($teachers) {
1669 foreach ($teachers as $teacher) {
1670 $students[$teacher->id] = $teacher;
1671 }
1672 }
1673 //Return students array (it contains an array of unique users)
1674 return ($students);
1675}
1676
73097f07 1677function assignment_scale_used ($assignmentid,$scaleid) {
1678//This function returns if a scale is being used by one assignment
1679
1680 $return = false;
1681
1682 $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid);
1683
1684 if (!empty($rec) && !empty($scaleid)) {
1685 $return = true;
1686 }
1687
1688 return $return;
1689}
1690
1691
1692function assignment_refresh_events($courseid = 0) {
1693// This standard function will check all instances of this module
1694// and make sure there are up-to-date events created for each of them.
1695// If courseid = 0, then every assignment event in the site is checked, else
1696// only assignment events belonging to the course specified are checked.
1697// This function is used, in its new format, by restore_refresh_events()
1698
1699 if ($courseid == 0) {
1700 if (! $assignments = get_records("assignment")) {
1701 return true;
1702 }
1703 } else {
1704 if (! $assignments = get_records("assignment", "course", $courseid)) {
1705 return true;
1706 }
1707 }
1708 $moduleid = get_field('modules', 'id', 'name', 'assignment');
1709
1710 foreach ($assignments as $assignment) {
1711 $event = NULL;
1712 $event->name = addslashes($assignment->name);
1713 $event->description = addslashes($assignment->description);
1714 $event->timestart = $assignment->timedue;
1715
1716 if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) {
1717 update_event($event);
1718
1719 } else {
1720 $event->courseid = $assignment->course;
1721 $event->groupid = 0;
1722 $event->userid = 0;
1723 $event->modulename = 'assignment';
1724 $event->instance = $assignment->id;
1725 $event->eventtype = 'due';
1726 $event->timeduration = 0;
1727 $event->visible = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id);
1728 add_event($event);
1729 }
1730
1731 }
1732 return true;
1733}
1734
1735
1736function assignment_print_recent_activity($course, $isteacher, $timestart) {
1737 global $CFG;
1738
1739 $content = false;
1740 $assignments = NULL;
1741
1742 if (!$logs = get_records_select('log', 'time > \''.$timestart.'\' AND '.
1743 'course = \''.$course->id.'\' AND '.
1744 'module = \'assignment\' AND '.
1745 'action = \'upload\' ', 'time ASC')) {
1746 return false;
1747 }
1748
1749 foreach ($logs as $log) {
1750 //Create a temp valid module structure (course,id)
1751 $tempmod->course = $log->course;
1752 $tempmod->id = $log->info;
1753 //Obtain the visible property from the instance
1754 $modvisible = instance_is_visible($log->module,$tempmod);
1755
1756 //Only if the mod is visible
1757 if ($modvisible) {
1758 $assignments[$log->info] = assignment_log_info($log);
1759 $assignments[$log->info]->time = $log->time;
1760 $assignments[$log->info]->url = str_replace('&', '&amp;', $log->url);
1761 }
1762 }
1763
1764 if ($assignments) {
1765 print_headline(get_string('newsubmissions', 'assignment').':');
1766 foreach ($assignments as $assignment) {
1767 print_recent_activity_note($assignment->time, $assignment, $isteacher, $assignment->name,
1768 $CFG->wwwroot.'/mod/assignment/'.$assignment->url);
1769 }
1770 $content = true;
1771 }
1772
1773 return $content;
1774}
1775
1776
1777
1778function assignment_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $assignment="0", $user="", $groupid="") {
1779// Returns all assignments since a given time. If assignment is specified then
1780// this restricts the results
1781
1782 global $CFG;
1783
1784 if ($assignment) {
1785 $assignmentselect = " AND cm.id = '$assignment'";
1786 } else {
1787 $assignmentselect = "";
1788 }
1789 if ($user) {
1790 $userselect = " AND u.id = '$user'";
1791 } else {
1792 $userselect = "";
1793 }
1794
1795 $assignments = get_records_sql("SELECT asub.*, u.firstname, u.lastname, u.picture, u.id as userid,
1796 a.grade as maxgrade, name, cm.instance, cm.section, a.assignmenttype
1797 FROM {$CFG->prefix}assignment_submissions asub,
1798 {$CFG->prefix}user u,
1799 {$CFG->prefix}assignment a,
1800 {$CFG->prefix}course_modules cm
1801 WHERE asub.timemodified > '$sincetime'
1802 AND asub.userid = u.id $userselect
1803 AND a.id = asub.assignment $assignmentselect
1804 AND cm.course = '$courseid'
1805 AND cm.instance = a.id
1806 ORDER BY asub.timemodified ASC");
1807
1808 if (empty($assignments))
1809 return;
1810
1811 foreach ($assignments as $assignment) {
1812 if (empty($groupid) || ismember($groupid, $assignment->userid)) {
1813
1814 $tmpactivity = new Object;
1815
1816 $tmpactivity->type = "assignment";
1817 $tmpactivity->defaultindex = $index;
1818 $tmpactivity->instance = $assignment->instance;
1819 $tmpactivity->name = $assignment->name;
1820 $tmpactivity->section = $assignment->section;
1821
1822 $tmpactivity->content->grade = $assignment->grade;
1823 $tmpactivity->content->maxgrade = $assignment->maxgrade;
1824 $tmpactivity->content->type = $assignment->assignmenttype;
1825
1826 $tmpactivity->user->userid = $assignment->userid;
1827 $tmpactivity->user->fullname = fullname($assignment);
1828 $tmpactivity->user->picture = $assignment->picture;
1829
1830 $tmpactivity->timestamp = $assignment->timemodified;
1831
1832 $activities[] = $tmpactivity;
1833
1834 $index++;
1835 }
1836 }
1837
1838 return;
1839}
1840
1841
1842function assignment_print_recent_mod_activity($activity, $course, $detail=false) {
1843 global $CFG;
1844
1845 echo '<table border="0" cellpadding="3" cellspacing="0">';
1846
1847 echo "<tr><td class=\"userpicture\" width=\"35\" valign=\"top\">";
1848 print_user_picture($activity->user->userid, $course, $activity->user->picture);
1849 echo "</td><td width=\"100%\"><font size=2>";
1850
1851 if ($detail) {
1852 echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
1853 "height=16 width=16 alt=\"$activity->type\"> ";
1854 echo "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=" . $activity->instance . "\">"
1855 . format_string($activity->name,true) . "</a> - ";
1856
1857 }
1858
1859 if (isteacher($course)) {
1860 $grades = "(" . $activity->content->grade . " / " . $activity->content->maxgrade . ") ";
1861
1862 $assignment->id = $activity->instance;
1863 $assignment->course = $course;
1864 $user->id = $activity->user->userid;
1865
1866 echo $grades;
1867 echo "<br />";
1868 }
1869 echo "<a href=\"$CFG->wwwroot/user/view.php?id="
1870 . $activity->user->userid . "&amp;course=$course\">"
1871 . $activity->user->fullname . "</a> ";
1872
1873 echo " - " . userdate($activity->timestamp);
1874
1875 echo "</font></td></tr>";
1876 echo "</table>";
1877
1878 return;
1879}
1880
1881/// GENERIC SQL FUNCTIONS
1882
1883function assignment_log_info($log) {
1884 global $CFG;
1885 return get_record_sql("SELECT a.name, u.firstname, u.lastname
1886 FROM {$CFG->prefix}assignment a,
1887 {$CFG->prefix}user u
1888 WHERE a.id = '$log->info'
1889 AND u.id = '$log->userid'");
1890}
1891
1892function assignment_get_unmailed_submissions($starttime, $endtime) {
1893/// Return list of marked submissions that have not been mailed out for currently enrolled students
1894 global $CFG;
1895 return get_records_sql("SELECT s.*, a.course, a.name
1896 FROM {$CFG->prefix}assignment_submissions s,
1897 {$CFG->prefix}assignment a,
1898 {$CFG->prefix}user_students us
1899 WHERE s.mailed = 0
1900 AND s.timemarked <= $endtime
1901 AND s.timemarked >= $starttime
1902 AND s.assignment = a.id
1903 AND s.userid = us.userid
1904 AND a.course = us.course");
1905}
1906
1907function assignment_count_real_submissions($assignment, $groupid=0) {
1908/// Return all real assignment submissions by ENROLLED students (not empty ones)
1909 global $CFG;
1910
1911 if ($groupid) { /// How many in a particular group?
1912 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
1913 FROM {$CFG->prefix}assignment_submissions a,
1914 {$CFG->prefix}groups_members g
1915 WHERE a.assignment = $assignment->id
1916 AND a.timemodified > 0
1917 AND g.groupid = '$groupid'
1918 AND a.userid = g.userid ");
1919 } else {
1920 $select = "s.course = '$assignment->course' AND";
1921 if ($assignment->course == SITEID) {
1922 $select = '';
1923 }
1924 return count_records_sql("SELECT COUNT(*)
1925 FROM {$CFG->prefix}assignment_submissions a,
1926 {$CFG->prefix}user_students s
1927 WHERE a.assignment = '$assignment->id'
1928 AND a.timemodified > 0
1929 AND $select a.userid = s.userid ");
1930 }
1931}
1932
1933function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") {
1934/// Return all assignment submissions by ENROLLED students (even empty)
1935 global $CFG;
1936
1937 if ($sort == "lastname" or $sort == "firstname") {
1938 $sort = "u.$sort $dir";
1939 } else if (empty($sort)) {
1940 $sort = "a.timemodified DESC";
1941 } else {
1942 $sort = "a.$sort $dir";
1943 }
1944
1945 $select = "s.course = '$assignment->course' AND";
1946 if ($assignment->course == SITEID) {
1947 $select = '';
1948 }
1949 return get_records_sql("SELECT a.*
1950 FROM {$CFG->prefix}assignment_submissions a,
1951 {$CFG->prefix}user_students s,
1952 {$CFG->prefix}user u
1953 WHERE a.userid = s.userid
1954 AND u.id = a.userid
1955 AND $select a.assignment = '$assignment->id'
1956 ORDER BY $sort");
1957}
1958
1959
1960
1961
1962/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS ///////////////////////////////////////
1963
1964
b0f2597e 1965function assignment_types() {
1966 $types = array();
1967 $names = get_list_of_plugins('mod/assignment/type');
1968 foreach ($names as $name) {
1969 $types[$name] = get_string('type'.$name, 'assignment');
ffeca120 1970 }
b0f2597e 1971 asort($types);
1972 return $types;
f466c9ed 1973}
1974
b0f2597e 1975function assignment_upgrade_submodules() {
f1c1d2f1 1976 global $CFG;
26b90e70 1977
b0f2597e 1978 $types = assignment_types();
26b90e70 1979
d175966b 1980 include($CFG->dirroot.'/mod/assignment/version.php'); // defines $module with version etc
26b90e70 1981
d175966b 1982 foreach ($types as $type => $typename) {
26b90e70 1983
b0f2597e 1984 $fullpath = $CFG->dirroot.'/mod/assignment/type/'.$type;
26b90e70 1985
b0f2597e 1986 /// Check for an external version file (defines $submodule)
26b90e70 1987
b0f2597e 1988 if (!is_readable($fullpath .'/version.php')) {
1989 continue;
ffeca120 1990 }
b0f2597e 1991 include_once($fullpath .'/version.php');
26b90e70 1992
b0f2597e 1993 /// Check whether we need to upgrade
26b90e70 1994
b0f2597e 1995 if (!isset($submodule->version)) {
1996 continue;
1997 }
26b90e70 1998
b0f2597e 1999 /// Make sure this submodule will work with this assignment version
26b90e70 2000
d175966b 2001 if (isset($submodule->requires) and ($submodule->requires > $module->version)) {
b0f2597e 2002 notify("Assignment submodule '$type' is too new for your assignment");
2003 continue;
2004 }
f466c9ed 2005
a86a538f 2006 /// If the submodule is new, then let's install it!
f466c9ed 2007
b0f2597e 2008 $currentversion = 'assignment_'.$type.'_version';
f466c9ed 2009
a86a538f 2010 if (!isset($CFG->$currentversion)) { // First install!
2011 set_config($currentversion, $submodule->version); // Must keep track of version
2012
2013 if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.sql')) {
2014 continue;
2015 }
2016
2017 $db->debug=true;
2018 if (!modify_database($fullpath .'/db/'.$CFG->dbtype.'.sql')) {
2019 notify("Error installing tables for submodule '$type'!");
2020 }
2021 $db->debug=false;
2022 continue;
f466c9ed 2023 }
f466c9ed 2024
b0f2597e 2025 /// See if we need to upgrade
2026
2027 if ($submodule->version <= $CFG->$currentversion) {
2028 continue;
59c005b7 2029 }
59c005b7 2030
b0f2597e 2031 /// Look for the upgrade file
59c005b7 2032
b0f2597e 2033 if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.php')) {
2034 continue;
2035 }
59c005b7 2036
b0f2597e 2037 include_once($fullpath .'/db/'. $CFG->dbtype .'.php'); // defines assignment_xxx_upgrade
59c005b7 2038
b0f2597e 2039 /// Perform the upgrade
59c005b7 2040
b0f2597e 2041 $upgrade_function = 'assignment_'.$type.'_upgrade';
2042 if (function_exists($upgrade_function)) {
2043 $db->debug=true;
2044 if ($upgrade_function($CFG->$currentversion)) {
2045 $db->debug=false;
2046 set_config($currentversion, $submodule->version);
59c005b7 2047 }
b0f2597e 2048 $db->debug=false;
59c005b7 2049 }
2050 }
2051}
2052
04eba58f 2053?>