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