3 * assignment_base is the base class for assignment types
5 * This class provides all the functionality for an assignment
9 if (!isset($CFG->assignment_maxbytes
)) {
10 set_config("assignment_maxbytes", 1024000); // Default maximum size for all assignments
15 * Standard base class for all assignment submodules (assignment types).
19 class assignment_base
{
26 * Constructor for the base assignment class
28 * Constructor for the base assignment class.
29 * If cmid is set create the cm, course, assignment objects.
31 * @param cmid integer, the current course module id - not set for new assignments
32 * @param assignment object, usually null, but if we have it we pass it to save db access
34 function assignment_base($cmid=0, $assignment=NULL, $cm=NULL, $course=NULL) {
41 } else if (! $this->cm
= get_record('course_modules', 'id', $cmid)) {
42 error('Course Module ID was incorrect');
46 $this->course
= $course;
47 } else if (! $this->course
= get_record('course', 'id', $this->cm
->course
)) {
48 error('Course is misconfigured');
52 $this->assignment
= $assignment;
53 } else if (! $this->assignment
= get_record('assignment', 'id', $this->cm
->instance
)) {
54 error('assignment ID was incorrect');
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');
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> ->";
66 $this->navigation
= "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
69 $this->pagetitle
= strip_tags($this->course
->shortname
.': '.$this->strassignment
.': '.format_string($this->assignment
->name
,true));
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}");
78 $this->currentgroup
= get_current_group($this->course
->id
);
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
;
85 $this->defaultformat
= FORMAT_MOODLE
;
91 * Display the assignment to students (sub-modules will most likely override this)
96 add_to_log($this->course
->id
, "assignment", "view", "view.php?id={$this->cm->id}",
97 $this->assignment
->id
, $this->cm
->id
);
105 $this->view_feedback();
107 $this->view_footer();
111 * Display the top of the view.php page, this doesn't change much for submodules
113 function view_header($subpage='') {
118 $extranav = '<a target="'.$CFG->framename
.'" href="view.php?id='.$this->cm
->id
.'">'.
119 format_string($this->assignment
->name
,true).'</a> -> '.$subpage;
121 $extranav = ' '.format_string($this->assignment
->name
,true);
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
));
128 echo '<div class="reportlink">'.$this->submittedlink().'</div>';
133 * Display the assignment intro
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();
142 * Display the assignment dates
144 function view_dates() {
145 if (!$this->assignment
->timeavailable
&& !$this->assignment
->timedue
) {
149 print_simple_box_start('center', '', '', '', 'generalbox', 'dates');
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>';
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>';
160 print_simple_box_end();
165 * Display the bottom of the view.php page, this doesn't change much for submodules
167 function view_footer() {
168 print_footer($this->course
);
172 function view_feedback($submission=NULL) {
175 if (!$submission) { /// Get submission for this assignment
176 $submission = $this->get_submission($USER->id
);
179 if (empty($submission->timemarked
)) { /// Nothing to show, so print nothing
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');
189 /// Print the feedback
190 print_heading(get_string('feedbackfromteacher', 'assignment', $this->course
->teacher
));
192 echo '<table cellspacing="0" class="feedback">';
195 echo '<td class="left picture">';
196 print_user_picture($teacher->id
, $this->course
->id
, $teacher->picture
);
198 echo '<td class="topic">';
199 echo '<div class="from">';
200 echo '<div class="fullname">'.fullname($teacher).'</div>';
201 echo '<div class="time">'.userdate($submission->timemarked
).'</div>';
203 $this->print_user_files($submission->userid
);
209 echo '<td class="left side"> </td>';
210 echo '<td class="content">';
211 if ($this->assignment
->grade
) {
212 echo '<div class="grade">';
213 echo get_string("grade").': '.$this->display_grade($submission->grade
);
215 echo '<div class="clearer"></div>';
218 echo '<div class="comment">';
219 echo format_text($submission->comment
, $submission->format
);
229 * Returns a link with info about the state of the assignment submissions
231 function submittedlink() {
236 if (isteacher($this->course
->id
)) {
237 if (!isteacheredit($this->course
->id
) and user_group($this->course
->id
, $USER->id
)) {
238 $count = $this->count_real_submissions($this->currentgroup
); // Only their group
240 $count = $this->count_real_submissions(); // Everyone
242 $submitted = '<a href="submissions.php?id='.$this->cm
->id
.'">'.
243 get_string('viewsubmissions', 'assignment', $count).'</a>';
245 if (isset($USER->id
)) {
246 if ($submission = $this->get_submission($USER->id
)) {
247 if ($submission->timemodified
) {
248 if ($submission->timemodified
<= $this->assignment
->timedue
) {
249 $submitted = '<span class="early">'.userdate($submission->timemodified
).'</span>';
251 $submitted = '<span class="late">'.userdate($submission->timemodified
).'</span>';
263 * Print the start of the setup form for the current assignment type
265 function setup(&$form, $action='') {
268 if (empty($this->course
)) {
269 if (! $this->course
= get_record("course", "id", $form->course
)) {
270 error("Course is misconfigured");
273 if (empty($action)) { // Default destination for this form
274 $action = $CFG->wwwroot
.'/course/mod.php';
277 if (empty($form->name
)) {
280 if (empty($form->assignmenttype
)) {
281 $form->assignmenttype
= "";
283 if (empty($form->description
)) {
284 $form->description
= "";
287 $strname = get_string('name');
288 $strassignments = get_string('modulenameplural', 'assignment');
289 $strheading = empty($form->name
) ?
get_string("type$form->assignmenttype",'assignment') : s(format_string(stripslashes($form->name
),true));
291 print_header($this->course
->shortname
.': '.$strheading, "$strheading",
292 "<a href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname} </a> -> ".
293 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading");
295 print_simple_box_start('center', '70%');
296 print_heading(get_string('type'.$form->assignmenttype
,'assignment'));
297 print_simple_box(get_string('help'.$form->assignmenttype
, 'assignment'), 'center');
298 include("$CFG->dirroot/mod/assignment/type/common.html");
300 include("$CFG->dirroot/mod/assignment/type/".$form->assignmenttype
."/mod.html");
305 * Print the end of the setup form for the current assignment type
307 function setup_end() {
310 include($CFG->dirroot
.'/mod/assignment/type/common_end.html');
312 print_simple_box_end();
314 if ($this->usehtmleditor
) {
318 print_footer($this->course
);
322 function add_instance($assignment) {
323 // Given an object containing all the necessary data,
324 // (defined by the form in mod.html) this function
325 // will create a new instance and return the id number
326 // of the new instance.
328 $assignment->timemodified
= time();
329 if (empty($assignment->dueenable
)) {
330 $assignment->timedue
= 0;
332 $assignment->timedue
= make_timestamp($assignment->dueyear
, $assignment->duemonth
,
333 $assignment->dueday
, $assignment->duehour
,
334 $assignment->dueminute
);
336 if (empty($assignment->availableenable
)) {
337 $assignment->timeavailable
= 0;
338 $assignment->preventlate
= 0;
340 $assignment->timeavailable
= make_timestamp($assignment->availableyear
, $assignment->availablemonth
,
341 $assignment->availableday
, $assignment->availablehour
,
342 $assignment->availableminute
);
345 return insert_record('assignment', $assignment);
348 function delete_instance($assignment) {
349 return delete_records('assignment', 'id', $assignment->id
);
352 function update_instance($assignment) {
353 // Given an object containing all the necessary data,
354 // (defined by the form in mod.html) this function
355 // will create a new instance and return the id number
356 // of the new instance.
358 $assignment->timemodified
= time();
359 $assignment->timemodified
= time();
360 if (empty($assignment->dueenable
)) {
361 $assignment->timedue
= 0;
363 $assignment->timedue
= make_timestamp($assignment->dueyear
, $assignment->duemonth
,
364 $assignment->dueday
, $assignment->duehour
,
365 $assignment->dueminute
);
367 if (empty($assignment->availableenable
)) {
368 $assignment->timeavailable
= 0;
369 $assignment->preventlate
= 0;
371 $assignment->timeavailable
= make_timestamp($assignment->availableyear
, $assignment->availablemonth
,
372 $assignment->availableday
, $assignment->availablehour
,
373 $assignment->availableminute
);
376 $assignment->id
= $assignment->instance
;
377 return update_record('assignment', $assignment);
383 * Top-level function for handling of submissions called by submissions.php
386 function submissions($mode) {
388 case 'grade': // We are in a popup window grading
389 if ($submission = $this->process_feedback()) {
390 print_heading(get_string('changessaved'));
391 $this->update_main_listing($submission);
396 case 'single': // We are in a popup window displaying submission
397 $this->display_submission();
400 case 'all': // Main window, display everything
401 $this->display_submissions();
406 function update_main_listing($submission) {
409 /// Run some Javascript to try and update the parent page
410 echo '<script type="text/javascript">'."\n<!--\n";
411 if (empty($SESSION->flextable
['mod-assignment-submissions']->collapse
['grade'])) {
412 echo 'opener.document.getElementById("g'.$submission->userid
.
413 '").innerHTML="'.$this->display_grade($submission->grade
)."\";\n";
415 if (empty($SESSION->flextable
['mod-assignment-submissions']->collapse
['comment'])) {
416 echo 'opener.document.getElementById("com'.$submission->userid
.
417 '").innerHTML="'.shorten_text(strip_tags($submission->comment
), 15)."\";\n";
419 if (empty($SESSION->flextable
['mod-assignment-submissions']->collapse
['timemodified']) &&
420 $submission->timemodified
) {
421 echo 'opener.document.getElementById("ts'.$submission->userid
.
422 '").innerHTML="'.userdate($submission->timemodified
)."\";\n";
424 if (empty($SESSION->flextable
['mod-assignment-submissions']->collapse
['timemarked']) &&
425 $submission->timemarked
) {
426 echo 'opener.document.getElementById("tt'.$submission->userid
.
427 '").innerHTML="'.userdate($submission->timemarked
)."\";\n";
429 if (empty($SESSION->flextable
['mod-assignment-submissions']->collapse
['status'])) {
430 echo 'opener.document.getElementById("up'.$submission->userid
.'").className="s1";';
431 echo 'opener.document.getElementById("button'.$submission->userid
.'").value="'.get_string('update').' ...";';
433 echo "\n-->\n</script>";
438 * Display a grade in user-friendly form, whether it's a scale or not
441 function display_grade($grade) {
443 static $scalegrades; // Cached because we only have one per assignment
445 if ($this->assignment
->grade
>= 0) { // Normal number
446 return $grade.' / '.$this->assignment
->grade
;
449 if (empty($scalegrades)) {
450 if ($scale = get_record('scale', 'id', -($this->assignment
->grade
))) {
451 $scalegrades = make_menu_from_list($scale->scale
);
456 if (isset($scalegrades[$grade])) {
457 return $scalegrades[$grade];
464 * Display a single submission, ready for grading on a popup window
467 function display_submission() {
469 $userid = required_param('userid');
471 if (!$user = get_record('user', 'id', $userid)) {
472 error('No such user!');
475 if (!$submission = $this->get_submission($user->id
, true)) { // Get one or make one
476 error('Could not find submission!');
479 if ($submission->timemodified
> $submission->timemarked
) {
480 $subtype = 'assignmentnew';
482 $subtype = 'assignmentold';
485 print_header(get_string('feedback', 'assignment').':'.fullname($user, true).':'.format_string($this->assignment
->name
));
488 echo '<table cellspacing="0" class="feedback '.$subtype.'" >';
491 echo '<td width="35" valign="top" class="picture user">';
492 print_user_picture($user->id
, $this->course
->id
, $user->picture
);
494 echo '<td class="topic">';
495 echo '<div class="from">';
496 echo '<div class="fullname">'.fullname($user, true).'</div>';
497 if ($submission->timemodified
) {
498 echo '<div class="time">'.userdate($submission->timemodified
).
499 $this->display_lateness($submission->timemodified
).'</div>';
502 $this->print_user_files($user->id
);
507 echo '<td width="35" valign="top" class="picture teacher">';
508 if ($submission->teacher
) {
509 $teacher = get_record('user', 'id', $submission->teacher
);
514 print_user_picture($teacher->id
, $this->course
->id
, $teacher->picture
);
516 echo '<td class="content">';
518 echo '<form action="submissions.php" method="post">';
519 echo '<input type="hidden" name="userid" value="'.$userid.'">';
520 echo '<input type="hidden" name="id" value="'.$this->cm
->id
.'">';
521 echo '<input type="hidden" name="mode" value="grade">';
522 if (!$submission->grade
and !$submission->timemarked
) {
523 $submission->grade
= -1; /// Hack to stop zero being selected on the menu below (so it shows 'no grade')
525 if ($submission->timemarked
) {
526 echo '<div class="from">';
527 echo '<div class="fullname">'.fullname($teacher, true).'</div>';
528 echo '<div class="time">'.userdate($submission->timemarked
).'</div>';
531 echo '<div class="grade">'.get_string('grade').':';
532 choose_from_menu(make_grades_menu($this->assignment
->grade
), 'grade',
533 $submission->grade
, get_string('nograde'));
535 echo '<div class="clearer"></div>';
537 $this->preprocess_submission($submission);
540 print_textarea($this->usehtmleditor
, 12, 58, 0, 0, 'comment', $submission->comment
, $this->course
->id
);
542 if ($this->usehtmleditor
) {
543 echo '<input type="hidden" name="format" value="'.FORMAT_HTML
.'" />';
545 echo '<div align="right" class="format">';
546 choose_from_menu(format_text_menu(), "format", $submission->format
, "");
547 helpbutton("textformat", get_string("helpformatting"));
551 echo '<div class="buttons" align="center">';
552 echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" />';
553 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
562 if ($this->usehtmleditor
) {
566 print_footer('none');
570 * Preprocess submission before grading
572 function preprocess_submission(&$submission) {
576 * Display all the submissions ready for grading
578 function display_submissions() {
582 $teacherattempts = true; /// Temporary measure
584 $page = optional_param('page', 0);
585 $perpage = optional_param('perpage', 10);
587 $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
589 /// Some shortcuts to make the code read better
591 $course = $this->course
;
592 $assignment = $this->assignment
;
596 add_to_log($course->id
, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment
->id
, $this->assignment
->id
, $this->cm
->id
);
598 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));
601 $tablecolumns = array('picture', 'fullname', 'grade', 'comment', 'timemodified', 'timemarked', 'status');
602 $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'));
605 require_once($CFG->libdir
.'/tablelib.php');
606 $table = new flexible_table('mod-assignment-submissions');
608 $table->define_columns($tablecolumns);
609 $table->define_headers($tableheaders);
610 $table->define_baseurl($CFG->wwwroot
.'/mod/assignment/submissions.php?id='.$this->cm
->id
);
612 $table->sortable(true);
613 $table->collapsible(true);
614 $table->initialbars(true);
616 $table->column_suppress('picture');
617 $table->column_suppress('fullname');
619 $table->column_class('picture', 'picture');
620 $table->column_class('fullname', 'fullname');
621 $table->column_class('grade', 'grade');
622 $table->column_class('comment', 'comment');
623 $table->column_class('timemodified', 'timemodified');
624 $table->column_class('timemarked', 'timemarked');
625 $table->column_class('status', 'status');
627 $table->set_attribute('cellspacing', '0');
628 $table->set_attribute('id', 'attempts');
629 $table->set_attribute('class', 'submissions');
630 $table->set_attribute('width', '90%');
631 $table->set_attribute('align', 'center');
633 // Start working -- this is necessary as soon as the niceties are over
638 /// Check to see if groups are being used in this assignment
639 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
640 $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm
->id
);
642 $currentgroup = false;
646 /// Get all teachers and students
648 $users = get_group_users($currentgroup);
650 $users = get_course_users($course->id
);
653 if (!$teacherattempts) {
654 $teachers = get_course_teachers($course->id
);
655 if (!empty($teachers)) {
656 $keys = array_keys($teachers);
658 foreach ($keys as $key) {
664 print_heading($strnoattempts);
669 /// Construct the SQL
671 if ($where = $table->get_sql_where()) {
672 $where = str_replace('firstname', 'u.firstname', $where);
673 $where = str_replace('lastname', 'u.lastname', $where);
677 if ($sort = $table->get_sql_sort()) {
678 $sortparts = explode(',', $sort);
680 foreach ($sortparts as $sortpart) {
681 $sortpart = trim($sortpart);
682 $newsort[] = $sortpart;
684 $sort = ' ORDER BY '.implode(', ', $newsort);
688 $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 ';
689 $group = 'GROUP BY uvs ';
690 $sql = 'FROM '.$CFG->prefix
.'user u '.
691 'LEFT JOIN '.$CFG->prefix
.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment
->id
.' '.
692 'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') ';
695 $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('s.userid', '0')).')) '.$sql);
697 $table->pagesize($perpage, $total);
699 if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
700 $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
706 $strupdate = get_string('update');
707 $strgrade = get_string('grade');
708 $grademenu = make_grades_menu($this->assignment
->grade
);
710 if (($ausers = get_records_sql($select.$sql.$group.$sort.$limit)) !== false) {
712 foreach ($ausers as $auser) {
713 $picture = print_user_picture($auser->id
, $course->id
, $auser->picture
, false, true);
714 if (!empty($auser->submissionid
)) {
715 if ($auser->timemodified
> 0) {
716 $studentmodified = '<div id="ts'.$auser->id
.'">'.userdate($auser->timemodified
).'</div>';
718 $studentmodified = '<div id="ts'.$auser->id
.'"> </div>';
720 if ($auser->timemarked
> 0) {
721 $teachermodified = '<div id="tt'.$auser->id
.'">'.userdate($auser->timemarked
).'</div>';
722 $grade = '<div id="g'.$auser->id
.'">'.$this->display_grade($auser->grade
).'</div>';
724 $teachermodified = '<div id="tt'.$auser->id
.'"> </div>';
725 $grade = '<div id="g'.$auser->id
.'"></div>';
728 $comment = '<div id="com'.$auser->id
.'">'.shorten_text(strip_tags($auser->comment
), 15).'</div>';
731 $studentmodified = '<div id="ts'.$auser->id
.'"> </div>';
732 $teachermodified = '<div id="tt'.$auser->id
.'"> </div>';
733 $status = '<div id="st'.$auser->id
.'"></div>';
734 $grade = '<div id="g'.$auser->id
.'"> </div>';
735 $comment = '<div id="com'.$auser->id
.'"> </div>';
738 if ($auser->status
=== NULL) {
742 $buttontext = ($auser->status
== 1) ?
$strupdate : $strgrade;
744 $button = button_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm
->id
.'&userid='.$auser->id
.'&mode=single',
745 'grade'.$auser->id
, $buttontext, 450, 700, $buttontext, 'none', true, 'button'.$auser->id
);
747 $status = '<div id="up'.$auser->id
.'" class="s'.$auser->status
.'">'.$button.'</div>';
749 $row = array($picture, fullname($auser), $grade, $comment, $studentmodified, $teachermodified, $status);
750 $table->add_data($row);
754 $table->print_html();
756 print_footer($this->course
);
763 * Display and process the submissions
765 function process_feedback() {
769 if (!$feedback = data_submitted()) { // No incoming data?
773 if (!empty($feedback->cancel
)) { // User hit cancel button
777 $newsubmission = $this->get_submission($feedback->userid
, true); // Get or make one
779 $newsubmission->grade
= $feedback->grade
;
780 $newsubmission->comment
= $feedback->comment
;
781 $newsubmission->format
= $feedback->format
;
782 $newsubmission->teacher
= $USER->id
;
783 $newsubmission->mailed
= 0; // Make sure mail goes out (again, even)
784 $newsubmission->timemarked
= time();
786 if (empty($submission->timemodified
)) { // eg for offline assignments
787 $newsubmission->timemodified
= time();
790 if (! update_record('assignment_submissions', $newsubmission)) {
794 add_to_log($this->course
->id
, 'assignment', 'update grades',
795 'submissions.php?id='.$this->assignment
->id
.'&user='.$feedback->userid
, $feedback->userid
, $this->cm
->id
);
797 return $newsubmission;
802 function get_submission($userid=0, $createnew=false) {
805 if (empty($userid)) {
809 $submission = get_record('assignment_submissions', 'assignment', $this->assignment
->id
, 'userid', $userid);
811 if ($submission ||
!$createnew) {
815 $newsubmission = new Object;
816 $newsubmission->assignment
= $this->assignment
->id
;
817 $newsubmission->userid
= $userid;
818 $newsubmission->timecreated
= time();
819 if (!insert_record("assignment_submissions", $newsubmission)) {
820 error("Could not insert a new empty submission");
823 return get_record('assignment_submissions', 'assignment', $this->assignment
->id
, 'userid', $userid);
827 function get_submissions($sort='', $dir='DESC') {
828 /// Return all assignment submissions by ENROLLED students (even empty)
831 if ($sort == "lastname" or $sort == "firstname") {
832 $sort = "u.$sort $dir";
833 } else if (empty($sort)) {
834 $sort = "a.timemodified DESC";
836 $sort = "a.$sort $dir";
839 $select = "s.course = '$this->assignment->course' AND";
841 if ($this->assignment
->course
== $site->id
) {
844 return get_records_sql("SELECT a.*
845 FROM {$CFG->prefix}assignment_submissions a,
846 {$CFG->prefix}user_students s,
848 WHERE a.userid = s.userid
850 AND $select a.assignment = '$this->assignment->id'
855 function count_real_submissions($groupid=0) {
856 /// Return all real assignment submissions by ENROLLED students (not empty ones)
859 if ($groupid) { /// How many in a particular group?
860 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
861 FROM {$CFG->prefix}assignment_submissions a,
862 {$CFG->prefix}groups_members g
863 WHERE a.assignment = {$this->assignment->id}
864 AND a.timemodified > 0
865 AND g.groupid = '$groupid'
866 AND a.userid = g.userid ");
868 $select = "s.course = '{$this->assignment->course}' AND";
869 if ($this->assignment
->course
== SITEID
) {
872 return count_records_sql("SELECT COUNT(*)
873 FROM {$CFG->prefix}assignment_submissions a,
874 {$CFG->prefix}user_students s
875 WHERE a.assignment = '{$this->assignment->id}'
876 AND a.timemodified > 0
877 AND $select a.userid = s.userid ");
881 function email_teachers($submission) {
882 /// Alerts teachers by email of new or changed assignments that need grading
886 if (empty($this->assignment
->emailteachers
)) { // No need to do anything
890 $user = get_record('user', 'id', $submission->userid
);
892 if (groupmode($this->course
, $this->cm
) == SEPARATEGROUPS
) { // Separate groups are being used
893 if (!$group = user_group($this->course
->id
, $user->id
)) { // Try to find a group
894 $group->id
= 0; // Not in a group, never mind
896 $teachers = get_group_teachers($this->course
->id
, $group->id
); // Works even if not in group
898 $teachers = get_course_teachers($this->course
->id
);
903 $strassignments = get_string('modulenameplural', 'assignment');
904 $strassignment = get_string('modulename', 'assignment');
905 $strsubmitted = get_string('submitted', 'assignment');
907 foreach ($teachers as $teacher) {
909 $info->username
= fullname($user);
910 $info->assignment
= format_string($this->assignment
->name
,true);
911 $info->url
= $CFG->wwwroot
.'/mod/assignment/submissions.php?id='.$this->cm
->id
;
913 $postsubject = $strsubmitted.': '.$info->username
.' -> '.$this->assignment
->name
;
914 $posttext = $this->email_teachers_text($info);
915 $posthtml = ($teacher->mailformat
== 1) ?
$this->email_teachers_html($info) : '';
917 @email_to_user
($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
922 function email_teachers_text($info) {
923 $posttext = $this->course
->shortname
.' -> '.$this->strassignments
.' -> '.
924 format_string($this->assignment
->name
, true)."\n";
925 $posttext .= '---------------------------------------------------------------------'."\n";
926 $posttext .= get_string("emailteachermail", "assignment", $info)."\n";
927 $posttext .= '---------------------------------------------------------------------'."\n";
932 function email_teachers_html($info) {
933 $posthtml = '<p><font face="sans-serif">'.
934 '<a href="'.$CFG->wwwroot
.'/course/view.php?id='.$this->course
->id
.'">'.$course->shortname
.'</a> ->'.
935 '<a href="'.$CFG->wwwroot
.'/mod/assignment/index.php?id='.$this->course
->id
.'">'.$this->strassignments
.'</a> ->'.
936 '<a href="'.$CFG->wwwroot
.'/mod/assignment/view.php?id='.$cm->id
.'">'.format_string($this->assignment
->name
,true).'</a></font></p>';
937 $posthtml .= '<hr /><font face="sans-serif">';
938 $posthtml .= '<p>'.get_string('emailteachermailhtml', 'assignment', $info).'</p>';
939 $posthtml .= '</font><hr />';
943 function print_user_files($userid=0, $return=false) {
954 $filearea = $this->file_area_name($userid);
958 if ($basedir = $this->file_area($userid)) {
959 if ($files = get_directory_list($basedir)) {
960 foreach ($files as $key => $file) {
961 require_once($CFG->libdir
.'/filelib.php');
962 $icon = mimeinfo('icon', $file);
963 if ($CFG->slasharguments
) {
964 $ffurl = "file.php/$filearea/$file";
966 $ffurl = "file.php?file=/$filearea/$file";
969 $output = '<img align="middle" src="'.$CFG->pixpath
.'/f/'.$icon.'" height="16" width="16" alt="'.$icon.'" />'.
970 link_to_popup_window ('/'.$ffurl, 'file'.$key, $file, 450, 580, $file, 'none', true).
976 $output = '<div class="files">'.$output.'</div>';
984 function count_user_files($userid) {
987 $filearea = $this->file_area_name($userid);
989 if ($basedir = $this->file_area($userid)) {
990 if ($files = get_directory_list($basedir)) {
991 return count($files);
997 function file_area_name($userid) {
998 // Creates a directory file name, suitable for make_upload_directory()
1001 return $this->course
->id
.'/'.$CFG->moddata
.'/assignment/'.$this->assignment
->id
.'/'.$userid;
1004 function file_area($userid) {
1005 return make_upload_directory( $this->file_area_name($userid) );
1010 if ($this->assignment
->preventlate
) {
1011 return ($this->assignment
->timeavailable
<= $time && $time <= $this->assignment
->timedue
);
1013 return ($this->assignment
->timeavailable
<= $time);
1017 function user_outline($user) {
1018 if ($submission = $this->get_submission($user->id
)) {
1020 if ($submission->grade
) {
1021 $result->info
= get_string('grade').': '.$this->display_grade($submission->grade
);
1023 $result->time
= $submission->timemodified
;
1029 function user_complete($user) {
1030 if ($submission = $this->get_submission($user->id
)) {
1031 if ($basedir = $this->file_area($user->id
)) {
1032 if ($files = get_directory_list($basedir)) {
1033 $countfiles = count($files)." ".get_string("uploadedfiles", "assignment");
1034 foreach ($files as $file) {
1035 $countfiles .= "; $file";
1040 print_simple_box_start();
1041 echo get_string("lastmodified").": ";
1042 echo userdate($submission->timemodified
);
1043 echo $this->display_lateness($submission->timemodified
);
1045 $this->print_user_files($user->id
);
1049 if (empty($submission->timemarked
)) {
1050 print_string("notgradedyet", "assignment");
1052 $this->view_feedback($submission);
1055 print_simple_box_end();
1058 print_string("notsubmittedyet", "assignment");
1062 function display_lateness($timesubmitted) {
1063 $time = $this->assignment
->timedue
- $timesubmitted;
1065 $timetext = get_string('late', 'assignment', format_time($time));
1066 return ' (<span class="late">'.$timetext.'</span>)';
1068 $timetext = get_string('early', 'assignment', format_time($time));
1069 return ' (<span class="early">'.$timetext.'</span>)';
1077 } ////// End of the assignment_base class
1081 /// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////
1084 function assignment_delete_instance($id){
1087 if (! $assignment = get_record('assignment', 'id', $id)) {
1091 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1092 $assignmentclass = "assignment_$assignment->assignmenttype";
1093 $ass = new $assignmentclass();
1094 return $ass->delete_instance($assignment);
1098 function assignment_update_instance($assignment){
1101 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1102 $assignmentclass = "assignment_$assignment->assignmenttype";
1103 $ass = new $assignmentclass();
1104 return $ass->update_instance($assignment);
1108 function assignment_add_instance($assignment) {
1111 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1112 $assignmentclass = "assignment_$assignment->assignmenttype";
1113 $ass = new $assignmentclass();
1114 return $ass->add_instance($assignment);
1118 function assignment_user_outline($course, $user, $mod, $assignment) {
1121 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1122 $assignmentclass = "assignment_$assignment->assignmenttype";
1123 $ass = new $assignmentclass($mod->id
, $assignment, $mod, $course);
1124 return $ass->user_outline($user);
1127 function assignment_user_complete($course, $user, $mod, $assignment) {
1130 require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
1131 $assignmentclass = "assignment_$assignment->assignmenttype";
1132 $ass = new $assignmentclass($mod->id
, $assignment, $mod, $course);
1133 return $ass->user_complete($user);
1137 function assignment_cron () {
1138 // Function to be run periodically according to the moodle cron
1139 // Finds all assignment notifications that have yet to be mailed out, and mails them
1143 /// Notices older than 1 day will not be mailed. This is to avoid the problem where
1144 /// cron has not been running for a long time, and then suddenly people are flooded
1145 /// with mail from the past few weeks or months
1148 $endtime = $timenow - $CFG->maxeditingtime
;
1149 $starttime = $endtime - 24 * 3600; /// One day earlier
1151 if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) {
1153 foreach ($submissions as $key => $submission) {
1154 if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) {
1155 echo "Could not update the mailed field for id $submission->id. Not mailed.\n";
1156 unset($submissions[$key]);
1162 foreach ($submissions as $submission) {
1164 echo "Processing assignment submission $submission->id\n";
1166 if (! $user = get_record("user", "id", "$submission->userid")) {
1167 echo "Could not find user $post->userid\n";
1171 $USER->lang
= $user->lang
;
1173 if (! $course = get_record("course", "id", "$submission->course")) {
1174 echo "Could not find course $submission->course\n";
1178 if (! isstudent($course->id
, $user->id
) and !isteacher($course->id
, $user->id
)) {
1179 echo fullname($user)." not an active participant in $course->shortname\n";
1183 if (! $teacher = get_record("user", "id", "$submission->teacher")) {
1184 echo "Could not find teacher $submission->teacher\n";
1188 if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment
, $course->id
)) {
1189 echo "Could not find course module for assignment id $submission->assignment\n";
1193 if (! $mod->visible
) { /// Hold mail notification for hidden assignments until later
1197 $strassignments = get_string("modulenameplural", "assignment");
1198 $strassignment = get_string("modulename", "assignment");
1200 unset($assignmentinfo);
1201 $assignmentinfo->teacher
= fullname($teacher);
1202 $assignmentinfo->assignment
= format_string($submission->name
,true);
1203 $assignmentinfo->url
= "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id";
1205 $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name
,true);
1206 $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name
,true)."\n";
1207 $posttext .= "---------------------------------------------------------------------\n";
1208 $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo);
1209 $posttext .= "---------------------------------------------------------------------\n";
1211 if ($user->mailformat
== 1) { // HTML
1212 $posthtml = "<p><font face=\"sans-serif\">".
1213 "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
1214 "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
1215 "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name
,true)."</a></font></p>";
1216 $posthtml .= "<hr /><font face=\"sans-serif\">";
1217 $posthtml .= "<p>".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."</p>";
1218 $posthtml .= "</font><hr />";
1223 if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) {
1224 echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n";
1232 function assignment_grades($assignmentid) {
1233 /// Must return an array of grades, indexed by user, and a max grade.
1236 if (!$assignment = get_record("assignment", "id", $assignmentid)) {
1240 $grades = get_records_menu("assignment_submissions", "assignment",
1241 $assignment->id
, "", "userid,grade");
1243 if ($assignment->grade
>= 0) {
1244 $return->grades
= $grades;
1245 $return->maxgrade
= $assignment->grade
;
1249 $scaleid = - ($assignment->grade
);
1250 if ($scale = get_record('scale', 'id', $scaleid)) {
1251 $scalegrades = make_menu_from_list($scale->scale
);
1252 foreach ($grades as $key => $grade) {
1253 $grades[$key] = $scalegrades[$grade];
1257 $return->grades
= $grades;
1258 $return->maxgrade
= "";
1264 function assignment_get_participants($assignmentid) {
1265 //Returns the users with data in one assignment
1266 //(users with records in assignment_submissions, students and teachers)
1271 $students = get_records_sql("SELECT DISTINCT u.id, u.id
1272 FROM {$CFG->prefix}user u,
1273 {$CFG->prefix}assignment_submissions a
1274 WHERE a.assignment = '$assignmentid' and
1277 $teachers = get_records_sql("SELECT DISTINCT u.id, u.id
1278 FROM {$CFG->prefix}user u,
1279 {$CFG->prefix}assignment_submissions a
1280 WHERE a.assignment = '$assignmentid' and
1283 //Add teachers to students
1285 foreach ($teachers as $teacher) {
1286 $students[$teacher->id
] = $teacher;
1289 //Return students array (it contains an array of unique users)
1294 function assignment_scale_used ($assignmentid,$scaleid) {
1295 //This function returns if a scale is being used by one assignment
1299 $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid);
1301 if (!empty($rec) && !empty($scaleid)) {
1309 function assignment_refresh_events($courseid = 0) {
1310 // This standard function will check all instances of this module
1311 // and make sure there are up-to-date events created for each of them.
1312 // If courseid = 0, then every assignment event in the site is checked, else
1313 // only assignment events belonging to the course specified are checked.
1314 // This function is used, in its new format, by restore_refresh_events()
1316 if ($courseid == 0) {
1317 if (! $assignments = get_records("assignment")) {
1321 if (! $assignments = get_records("assignment", "course", $courseid)) {
1325 $moduleid = get_field('modules', 'id', 'name', 'assignment');
1327 foreach ($assignments as $assignment) {
1329 $event->name
= addslashes($assignment->name
);
1330 $event->description
= addslashes($assignment->description
);
1331 $event->timestart
= $assignment->timedue
;
1333 if ($event->id
= get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id
)) {
1334 update_event($event);
1337 $event->courseid
= $assignment->course
;
1338 $event->groupid
= 0;
1340 $event->modulename
= 'assignment';
1341 $event->instance
= $assignment->id
;
1342 $event->eventtype
= 'due';
1343 $event->timeduration
= 0;
1344 $event->visible
= get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id
);
1353 function assignment_print_recent_activity($course, $isteacher, $timestart) {
1357 $assignments = NULL;
1359 if (!$logs = get_records_select('log', 'time > \''.$timestart.'\' AND '.
1360 'course = \''.$course->id
.'\' AND '.
1361 'module = \'assignment\' AND '.
1362 'action = \'upload\' ', 'time ASC')) {
1366 foreach ($logs as $log) {
1367 //Create a temp valid module structure (course,id)
1368 $tempmod->course
= $log->course
;
1369 $tempmod->id
= $log->info
;
1370 //Obtain the visible property from the instance
1371 $modvisible = instance_is_visible($log->module
,$tempmod);
1373 //Only if the mod is visible
1375 $assignments[$log->info
] = assignment_log_info($log);
1376 $assignments[$log->info
]->time
= $log->time
;
1377 $assignments[$log->info
]->url
= str_replace('&', '&', $log->url
);
1382 print_headline(get_string('newsubmissions', 'assignment').':');
1383 foreach ($assignments as $assignment) {
1384 print_recent_activity_note($assignment->time
, $assignment, $isteacher, $assignment->name
,
1385 $CFG->wwwroot
.'/mod/assignment/'.$assignment->url
);
1395 function assignment_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $assignment="0", $user="", $groupid="") {
1396 // Returns all assignments since a given time. If assignment is specified then
1397 // this restricts the results
1402 $assignmentselect = " AND cm.id = '$assignment'";
1404 $assignmentselect = "";
1407 $userselect = " AND u.id = '$user'";
1412 $assignments = get_records_sql("SELECT asub.*, u.firstname, u.lastname, u.picture, u.id as userid,
1413 a.grade as maxgrade, name, cm.instance, cm.section, a.assignmenttype
1414 FROM {$CFG->prefix}assignment_submissions asub,
1415 {$CFG->prefix}user u,
1416 {$CFG->prefix}assignment a,
1417 {$CFG->prefix}course_modules cm
1418 WHERE asub.timemodified > '$sincetime'
1419 AND asub.userid = u.id $userselect
1420 AND a.id = asub.assignment $assignmentselect
1421 AND cm.course = '$courseid'
1422 AND cm.instance = a.id
1423 ORDER BY asub.timemodified ASC");
1425 if (empty($assignments))
1428 foreach ($assignments as $assignment) {
1429 if (empty($groupid) ||
ismember($groupid, $assignment->userid
)) {
1431 $tmpactivity = new Object;
1433 $tmpactivity->type
= "assignment";
1434 $tmpactivity->defaultindex
= $index;
1435 $tmpactivity->instance
= $assignment->instance
;
1436 $tmpactivity->name
= $assignment->name
;
1437 $tmpactivity->section
= $assignment->section
;
1439 $tmpactivity->content
->grade
= $assignment->grade
;
1440 $tmpactivity->content
->maxgrade
= $assignment->maxgrade
;
1441 $tmpactivity->content
->type
= $assignment->assignmenttype
;
1443 $tmpactivity->user
->userid
= $assignment->userid
;
1444 $tmpactivity->user
->fullname
= fullname($assignment);
1445 $tmpactivity->user
->picture
= $assignment->picture
;
1447 $tmpactivity->timestamp
= $assignment->timemodified
;
1449 $activities[] = $tmpactivity;
1459 function assignment_print_recent_mod_activity($activity, $course, $detail=false) {
1462 echo '<table border="0" cellpadding="3" cellspacing="0">';
1464 echo "<tr><td class=\"userpicture\" width=\"35\" valign=\"top\">";
1465 print_user_picture($activity->user
->userid
, $course, $activity->user
->picture
);
1466 echo "</td><td width=\"100%\"><font size=2>";
1469 echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
1470 "height=16 width=16 alt=\"$activity->type\"> ";
1471 echo "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=" . $activity->instance
. "\">"
1472 . format_string($activity->name
,true) . "</a> - ";
1476 if (isteacher($course)) {
1477 $grades = "(" . $activity->content
->grade
. " / " . $activity->content
->maxgrade
. ") ";
1479 $assignment->id
= $activity->instance
;
1480 $assignment->course
= $course;
1481 $user->id
= $activity->user
->userid
;
1486 echo "<a href=\"$CFG->wwwroot/user/view.php?id="
1487 . $activity->user
->userid
. "&course=$course\">"
1488 . $activity->user
->fullname
. "</a> ";
1490 echo " - " . userdate($activity->timestamp
);
1492 echo "</font></td></tr>";
1498 /// GENERIC SQL FUNCTIONS
1500 function assignment_log_info($log) {
1502 return get_record_sql("SELECT a.name, u.firstname, u.lastname
1503 FROM {$CFG->prefix}assignment a,
1504 {$CFG->prefix}user u
1505 WHERE a.id = '$log->info'
1506 AND u.id = '$log->userid'");
1509 function assignment_get_unmailed_submissions($starttime, $endtime) {
1510 /// Return list of marked submissions that have not been mailed out for currently enrolled students
1512 return get_records_sql("SELECT s.*, a.course, a.name
1513 FROM {$CFG->prefix}assignment_submissions s,
1514 {$CFG->prefix}assignment a,
1515 {$CFG->prefix}user_students us
1517 AND s.timemarked <= $endtime
1518 AND s.timemarked >= $starttime
1519 AND s.assignment = a.id
1520 AND s.userid = us.userid
1521 AND a.course = us.course");
1524 function assignment_count_real_submissions($assignment, $groupid=0) {
1525 /// Return all real assignment submissions by ENROLLED students (not empty ones)
1528 if ($groupid) { /// How many in a particular group?
1529 return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
1530 FROM {$CFG->prefix}assignment_submissions a,
1531 {$CFG->prefix}groups_members g
1532 WHERE a.assignment = $assignment->id
1533 AND a.timemodified > 0
1534 AND g.groupid = '$groupid'
1535 AND a.userid = g.userid ");
1537 $select = "s.course = '$assignment->course' AND";
1538 if ($assignment->course
== SITEID
) {
1541 return count_records_sql("SELECT COUNT(*)
1542 FROM {$CFG->prefix}assignment_submissions a,
1543 {$CFG->prefix}user_students s
1544 WHERE a.assignment = '$assignment->id'
1545 AND a.timemodified > 0
1546 AND $select a.userid = s.userid ");
1550 function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") {
1551 /// Return all assignment submissions by ENROLLED students (even empty)
1554 if ($sort == "lastname" or $sort == "firstname") {
1555 $sort = "u.$sort $dir";
1556 } else if (empty($sort)) {
1557 $sort = "a.timemodified DESC";
1559 $sort = "a.$sort $dir";
1562 $select = "s.course = '$assignment->course' AND";
1563 if ($assignment->course
== SITEID
) {
1566 return get_records_sql("SELECT a.*
1567 FROM {$CFG->prefix}assignment_submissions a,
1568 {$CFG->prefix}user_students s,
1569 {$CFG->prefix}user u
1570 WHERE a.userid = s.userid
1572 AND $select a.assignment = '$assignment->id'
1579 /// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS ///////////////////////////////////////
1582 function assignment_types() {
1584 $names = get_list_of_plugins('mod/assignment/type');
1585 foreach ($names as $name) {
1586 $types[$name] = get_string('type'.$name, 'assignment');
1592 function assignment_upgrade_submodules() {
1595 $types = assignment_types();
1597 include($CFG->dirroot
.'/mod/assignment/version.php'); // defines $module with version etc
1599 foreach ($types as $type => $typename) {
1601 $fullpath = $CFG->dirroot
.'/mod/assignment/type/'.$type;
1603 /// Check for an external version file (defines $submodule)
1605 if (!is_readable($fullpath .'/version.php')) {
1608 include_once($fullpath .'/version.php');
1610 /// Check whether we need to upgrade
1612 if (!isset($submodule->version
)) {
1616 /// Make sure this submodule will work with this assignment version
1618 if (isset($submodule->requires
) and ($submodule->requires
> $module->version
)) {
1619 notify("Assignment submodule '$type' is too new for your assignment");
1623 /// If we use versions, make sure an internal record exists
1625 $currentversion = 'assignment_'.$type.'_version';
1627 if (!isset($CFG->$currentversion)) {
1628 set_config($currentversion, 0);
1631 /// See if we need to upgrade
1633 if ($submodule->version
<= $CFG->$currentversion) {
1637 /// Look for the upgrade file
1639 if (!is_readable($fullpath .'/db/'.$CFG->dbtype
.'.php')) {
1643 include_once($fullpath .'/db/'. $CFG->dbtype
.'.php'); // defines assignment_xxx_upgrade
1645 /// Perform the upgrade
1647 $upgrade_function = 'assignment_'.$type.'_upgrade';
1648 if (function_exists($upgrade_function)) {
1650 if ($upgrade_function($CFG->$currentversion)) {
1652 set_config($currentversion, $submodule->version
);