DIsplay numerical grades with total grade: 9 / 10
[moodle.git] / mod / assignment / lib.php
CommitLineData
b0f2597e 1<?PHP // $Id$
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
d699cd1e 8
4909e176 9if (!isset($CFG->assignment_maxbytes)) {
10 set_config("assignment_maxbytes", 1024000); // Default maximum size for all assignments
04eba58f 11}
12
13
b0f2597e 14/*
15 * Standard base class for all assignment submodules (assignment types).
16 *
17 *
18 */
19class assignment_base {
20
21 var $cm;
22 var $course;
23 var $assignment;
24
25 /**
26 * Constructor for the base assignment class
27 *
28 * Constructor for the base assignment class.
29 * If cmid is set create the cm, course, assignment objects.
30 *
31 * @param cmid integer, the current course module id - not set for new assignments
73097f07 32 * @param assignment object, usually null, but if we have it we pass it to save db access
b0f2597e 33 */
73097f07 34 function assignment_base($cmid=0, $assignment=NULL, $cm=NULL, $course=NULL) {
b0f2597e 35
36 global $CFG;
37
38 if ($cmid) {
73097f07 39 if ($cm) {
40 $this->cm = $cm;
41 } else if (! $this->cm = get_record('course_modules', 'id', $cmid)) {
42 error('Course Module ID was incorrect');
b0f2597e 43 }
04eba58f 44
73097f07 45 if ($course) {
46 $this->course = $course;
47 } else if (! $this->course = get_record('course', 'id', $this->cm->course)) {
48 error('Course is misconfigured');
b0f2597e 49 }
04eba58f 50
73097f07 51 if ($assignment) {
52 $this->assignment = $assignment;
53 } else if (! $this->assignment = get_record('assignment', 'id', $this->cm->instance)) {
54 error('assignment ID was incorrect');
b0f2597e 55 }
e6a4906b 56
b0f2597e 57 $this->strassignment = get_string('modulename', 'assignment');
58 $this->strassignments = get_string('modulenameplural', 'assignment');
59 $this->strsubmissions = get_string('submissions', 'assignment');
60 $this->strlastmodified = get_string('lastmodified');
e6a4906b 61
b0f2597e 62 if ($this->course->category) {
63 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname}</a> -> ".
64 "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
65 } else {
66 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
67 }
e6a4906b 68
b0f2597e 69 $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.$this->assignment->name);
e6a4906b 70
b0f2597e 71 if (!$this->cm->visible and !isteacher($this->course->id)) {
72 $pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment);
73 print_header($pagetitle, $this->course->fullname, "$this->navigation $this->strassignment",
74 "", "", true, '', navmenu($this->course, $this->cm));
75 notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}");
76 }
77
78 $this->currentgroup = get_current_group($this->course->id);
73097f07 79 }
e6a4906b 80
73097f07 81 /// Set up things for a HTML editor if it's needed
82 if ($this->usehtmleditor = can_use_html_editor()) {
83 $this->defaultformat = FORMAT_HTML;
84 } else {
85 $this->defaultformat = FORMAT_MOODLE;
e6a4906b 86 }
73097f07 87
e6a4906b 88 }
89
b0f2597e 90 /*
91 * Display the assignment to students (sub-modules will most likely override this)
92 */
04eba58f 93
b0f2597e 94 function view() {
04eba58f 95
b0f2597e 96 add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}",
97 $this->assignment->id, $this->cm->id);
04eba58f 98
73097f07 99 $this->view_header();
04eba58f 100
b0f2597e 101 print_simple_box_start('center');
102 echo format_text($this->assignment->description, $this->assignment->format);
103 print_simple_box_end();
04eba58f 104
b0f2597e 105 print_simple_box_start('center', '', '', '', 'time');
106 echo '<table>';
107 echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
108 echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
109 echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
110 echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
111 echo '</table>';
b0f2597e 112 print_simple_box_end();
04eba58f 113
b0f2597e 114 $this->view_feedback();
115
116 print_footer($this->course);
36eb856f 117 }
118
73097f07 119 /*
120 * Display the top of the view.php page, this doesn't change much for submodules
121 */
122 function view_header($subpage='') {
123
124 global $CFG;
125
126 if ($subpage) {
127 $extranav = '<a target="'.$CFG->framename.'" href="view.php?id='.$this->cm->id.'">'.
128 $this->assignment->name.'</a> -> '.$subpage;
129 } else {
130 $extranav = ' '.$this->assignment->name;
131 }
132
133 print_header($this->pagetitle, $this->course->fullname, $this->navigation.$extranav, '', '',
134 true, update_module_button($this->cm->id, $this->course->id, $this->strassignment),
135 navmenu($this->course, $this->cm));
136
137 echo '<div class="reportlink">'.$this->submittedlink().'</div>';
138 }
139
140
141 /*
142 * Display the bottom of the view.php page, this doesn't change much for submodules
143 */
144 function view_footer() {
145 print_footer($this->course);
146 }
147
04eba58f 148
73097f07 149 function view_feedback($submission=NULL) {
b0f2597e 150 global $USER;
e6a4906b 151
73097f07 152 if (!$submission) { /// Get submission for this assignment
153 $submission = $this->get_submission($USER->id);
154 if (empty($submission->timemarked)) { /// Nothing to show, so print nothing
155 return;
156 }
9c48354d 157 }
e6a4906b 158
b0f2597e 159 /// We need the teacher info
160 if (! $teacher = get_record('user', 'id', $submission->teacher)) {
161 print_object($submission);
162 error('Could not find the teacher');
163 }
e6a4906b 164
b0f2597e 165 /// Print the feedback
6d4ecaec 166 print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher));
167
b0f2597e 168 echo '<table cellspacing="0" class="feedback">';
169
170 echo '<tr>';
171 echo '<td class="left picture">';
172 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
173 echo '</td>';
6d4ecaec 174 echo '<td class="topic">';
73097f07 175 echo '<div class="fullname">'.fullname($teacher).'</div>';
6d4ecaec 176 echo '<div class="time">'.userdate($submission->timemarked).'</div>';
b0f2597e 177 echo '</td>';
178 echo '</tr>';
179
180 echo '<tr>';
181 echo '<td class="left side">&nbsp;</td>';
6d4ecaec 182 echo '<td class="content">';
b0f2597e 183 if ($this->assignment->grade) {
6d4ecaec 184 echo '<div class="grade">';
b0f2597e 185 if ($submission->grade or $submission->timemarked) {
6d4ecaec 186 echo get_string("grade").': '.$this->display_grade($submission->grade);
b0f2597e 187 } else {
188 echo get_string("nograde");
189 }
6d4ecaec 190 echo '</div>';
e6a4906b 191 }
dcd338ff 192
6d4ecaec 193 echo '<div class="comment">';
b0f2597e 194 echo text_to_html($submission->comment);
6d4ecaec 195 echo '</div>';
b0f2597e 196 echo '</tr>';
197
198 echo '</table>';
e6a4906b 199 }
e6a4906b 200
201
77db7e4c 202
b0f2597e 203 /*
204 * Print the start of the setup form for the current assignment type
205 */
206 function setup(&$form, $action='') {
207 global $CFG, $THEME;
208
209 if (empty($this->course)) {
210 if (! $this->course = get_record("course", "id", $form->course)) {
211 error("Course is misconfigured");
77db7e4c 212 }
213 }
b0f2597e 214 if (empty($action)) { // Default destination for this form
215 $action = $CFG->wwwroot.'/course/mod.php';
216 }
77db7e4c 217
b0f2597e 218 if (empty($form->name)) {
219 $form->name = "";
220 }
221 if (empty($form->assignmenttype)) {
222 $form->assignmenttype = "";
223 }
224 if (empty($form->description)) {
225 $form->description = "";
226 }
77db7e4c 227
b0f2597e 228 $strname = get_string('name');
229 $strassignments = get_string('modulenameplural', 'assignment');
73097f07 230 $strheading = empty($form->name) ? get_string("type$form->assignmenttype",'assignment') : s($form->name);
77db7e4c 231
b0f2597e 232 print_header($this->course->shortname.': '.$strheading, "$strheading",
233 "<a href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname} </a> -> ".
234 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading");
77db7e4c 235
b0f2597e 236 print_simple_box_start("center");
237 print_heading(get_string("type$form->assignmenttype",'assignment'));
238 include("$CFG->dirroot/mod/assignment/type/common.html");
239 }
240
241 /*
242 * Print the end of the setup form for the current assignment type
243 */
244 function setup_end() {
73097f07 245 global $CFG;
b0f2597e 246
247 include($CFG->dirroot.'/mod/assignment/type/common_end.html');
77db7e4c 248
249 print_simple_box_end();
250
73097f07 251 if ($this->usehtmleditor) {
b0f2597e 252 use_html_editor();
253 }
254
255 print_footer($this->course);
77db7e4c 256 }
77db7e4c 257
258
b0f2597e 259 function add_instance($assignment) {
260 // Given an object containing all the necessary data,
261 // (defined by the form in mod.html) this function
262 // will create a new instance and return the id number
263 // of the new instance.
264
265 $assignment->timemodified = time();
266 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
267 $assignment->dueday, $assignment->duehour,
268 $assignment->dueminute);
269 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
270 $assignment->availableday, $assignment->availablehour,
271 $assignment->availableminute);
d699cd1e 272
b0f2597e 273 return insert_record("assignment", $assignment);
274 }
d699cd1e 275
b0f2597e 276 function delete_instance($assignment) {
277 if (! delete_records("assignment", "id", "$assignment->id")) {
278 $result = false;
279 }
280 return $result;
281 }
d699cd1e 282
b0f2597e 283 function update_instance($assignment) {
284 // Given an object containing all the necessary data,
285 // (defined by the form in mod.html) this function
286 // will create a new instance and return the id number
287 // of the new instance.
288
289 $assignment->timemodified = time();
290 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
291 $assignment->dueday, $assignment->duehour,
292 $assignment->dueminute);
293 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
294 $assignment->availableday, $assignment->availablehour,
295 $assignment->availableminute);
296 $assignment->id = $assignment->instance;
297 return update_record("assignment", $assignment);
298 }
299
300
301
302 /*
303 * Top-level function for handling of submissions called by submissions.php
304 *
305 */
306 function submissions($mode) {
307 switch ($mode) {
308 case 'grade': // We are in a popup window grading
309 if ($submission = $this->process_feedback()) {
310 print_heading(get_string('changessaved'));
be86672d 311 $this->update_main_listing($submission);
b0f2597e 312 }
313 close_window();
314 break;
9cc9b7c1 315
b0f2597e 316 case 'single': // We are in a popup window displaying submission
317 $this->display_submission();
318 break;
a56d79cd 319
b0f2597e 320 case 'all': // Main window, display everything
321 $this->display_submissions();
322 break;
a56d79cd 323 }
b0f2597e 324 }
a56d79cd 325
be86672d 326 function update_main_listing($submission) {
327 global $SESSION;
328
329 /// Run some Javascript to try and update the parent page
330 echo '<script type="text/javascript">'."\n<!--\n";
331 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['grade'])) {
332 echo 'opener.document.getElementById("g'.$submission->userid.
333 '").innerHTML="'.$this->display_grade($submission->grade)."\";\n";
334 }
335 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['comment'])) {
336 echo 'opener.document.getElementById("com'.$submission->userid.
337 '").innerHTML="'.shorten_text($submission->comment, 15)."\";\n";
338 }
73097f07 339 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemodified']) &&
340 $submission->timemodified) {
be86672d 341 echo 'opener.document.getElementById("ts'.$submission->userid.
342 '").innerHTML="'.userdate($submission->timemodified)."\";\n";
343 }
73097f07 344 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemarked']) &&
345 $submission->timemarked) {
be86672d 346 echo 'opener.document.getElementById("tt'.$submission->userid.
347 '").innerHTML="'.userdate($submission->timemarked)."\";\n";
348 }
349 if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['status'])) {
350 echo 'opener.document.getElementById("up'.$submission->userid.'").className="s1";';
6d4ecaec 351 echo 'opener.document.getElementById("button'.$submission->userid.'").value="'.get_string('update').' ...";';
be86672d 352 }
353 echo "\n-->\n</script>";
354 fflush();
355 }
d699cd1e 356
d59269cf 357 /*
358 * Display a grade in user-friendly form, whether it's a scale or not
359 *
360 */
361 function display_grade($grade) {
362
363 static $scalegrades; // Cached because we only have one per assignment
364
365 if ($this->assignment->grade >= 0) { // Normal number
3a3643df 366 return $grade.' / '.$this->assignment->grade;
d59269cf 367
368 } else { // Scale
369 if (empty($scalegrades)) {
370 if ($scale = get_record('scale', 'id', -($this->assignment->grade))) {
371 $scalegrades = make_menu_from_list($scale->scale);
372 } else {
373 return '-';
374 }
375 }
0f7d4e5e 376 if (isset($scalegrades[$grade])) {
377 return $scalegrades[$grade];
378 }
379 return '';
d59269cf 380 }
381 }
382
b0f2597e 383 /*
384 * Display a single submission, ready for grading on a popup window
385 *
386 */
387 function display_submission() {
b0f2597e 388
389 $userid = required_param('userid');
d699cd1e 390
b0f2597e 391 if (!$user = get_record('user', 'id', $userid)) {
392 error('No such user!');
393 }
d699cd1e 394
0f7d4e5e 395 if (!$submission = $this->get_submission($user->id, true)) { // Get one or make one
b0f2597e 396 error('Could not find submission!');
397 }
a5a4cd60 398
b0f2597e 399 if ($submission->timemodified > $submission->timemarked) {
400 $subtype = 'assignmentnew';
401 } else {
402 $subtype = 'assignmentold';
403 }
d699cd1e 404
b0f2597e 405 print_header($this->assignment->name.' '.fullname($user, true));
d699cd1e 406
d699cd1e 407
b0f2597e 408 echo '<table cellspacing="0" class="submission '.$subtype.'" >';
d699cd1e 409
b0f2597e 410 echo '<tr>';
411 echo '<td width="35" valign="top" class="picture user">';
412 print_user_picture($user->id, $this->course->id, $user->picture);
413 echo '</td>';
73097f07 414 echo '<td class="heading">';
415 echo '<div class="fullname">'.fullname($user, true).'</div>';
416 $this->print_user_files($user);
417 echo '</td>';
b0f2597e 418 echo '</tr>';
c69cb506 419
b0f2597e 420 echo '<tr>';
421 echo '<td width="35" valign="top" class="picture teacher">';
422 if ($submission->teacher) {
423 $teacher = get_record('user', 'id', $submission->teacher);
424 } else {
425 global $USER;
426 $teacher = $USER;
427 }
428 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
429 echo '</td>';
430 echo '<td class="content">';
d699cd1e 431
73097f07 432 echo '<form action="submissions.php" method="post">';
433 echo '<input type="hidden" name="userid" value="'.$userid.'">';
434 echo '<input type="hidden" name="id" value="'.$this->cm->id.'">';
435 echo '<input type="hidden" name="mode" value="grade">';
b0f2597e 436 if (!$submission->grade and !$submission->timemarked) {
437 $submission->grade = -1; /// Hack to stop zero being selected on the menu below (so it shows 'no grade')
438 }
439 echo get_string('feedback', 'assignment').':';
440 choose_from_menu(make_grades_menu($this->assignment->grade), 'grade',
441 $submission->grade, get_string('nograde'));
442
443 if ($submission->timemarked) {
444 echo '&nbsp;&nbsp;'.userdate($submission->timemarked);
d699cd1e 445 }
b0f2597e 446 echo '<br />';
73097f07 447 print_textarea($this->usehtmleditor, 10, 60, 0, 0, 'comment', $submission->comment, $this->course->id);
b0f2597e 448
73097f07 449 echo '<div class="buttons" align="center">';
b0f2597e 450 echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" />';
451 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
73097f07 452 echo '</div>';
453
b0f2597e 454 echo '</form>';
73097f07 455
456 echo '</td></tr>';
457 echo '</table>';
458
459
460 if ($this->usehtmleditor) {
461 use_html_editor();
462 }
463
b0f2597e 464 print_footer('none');
d699cd1e 465 }
466
d699cd1e 467
b0f2597e 468 /*
469 * Display all the submissions ready for grading
470 */
471 function display_submissions() {
3446205d 472
b0f2597e 473 global $CFG, $db;
3446205d 474
b0f2597e 475 $teacherattempts = true; /// Temporary measure
1b5910c4 476
b0f2597e 477 $page = optional_param('page', 0);
478 $perpage = optional_param('perpage', 10);
d699cd1e 479
b0f2597e 480 $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
d0ac6bc2 481
b0f2597e 482 /// Some shortcuts to make the code read better
483
484 $course = $this->course;
485 $assignment = $this->assignment;
486 $cm = $this->cm;
91719320 487
91719320 488
b0f2597e 489 add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id);
490
491 print_header_simple($this->assignment->name, "", '<a href="index.php?id='.$course->id.'">'.$this->strassignments.'</a> -> <a href="view.php?a='.$this->assignment->id.'">'.$this->assignment->name.'</a> -> '. $this->strsubmissions, '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm));
91719320 492
91719320 493
9437c854 494 $tablecolumns = array('picture', 'fullname', 'grade', 'comment', 'timemodified', 'timemarked', 'status');
495 $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 496
d0ac6bc2 497
b0f2597e 498 require_once($CFG->libdir.'/tablelib.php');
499 $table = new flexible_table('mod-assignment-submissions');
500
501 $table->define_columns($tablecolumns);
502 $table->define_headers($tableheaders);
503 $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id);
504
505 $table->sortable(true);
506 $table->collapsible(true);
507 $table->initialbars(true);
508
509 $table->column_suppress('picture');
510 $table->column_suppress('fullname');
511
512 $table->column_class('picture', 'picture');
9437c854 513 $table->column_class('fullname', 'fullname');
514 $table->column_class('grade', 'grade');
515 $table->column_class('comment', 'comment');
516 $table->column_class('timemodified', 'timemodified');
517 $table->column_class('timemarked', 'timemarked');
518 $table->column_class('status', 'status');
b0f2597e 519
520 $table->set_attribute('cellspacing', '0');
521 $table->set_attribute('id', 'attempts');
9437c854 522 $table->set_attribute('class', 'submissions');
b0f2597e 523 $table->set_attribute('width', '90%');
524 $table->set_attribute('align', 'center');
525
526 // Start working -- this is necessary as soon as the niceties are over
527 $table->setup();
528
05855091 529
05855091 530
b0f2597e 531 /// Check to see if groups are being used in this assignment
532 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
306dc7e5 533 $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
b0f2597e 534 } else {
535 $currentgroup = false;
05855091 536 }
05855091 537
0f1a97c2 538
b0f2597e 539 /// Get all teachers and students
540 if ($currentgroup) {
541 $users = get_group_users($currentgroup);
542 } else {
543 $users = get_course_users($course->id);
544 }
545
546 if (!$teacherattempts) {
547 $teachers = get_course_teachers($course->id);
548 if (!empty($teachers)) {
549 $keys = array_keys($teachers);
550 }
551 foreach ($keys as $key) {
552 unset($users[$key]);
553 }
554 }
555
556 if (empty($users)) {
557 print_heading($strnoattempts);
558 return true;
559 }
0f1a97c2 560
0f1a97c2 561
b0f2597e 562 /// Construct the SQL
0f1a97c2 563
b0f2597e 564 if ($where = $table->get_sql_where()) {
565 $where = str_replace('firstname', 'u.firstname', $where);
566 $where = str_replace('lastname', 'u.lastname', $where);
567 $where .= ' AND ';
568 }
0f1a97c2 569
b0f2597e 570 if ($sort = $table->get_sql_sort()) {
571 $sortparts = explode(',', $sort);
572 $newsort = array();
573 foreach ($sortparts as $sortpart) {
574 $sortpart = trim($sortpart);
575 $newsort[] = $sortpart;
576 }
577 $sort = ' ORDER BY '.implode(', ', $newsort);
578 }
9fa49e22 579
9fa49e22 580
9437c854 581 $select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('s.userid', '0')).' AS uvs, u.id, u.firstname, u.lastname, u.picture, s.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) && (s.timemarked >= s.timemodified)) AS status ';
d59269cf 582 $group = 'GROUP BY uvs ';
b0f2597e 583 $sql = 'FROM '.$CFG->prefix.'user u '.
306dc7e5 584 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment->id.' '.
585 'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') ';
8ff79e8c 586
8ff79e8c 587
d59269cf 588 $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('s.userid', '0')).')) '.$sql);
000cc405 589
b0f2597e 590 $table->pagesize($perpage, $total);
591
592 if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
593 $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
594 }
595 else {
596 $limit = '';
597 }
9fa49e22 598
b0f2597e 599 $strupdate = get_string('update');
9437c854 600 $strgrade = get_string('grade');
b0f2597e 601 $grademenu = make_grades_menu($this->assignment->grade);
602
9437c854 603 if (($ausers = get_records_sql($select.$sql.$group.$sort.$limit)) !== false) {
d59269cf 604
d59269cf 605 foreach ($ausers as $auser) {
606 $picture = print_user_picture($auser->id, $course->id, $auser->picture, false, true);
607 if (!empty($auser->submissionid)) {
608 if ($auser->timemodified > 0) {
609 $studentmodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>';
d59269cf 610 } else {
9437c854 611 $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
d59269cf 612 }
613 if ($auser->timemarked > 0) {
614 $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
b0f2597e 615 } else {
9437c854 616 $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
b0f2597e 617 }
9437c854 618
d59269cf 619 $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
9437c854 620 $comment = '<div id="com'.$auser->id.'">'.shorten_text($auser->comment, 15).'</div>';
d59269cf 621
b0f2597e 622 } else {
9437c854 623 $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
624 $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
d59269cf 625 $status = '<div id="st'.$auser->id.'"></div>';
9437c854 626 $grade = '<div id="g'.$auser->id.'">&nbsp;</div>';
627 $comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
b0f2597e 628 }
9fa49e22 629
0f7d4e5e 630 if ($auser->status === NULL) {
631 $auser->status = 0;
632 }
633
9437c854 634 $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
9fa49e22 635
9437c854 636 $button = button_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;userid='.$auser->id.'&amp;mode=single',
0f7d4e5e 637 'grade'.$auser->id, $buttontext, 450, 600, $buttontext, 'none', true, 'button'.$auser->id);
638
9437c854 639 $status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
306dc7e5 640
9437c854 641 $row = array($picture, fullname($auser), $grade, $comment, $studentmodified, $teachermodified, $status);
d59269cf 642 $table->add_data($row);
643 }
b0f2597e 644 }
d699cd1e 645
b0f2597e 646 $table->print_html();
d699cd1e 647
b0f2597e 648 print_footer($this->course);
d699cd1e 649
8e340cb0 650 }
d699cd1e 651
d699cd1e 652
d699cd1e 653
b0f2597e 654 /*
655 * Display and process the submissions
656 */
657 function process_feedback() {
d699cd1e 658
b0f2597e 659 global $USER;
d699cd1e 660
b0f2597e 661 if (!$feedback = data_submitted()) { // No incoming data?
662 return false;
d699cd1e 663 }
b7b42874 664
b0f2597e 665 if (!empty($feedback->cancel)) { // User hit cancel button
666 return false;
667 }
d699cd1e 668
0f7d4e5e 669 $newsubmission = $this->get_submission($feedback->userid, true); // Get or make one
d699cd1e 670
b0f2597e 671 $newsubmission->grade = $feedback->grade;
672 $newsubmission->comment = $feedback->comment;
673 $newsubmission->teacher = $USER->id;
674 $newsubmission->mailed = 0; // Make sure mail goes out (again, even)
675 $newsubmission->timemarked = time();
d699cd1e 676
b0f2597e 677 if (empty($submission->timemodified)) { // eg for offline assignments
678 $newsubmission->timemodified = time();
679 }
d699cd1e 680
b0f2597e 681 if (! update_record('assignment_submissions', $newsubmission)) {
682 return false;
683 }
d699cd1e 684
b0f2597e 685 add_to_log($this->course->id, 'assignment', 'update grades',
686 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
687
688 return $newsubmission;
d699cd1e 689
d699cd1e 690 }
d699cd1e 691
d699cd1e 692
0f7d4e5e 693 function get_submission($userid, $createnew=false) {
b0f2597e 694 $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
d699cd1e 695
b0f2597e 696 if ($submission || !$createnew) {
697 return $submission;
698 }
d699cd1e 699
b0f2597e 700 $newsubmission = new Object;
701 $newsubmission->assignment = $this->assignment->id;
702 $newsubmission->userid = $userid;
703 $newsubmission->timecreated = time();
704 if (!insert_record("assignment_submissions", $newsubmission)) {
705 error("Could not insert a new empty submission");
706 }
d699cd1e 707
b0f2597e 708 return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
709 }
d699cd1e 710
3f8247c2 711
b0f2597e 712 function get_submissions($sort='', $dir='DESC') {
713 /// Return all assignment submissions by ENROLLED students (even empty)
714 global $CFG;
715
716 if ($sort == "lastname" or $sort == "firstname") {
717 $sort = "u.$sort $dir";
718 } else if (empty($sort)) {
719 $sort = "a.timemodified DESC";
720 } else {
721 $sort = "a.$sort $dir";
d699cd1e 722 }
d699cd1e 723
b0f2597e 724 $select = "s.course = '$this->assignment->course' AND";
725 $site = get_site();
726 if ($this->assignment->course == $site->id) {
727 $select = '';
728 }
729 return get_records_sql("SELECT a.*
730 FROM {$CFG->prefix}assignment_submissions a,
731 {$CFG->prefix}user_students s,
732 {$CFG->prefix}user u
733 WHERE a.userid = s.userid
734 AND u.id = a.userid
735 AND $select a.assignment = '$this->assignment->id'
736 ORDER BY $sort");
737 }
738
739
740 function count_real_submissions($groupid=0) {
741 /// Return all real assignment submissions by ENROLLED students (not empty ones)
742 global $CFG;
743
744 if ($groupid) { /// How many in a particular group?
745 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
746 FROM {$CFG->prefix}assignment_submissions a,
747 {$CFG->prefix}groups_members g
748 WHERE a.assignment = {$this->assignment->id}
749 AND a.timemodified > 0
750 AND g.groupid = '$groupid'
751 AND a.userid = g.userid ");
752 } else {
753 $select = "s.course = '{$this->assignment->course}' AND";
754 if ($this->assignment->course == SITEID) {
755 $select = '';
d699cd1e 756 }
b0f2597e 757 return count_records_sql("SELECT COUNT(*)
758 FROM {$CFG->prefix}assignment_submissions a,
759 {$CFG->prefix}user_students s
760 WHERE a.assignment = '{$this->assignment->id}'
761 AND a.timemodified > 0
762 AND $select a.userid = s.userid ");
763 }
d59269cf 764 }
d699cd1e 765
73097f07 766 function email_teachers($submission) {
767 /// Alerts teachers by email of new or changed assignments that need grading
768
769 global $CFG;
770
771 if (empty($assignment->emailteachers)) { // No need to do anything
772 return;
773 }
774
775 $user = get_record('user', 'id', $submission->userid);
776
777 $course = $this->course; // Shortcuts
778 $assignment = $this->assignment;
779 $cm = $this->cm;
780
781 if (groupmode($course, $cm) == SEPARATEGROUPS) { // Separate groups are being used
782 if (!$group = user_group($course->id, $user->id)) { // Try to find a group
783 $group->id = 0; // Not in a group, never mind
784 }
785 $teachers = get_group_teachers($course->id, $group->id); // Works even if not in group
786 } else {
787 $teachers = get_course_teachers($course->id);
788 }
789
790 if ($teachers) {
791
792 $strassignments = get_string('modulenameplural', 'assignment');
793 $strassignment = get_string('modulename', 'assignment');
794 $strsubmitted = get_string('submitted', 'assignment');
795
796 foreach ($teachers as $teacher) {
797 unset($info);
798 $info->username = fullname($user);
799 $info->assignment = format_string($assignment->name,true);
800 $info->url = "$CFG->wwwroot/mod/assignment/submissions.php?id=$assignment->id";
801
802 $postsubject = "$strsubmitted: $info->username -> $assignment->name";
803 $posttext = "$course->shortname -> $strassignments -> ".format_string($assignment->name,true)."\n";
804 $posttext .= "---------------------------------------------------------------------\n";
805 $posttext .= get_string("emailteachermail", "assignment", $info);
806 $posttext .= "\n---------------------------------------------------------------------\n";
807
808 if ($user->mailformat == 1) { // HTML
809 $posthtml = "<p><font face=\"sans-serif\">".
810 "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
811 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
812 "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$cm->id\">".format_string($assignment->name,true)."</a></font></p>";
813 $posthtml .= "<hr /><font face=\"sans-serif\">";
814 $posthtml .= "<p>".get_string("emailteachermailhtml", "assignment", $info)."</p>";
815 $posthtml .= "</font><hr />";
816 } else {
817 $posthtml = "";
818 }
819
820 @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
821 }
822 }
823 }
824
825 function print_user_files($user, $return=false) {
826
827 global $CFG;
828
829 $filearea = $this->file_area_name($user);
830
831 $output = '';
832
833 if ($basedir = $this->file_area($user)) {
834 if ($files = get_directory_list($basedir)) {
835 foreach ($files as $key => $file) {
836 require_once($CFG->libdir.'/filelib.php');
837 $icon = mimeinfo('icon', $file);
838 if ($CFG->slasharguments) {
839 $ffurl = "file.php/$filearea/$file";
840 } else {
841 $ffurl = "file.php?file=/$filearea/$file";
842 }
843
844 $output = '<img align="middle" src="'.$CFG->pixpath.'/f/'.$icon.'" height="16" width="16" alt="'.$icon.'" />'.
845 link_to_popup_window ('/'.$ffurl, 'file'.$key, $file, 450, 580, $file, 'none', true).
846 '<br />';
847 }
848 }
849 }
850
851 $output = '<div class="files">'.$output.'</div>';
852
853 if ($return) {
854 return $output;
855 }
856 echo $output;
857 }
858
859
860 function file_area_name($user) {
861 // Creates a directory file name, suitable for make_upload_directory()
862 global $CFG;
863
864 return $this->course->id.'/'.$CFG->moddata.'/assignment/'.$this->assignment->id.'/'.$user->id;
865 }
866
867 function file_area($user) {
868 return make_upload_directory( $this->file_area_name($user) );
869 }
870
871 function user_outline($user) {
872 if ($submission = $this->get_submission($user->id)) {
873
874 if ($submission->grade) {
875 $result->info = get_string("grade").": $submission->grade";
876 }
877 $result->time = $submission->timemodified;
878 return $result;
879 }
880 return NULL;
881 }
882
883 function user_complete($user) {
884 if ($submission = $this->get_submission($user->id)) {
885 if ($basedir = $this->file_area($user)) {
886 if ($files = get_directory_list($basedir)) {
887 $countfiles = count($files)." ".get_string("uploadedfiles", "assignment");
888 foreach ($files as $file) {
889 $countfiles .= "; $file";
890 }
891 }
892 }
893
894 print_simple_box_start();
895 echo get_string("lastmodified").": ";
896 echo userdate($submission->timemodified);
897 echo $this->display_lateness($this->assignment->timedue - $this->submission->timemodified);
898
899 $this->print_user_files($user);
900
901 echo '<br />';
902
903 if (empty($submission->timemarked)) {
904 print_string("notgradedyet", "assignment");
905 } else {
906 $this->view_feedback($submission);
907 }
908
909 print_simple_box_end();
910
911 } else {
912 print_string("notsubmittedyet", "assignment");
913 }
914 }
915
916 function display_lateness($time) {
917 if ($time < 0) {
918 $timetext = get_string('late', 'assignment', format_time($time));
919 return ' (<span class="timelate">'.$timetext.'</span>)';
920 } else {
921 $timetext = get_string('early', 'assignment', format_time($time));
922 return ' (<span class="timeearly">'.$timetext.'</span>)';
923 }
924 }
925
926
927
928
929
b0f2597e 930} ////// End of the assignment_base class
d699cd1e 931
18b8fbfa 932
04eba58f 933
b0f2597e 934/// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////
935
936
937function assignment_delete_instance($id){
26b90e70 938 global $CFG;
939
b0f2597e 940 if (! $assignment = get_record('assignment', 'id', $id)) {
941 return false;
26b90e70 942 }
943
b0f2597e 944 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
945 $assignmentclass = "assignment_$assignment->assignmenttype";
946 $ass = new $assignmentclass();
947 return $ass->delete_instance($assignment);
948}
f466c9ed 949
ac21ad39 950
b0f2597e 951function assignment_update_instance($assignment){
952 global $CFG;
26b90e70 953
b0f2597e 954 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
955 $assignmentclass = "assignment_$assignment->assignmenttype";
956 $ass = new $assignmentclass();
957 return $ass->update_instance($assignment);
958}
26b90e70 959
26b90e70 960
b0f2597e 961function assignment_add_instance($assignment) {
962 global $CFG;
f466c9ed 963
b0f2597e 964 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
965 $assignmentclass = "assignment_$assignment->assignmenttype";
966 $ass = new $assignmentclass();
967 return $ass->add_instance($assignment);
968}
f466c9ed 969
73097f07 970
971function assignment_user_outline($course, $user, $mod, $assignment) {
972 global $CFG;
973
974 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
975 $assignmentclass = "assignment_$assignment->assignmenttype";
976 $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
977 return $ass->user_outline($user);
978}
979
980function assignment_user_complete($course, $user, $mod, $assignment) {
981 global $CFG;
982
983 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
984 $assignmentclass = "assignment_$assignment->assignmenttype";
985 $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
986 return $ass->user_complete($user);
987}
988
989
990function assignment_cron () {
991// Function to be run periodically according to the moodle cron
992// Finds all assignment notifications that have yet to be mailed out, and mails them
993
994 global $CFG, $USER;
995
996 /// Notices older than 1 day will not be mailed. This is to avoid the problem where
997 /// cron has not been running for a long time, and then suddenly people are flooded
998 /// with mail from the past few weeks or months
999
1000 $timenow = time();
1001 $endtime = $timenow - $CFG->maxeditingtime;
1002 $starttime = $endtime - 24 * 3600; /// One day earlier
1003
1004 if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) {
1005
1006 foreach ($submissions as $key => $submission) {
1007 if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) {
1008 echo "Could not update the mailed field for id $submission->id. Not mailed.\n";
1009 unset($submissions[$key]);
1010 }
1011 }
1012
1013 $timenow = time();
1014
1015 foreach ($submissions as $submission) {
1016
1017 echo "Processing assignment submission $submission->id\n";
1018
1019 if (! $user = get_record("user", "id", "$submission->userid")) {
1020 echo "Could not find user $post->userid\n";
1021 continue;
1022 }
1023
1024 $USER->lang = $user->lang;
1025
1026 if (! $course = get_record("course", "id", "$submission->course")) {
1027 echo "Could not find course $submission->course\n";
1028 continue;
1029 }
1030
1031 if (! isstudent($course->id, $user->id) and !isteacher($course->id, $user->id)) {
1032 echo fullname($user)." not an active participant in $course->shortname\n";
1033 continue;
1034 }
1035
1036 if (! $teacher = get_record("user", "id", "$submission->teacher")) {
1037 echo "Could not find teacher $submission->teacher\n";
1038 continue;
1039 }
1040
1041 if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment, $course->id)) {
1042 echo "Could not find course module for assignment id $submission->assignment\n";
1043 continue;
1044 }
1045
1046 if (! $mod->visible) { /// Hold mail notification for hidden assignments until later
1047 continue;
1048 }
1049
1050 $strassignments = get_string("modulenameplural", "assignment");
1051 $strassignment = get_string("modulename", "assignment");
1052
1053 unset($assignmentinfo);
1054 $assignmentinfo->teacher = fullname($teacher);
1055 $assignmentinfo->assignment = format_string($submission->name,true);
1056 $assignmentinfo->url = "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id";
1057
1058 $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true);
1059 $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n";
1060 $posttext .= "---------------------------------------------------------------------\n";
1061 $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo);
1062 $posttext .= "---------------------------------------------------------------------\n";
1063
1064 if ($user->mailformat == 1) { // HTML
1065 $posthtml = "<p><font face=\"sans-serif\">".
1066 "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
1067 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
1068 "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."</a></font></p>";
1069 $posthtml .= "<hr /><font face=\"sans-serif\">";
1070 $posthtml .= "<p>".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."</p>";
1071 $posthtml .= "</font><hr />";
1072 } else {
1073 $posthtml = "";
1074 }
1075
1076 if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) {
1077 echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n";
1078 }
1079 }
1080 }
1081
1082 return true;
1083}
1084
1085function assignment_grades($assignmentid) {
1086/// Must return an array of grades, indexed by user, and a max grade.
1087
1088
1089 if (!$assignment = get_record("assignment", "id", $assignmentid)) {
1090 return NULL;
1091 }
1092
1093 $grades = get_records_menu("assignment_submissions", "assignment",
1094 $assignment->id, "", "userid,grade");
1095
1096 if ($assignment->grade >= 0) {
1097 $return->grades = $grades;
1098 $return->maxgrade = $assignment->grade;
1099
1100 } else { // Scale
1101 if ($grades) {
1102 $scaleid = - ($assignment->grade);
1103 if ($scale = get_record('scale', 'id', $scaleid)) {
1104 $scalegrades = make_menu_from_list($scale->scale);
1105 foreach ($grades as $key => $grade) {
1106 $grades[$key] = $scalegrades[$grade];
1107 }
1108 }
1109 }
1110 $return->grades = $grades;
1111 $return->maxgrade = "";
1112 }
1113
1114 return $return;
1115}
1116
1117function assignment_get_participants($assignmentid) {
1118//Returns the users with data in one assignment
1119//(users with records in assignment_submissions, students and teachers)
1120
1121 global $CFG;
1122
1123 //Get students
1124 $students = get_records_sql("SELECT DISTINCT u.id, u.id
1125 FROM {$CFG->prefix}user u,
1126 {$CFG->prefix}assignment_submissions a
1127 WHERE a.assignment = '$assignmentid' and
1128 u.id = a.userid");
1129 //Get teachers
1130 $teachers = get_records_sql("SELECT DISTINCT u.id, u.id
1131 FROM {$CFG->prefix}user u,
1132 {$CFG->prefix}assignment_submissions a
1133 WHERE a.assignment = '$assignmentid' and
1134 u.id = a.teacher");
1135
1136 //Add teachers to students
1137 if ($teachers) {
1138 foreach ($teachers as $teacher) {
1139 $students[$teacher->id] = $teacher;
1140 }
1141 }
1142 //Return students array (it contains an array of unique users)
1143 return ($students);
1144}
1145
1146
1147function assignment_scale_used ($assignmentid,$scaleid) {
1148//This function returns if a scale is being used by one assignment
1149
1150 $return = false;
1151
1152 $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid);
1153
1154 if (!empty($rec) && !empty($scaleid)) {
1155 $return = true;
1156 }
1157
1158 return $return;
1159}
1160
1161
1162function assignment_refresh_events($courseid = 0) {
1163// This standard function will check all instances of this module
1164// and make sure there are up-to-date events created for each of them.
1165// If courseid = 0, then every assignment event in the site is checked, else
1166// only assignment events belonging to the course specified are checked.
1167// This function is used, in its new format, by restore_refresh_events()
1168
1169 if ($courseid == 0) {
1170 if (! $assignments = get_records("assignment")) {
1171 return true;
1172 }
1173 } else {
1174 if (! $assignments = get_records("assignment", "course", $courseid)) {
1175 return true;
1176 }
1177 }
1178 $moduleid = get_field('modules', 'id', 'name', 'assignment');
1179
1180 foreach ($assignments as $assignment) {
1181 $event = NULL;
1182 $event->name = addslashes($assignment->name);
1183 $event->description = addslashes($assignment->description);
1184 $event->timestart = $assignment->timedue;
1185
1186 if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) {
1187 update_event($event);
1188
1189 } else {
1190 $event->courseid = $assignment->course;
1191 $event->groupid = 0;
1192 $event->userid = 0;
1193 $event->modulename = 'assignment';
1194 $event->instance = $assignment->id;
1195 $event->eventtype = 'due';
1196 $event->timeduration = 0;
1197 $event->visible = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id);
1198 add_event($event);
1199 }
1200
1201 }
1202 return true;
1203}
1204
1205
1206function assignment_print_recent_activity($course, $isteacher, $timestart) {
1207 global $CFG;
1208
1209 $content = false;
1210 $assignments = NULL;
1211
1212 if (!$logs = get_records_select('log', 'time > \''.$timestart.'\' AND '.
1213 'course = \''.$course->id.'\' AND '.
1214 'module = \'assignment\' AND '.
1215 'action = \'upload\' ', 'time ASC')) {
1216 return false;
1217 }
1218
1219 foreach ($logs as $log) {
1220 //Create a temp valid module structure (course,id)
1221 $tempmod->course = $log->course;
1222 $tempmod->id = $log->info;
1223 //Obtain the visible property from the instance
1224 $modvisible = instance_is_visible($log->module,$tempmod);
1225
1226 //Only if the mod is visible
1227 if ($modvisible) {
1228 $assignments[$log->info] = assignment_log_info($log);
1229 $assignments[$log->info]->time = $log->time;
1230 $assignments[$log->info]->url = str_replace('&', '&amp;', $log->url);
1231 }
1232 }
1233
1234 if ($assignments) {
1235 print_headline(get_string('newsubmissions', 'assignment').':');
1236 foreach ($assignments as $assignment) {
1237 print_recent_activity_note($assignment->time, $assignment, $isteacher, $assignment->name,
1238 $CFG->wwwroot.'/mod/assignment/'.$assignment->url);
1239 }
1240 $content = true;
1241 }
1242
1243 return $content;
1244}
1245
1246
1247
1248function assignment_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $assignment="0", $user="", $groupid="") {
1249// Returns all assignments since a given time. If assignment is specified then
1250// this restricts the results
1251
1252 global $CFG;
1253
1254 if ($assignment) {
1255 $assignmentselect = " AND cm.id = '$assignment'";
1256 } else {
1257 $assignmentselect = "";
1258 }
1259 if ($user) {
1260 $userselect = " AND u.id = '$user'";
1261 } else {
1262 $userselect = "";
1263 }
1264
1265 $assignments = get_records_sql("SELECT asub.*, u.firstname, u.lastname, u.picture, u.id as userid,
1266 a.grade as maxgrade, name, cm.instance, cm.section, a.assignmenttype
1267 FROM {$CFG->prefix}assignment_submissions asub,
1268 {$CFG->prefix}user u,
1269 {$CFG->prefix}assignment a,
1270 {$CFG->prefix}course_modules cm
1271 WHERE asub.timemodified > '$sincetime'
1272 AND asub.userid = u.id $userselect
1273 AND a.id = asub.assignment $assignmentselect
1274 AND cm.course = '$courseid'
1275 AND cm.instance = a.id
1276 ORDER BY asub.timemodified ASC");
1277
1278 if (empty($assignments))
1279 return;
1280
1281 foreach ($assignments as $assignment) {
1282 if (empty($groupid) || ismember($groupid, $assignment->userid)) {
1283
1284 $tmpactivity = new Object;
1285
1286 $tmpactivity->type = "assignment";
1287 $tmpactivity->defaultindex = $index;
1288 $tmpactivity->instance = $assignment->instance;
1289 $tmpactivity->name = $assignment->name;
1290 $tmpactivity->section = $assignment->section;
1291
1292 $tmpactivity->content->grade = $assignment->grade;
1293 $tmpactivity->content->maxgrade = $assignment->maxgrade;
1294 $tmpactivity->content->type = $assignment->assignmenttype;
1295
1296 $tmpactivity->user->userid = $assignment->userid;
1297 $tmpactivity->user->fullname = fullname($assignment);
1298 $tmpactivity->user->picture = $assignment->picture;
1299
1300 $tmpactivity->timestamp = $assignment->timemodified;
1301
1302 $activities[] = $tmpactivity;
1303
1304 $index++;
1305 }
1306 }
1307
1308 return;
1309}
1310
1311
1312function assignment_print_recent_mod_activity($activity, $course, $detail=false) {
1313 global $CFG;
1314
1315 echo '<table border="0" cellpadding="3" cellspacing="0">';
1316
1317 echo "<tr><td class=\"userpicture\" width=\"35\" valign=\"top\">";
1318 print_user_picture($activity->user->userid, $course, $activity->user->picture);
1319 echo "</td><td width=\"100%\"><font size=2>";
1320
1321 if ($detail) {
1322 echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
1323 "height=16 width=16 alt=\"$activity->type\"> ";
1324 echo "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=" . $activity->instance . "\">"
1325 . format_string($activity->name,true) . "</a> - ";
1326
1327 }
1328
1329 if (isteacher($course)) {
1330 $grades = "(" . $activity->content->grade . " / " . $activity->content->maxgrade . ") ";
1331
1332 $assignment->id = $activity->instance;
1333 $assignment->course = $course;
1334 $user->id = $activity->user->userid;
1335
1336 echo $grades;
1337 echo "<br />";
1338 }
1339 echo "<a href=\"$CFG->wwwroot/user/view.php?id="
1340 . $activity->user->userid . "&amp;course=$course\">"
1341 . $activity->user->fullname . "</a> ";
1342
1343 echo " - " . userdate($activity->timestamp);
1344
1345 echo "</font></td></tr>";
1346 echo "</table>";
1347
1348 return;
1349}
1350
1351/// GENERIC SQL FUNCTIONS
1352
1353function assignment_log_info($log) {
1354 global $CFG;
1355 return get_record_sql("SELECT a.name, u.firstname, u.lastname
1356 FROM {$CFG->prefix}assignment a,
1357 {$CFG->prefix}user u
1358 WHERE a.id = '$log->info'
1359 AND u.id = '$log->userid'");
1360}
1361
1362function assignment_get_unmailed_submissions($starttime, $endtime) {
1363/// Return list of marked submissions that have not been mailed out for currently enrolled students
1364 global $CFG;
1365 return get_records_sql("SELECT s.*, a.course, a.name
1366 FROM {$CFG->prefix}assignment_submissions s,
1367 {$CFG->prefix}assignment a,
1368 {$CFG->prefix}user_students us
1369 WHERE s.mailed = 0
1370 AND s.timemarked <= $endtime
1371 AND s.timemarked >= $starttime
1372 AND s.assignment = a.id
1373 AND s.userid = us.userid
1374 AND a.course = us.course");
1375}
1376
1377function assignment_count_real_submissions($assignment, $groupid=0) {
1378/// Return all real assignment submissions by ENROLLED students (not empty ones)
1379 global $CFG;
1380
1381 if ($groupid) { /// How many in a particular group?
1382 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
1383 FROM {$CFG->prefix}assignment_submissions a,
1384 {$CFG->prefix}groups_members g
1385 WHERE a.assignment = $assignment->id
1386 AND a.timemodified > 0
1387 AND g.groupid = '$groupid'
1388 AND a.userid = g.userid ");
1389 } else {
1390 $select = "s.course = '$assignment->course' AND";
1391 if ($assignment->course == SITEID) {
1392 $select = '';
1393 }
1394 return count_records_sql("SELECT COUNT(*)
1395 FROM {$CFG->prefix}assignment_submissions a,
1396 {$CFG->prefix}user_students s
1397 WHERE a.assignment = '$assignment->id'
1398 AND a.timemodified > 0
1399 AND $select a.userid = s.userid ");
1400 }
1401}
1402
1403function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") {
1404/// Return all assignment submissions by ENROLLED students (even empty)
1405 global $CFG;
1406
1407 if ($sort == "lastname" or $sort == "firstname") {
1408 $sort = "u.$sort $dir";
1409 } else if (empty($sort)) {
1410 $sort = "a.timemodified DESC";
1411 } else {
1412 $sort = "a.$sort $dir";
1413 }
1414
1415 $select = "s.course = '$assignment->course' AND";
1416 if ($assignment->course == SITEID) {
1417 $select = '';
1418 }
1419 return get_records_sql("SELECT a.*
1420 FROM {$CFG->prefix}assignment_submissions a,
1421 {$CFG->prefix}user_students s,
1422 {$CFG->prefix}user u
1423 WHERE a.userid = s.userid
1424 AND u.id = a.userid
1425 AND $select a.assignment = '$assignment->id'
1426 ORDER BY $sort");
1427}
1428
1429
1430
1431
1432/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS ///////////////////////////////////////
1433
1434
b0f2597e 1435function assignment_types() {
1436 $types = array();
1437 $names = get_list_of_plugins('mod/assignment/type');
1438 foreach ($names as $name) {
1439 $types[$name] = get_string('type'.$name, 'assignment');
ffeca120 1440 }
b0f2597e 1441 asort($types);
1442 return $types;
f466c9ed 1443}
1444
b0f2597e 1445function assignment_upgrade_submodules() {
f1c1d2f1 1446 global $CFG;
26b90e70 1447
b0f2597e 1448 $types = assignment_types();
26b90e70 1449
b0f2597e 1450 include_once($CFG->dirroot.'/mod/assignment/version.php'); // defines $module with version etc
26b90e70 1451
b0f2597e 1452 foreach ($types as $type) {
26b90e70 1453
b0f2597e 1454 $fullpath = $CFG->dirroot.'/mod/assignment/type/'.$type;
26b90e70 1455
b0f2597e 1456 /// Check for an external version file (defines $submodule)
26b90e70 1457
b0f2597e 1458 if (!is_readable($fullpath .'/version.php')) {
1459 continue;
ffeca120 1460 }
b0f2597e 1461 unset($module);
1462 include_once($fullpath .'/version.php');
26b90e70 1463
b0f2597e 1464 /// Check whether we need to upgrade
26b90e70 1465
b0f2597e 1466 if (!isset($submodule->version)) {
1467 continue;
1468 }
26b90e70 1469
b0f2597e 1470 /// Make sure this submodule will work with this assignment version
26b90e70 1471
b0f2597e 1472 if (isset($submodule->requires) and ($submodules->requires > $module->version)) {
1473 notify("Assignment submodule '$type' is too new for your assignment");
1474 continue;
1475 }
f466c9ed 1476
b0f2597e 1477 /// If we use versions, make sure an internal record exists
f466c9ed 1478
b0f2597e 1479 $currentversion = 'assignment_'.$type.'_version';
f466c9ed 1480
b0f2597e 1481 if (!isset($CFG->$currentversion)) {
1482 set_config($currentversion, 0);
f466c9ed 1483 }
f466c9ed 1484
b0f2597e 1485 /// See if we need to upgrade
1486
1487 if ($submodule->version <= $CFG->$currentversion) {
1488 continue;
59c005b7 1489 }
59c005b7 1490
b0f2597e 1491 /// Look for the upgrade file
59c005b7 1492
b0f2597e 1493 if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.php')) {
1494 continue;
1495 }
59c005b7 1496
b0f2597e 1497 include_once($fullpath .'/db/'. $CFG->dbtype .'.php'); // defines assignment_xxx_upgrade
59c005b7 1498
b0f2597e 1499 /// Perform the upgrade
59c005b7 1500
b0f2597e 1501 $upgrade_function = 'assignment_'.$type.'_upgrade';
1502 if (function_exists($upgrade_function)) {
1503 $db->debug=true;
1504 if ($upgrade_function($CFG->$currentversion)) {
1505 $db->debug=false;
1506 set_config($currentversion, $submodule->version);
59c005b7 1507 }
b0f2597e 1508 $db->debug=false;
59c005b7 1509 }
1510 }
9437c854 1511
1512
59c005b7 1513}
1514
04eba58f 1515?>