Added explanation about editing quizzes that have already been attempted by students...
[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
32 */
33 function assignment_base($cmid=0) {
34
35 global $CFG;
36
37 if ($cmid) {
38 if (! $this->cm = get_record("course_modules", "id", $cmid)) {
39 error("Course Module ID was incorrect");
40 }
04eba58f 41
b0f2597e 42 if (! $this->course = get_record("course", "id", $this->cm->course)) {
43 error("Course is misconfigured");
44 }
04eba58f 45
b0f2597e 46 if (! $this->assignment = get_record("assignment", "id", $this->cm->instance)) {
47 error("assignment ID was incorrect");
48 }
e6a4906b 49
b0f2597e 50 $this->strassignment = get_string('modulename', 'assignment');
51 $this->strassignments = get_string('modulenameplural', 'assignment');
52 $this->strsubmissions = get_string('submissions', 'assignment');
53 $this->strlastmodified = get_string('lastmodified');
e6a4906b 54
b0f2597e 55 if ($this->course->category) {
56 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname}</a> -> ".
57 "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
58 } else {
59 $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
60 }
e6a4906b 61
b0f2597e 62 $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.$this->assignment->name);
e6a4906b 63
b0f2597e 64 if (!$this->cm->visible and !isteacher($this->course->id)) {
65 $pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment);
66 print_header($pagetitle, $this->course->fullname, "$this->navigation $this->strassignment",
67 "", "", true, '', navmenu($this->course, $this->cm));
68 notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}");
69 }
70
71 $this->currentgroup = get_current_group($this->course->id);
e6a4906b 72
e6a4906b 73 }
74 }
75
b0f2597e 76 /*
77 * Display the assignment to students (sub-modules will most likely override this)
78 */
04eba58f 79
b0f2597e 80 function view() {
81 global $CFG;
04eba58f 82
b0f2597e 83 add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}",
84 $this->assignment->id, $this->cm->id);
04eba58f 85
b0f2597e 86 print_header($this->pagetitle, $this->course->fullname, $this->navigation.' '.$this->assignment->name, '', '',
87 true, update_module_button($this->cm->id, $this->course->id, $this->strassignment),
88 navmenu($this->course, $this->cm));
04eba58f 89
b0f2597e 90 echo '<div class="reportlink">'.$this->submittedlink().'</div>';
04eba58f 91
b0f2597e 92 print_simple_box_start('center');
93 echo format_text($this->assignment->description, $this->assignment->format);
94 print_simple_box_end();
04eba58f 95
b0f2597e 96 print_simple_box_start('center', '', '', '', 'time');
97 echo '<table>';
98 echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
99 echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
100 echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
101 echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
102 echo '</table>';
103
104 print_simple_box_end();
04eba58f 105
b0f2597e 106 $this->view_feedback();
107
108 print_footer($this->course);
36eb856f 109 }
110
04eba58f 111
b0f2597e 112 function view_feedback() {
113 global $USER;
e6a4906b 114
b0f2597e 115 /// Get submission for this assignment
116 /// If no submission then just return quietly
117 $submission = $this->get_submission($USER->id);
118 if (empty($submission->timemarked)) {
119 return;
9c48354d 120 }
e6a4906b 121
b0f2597e 122 /// We need the teacher info
123 if (! $teacher = get_record('user', 'id', $submission->teacher)) {
124 print_object($submission);
125 error('Could not find the teacher');
126 }
e6a4906b 127
b0f2597e 128 /// Print the feedback
129 echo '<table cellspacing="0" class="feedback">';
130
131 echo '<tr>';
132 echo '<td class="left picture">';
133 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
134 echo '</td>';
135 echo '<td class="feedbackheader">';
136 echo '<span class="author">'.fullname($teacher).'</span>';
137 echo '<span class="time">'.userdate($submission->timemarked).'</span>';
138 echo '</td>';
139 echo '</tr>';
140
141 echo '<tr>';
142 echo '<td class="left side">&nbsp;</td>';
143 echo '<td class="feedback">';
144 if ($this->assignment->grade) {
145 echo '<span class="grade">';
146 if ($submission->grade or $submission->timemarked) {
147 echo get_string("grade").": $submission->grade";
148 } else {
149 echo get_string("nograde");
150 }
151 echo '</span>';
e6a4906b 152 }
dcd338ff 153
b0f2597e 154 echo text_to_html($submission->comment);
155 echo '</tr>';
156
157 echo '</table>';
e6a4906b 158 }
e6a4906b 159
160
77db7e4c 161
b0f2597e 162 /*
163 * Print the start of the setup form for the current assignment type
164 */
165 function setup(&$form, $action='') {
166 global $CFG, $THEME;
167
168 if (empty($this->course)) {
169 if (! $this->course = get_record("course", "id", $form->course)) {
170 error("Course is misconfigured");
77db7e4c 171 }
172 }
b0f2597e 173 if (empty($action)) { // Default destination for this form
174 $action = $CFG->wwwroot.'/course/mod.php';
175 }
77db7e4c 176
b0f2597e 177 if (empty($form->name)) {
178 $form->name = "";
179 }
180 if (empty($form->assignmenttype)) {
181 $form->assignmenttype = "";
182 }
183 if (empty($form->description)) {
184 $form->description = "";
185 }
77db7e4c 186
b0f2597e 187 $strname = get_string('name');
188 $strassignments = get_string('modulenameplural', 'assignment');
189 $strheading = empty($form->name) ? get_string("type$form->assignmenttype",'assignment') : $form->name;
77db7e4c 190
b0f2597e 191 print_header($this->course->shortname.': '.$strheading, "$strheading",
192 "<a href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname} </a> -> ".
193 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading");
77db7e4c 194
b0f2597e 195 print_simple_box_start("center");
196 print_heading(get_string("type$form->assignmenttype",'assignment'));
197 include("$CFG->dirroot/mod/assignment/type/common.html");
198 }
199
200 /*
201 * Print the end of the setup form for the current assignment type
202 */
203 function setup_end() {
204 global $CFG, $usehtmleditor;
205
206 include($CFG->dirroot.'/mod/assignment/type/common_end.html');
77db7e4c 207
208 print_simple_box_end();
209
b0f2597e 210 if ($usehtmleditor) {
211 use_html_editor();
212 }
213
214 print_footer($this->course);
77db7e4c 215 }
77db7e4c 216
217
b0f2597e 218 function add_instance($assignment) {
219 // Given an object containing all the necessary data,
220 // (defined by the form in mod.html) this function
221 // will create a new instance and return the id number
222 // of the new instance.
223
224 $assignment->timemodified = time();
225 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
226 $assignment->dueday, $assignment->duehour,
227 $assignment->dueminute);
228 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
229 $assignment->availableday, $assignment->availablehour,
230 $assignment->availableminute);
d699cd1e 231
b0f2597e 232 return insert_record("assignment", $assignment);
233 }
d699cd1e 234
b0f2597e 235 function delete_instance($assignment) {
236 if (! delete_records("assignment", "id", "$assignment->id")) {
237 $result = false;
238 }
239 return $result;
240 }
d699cd1e 241
b0f2597e 242 function update_instance($assignment) {
243 // Given an object containing all the necessary data,
244 // (defined by the form in mod.html) this function
245 // will create a new instance and return the id number
246 // of the new instance.
247
248 $assignment->timemodified = time();
249 $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth,
250 $assignment->dueday, $assignment->duehour,
251 $assignment->dueminute);
252 $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth,
253 $assignment->availableday, $assignment->availablehour,
254 $assignment->availableminute);
255 $assignment->id = $assignment->instance;
256 return update_record("assignment", $assignment);
257 }
258
259
260
261 /*
262 * Top-level function for handling of submissions called by submissions.php
263 *
264 */
265 function submissions($mode) {
266 switch ($mode) {
267 case 'grade': // We are in a popup window grading
268 if ($submission = $this->process_feedback()) {
269 print_heading(get_string('changessaved'));
270 /// Run some Javascript to try and update the parent page
271 echo '<script type="text/javascript">'."\n<!--\n";
272 echo 'opener.document.getElementById("ts'.$submission->userid.'").innerHTML="'.userdate($submission->timemodified)."\";\n";
273 echo 'opener.document.getElementById("tt'.$submission->userid.'").innerHTML="'.userdate($submission->timemarked)."\";\n";
274 echo 'grademenu = opener.document.getElementById("menug8");'."\n";
275 echo 'for (i=0;i<grademenu.options.length;i++)';
276 echo ' if (grademenu.options[i].value == "'.$submission->grade.'")';
277 echo ' grademenu.selectedIndex = i;';
278
279 echo "\n-->\n</script>";
280 fflush();
281 }
282 close_window();
283 break;
9cc9b7c1 284
b0f2597e 285 case 'single': // We are in a popup window displaying submission
286 $this->display_submission();
287 break;
a56d79cd 288
b0f2597e 289 case 'all': // Main window, display everything
290 $this->display_submissions();
291 break;
a56d79cd 292 }
b0f2597e 293 }
a56d79cd 294
d699cd1e 295
b0f2597e 296 /*
297 * Display a single submission, ready for grading on a popup window
298 *
299 */
300 function display_submission() {
d699cd1e 301
b0f2597e 302
303 $userid = required_param('userid');
d699cd1e 304
b0f2597e 305 if (!$user = get_record('user', 'id', $userid)) {
306 error('No such user!');
307 }
d699cd1e 308
b0f2597e 309 if (!$submission = $this->get_submission($user->id)) { // Get or make one
310 error('Could not find submission!');
311 }
a5a4cd60 312
b0f2597e 313 if ($submission->timemodified > $submission->timemarked) {
314 $subtype = 'assignmentnew';
315 } else {
316 $subtype = 'assignmentold';
317 }
d699cd1e 318
b0f2597e 319 print_header($this->assignment->name.' '.fullname($user, true));
d699cd1e 320
b0f2597e 321 echo '<form action="submissions.php" method="post">';
322 echo '<input type="hidden" name="userid" value="'.$userid.'">';
323 echo '<input type="hidden" name="id" value="'.$this->cm->id.'">';
324 echo '<input type="hidden" name="mode" value="grade">';
d699cd1e 325
b0f2597e 326 echo '<table cellspacing="0" class="submission '.$subtype.'" >';
d699cd1e 327
b0f2597e 328 echo '<tr>';
329 echo '<td width="35" valign="top" class="picture user">';
330 print_user_picture($user->id, $this->course->id, $user->picture);
331 echo '</td>';
332 echo '<td class="heading">'.fullname($user, true).'</td>';
333 echo '</tr>';
c69cb506 334
b0f2597e 335 echo '<tr>';
336 echo '<td width="35" valign="top" class="picture teacher">';
337 if ($submission->teacher) {
338 $teacher = get_record('user', 'id', $submission->teacher);
339 } else {
340 global $USER;
341 $teacher = $USER;
342 }
343 print_user_picture($teacher->id, $this->course->id, $teacher->picture);
344 echo '</td>';
345 echo '<td class="content">';
d699cd1e 346
b0f2597e 347 if (!$submission->grade and !$submission->timemarked) {
348 $submission->grade = -1; /// Hack to stop zero being selected on the menu below (so it shows 'no grade')
349 }
350 echo get_string('feedback', 'assignment').':';
351 choose_from_menu(make_grades_menu($this->assignment->grade), 'grade',
352 $submission->grade, get_string('nograde'));
353
354 if ($submission->timemarked) {
355 echo '&nbsp;&nbsp;'.userdate($submission->timemarked);
d699cd1e 356 }
b0f2597e 357 echo '<br />';
358 print_textarea(false, 6, 60, 500, 400, 'comment', $submission->comment, $this->course->id);
359 echo '</td></tr>';
360 echo '</table>';
361
362 echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" />';
363 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
364 echo '</form>';
365 print_footer('none');
d699cd1e 366 }
367
d699cd1e 368
b0f2597e 369 /*
370 * Display all the submissions ready for grading
371 */
372 function display_submissions() {
3446205d 373
b0f2597e 374 global $CFG, $db;
3446205d 375
b0f2597e 376 $teacherattempts = true; /// Temporary measure
1b5910c4 377
3446205d 378
b0f2597e 379 $sort = optional_param('sort', 'timemodified');
380 $dir = optional_param('dir', 'DESC');
381 $timenow = optional_param('timenow', 0);
382 $page = optional_param('page', 0);
383 $perpage = optional_param('perpage', 10);
d699cd1e 384
b0f2597e 385 $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
d0ac6bc2 386
b0f2597e 387 /// Some shortcuts to make the code read better
388
389 $course = $this->course;
390 $assignment = $this->assignment;
391 $cm = $this->cm;
91719320 392
91719320 393
b0f2597e 394 add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id);
395
396 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 397
91719320 398
b0f2597e 399 $tablecolumns = array('picture', 'fullname', 'grade', 'timemodified', 'timemarked', 'status');
400 $tableheaders = array('', get_string('fullname'), get_string('grade'), get_string('lastmodified').' ('.$course->student.')', get_string('lastmodified').' ('.$course->teacher.')', get_string('status'));
91719320 401
d0ac6bc2 402
b0f2597e 403 require_once($CFG->libdir.'/tablelib.php');
404 $table = new flexible_table('mod-assignment-submissions');
405
406 $table->define_columns($tablecolumns);
407 $table->define_headers($tableheaders);
408 $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id);
409
410 $table->sortable(true);
411 $table->collapsible(true);
412 $table->initialbars(true);
413
414 $table->column_suppress('picture');
415 $table->column_suppress('fullname');
416
417 $table->column_class('picture', 'picture');
418
419 $table->set_attribute('cellspacing', '0');
420 $table->set_attribute('id', 'attempts');
421 $table->set_attribute('class', 'generaltable generalbox');
422 $table->set_attribute('width', '90%');
423 $table->set_attribute('align', 'center');
424
425 // Start working -- this is necessary as soon as the niceties are over
426 $table->setup();
427
05855091 428
05855091 429
b0f2597e 430 /// Check to see if groups are being used in this assignment
431 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
306dc7e5 432 $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
b0f2597e 433 } else {
434 $currentgroup = false;
05855091 435 }
05855091 436
0f1a97c2 437
b0f2597e 438 /// Get all teachers and students
439 if ($currentgroup) {
440 $users = get_group_users($currentgroup);
441 } else {
442 $users = get_course_users($course->id);
443 }
444
445 if (!$teacherattempts) {
446 $teachers = get_course_teachers($course->id);
447 if (!empty($teachers)) {
448 $keys = array_keys($teachers);
449 }
450 foreach ($keys as $key) {
451 unset($users[$key]);
452 }
453 }
454
455 if (empty($users)) {
456 print_heading($strnoattempts);
457 return true;
458 }
0f1a97c2 459
0f1a97c2 460
b0f2597e 461 /// Construct the SQL
0f1a97c2 462
b0f2597e 463 if ($where = $table->get_sql_where()) {
464 $where = str_replace('firstname', 'u.firstname', $where);
465 $where = str_replace('lastname', 'u.lastname', $where);
466 $where .= ' AND ';
467 }
0f1a97c2 468
b0f2597e 469 if ($sort = $table->get_sql_sort()) {
470 $sortparts = explode(',', $sort);
471 $newsort = array();
472 foreach ($sortparts as $sortpart) {
473 $sortpart = trim($sortpart);
474 $newsort[] = $sortpart;
475 }
476 $sort = ' ORDER BY '.implode(', ', $newsort);
477 }
9fa49e22 478
9fa49e22 479
306dc7e5 480 $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, s.id AS submissionid, s.grade, s.timemodified, s.timemarked ';
b0f2597e 481 $group = '';
482 $sql = 'FROM '.$CFG->prefix.'user u '.
306dc7e5 483 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment->id.' '.
484 'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') ';
8ff79e8c 485
8ff79e8c 486
b0f2597e 487 $total = count_records_sql('SELECT COUNT(u.id) '.$sql);
000cc405 488
b0f2597e 489 $table->pagesize($perpage, $total);
490
491 if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
492 $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
493 }
494 else {
495 $limit = '';
496 }
9fa49e22 497
b0f2597e 498 $strupdate = get_string('update');
499 $grademenu = make_grades_menu($this->assignment->grade);
500
306dc7e5 501 if (($ausers = get_records_sql($select.$sql.$group.$sort.$limit)) === false) {
502 $ausers = array();
503 }
b0f2597e 504
505 foreach ($ausers as $auser) {
506 $picture = print_user_picture($auser->id, $course->id, $auser->picture, false, true);
306dc7e5 507 if (!empty($auser->submissionid)) {
508 if ($auser->timemodified > 0) {
509 $studentmodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>';
14a4e028 510 if ($auser->timemarked > $auser->timemodified) {
b0f2597e 511 $status = '<div id="st'.$auser->id.'">YES</div>';
512 } else {
513 $status = '<div id="st'.$auser->id.'">NO</div>';
514 }
515 } else {
516 $studentmodified = '<div id="ts'.$auser->id.'">-</div>';
517 $status = '<div id="st'.$auser->id.'"></div>';
518 }
306dc7e5 519 if ($auser->timemarked > 0) {
520 $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
b0f2597e 521 } else {
522 $teachermodified = '<div id="tt'.$auser->id.'">-</div>';
523 }
9fa49e22 524
306dc7e5 525 $grade = choose_from_menu($grademenu, 'g'.$auser->id, $auser->grade, get_string('nograde'), '', 0, true);
b0f2597e 526
527 } else {
528 $studentmodified = '<div id="ts'.$auser->id.'">-</div>';
529 $teachermodified = '<div id="tt'.$auser->id.'">-</div>';
530 $status = '<div id="st'.$auser->id.'"></div>';
531 $grade = choose_from_menu($grademenu, 'g'.$auser->id, -1, get_string('nograde'), '', 0, true);
532 }
9fa49e22 533
b0f2597e 534 $button = button_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;userid='.$auser->id.'&amp;mode=single',
535 'grade'.$auser->id, $strupdate, 450, 600, $strupdate, 'none', true);
9fa49e22 536
306dc7e5 537
b0f2597e 538 $row = array($picture, fullname($auser), $grade, $studentmodified, $teachermodified, $status.'&nbsp;'.$button);
539 $table->add_data($row);
540 }
d699cd1e 541
ca4f8eb8 542
306dc7e5 543
b0f2597e 544 $table->print_html();
d699cd1e 545
b0f2597e 546 print_footer($this->course);
d699cd1e 547
8e340cb0 548 }
d699cd1e 549
d699cd1e 550
d699cd1e 551
b0f2597e 552 /*
553 * Display and process the submissions
554 */
555 function process_feedback() {
d699cd1e 556
b0f2597e 557 global $USER;
d699cd1e 558
b0f2597e 559 if (!$feedback = data_submitted()) { // No incoming data?
560 return false;
d699cd1e 561 }
b7b42874 562
b0f2597e 563 if (!empty($feedback->cancel)) { // User hit cancel button
564 return false;
565 }
d699cd1e 566
b0f2597e 567 $newsubmission = $this->get_submission($feedback->userid);
d699cd1e 568
b0f2597e 569 $newsubmission->grade = $feedback->grade;
570 $newsubmission->comment = $feedback->comment;
571 $newsubmission->teacher = $USER->id;
572 $newsubmission->mailed = 0; // Make sure mail goes out (again, even)
573 $newsubmission->timemarked = time();
d699cd1e 574
b0f2597e 575 if (empty($submission->timemodified)) { // eg for offline assignments
576 $newsubmission->timemodified = time();
577 }
d699cd1e 578
b0f2597e 579 if (! update_record('assignment_submissions', $newsubmission)) {
580 return false;
581 }
d699cd1e 582
b0f2597e 583 add_to_log($this->course->id, 'assignment', 'update grades',
584 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
585
586 return $newsubmission;
d699cd1e 587
d699cd1e 588 }
d699cd1e 589
d699cd1e 590
b0f2597e 591 function get_submission($userid, $createnew=true) {
592 $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
d699cd1e 593
b0f2597e 594 if ($submission || !$createnew) {
595 return $submission;
596 }
d699cd1e 597
b0f2597e 598 $newsubmission = new Object;
599 $newsubmission->assignment = $this->assignment->id;
600 $newsubmission->userid = $userid;
601 $newsubmission->timecreated = time();
602 if (!insert_record("assignment_submissions", $newsubmission)) {
603 error("Could not insert a new empty submission");
604 }
d699cd1e 605
b0f2597e 606 return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
607 }
d699cd1e 608
3f8247c2 609
b0f2597e 610 function get_submissions($sort='', $dir='DESC') {
611 /// Return all assignment submissions by ENROLLED students (even empty)
612 global $CFG;
613
614 if ($sort == "lastname" or $sort == "firstname") {
615 $sort = "u.$sort $dir";
616 } else if (empty($sort)) {
617 $sort = "a.timemodified DESC";
618 } else {
619 $sort = "a.$sort $dir";
d699cd1e 620 }
d699cd1e 621
b0f2597e 622 $select = "s.course = '$this->assignment->course' AND";
623 $site = get_site();
624 if ($this->assignment->course == $site->id) {
625 $select = '';
626 }
627 return get_records_sql("SELECT a.*
628 FROM {$CFG->prefix}assignment_submissions a,
629 {$CFG->prefix}user_students s,
630 {$CFG->prefix}user u
631 WHERE a.userid = s.userid
632 AND u.id = a.userid
633 AND $select a.assignment = '$this->assignment->id'
634 ORDER BY $sort");
635 }
636
637
638 function count_real_submissions($groupid=0) {
639 /// Return all real assignment submissions by ENROLLED students (not empty ones)
640 global $CFG;
641
642 if ($groupid) { /// How many in a particular group?
643 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
644 FROM {$CFG->prefix}assignment_submissions a,
645 {$CFG->prefix}groups_members g
646 WHERE a.assignment = {$this->assignment->id}
647 AND a.timemodified > 0
648 AND g.groupid = '$groupid'
649 AND a.userid = g.userid ");
650 } else {
651 $select = "s.course = '{$this->assignment->course}' AND";
652 if ($this->assignment->course == SITEID) {
653 $select = '';
d699cd1e 654 }
b0f2597e 655 return count_records_sql("SELECT COUNT(*)
656 FROM {$CFG->prefix}assignment_submissions a,
657 {$CFG->prefix}user_students s
658 WHERE a.assignment = '{$this->assignment->id}'
659 AND a.timemodified > 0
660 AND $select a.userid = s.userid ");
661 }
662 }
d699cd1e 663
b0f2597e 664} ////// End of the assignment_base class
d699cd1e 665
18b8fbfa 666
04eba58f 667
b0f2597e 668/// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////
669
670
671function assignment_delete_instance($id){
26b90e70 672 global $CFG;
673
b0f2597e 674 if (! $assignment = get_record('assignment', 'id', $id)) {
675 return false;
26b90e70 676 }
677
b0f2597e 678 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
679 $assignmentclass = "assignment_$assignment->assignmenttype";
680 $ass = new $assignmentclass();
681 return $ass->delete_instance($assignment);
682}
f466c9ed 683
ac21ad39 684
b0f2597e 685function assignment_update_instance($assignment){
686 global $CFG;
26b90e70 687
b0f2597e 688 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
689 $assignmentclass = "assignment_$assignment->assignmenttype";
690 $ass = new $assignmentclass();
691 return $ass->update_instance($assignment);
692}
26b90e70 693
26b90e70 694
b0f2597e 695function assignment_add_instance($assignment) {
696 global $CFG;
f466c9ed 697
b0f2597e 698 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
699 $assignmentclass = "assignment_$assignment->assignmenttype";
700 $ass = new $assignmentclass();
701 return $ass->add_instance($assignment);
702}
f466c9ed 703
b0f2597e 704function assignment_types() {
705 $types = array();
706 $names = get_list_of_plugins('mod/assignment/type');
707 foreach ($names as $name) {
708 $types[$name] = get_string('type'.$name, 'assignment');
ffeca120 709 }
b0f2597e 710 asort($types);
711 return $types;
f466c9ed 712}
713
b0f2597e 714function assignment_upgrade_submodules() {
f1c1d2f1 715 global $CFG;
26b90e70 716
b0f2597e 717 $types = assignment_types();
26b90e70 718
b0f2597e 719 include_once($CFG->dirroot.'/mod/assignment/version.php'); // defines $module with version etc
26b90e70 720
b0f2597e 721 foreach ($types as $type) {
26b90e70 722
b0f2597e 723 $fullpath = $CFG->dirroot.'/mod/assignment/type/'.$type;
26b90e70 724
b0f2597e 725 /// Check for an external version file (defines $submodule)
26b90e70 726
b0f2597e 727 if (!is_readable($fullpath .'/version.php')) {
728 continue;
ffeca120 729 }
b0f2597e 730 unset($module);
731 include_once($fullpath .'/version.php');
26b90e70 732
b0f2597e 733 /// Check whether we need to upgrade
26b90e70 734
b0f2597e 735 if (!isset($submodule->version)) {
736 continue;
737 }
26b90e70 738
b0f2597e 739 /// Make sure this submodule will work with this assignment version
26b90e70 740
b0f2597e 741 if (isset($submodule->requires) and ($submodules->requires > $module->version)) {
742 notify("Assignment submodule '$type' is too new for your assignment");
743 continue;
744 }
f466c9ed 745
b0f2597e 746 /// If we use versions, make sure an internal record exists
f466c9ed 747
b0f2597e 748 $currentversion = 'assignment_'.$type.'_version';
f466c9ed 749
b0f2597e 750 if (!isset($CFG->$currentversion)) {
751 set_config($currentversion, 0);
f466c9ed 752 }
f466c9ed 753
b0f2597e 754 /// See if we need to upgrade
755
756 if ($submodule->version <= $CFG->$currentversion) {
757 continue;
59c005b7 758 }
59c005b7 759
b0f2597e 760 /// Look for the upgrade file
59c005b7 761
b0f2597e 762 if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.php')) {
763 continue;
764 }
59c005b7 765
b0f2597e 766 include_once($fullpath .'/db/'. $CFG->dbtype .'.php'); // defines assignment_xxx_upgrade
59c005b7 767
b0f2597e 768 /// Perform the upgrade
59c005b7 769
b0f2597e 770 $upgrade_function = 'assignment_'.$type.'_upgrade';
771 if (function_exists($upgrade_function)) {
772 $db->debug=true;
773 if ($upgrade_function($CFG->$currentversion)) {
774 $db->debug=false;
775 set_config($currentversion, $submodule->version);
59c005b7 776 }
b0f2597e 777 $db->debug=false;
59c005b7 778 }
779 }
780}
781
04eba58f 782?>