diff -Naur moodle_assignment_work_1.9.4_Pure/lang/en_utf8/assignment.php moodle_assignment_work_1.9.4_Modified/lang/en_utf8/assignment.php --- moodle_assignment_work_1.9.4_Pure/lang/en_utf8/assignment.php 2008-02-28 10:15:14.000000000 +0000 +++ moodle_assignment_work_1.9.4_Modified/lang/en_utf8/assignment.php 2009-04-23 15:43:50.000000000 +0100 @@ -1,142 +1,144 @@ -teacher has posted some feedback on your -assignment submission for \'$a->assignment\' - -You can see it appended to your assignment submission: - - $a->url'; -$string['assignmentmailhtml'] = '$a->teacher has posted some feedback on your -assignment submission for \'$a->assignment\'

-You can see it appended to your url\">assignment submission.'; -$string['assignmentname'] = 'Assignment name'; -$string['assignmenttype'] = 'Assignment type'; -$string['availabledate'] = 'Available from'; -$string['cannotdeletefiles'] = 'An error occurred and files could not be deleted'; -$string['comment'] = 'Comment'; -$string['commentinline'] = 'Comment inline'; -$string['configitemstocount'] = 'Nature of items to be counted for student submissions in online assignments.'; -$string['configmaxbytes'] = 'Default maximum assignment size for all assignments on the site (subject to course limits and other local settings)'; -$string['configshowrecentsubmissions'] = 'Everyone can see notifications of submissions in recent activity reports.'; -$string['confirmdeletefile'] = 'Are you absolutely sure you want to delete this file?
$a'; -$string['deleteallsubmissions'] = 'Delete all submissions'; -$string['deletefilefailed'] = 'Deleting of file failed.'; -$string['description'] = 'Description'; -$string['draft'] = 'Draft'; -$string['duedate'] = 'Due date'; -$string['duedateno'] = 'No due date'; -$string['early'] = '$a early'; -$string['editmysubmission'] = 'Edit my submission'; -$string['emailstudents'] = 'Email alerts to students'; -$string['emailteachermail'] = '$a->username has updated their assignment submission -for \'$a->assignment\' - -It is available here: - - $a->url'; -$string['emailteachermailhtml'] = '$a->username has updated their assignment submission -for \'$a->assignment\'

-It is url\">available on the web site.'; -$string['emailteachers'] = 'Email alerts to teachers'; -$string['emptysubmission'] = 'You have not submitted anything yet'; -$string['enableemailnotification'] = 'Send notification emails'; -$string['existingfiledeleted'] = 'Existing file has been deleted: $a'; -$string['failedupdatefeedback'] = 'Failed to update submission feedback for user $a'; -$string['feedback'] = 'Feedback'; -$string['feedbackfromteacher'] = 'Feedback from the $a'; -$string['feedbackupdated'] = 'Submissions feedback updated for $a people'; -$string['finalize'] = 'No more submissions'; -$string['finalizeerror'] = 'An error occurred and that submission could not be finalised'; -$string['graded'] = 'Graded'; -$string['guestnosubmit'] = 'Sorry, guests are not allowed to submit an assignment. You have to log in/ register before you can submit your answer'; -$string['guestnoupload'] = 'Sorry, guests are not allowed to upload'; -$string['helpoffline'] = '

This is useful when the assignment is performed outside of Moodle. It could be - something elsewhere on the web or face-to-face.

Students can see a description of the assignment, - but can\'t upload files or anything. Grading works normally, and students will get notifications of - their grades.

'; -$string['helponline'] = '

This assignment type asks users to edit a text, using the normal - editing tools. Teachers can grade them online, and even add inline comments or changes.

-

(If you are familiar with older versions of Moodle, this Assignment - type does the same thing as the old Journal module used to do.)

'; -$string['helpupload'] = '

This type of assignment allows each participant to upload one or more files in any format. - These might be a Word processor documents, images, a zipped web site, or anything you ask them to submit.

-

This type also allows you to upload multiple response files. Response files can be also uploaded before submission which - can be used to give each participant different file to work with.

-

Participants may also enter notes describing the submitted files, progress status or any other text information.

-

Submission of this type of assignment must be manually finalised by the participant. You can review the current status - at any time, unfinished assignments are marked as Draft. You can revert any ungraded assignment back to draft status.

'; -$string['helpuploadsingle'] = '

This type of assignment allows each participant to upload a - single file, of any type.

This might be a Word processor document, an image, - a zipped web site, or anything you ask them to submit.

'; -$string['hideintro'] = 'Hide description before available date'; -$string['itemstocount'] = 'Count'; -$string['late'] = '$a late'; -$string['maximumgrade'] = 'Maximum grade'; -$string['maximumsize'] = 'Maximum size'; -$string['modulename'] = 'Assignment'; -$string['modulenameplural'] = 'Assignments'; -$string['newsubmissions'] = 'Assignments submitted'; -$string['noassignments'] = 'There are no assignments yet'; -$string['noattempts'] = 'No attempts have been made on this assignment'; -$string['nofiles'] = 'No files were submitted'; -$string['nofilesyet'] = 'No files submitted yet'; -$string['nomoresubmissions'] = 'No further submissions are allowed.'; -$string['notavailableyet'] = 'Sorry, this assignment is not yet available.
Assignment instructions will be displayed here on the date given below.'; -$string['notes'] = 'Notes'; -$string['notesempty'] = 'No entry'; -$string['notesupdateerror'] = 'Error when updating notes'; -$string['notgradedyet'] = 'Not graded yet'; -$string['notsubmittedyet'] = 'Not submitted yet'; -$string['nosubmitusers'] = 'No users were found with permissions to submit this assignment'; -$string['onceassignmentsent'] = 'Once the assignment is sent for marking, you will no longer be able to delete or attach file(s). Do you want to continue?'; -$string['overwritewarning'] = 'Warning: uploading again will REPLACE your current submission'; -$string['pagesize'] = 'Submissions shown per page'; -$string['preventlate'] = 'Prevent late submissions'; -$string['quickgrade'] = 'Allow quick grading'; -$string['responsefiles'] = 'Response files'; -$string['reviewed'] = 'Reviewed'; -$string['saveallfeedback'] = 'Save all my feedback'; -$string['sendformarking'] = 'Send for marking'; -$string['showrecentsubmissions'] = 'Show recent submissions'; -$string['submission'] = 'Submission'; -$string['submissiondraft'] = 'Submission draft'; -$string['submissionfeedback'] = 'Submission feedback'; -$string['submissions'] = 'Submissions'; -$string['submissionsaved'] = 'Your changes have been saved'; -$string['submissionsnotgraded'] = '$a submissions not graded'; -$string['submitassignment'] = 'Submit your assignment using this form'; -$string['submitedformarking'] = 'Assignment was already submitted for marking and can not be updated'; -$string['submitformarking'] = 'Final submission for assignment marking'; -$string['submitted'] = 'Submitted'; -$string['submittedfiles'] = 'Submitted files'; -$string['trackdrafts'] = 'Enable Send for marking'; -$string['typeoffline'] = 'Offline activity'; -$string['typeonline'] = 'Online text'; -$string['typeupload'] = 'Advanced uploading of files'; -$string['typeuploadsingle'] = 'Upload a single file'; -$string['unfinalize'] = 'Revert to draft'; -$string['unfinalizeerror'] = 'An error occurred and that submission could not be reverted to draft'; -$string['uploadbadname'] = 'This filename contained strange characters and couldn\'t be uploaded'; -$string['uploadedfiles'] = 'uploaded files'; -$string['uploaderror'] = 'An error happened while saving the file on the server'; -$string['uploadfailnoupdate'] = 'File was uploaded OK but could not update your submission!'; -$string['uploadfiletoobig'] = 'Sorry, but that file is too big (limit is $a bytes)'; -$string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?'; -$string['uploadnotregistered'] = '\'$a\' was uploaded OK but submission did not register!'; -$string['uploadsuccess'] = 'Uploaded \'$a\' successfully'; -$string['viewfeedback'] = 'View assignment grades and feedback'; -$string['viewsubmissions'] = 'View $a submitted assignments'; -$string['yoursubmission'] = 'Your submission'; - -?> +teacher has posted some feedback on your +assignment submission for \'$a->assignment\' + +You can see it appended to your assignment submission: + + $a->url'; +$string['assignmentmailhtml'] = '$a->teacher has posted some feedback on your +assignment submission for \'$a->assignment\'

+You can see it appended to your url\">assignment submission.'; +$string['assignmentname'] = 'Assignment name'; +$string['assignmenttemplatefile'] = 'Assignment template location'; +$string['assignmenttemplatetext'] = 'Assignment template text'; +$string['assignmenttype'] = 'Assignment type'; +$string['availabledate'] = 'Available from'; +$string['cannotdeletefiles'] = 'An error occurred and files could not be deleted'; +$string['comment'] = 'Comment'; +$string['commentinline'] = 'Comment inline'; +$string['configitemstocount'] = 'Nature of items to be counted for student submissions in online assignments.'; +$string['configmaxbytes'] = 'Default maximum assignment size for all assignments on the site (subject to course limits and other local settings)'; +$string['configshowrecentsubmissions'] = 'Everyone can see notifications of submissions in recent activity reports.'; +$string['confirmdeletefile'] = 'Are you absolutely sure you want to delete this file?
$a'; +$string['deleteallsubmissions'] = 'Delete all submissions'; +$string['deletefilefailed'] = 'Deleting of file failed.'; +$string['description'] = 'Description'; +$string['draft'] = 'Draft'; +$string['duedate'] = 'Due date'; +$string['duedateno'] = 'No due date'; +$string['early'] = '$a early'; +$string['editmysubmission'] = 'Edit my submission'; +$string['emailstudents'] = 'Email alerts to students'; +$string['emailteachermail'] = '$a->username has updated their assignment submission +for \'$a->assignment\' + +It is available here: + + $a->url'; +$string['emailteachermailhtml'] = '$a->username has updated their assignment submission +for \'$a->assignment\'

+It is url\">available on the web site.'; +$string['emailteachers'] = 'Email alerts to teachers'; +$string['emptysubmission'] = 'You have not submitted anything yet'; +$string['enableemailnotification'] = 'Send notification emails'; +$string['existingfiledeleted'] = 'Existing file has been deleted: $a'; +$string['failedupdatefeedback'] = 'Failed to update submission feedback for user $a'; +$string['feedback'] = 'Feedback'; +$string['feedbackfromteacher'] = 'Feedback from the $a'; +$string['feedbackupdated'] = 'Submissions feedback updated for $a people'; +$string['finalize'] = 'No more submissions'; +$string['finalizeerror'] = 'An error occurred and that submission could not be finalised'; +$string['graded'] = 'Graded'; +$string['guestnosubmit'] = 'Sorry, guests are not allowed to submit an assignment. You have to log in/ register before you can submit your answer'; +$string['guestnoupload'] = 'Sorry, guests are not allowed to upload'; +$string['helpoffline'] = '

This is useful when the assignment is performed outside of Moodle. It could be + something elsewhere on the web or face-to-face.

Students can see a description of the assignment, + but can\'t upload files or anything. Grading works normally, and students will get notifications of + their grades.

'; +$string['helponline'] = '

This assignment type asks users to edit a text, using the normal + editing tools. Teachers can grade them online, and even add inline comments or changes.

+

(If you are familiar with older versions of Moodle, this Assignment + type does the same thing as the old Journal module used to do.)

'; +$string['helpupload'] = '

This type of assignment allows each participant to upload one or more files in any format. + These might be a Word processor documents, images, a zipped web site, or anything you ask them to submit.

+

This type also allows you to upload multiple response files. Response files can be also uploaded before submission which + can be used to give each participant different file to work with.

+

Participants may also enter notes describing the submitted files, progress status or any other text information.

+

Submission of this type of assignment must be manually finalised by the participant. You can review the current status + at any time, unfinished assignments are marked as Draft. You can revert any ungraded assignment back to draft status.

'; +$string['helpuploadsingle'] = '

This type of assignment allows each participant to upload a + single file, of any type.

This might be a Word processor document, an image, + a zipped web site, or anything you ask them to submit.

'; +$string['hideintro'] = 'Hide description before available date'; +$string['itemstocount'] = 'Count'; +$string['late'] = '$a late'; +$string['maximumgrade'] = 'Maximum grade'; +$string['maximumsize'] = 'Maximum size'; +$string['modulename'] = 'Assignment'; +$string['modulenameplural'] = 'Assignments'; +$string['newsubmissions'] = 'Assignments submitted'; +$string['noassignments'] = 'There are no assignments yet'; +$string['noattempts'] = 'No attempts have been made on this assignment'; +$string['nofiles'] = 'No files were submitted'; +$string['nofilesyet'] = 'No files submitted yet'; +$string['nomoresubmissions'] = 'No further submissions are allowed.'; +$string['notavailableyet'] = 'Sorry, this assignment is not yet available.
Assignment instructions will be displayed here on the date given below.'; +$string['notes'] = 'Notes'; +$string['notesempty'] = 'No entry'; +$string['notesupdateerror'] = 'Error when updating notes'; +$string['notgradedyet'] = 'Not graded yet'; +$string['notsubmittedyet'] = 'Not submitted yet'; +$string['nosubmitusers'] = 'No users were found with permissions to submit this assignment'; +$string['onceassignmentsent'] = 'Once the assignment is sent for marking, you will no longer be able to delete or attach file(s). Do you want to continue?'; +$string['overwritewarning'] = 'Warning: uploading again will REPLACE your current submission'; +$string['pagesize'] = 'Submissions shown per page'; +$string['preventlate'] = 'Prevent late submissions'; +$string['quickgrade'] = 'Allow quick grading'; +$string['responsefiles'] = 'Response files'; +$string['reviewed'] = 'Reviewed'; +$string['saveallfeedback'] = 'Save all my feedback'; +$string['sendformarking'] = 'Send for marking'; +$string['showrecentsubmissions'] = 'Show recent submissions'; +$string['submission'] = 'Submission'; +$string['submissiondraft'] = 'Submission draft'; +$string['submissionfeedback'] = 'Submission feedback'; +$string['submissions'] = 'Submissions'; +$string['submissionsaved'] = 'Your changes have been saved'; +$string['submissionsnotgraded'] = '$a submissions not graded'; +$string['submitassignment'] = 'Submit your assignment using this form'; +$string['submitedformarking'] = 'Assignment was already submitted for marking and can not be updated'; +$string['submitformarking'] = 'Final submission for assignment marking'; +$string['submitted'] = 'Submitted'; +$string['submittedfiles'] = 'Submitted files'; +$string['trackdrafts'] = 'Enable Send for marking'; +$string['typeoffline'] = 'Offline activity'; +$string['typeonline'] = 'Online text'; +$string['typeupload'] = 'Advanced uploading of files'; +$string['typeuploadsingle'] = 'Upload a single file'; +$string['unfinalize'] = 'Revert to draft'; +$string['unfinalizeerror'] = 'An error occurred and that submission could not be reverted to draft'; +$string['uploadbadname'] = 'This filename contained strange characters and couldn\'t be uploaded'; +$string['uploadedfiles'] = 'uploaded files'; +$string['uploaderror'] = 'An error happened while saving the file on the server'; +$string['uploadfailnoupdate'] = 'File was uploaded OK but could not update your submission!'; +$string['uploadfiletoobig'] = 'Sorry, but that file is too big (limit is $a bytes)'; +$string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?'; +$string['uploadnotregistered'] = '\'$a\' was uploaded OK but submission did not register!'; +$string['uploadsuccess'] = 'Uploaded \'$a\' successfully'; +$string['viewfeedback'] = 'View assignment grades and feedback'; +$string['viewsubmissions'] = 'View $a submitted assignments'; +$string['yoursubmission'] = 'Your submission'; + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/lang/en_utf8/help/assignment/template.html moodle_assignment_work_1.9.4_Modified/lang/en_utf8/help/assignment/template.html --- moodle_assignment_work_1.9.4_Pure/lang/en_utf8/help/assignment/template.html 1970-01-01 01:00:00.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/lang/en_utf8/help/assignment/template.html 2009-04-24 09:45:24.000000000 +0100 @@ -0,0 +1,8 @@ +

Assignment Templates

+ +

This optional feature lets you upload a document for students. This might be a front + sheet, a quiz sheet, an example document or a zip file of many resources.

+ +

The template text box specifies the name the file have when students see it.

+ +

The template location box is the location of the file. Use the 'Choose or upload a file' button to set this.

diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/backuplib.php moodle_assignment_work_1.9.4_Modified/mod/assignment/backuplib.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/backuplib.php 2006-09-22 10:02:08.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/backuplib.php 2009-04-23 15:52:54.000000000 +0100 @@ -1,272 +1,310 @@ -id) - // | - // | - // | - // assignment_submisions - // (UL,pk->id, fk->assignment,files) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // nt->nested field (recursive data) - // CL->course level info - // UL->user level info - // files->table may have files) - // - //----------------------------------------------------------- - - //This function executes all the backup procedure about this mod - function assignment_backup_mods($bf,$preferences) { - - global $CFG; - - $status = true; - - //Iterate over assignment table - $assignments = get_records ("assignment","course",$preferences->backup_course,"id"); - if ($assignments) { - foreach ($assignments as $assignment) { - if (backup_mod_selected($preferences,'assignment',$assignment->id)) { - $status = assignment_backup_one_mod($bf,$preferences,$assignment); - // backup files happens in backup_one_mod now too. - } - } - } - return $status; - } - - function assignment_backup_one_mod($bf,$preferences,$assignment) { - - global $CFG; - - if (is_numeric($assignment)) { - $assignment = get_record('assignment','id',$assignment); - } - - $status = true; - - //Start mod - fwrite ($bf,start_tag("MOD",3,true)); - //Print assignment data - fwrite ($bf,full_tag("ID",4,false,$assignment->id)); - fwrite ($bf,full_tag("MODTYPE",4,false,"assignment")); - fwrite ($bf,full_tag("NAME",4,false,$assignment->name)); - fwrite ($bf,full_tag("DESCRIPTION",4,false,$assignment->description)); - fwrite ($bf,full_tag("FORMAT",4,false,$assignment->format)); - fwrite ($bf,full_tag("RESUBMIT",4,false,$assignment->resubmit)); - fwrite ($bf,full_tag("PREVENTLATE",4,false,$assignment->preventlate)); - fwrite ($bf,full_tag("EMAILTEACHERS",4,false,$assignment->emailteachers)); - fwrite ($bf,full_tag("VAR1",4,false,$assignment->var1)); - fwrite ($bf,full_tag("VAR2",4,false,$assignment->var2)); - fwrite ($bf,full_tag("VAR3",4,false,$assignment->var3)); - fwrite ($bf,full_tag("VAR4",4,false,$assignment->var4)); - fwrite ($bf,full_tag("VAR5",4,false,$assignment->var5)); - fwrite ($bf,full_tag("ASSIGNMENTTYPE",4,false,$assignment->assignmenttype)); - fwrite ($bf,full_tag("MAXBYTES",4,false,$assignment->maxbytes)); - fwrite ($bf,full_tag("TIMEDUE",4,false,$assignment->timedue)); - fwrite ($bf,full_tag("TIMEAVAILABLE",4,false,$assignment->timeavailable)); - fwrite ($bf,full_tag("GRADE",4,false,$assignment->grade)); - fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$assignment->timemodified)); - //if we've selected to backup users info, then execute backup_assignment_submisions and - //backup_assignment_files_instance - if (backup_userdata_selected($preferences,'assignment',$assignment->id)) { - $status = backup_assignment_submissions($bf,$preferences,$assignment->id); - if ($status) { - $status = backup_assignment_files_instance($bf,$preferences,$assignment->id); - } - } - //End mod - $status =fwrite ($bf,end_tag("MOD",3,true)); - - return $status; - } - - //Backup assignment_submissions contents (executed from assignment_backup_mods) - function backup_assignment_submissions ($bf,$preferences,$assignment) { - - global $CFG; - - $status = true; - - $assignment_submissions = get_records("assignment_submissions","assignment",$assignment,"id"); - //If there is submissions - if ($assignment_submissions) { - //Write start tag - $status =fwrite ($bf,start_tag("SUBMISSIONS",4,true)); - //Iterate over each submission - foreach ($assignment_submissions as $ass_sub) { - //Start submission - $status =fwrite ($bf,start_tag("SUBMISSION",5,true)); - //Print submission contents - fwrite ($bf,full_tag("ID",6,false,$ass_sub->id)); - fwrite ($bf,full_tag("USERID",6,false,$ass_sub->userid)); - fwrite ($bf,full_tag("TIMECREATED",6,false,$ass_sub->timecreated)); - fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$ass_sub->timemodified)); - fwrite ($bf,full_tag("NUMFILES",6,false,$ass_sub->numfiles)); - fwrite ($bf,full_tag("DATA1",6,false,$ass_sub->data1)); - fwrite ($bf,full_tag("DATA2",6,false,$ass_sub->data2)); - fwrite ($bf,full_tag("GRADE",6,false,$ass_sub->grade)); - fwrite ($bf,full_tag("SUBMISSIONCOMMENT",6,false,$ass_sub->submissioncomment)); - fwrite ($bf,full_tag("FORMAT",6,false,$ass_sub->format)); - fwrite ($bf,full_tag("TEACHER",6,false,$ass_sub->teacher)); - fwrite ($bf,full_tag("TIMEMARKED",6,false,$ass_sub->timemarked)); - fwrite ($bf,full_tag("MAILED",6,false,$ass_sub->mailed)); - //End submission - $status =fwrite ($bf,end_tag("SUBMISSION",5,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("SUBMISSIONS",4,true)); - } - return $status; - } - - //Backup assignment files because we've selected to backup user info - //and files are user info's level - function backup_assignment_files($bf,$preferences) { - - global $CFG; - - $status = true; - - //First we check to moddata exists and create it as necessary - //in temp/backup/$backup_code dir - $status = check_and_create_moddata_dir($preferences->backup_unique_code); - //Now copy the assignment dir - if ($status) { - //Only if it exists !! Thanks to Daniel Miksik. - if (is_dir($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment")) { - $status = backup_copy_file($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment", - $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment"); - } - } - - return $status; - - } - - function backup_assignment_files_instance($bf,$preferences,$instanceid) { - - global $CFG; - - $status = true; - - //First we check to moddata exists and create it as necessary - //in temp/backup/$backup_code dir - $status = check_and_create_moddata_dir($preferences->backup_unique_code); - $status = check_dir_exists($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment/",true); - //Now copy the assignment dir - if ($status) { - //Only if it exists !! Thanks to Daniel Miksik. - if (is_dir($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment/".$instanceid)) { - $status = backup_copy_file($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment/".$instanceid, - $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment/".$instanceid); - } - } - - return $status; - - } - - //Return an array of info (name,value) - function assignment_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { - if (!empty($instances) && is_array($instances) && count($instances)) { - $info = array(); - foreach ($instances as $id => $instance) { - $info += assignment_check_backup_mods_instances($instance,$backup_unique_code); - } - return $info; - } - //First the course data - $info[0][0] = get_string("modulenameplural","assignment"); - if ($ids = assignment_ids ($course)) { - $info[0][1] = count($ids); - } else { - $info[0][1] = 0; - } - - //Now, if requested, the user_data - if ($user_data) { - $info[1][0] = get_string("submissions","assignment"); - if ($ids = assignment_submission_ids_by_course ($course)) { - $info[1][1] = count($ids); - } else { - $info[1][1] = 0; - } - } - return $info; - } - - //Return an array of info (name,value) - function assignment_check_backup_mods_instances($instance,$backup_unique_code) { - $info[$instance->id.'0'][0] = ''.$instance->name.''; - $info[$instance->id.'0'][1] = ''; - if (!empty($instance->userdata)) { - $info[$instance->id.'1'][0] = get_string("submissions","assignment"); - if ($ids = assignment_submission_ids_by_instance ($instance->id)) { - $info[$instance->id.'1'][1] = count($ids); - } else { - $info[$instance->id.'1'][1] = 0; - } - } - return $info; - } - - //Return a content encoded to support interactivities linking. Every module - //should have its own. They are called automatically from the backup procedure. - function assignment_encode_content_links ($content,$preferences) { - - global $CFG; - - $base = preg_quote($CFG->wwwroot,"/"); - - //Link to the list of assignments - $buscar="/(".$base."\/mod\/assignment\/index.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@ASSIGNMENTINDEX*$2@$',$content); - - //Link to assignment view by moduleid - $buscar="/(".$base."\/mod\/assignment\/view.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@ASSIGNMENTVIEWBYID*$2@$',$result); - - return $result; - } - - // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE - - //Returns an array of assignments id - function assignment_ids ($course) { - - global $CFG; - - return get_records_sql ("SELECT a.id, a.course - FROM {$CFG->prefix}assignment a - WHERE a.course = '$course'"); - } - - //Returns an array of assignment_submissions id - function assignment_submission_ids_by_course ($course) { - - global $CFG; - - return get_records_sql ("SELECT s.id , s.assignment - FROM {$CFG->prefix}assignment_submissions s, - {$CFG->prefix}assignment a - WHERE a.course = '$course' AND - s.assignment = a.id"); - } - - //Returns an array of assignment_submissions id - function assignment_submission_ids_by_instance ($instanceid) { - - global $CFG; - - return get_records_sql ("SELECT s.id , s.assignment - FROM {$CFG->prefix}assignment_submissions s - WHERE s.assignment = $instanceid"); - } -?> +id) + // | + // | + // | + // assignment_submisions + // (UL,pk->id, fk->assignment,files) + // + // Meaning: pk->primary key field of the table + // fk->foreign key to link with parent + // nt->nested field (recursive data) + // CL->course level info + // UL->user level info + // files->table may have files) + // + //----------------------------------------------------------- + + //This function executes all the backup procedure about this mod + function assignment_backup_mods($bf,$preferences) { + + global $CFG; + + $status = true; + + //Iterate over assignment table + $assignments = get_records ("assignment","course",$preferences->backup_course,"id"); + if ($assignments) { + foreach ($assignments as $assignment) { + if (backup_mod_selected($preferences,'assignment',$assignment->id)) { + $status = assignment_backup_one_mod($bf,$preferences,$assignment); + // backup files happens in backup_one_mod now too. + } + } + } + return $status; + } + + function assignment_backup_one_mod($bf,$preferences,$assignment) { + + global $CFG; + + if (is_numeric($assignment)) { + $assignment = get_record('assignment','id',$assignment); + } + + $status = true; + + //Start mod + fwrite ($bf,start_tag("MOD",3,true)); + //Print assignment data + fwrite ($bf,full_tag("ID",4,false,$assignment->id)); + fwrite ($bf,full_tag("MODTYPE",4,false,"assignment")); + fwrite ($bf,full_tag("NAME",4,false,$assignment->name)); + fwrite ($bf,full_tag("DESCRIPTION",4,false,$assignment->description)); + fwrite ($bf,full_tag("FORMAT",4,false,$assignment->format)); + fwrite ($bf,full_tag("RESUBMIT",4,false,$assignment->resubmit)); + fwrite ($bf,full_tag("PREVENTLATE",4,false,$assignment->preventlate)); + fwrite ($bf,full_tag("EMAILTEACHERS",4,false,$assignment->emailteachers)); + fwrite ($bf,full_tag("VAR1",4,false,$assignment->var1)); + fwrite ($bf,full_tag("VAR2",4,false,$assignment->var2)); + fwrite ($bf,full_tag("VAR3",4,false,$assignment->var3)); + fwrite ($bf,full_tag("VAR4",4,false,$assignment->var4)); + fwrite ($bf,full_tag("VAR5",4,false,$assignment->var5)); + fwrite ($bf,full_tag("ASSIGNMENTTYPE",4,false,$assignment->assignmenttype)); + fwrite ($bf,full_tag("MAXBYTES",4,false,$assignment->maxbytes)); + fwrite ($bf,full_tag("TIMEDUE",4,false,$assignment->timedue)); + fwrite ($bf,full_tag("TIMEAVAILABLE",4,false,$assignment->timeavailable)); + fwrite ($bf,full_tag("GRADE",4,false,$assignment->grade)); + fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$assignment->timemodified)); + fwrite ($bf,full_tag("TEMPLATETEXT",4,false,$assignment->templatetext)); + fwrite ($bf,full_tag("TEMPLATEFILE",4,false,$assignment->templatefile)); + //if we've selected to backup users info, then execute backup_assignment_submisions and + //backup_assignment_files_instance + if (backup_userdata_selected($preferences,'assignment',$assignment->id)) { + $status = backup_assignment_submissions($bf,$preferences,$assignment->id); + if ($status) { + $status = backup_assignment_files_instance($bf,$preferences,$assignment->id); + } + } + if ($assignment->templatefile != '') { + if ($status) { + $status = backup_template_file($assignment->templatefile,$preferences); + } + } + //End mod + $status =fwrite ($bf,end_tag("MOD",3,true)); + + return $status; + } + + //Backup the assignment template file, which may just be a regular file as storing in + //mod/assignment would force duplication of files + function backup_template_file ($filelocation,$preferences) { + + global $CFG; + + $status = true; + + $intPos = 0; + $intLastPos = 0; + $intCount = 0; + + $status = check_dir_exists($CFG->dataroot.'/temp/backup/'.$preferences->backup_unique_code.'/', true); + + while ($status) { + $intPos = strpos($filelocation, '/', $intLastPos); + if ($intPos == 0 || $intCount > 20) { + break; + } + $strDirs = substr($filelocation, 0, strpos($filelocation, '/', $intPos) + 1); + $status = check_dir_exists($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code.'/'.$strDirs, true); + $intLastPos = $intPos+1; + $intCount = $intCount + 1; + } + + if ($status) { + $status = backup_copy_file($CFG->dataroot."/".$preferences->backup_course."/".$filelocation, $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code.'/'.$filelocation); + } + return $status; + } + + //Backup assignment_submissions contents (executed from assignment_backup_mods) + function backup_assignment_submissions ($bf,$preferences,$assignment) { + + global $CFG; + + $status = true; + + $assignment_submissions = get_records("assignment_submissions","assignment",$assignment,"id"); + //If there is submissions + if ($assignment_submissions) { + //Write start tag + $status =fwrite ($bf,start_tag("SUBMISSIONS",4,true)); + //Iterate over each submission + foreach ($assignment_submissions as $ass_sub) { + //Start submission + $status =fwrite ($bf,start_tag("SUBMISSION",5,true)); + //Print submission contents + fwrite ($bf,full_tag("ID",6,false,$ass_sub->id)); + fwrite ($bf,full_tag("USERID",6,false,$ass_sub->userid)); + fwrite ($bf,full_tag("TIMECREATED",6,false,$ass_sub->timecreated)); + fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$ass_sub->timemodified)); + fwrite ($bf,full_tag("NUMFILES",6,false,$ass_sub->numfiles)); + fwrite ($bf,full_tag("DATA1",6,false,$ass_sub->data1)); + fwrite ($bf,full_tag("DATA2",6,false,$ass_sub->data2)); + fwrite ($bf,full_tag("GRADE",6,false,$ass_sub->grade)); + fwrite ($bf,full_tag("SUBMISSIONCOMMENT",6,false,$ass_sub->submissioncomment)); + fwrite ($bf,full_tag("FORMAT",6,false,$ass_sub->format)); + fwrite ($bf,full_tag("TEACHER",6,false,$ass_sub->teacher)); + fwrite ($bf,full_tag("TIMEMARKED",6,false,$ass_sub->timemarked)); + fwrite ($bf,full_tag("MAILED",6,false,$ass_sub->mailed)); + //End submission + $status =fwrite ($bf,end_tag("SUBMISSION",5,true)); + } + //Write end tag + $status =fwrite ($bf,end_tag("SUBMISSIONS",4,true)); + } + return $status; + } + + //Backup assignment files because we've selected to backup user info + //and files are user info's level + function backup_assignment_files($bf,$preferences) { + + global $CFG; + + $status = true; + + //First we check to moddata exists and create it as necessary + //in temp/backup/$backup_code dir + $status = check_and_create_moddata_dir($preferences->backup_unique_code); + //Now copy the assignment dir + if ($status) { + //Only if it exists !! Thanks to Daniel Miksik. + if (is_dir($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment")) { + $status = backup_copy_file($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment", + $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment"); + } + } + + return $status; + + } + + function backup_assignment_files_instance($bf,$preferences,$instanceid) { + + global $CFG; + + $status = true; + + //First we check to moddata exists and create it as necessary + //in temp/backup/$backup_code dir + $status = check_and_create_moddata_dir($preferences->backup_unique_code); + $status = check_dir_exists($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment/",true); + //Now copy the assignment dir + if ($status) { + //Only if it exists !! Thanks to Daniel Miksik. + if (is_dir($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment/".$instanceid)) { + $status = backup_copy_file($CFG->dataroot."/".$preferences->backup_course."/".$CFG->moddata."/assignment/".$instanceid, + $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/moddata/assignment/".$instanceid); + } + } + + return $status; + + } + + //Return an array of info (name,value) + function assignment_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { + if (!empty($instances) && is_array($instances) && count($instances)) { + $info = array(); + foreach ($instances as $id => $instance) { + $info += assignment_check_backup_mods_instances($instance,$backup_unique_code); + } + return $info; + } + //First the course data + $info[0][0] = get_string("modulenameplural","assignment"); + if ($ids = assignment_ids ($course)) { + $info[0][1] = count($ids); + } else { + $info[0][1] = 0; + } + + //Now, if requested, the user_data + if ($user_data) { + $info[1][0] = get_string("submissions","assignment"); + if ($ids = assignment_submission_ids_by_course ($course)) { + $info[1][1] = count($ids); + } else { + $info[1][1] = 0; + } + } + return $info; + } + + //Return an array of info (name,value) + function assignment_check_backup_mods_instances($instance,$backup_unique_code) { + $info[$instance->id.'0'][0] = ''.$instance->name.''; + $info[$instance->id.'0'][1] = ''; + if (!empty($instance->userdata)) { + $info[$instance->id.'1'][0] = get_string("submissions","assignment"); + if ($ids = assignment_submission_ids_by_instance ($instance->id)) { + $info[$instance->id.'1'][1] = count($ids); + } else { + $info[$instance->id.'1'][1] = 0; + } + } + return $info; + } + + //Return a content encoded to support interactivities linking. Every module + //should have its own. They are called automatically from the backup procedure. + function assignment_encode_content_links ($content,$preferences) { + + global $CFG; + + $base = preg_quote($CFG->wwwroot,"/"); + + //Link to the list of assignments + $buscar="/(".$base."\/mod\/assignment\/index.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@ASSIGNMENTINDEX*$2@$',$content); + + //Link to assignment view by moduleid + $buscar="/(".$base."\/mod\/assignment\/view.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@ASSIGNMENTVIEWBYID*$2@$',$result); + + return $result; + } + + // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE + + //Returns an array of assignments id + function assignment_ids ($course) { + + global $CFG; + + return get_records_sql ("SELECT a.id, a.course + FROM {$CFG->prefix}assignment a + WHERE a.course = '$course'"); + } + + //Returns an array of assignment_submissions id + function assignment_submission_ids_by_course ($course) { + + global $CFG; + + return get_records_sql ("SELECT s.id , s.assignment + FROM {$CFG->prefix}assignment_submissions s, + {$CFG->prefix}assignment a + WHERE a.course = '$course' AND + s.assignment = a.id"); + } + + //Returns an array of assignment_submissions id + function assignment_submission_ids_by_instance ($instanceid) { + + global $CFG; + + return get_records_sql ("SELECT s.id , s.assignment + FROM {$CFG->prefix}assignment_submissions s + WHERE s.assignment = $instanceid"); + } +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/db/install.xml moodle_assignment_work_1.9.4_Modified/mod/assignment/db/install.xml --- moodle_assignment_work_1.9.4_Pure/mod/assignment/db/install.xml 2007-09-25 10:11:28.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/db/install.xml 2009-04-23 15:46:06.000000000 +0100 @@ -1,75 +1,77 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + +
diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/db/upgrade.php moodle_assignment_work_1.9.4_Modified/mod/assignment/db/upgrade.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/db/upgrade.php 2008-05-02 08:16:50.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/db/upgrade.php 2009-04-23 16:09:30.000000000 +0100 @@ -1,65 +1,75 @@ -setAttributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, null, null, 'numfiles'); - - /// Launch change of nullability for field data1 - $result = $result && change_field_notnull($table, $field); - - /// Changing nullability of field data2 on table assignment_submissions to null - $field = new XMLDBField('data2'); - $field->setAttributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, null, null, 'data1'); - - /// Launch change of nullability for field data2 - $result = $result && change_field_notnull($table, $field); - } - - if ($result && $oldversion < 2007091902) { - // add draft tracking default to existing upload assignments - $sql = "UPDATE {$CFG->prefix}assignment SET var4=1 WHERE assignmenttype='upload'"; - $result = execute_sql($sql); - } - -//===== 1.9.0 upgrade line ======// - - if ($result && $oldversion < 2007101511) { - notify('Processing assignment grades, this may take a while if there are many assignments...', 'notifysuccess'); - // change grade typo to text if no grades MDL-13920 - require_once $CFG->dirroot.'/mod/assignment/lib.php'; - // too much debug output - $db->debug = false; - assignment_update_grades(); - $db->debug = true; - } - - return $result; -} - -?> +setAttributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, null, null, 'numfiles'); + + /// Launch change of nullability for field data1 + $result = $result && change_field_notnull($table, $field); + + /// Changing nullability of field data2 on table assignment_submissions to null + $field = new XMLDBField('data2'); + $field->setAttributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, null, null, 'data1'); + + /// Launch change of nullability for field data2 + $result = $result && change_field_notnull($table, $field); + } + + if ($result && $oldversion < 2007091902) { + // add draft tracking default to existing upload assignments + $sql = "UPDATE {$CFG->prefix}assignment SET var4=1 WHERE assignmenttype='upload'"; + $result = execute_sql($sql); + } + +//===== 1.9.0 upgrade line ======// + + if ($result && $oldversion < 2007101511) { + notify('Processing assignment grades, this may take a while if there are many assignments...', 'notifysuccess'); + // change grade typo to text if no grades MDL-13920 + require_once $CFG->dirroot.'/mod/assignment/lib.php'; + // too much debug output + $db->debug = false; + assignment_update_grades(); + $db->debug = true; + } + +//===== 1.9.3 upgrade line ======// + if ($result && $oldversion < 2009031213) { + $sql = "ALTER TABLE {$CFG->prefix}assignment ADD COLUMN templatetext varchar(100) NULL"; + $result = execute_sql($sql); + + $sql = "ALTER TABLE {$CFG->prefix}assignment ADD COLUMN templatefile varchar(255) NULL"; + $result = execute_sql($sql); + notify('Updating assignments', 'notifysuccess'); + } + + return $result; +} + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/lib.php moodle_assignment_work_1.9.4_Modified/mod/assignment/lib.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/lib.php 2009-02-17 07:05:38.000000000 +0000 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/lib.php 2009-04-23 15:49:02.000000000 +0100 @@ -1,3090 +1,3104 @@ -cm = $cm; - } else if (! $this->cm = get_coursemodule_from_id('assignment', $cmid)) { - error('Course Module ID was incorrect'); - } - - $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id); - - if ($course) { - $this->course = $course; - } else if ($this->cm->course == $COURSE->id) { - $this->course = $COURSE; - } else if (! $this->course = get_record('course', 'id', $this->cm->course)) { - error('Course is misconfigured'); - } - - if ($assignment) { - $this->assignment = $assignment; - } else if (! $this->assignment = get_record('assignment', 'id', $this->cm->instance)) { - error('assignment ID was incorrect'); - } - - $this->assignment->cmidnumber = $this->cm->id; // compatibility with modedit assignment obj - $this->assignment->courseid = $this->course->id; // compatibility with modedit assignment obj - - $this->strassignment = get_string('modulename', 'assignment'); - $this->strassignments = get_string('modulenameplural', 'assignment'); - $this->strsubmissions = get_string('submissions', 'assignment'); - $this->strlastmodified = get_string('lastmodified'); - $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.format_string($this->assignment->name,true)); - - // visibility handled by require_login() with $cm parameter - // get current group only when really needed - - /// Set up things for a HTML editor if it's needed - if ($this->usehtmleditor = can_use_html_editor()) { - $this->defaultformat = FORMAT_HTML; - } else { - $this->defaultformat = FORMAT_MOODLE; - } - } - - /** - * Display the assignment, used by view.php - * - * This in turn calls the methods producing individual parts of the page - */ - function view() { - - $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); - require_capability('mod/assignment:view', $context); - - add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", - $this->assignment->id, $this->cm->id); - - $this->view_header(); - - $this->view_intro(); - - $this->view_dates(); - - $this->view_feedback(); - - $this->view_footer(); - } - - /** - * Display the header and top of a page - * - * (this doesn't change much for assignment types) - * This is used by the view() method to print the header of view.php but - * it can be used on other pages in which case the string to denote the - * page in the navigation trail should be passed as an argument - * - * @param $subpage string Description of subpage to be used in navigation trail - */ - function view_header($subpage='') { - - global $CFG; - - - if ($subpage) { - $navigation = build_navigation($subpage, $this->cm); - } else { - $navigation = build_navigation('', $this->cm); - } - - print_header($this->pagetitle, $this->course->fullname, $navigation, '', '', - true, update_module_button($this->cm->id, $this->course->id, $this->strassignment), - navmenu($this->course, $this->cm)); - - groups_print_activity_menu($this->cm, 'view.php?id=' . $this->cm->id); - - echo ''; - echo '
'; - } - - - /** - * Display the assignment intro - * - * This will most likely be extended by assignment type plug-ins - * The default implementation prints the assignment description in a box - */ - function view_intro() { - print_simple_box_start('center', '', '', 0, 'generalbox', 'intro'); - $formatoptions = new stdClass; - $formatoptions->noclean = true; - echo format_text($this->assignment->description, $this->assignment->format, $formatoptions); - print_simple_box_end(); - } - - /** - * Display the assignment dates - * - * Prints the assignment start and end dates in a box. - * This will be suitable for most assignment types - */ - function view_dates() { - if (!$this->assignment->timeavailable && !$this->assignment->timedue) { - return; - } - - print_simple_box_start('center', '', '', 0, 'generalbox', 'dates'); - echo ''; - if ($this->assignment->timeavailable) { - echo ''; - echo ' '; - } - if ($this->assignment->timedue) { - echo ''; - echo ' '; - } - echo '
'.get_string('availabledate','assignment').':'.userdate($this->assignment->timeavailable).'
'.get_string('duedate','assignment').':'.userdate($this->assignment->timedue).'
'; - print_simple_box_end(); - } - - - /** - * Display the bottom and footer of a page - * - * This default method just prints the footer. - * This will be suitable for most assignment types - */ - function view_footer() { - print_footer($this->course); - } - - /** - * Display the feedback to the student - * - * This default method prints the teacher picture and name, date when marked, - * grade and teacher submissioncomment. - * - * @param $submission object The submission object or NULL in which case it will be loaded - */ - function view_feedback($submission=NULL) { - global $USER, $CFG; - require_once($CFG->libdir.'/gradelib.php'); - - if (!has_capability('mod/assignment:submit', $this->context, $USER->id, false)) { - // can not submit assignments -> no feedback - return; - } - - if (!$submission) { /// Get submission for this assignment - $submission = $this->get_submission($USER->id); - } - - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id); - $item = $grading_info->items[0]; - $grade = $item->grades[$USER->id]; - - if ($grade->hidden or $grade->grade === false) { // hidden or error - return; - } - - if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet - return; - } - - $graded_date = $grade->dategraded; - $graded_by = $grade->usermodified; - - /// We need the teacher info - if (!$teacher = get_record('user', 'id', $graded_by)) { - error('Could not find the teacher'); - } - - /// Print the feedback - print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher)); // TODO: fix teacher string - - echo ''; - - echo ''; - echo ''; - echo ''; - echo ''; - - echo ''; - echo ''; - echo ''; - - echo '
'; - if ($teacher) { - print_user_picture($teacher, $this->course->id, $teacher->picture); - } - echo ''; - echo '
'; - if ($teacher) { - echo '
'.fullname($teacher).'
'; - } - echo '
'.userdate($graded_date).'
'; - echo '
'; - echo '
 '; - echo '
'; - echo get_string("grade").': '.$grade->str_long_grade; - echo '
'; - echo '
'; - - echo '
'; - echo $grade->str_feedback; - echo '
'; - echo '
'; - } - - /** - * Returns a link with info about the state of the assignment submissions - * - * This is used by view_header to put this link at the top right of the page. - * For teachers it gives the number of submitted assignments with a link - * For students it gives the time of their submission. - * This will be suitable for most assignment types. - * @param bool $allgroup print all groups info if user can access all groups, suitable for index.php - * @return string - */ - function submittedlink($allgroups=false) { - global $USER; - - $submitted = ''; - - $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); - if (has_capability('mod/assignment:grade', $context)) { - if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) { - $group = 0; - } else { - $group = groups_get_activity_group($this->cm); - } - if ($count = $this->count_real_submissions($group)) { - $submitted = ''. - get_string('viewsubmissions', 'assignment', $count).''; - } else { - $submitted = ''. - get_string('noattempts', 'assignment').''; - } - } else { - if (!empty($USER->id)) { - if ($submission = $this->get_submission($USER->id)) { - if ($submission->timemodified) { - if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) { - $submitted = ''.userdate($submission->timemodified).''; - } else { - $submitted = ''.userdate($submission->timemodified).''; - } - } - } - } - } - - return $submitted; - } - - - function setup_elements(&$mform) { - - } - - /** - * Create a new assignment activity - * - * Given an object containing all the necessary data, - * (defined by the form in mod.html) this function - * will create a new instance and return the id number - * of the new instance. - * The due data is added to the calendar - * This is common to all assignment types. - * - * @param $assignment object The data from the form on mod.html - * @return int The id of the assignment - */ - function add_instance($assignment) { - global $COURSE; - - $assignment->timemodified = time(); - $assignment->courseid = $assignment->course; - - if ($returnid = insert_record("assignment", $assignment)) { - $assignment->id = $returnid; - - if ($assignment->timedue) { - $event = new object(); - $event->name = $assignment->name; - $event->description = $assignment->description; - $event->courseid = $assignment->course; - $event->groupid = 0; - $event->userid = 0; - $event->modulename = 'assignment'; - $event->instance = $returnid; - $event->eventtype = 'due'; - $event->timestart = $assignment->timedue; - $event->timeduration = 0; - - add_event($event); - } - - $assignment = stripslashes_recursive($assignment); - assignment_grade_item_update($assignment); - - } - - - return $returnid; - } - - /** - * Deletes an assignment activity - * - * Deletes all database records, files and calendar events for this assignment. - * @param $assignment object The assignment to be deleted - * @return boolean False indicates error - */ - function delete_instance($assignment) { - global $CFG; - - $assignment->courseid = $assignment->course; - - $result = true; - - if (! delete_records('assignment_submissions', 'assignment', $assignment->id)) { - $result = false; - } - - if (! delete_records('assignment', 'id', $assignment->id)) { - $result = false; - } - - if (! delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id)) { - $result = false; - } - - // delete file area with all attachments - ignore errors - require_once($CFG->libdir.'/filelib.php'); - fulldelete($CFG->dataroot.'/'.$assignment->course.'/'.$CFG->moddata.'/assignment/'.$assignment->id); - - assignment_grade_item_delete($assignment); - - return $result; - } - - /** - * Updates a new assignment activity - * - * Given an object containing all the necessary data, - * (defined by the form in mod.html) this function - * will update the assignment instance and return the id number - * The due date is updated in the calendar - * This is common to all assignment types. - * - * @param $assignment object The data from the form on mod.html - * @return int The assignment id - */ - function update_instance($assignment) { - global $COURSE; - - $assignment->timemodified = time(); - - $assignment->id = $assignment->instance; - $assignment->courseid = $assignment->course; - - if (!update_record('assignment', $assignment)) { - return false; - } - - if ($assignment->timedue) { - $event = new object(); - - if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) { - - $event->name = $assignment->name; - $event->description = $assignment->description; - $event->timestart = $assignment->timedue; - - update_event($event); - } else { - $event = new object(); - $event->name = $assignment->name; - $event->description = $assignment->description; - $event->courseid = $assignment->course; - $event->groupid = 0; - $event->userid = 0; - $event->modulename = 'assignment'; - $event->instance = $assignment->id; - $event->eventtype = 'due'; - $event->timestart = $assignment->timedue; - $event->timeduration = 0; - - add_event($event); - } - } else { - delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id); - } - - // get existing grade item - $assignment = stripslashes_recursive($assignment); - - assignment_grade_item_update($assignment); - - return true; - } - - /** - * Update grade item for this submission. - */ - function update_grade($submission) { - assignment_update_grades($this->assignment, $submission->userid); - } - - /** - * Top-level function for handling of submissions called by submissions.php - * - * This is for handling the teacher interaction with the grading interface - * This should be suitable for most assignment types. - * - * @param $mode string Specifies the kind of teacher interaction taking place - */ - function submissions($mode) { - ///The main switch is changed to facilitate - ///1) Batch fast grading - ///2) Skip to the next one on the popup - ///3) Save and Skip to the next one on the popup - - //make user global so we can use the id - global $USER; - - $mailinfo = optional_param('mailinfo', null, PARAM_BOOL); - if (is_null($mailinfo)) { - $mailinfo = get_user_preferences('assignment_mailinfo', 0); - } else { - set_user_preference('assignment_mailinfo', $mailinfo); - } - - switch ($mode) { - case 'grade': // We are in a popup window grading - if ($submission = $this->process_feedback()) { - //IE needs proper header with encoding - print_header(get_string('feedback', 'assignment').':'.format_string($this->assignment->name)); - print_heading(get_string('changessaved')); - print $this->update_main_listing($submission); - } - close_window(); - break; - - case 'single': // We are in a popup window displaying submission - $this->display_submission(); - break; - - case 'all': // Main window, display everything - $this->display_submissions(); - break; - - case 'fastgrade': - ///do the fast grading stuff - this process should work for all 3 subclasses - - $grading = false; - $commenting = false; - $col = false; - if (isset($_POST['submissioncomment'])) { - $col = 'submissioncomment'; - $commenting = true; - } - if (isset($_POST['menu'])) { - $col = 'menu'; - $grading = true; - } - if (!$col) { - //both submissioncomment and grade columns collapsed.. - $this->display_submissions(); - break; - } - - foreach ($_POST[$col] as $id => $unusedvalue){ - - $id = (int)$id; //clean parameter name - - $this->process_outcomes($id); - - if (!$submission = $this->get_submission($id)) { - $submission = $this->prepare_new_submission($id); - $newsubmission = true; - } else { - $newsubmission = false; - } - unset($submission->data1); // Don't need to update this. - unset($submission->data2); // Don't need to update this. - - //for fast grade, we need to check if any changes take place - $updatedb = false; - - if ($grading) { - $grade = $_POST['menu'][$id]; - $updatedb = $updatedb || ($submission->grade != $grade); - $submission->grade = $grade; - } else { - if (!$newsubmission) { - unset($submission->grade); // Don't need to update this. - } - } - if ($commenting) { - $commentvalue = trim($_POST['submissioncomment'][$id]); - $updatedb = $updatedb || ($submission->submissioncomment != stripslashes($commentvalue)); - $submission->submissioncomment = $commentvalue; - } else { - unset($submission->submissioncomment); // Don't need to update this. - } - - $submission->teacher = $USER->id; - if ($updatedb) { - $submission->mailed = (int)(!$mailinfo); - } - - $submission->timemarked = time(); - - //if it is not an update, we don't change the last modified time etc. - //this will also not write into database if no submissioncomment and grade is entered. - - if ($updatedb){ - if ($newsubmission) { - if (!isset($submission->submissioncomment)) { - $submission->submissioncomment = ''; - } - if (!$sid = insert_record('assignment_submissions', $submission)) { - return false; - } - $submission->id = $sid; - } else { - if (!update_record('assignment_submissions', $submission)) { - return false; - } - } - - // triger grade event - $this->update_grade($submission); - - //add to log only if updating - add_to_log($this->course->id, 'assignment', 'update grades', - 'submissions.php?id='.$this->assignment->id.'&user='.$submission->userid, - $submission->userid, $this->cm->id); - } - - } - - $message = notify(get_string('changessaved'), 'notifysuccess', 'center', true); - - $this->display_submissions($message); - break; - - - case 'next': - /// We are currently in pop up, but we want to skip to next one without saving. - /// This turns out to be similar to a single case - /// The URL used is for the next submission. - - $this->display_submission(); - break; - - case 'saveandnext': - ///We are in pop up. save the current one and go to the next one. - //first we save the current changes - if ($submission = $this->process_feedback()) { - //print_heading(get_string('changessaved')); - $extra_javascript = $this->update_main_listing($submission); - } - - //then we display the next submission - $this->display_submission($extra_javascript); - break; - - default: - echo "something seriously is wrong!!"; - break; - } - } - - /** - * Helper method updating the listing on the main script from popup using javascript - * - * @param $submission object The submission whose data is to be updated on the main page - */ - function update_main_listing($submission) { - global $SESSION, $CFG; - - $output = ''; - - $perpage = get_user_preferences('assignment_perpage', 10); - - $quickgrade = get_user_preferences('assignment_quickgrade', 0); - - /// Run some Javascript to try and update the parent page - $output .= '"; - return $output; - } - - /** - * Return a grade in user-friendly form, whether it's a scale or not - * - * @param $grade - * @return string User-friendly representation of grade - */ - function display_grade($grade) { - - static $scalegrades = array(); // Cache scales for each assignment - they might have different scales!! - - if ($this->assignment->grade >= 0) { // Normal number - if ($grade == -1) { - return '-'; - } else { - return $grade.' / '.$this->assignment->grade; - } - - } else { // Scale - if (empty($scalegrades[$this->assignment->id])) { - if ($scale = get_record('scale', 'id', -($this->assignment->grade))) { - $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale); - } else { - return '-'; - } - } - if (isset($scalegrades[$this->assignment->id][$grade])) { - return $scalegrades[$this->assignment->id][$grade]; - } - return '-'; - } - } - - /** - * Display a single submission, ready for grading on a popup window - * - * This default method prints the teacher info and submissioncomment box at the top and - * the student info and submission at the bottom. - * This method also fetches the necessary data in order to be able to - * provide a "Next submission" button. - * Calls preprocess_submission() to give assignment type plug-ins a chance - * to process submissions before they are graded - * This method gets its arguments from the page parameters userid and offset - */ - function display_submission($extra_javascript = '') { - - global $CFG; - require_once($CFG->libdir.'/gradelib.php'); - require_once($CFG->libdir.'/tablelib.php'); - - $userid = required_param('userid', PARAM_INT); - $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student. - - if (!$user = get_record('user', 'id', $userid)) { - error('No such user!'); - } - - if (!$submission = $this->get_submission($user->id)) { - $submission = $this->prepare_new_submission($userid); - } - if ($submission->timemodified > $submission->timemarked) { - $subtype = 'assignmentnew'; - } else { - $subtype = 'assignmentold'; - } - - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array($user->id)); - $disabled = $grading_info->items[0]->grades[$userid]->locked || $grading_info->items[0]->grades[$userid]->overridden; - - /// construct SQL, using current offset to find the data of the next student - $course = $this->course; - $assignment = $this->assignment; - $cm = $this->cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - /// Get all ppl that can submit assignments - - $currentgroup = groups_get_activity_group($cm); - if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) { - $users = array_keys($users); - } - - // if groupmembersonly used, remove users who are not in any group - if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { - if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { - $users = array_intersect($users, array_keys($groupingusers)); - } - } - - $nextid = 0; - - if ($users) { - $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt, - s.id AS submissionid, s.grade, s.submissioncomment, - s.timemodified, s.timemarked, - COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status '; - $sql = 'FROM '.$CFG->prefix.'user u '. - 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid - AND s.assignment = '.$this->assignment->id.' '. - 'WHERE u.id IN ('.implode(',', $users).') '; - - if ($sort = flexible_table::get_sql_sort('mod-assignment-submissions')) { - $sort = 'ORDER BY '.$sort.' '; - } - - if (($auser = get_records_sql($select.$sql.$sort, $offset+1, 1)) !== false) { - $nextuser = array_shift($auser); - /// Calculate user status - $nextuser->status = ($nextuser->timemarked > 0) && ($nextuser->timemarked >= $nextuser->timemodified); - $nextid = $nextuser->id; - } - } - - print_header(get_string('feedback', 'assignment').':'.fullname($user, true).':'.format_string($this->assignment->name)); - - /// Print any extra javascript needed for saveandnext - echo $extra_javascript; - - ///SOme javascript to help with setting up >.> - - echo ''."\n"; - echo ''; - - ///Start of teacher info row - - echo ''; - echo ''; - echo ''; - - ///End of teacher info row, Start of student info row - echo ''; - echo ''; - echo ''; - echo ''; - - ///End of student info row - - echo '
'; - if ($submission->teacher) { - $teacher = get_record('user', 'id', $submission->teacher); - } else { - global $USER; - $teacher = $USER; - } - print_user_picture($teacher, $this->course->id, $teacher->picture); - echo ''; - echo '
'; - echo '
'; // xhtml compatibility - invisiblefieldset was breaking layout here - echo ''; - echo ''; - echo ''; - echo ''; - echo '';//selected menu index - - //new hidden field, initialized to -1. - echo ''; - - if ($submission->timemarked) { - echo '
'; - echo '
'.fullname($teacher, true).'
'; - echo '
'.userdate($submission->timemarked).'
'; - echo '
'; - } - echo '
'; - choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', $submission->grade, get_string('nograde'), '', -1, false, $disabled); - echo '
'; - - echo '
'; - echo '
'.get_string('finalgrade', 'grades').': '.$grading_info->items[0]->grades[$userid]->str_grade.'
'; - echo '
'; - - if (!empty($CFG->enableoutcomes)) { - foreach($grading_info->outcomes as $n=>$outcome) { - echo '
'; - $options = make_grades_menu(-$outcome->scaleid); - if ($outcome->grades[$submission->userid]->locked) { - $options[0] = get_string('nooutcome', 'grades'); - echo $options[$outcome->grades[$submission->userid]->grade]; - } else { - choose_from_menu($options, 'outcome_'.$n.'['.$userid.']', $outcome->grades[$submission->userid]->grade, get_string('nooutcome', 'grades'), '', 0, false, false, 0, 'menuoutcome_'.$n); - } - echo '
'; - echo '
'; - } - } - - - $this->preprocess_submission($submission); - - if ($disabled) { - echo '
'.$grading_info->items[0]->grades[$userid]->str_feedback.'
'; - - } else { - print_textarea($this->usehtmleditor, 14, 58, 0, 0, 'submissioncomment', $submission->submissioncomment, $this->course->id); - if ($this->usehtmleditor) { - echo ''; - } else { - echo '
'; - choose_from_menu(format_text_menu(), "format", $submission->format, ""); - helpbutton("textformat", get_string("helpformatting")); - echo '
'; - } - } - - $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : ''; - - ///Print Buttons in Single View - echo ''; - echo ''; - echo '
'; - echo ''; - echo ''; - //if there are more to be graded. - if ($nextid) { - echo ''; - echo ''; - } - echo '
'; - echo '
'; - - $customfeedback = $this->custom_feedbackform($submission, true); - if (!empty($customfeedback)) { - echo $customfeedback; - } - - echo '
'; - print_user_picture($user, $this->course->id, $user->picture); - echo ''; - echo '
'; - echo '
'.fullname($user, true).'
'; - if ($submission->timemodified) { - echo '
'.userdate($submission->timemodified). - $this->display_lateness($submission->timemodified).'
'; - } - echo '
'; - $this->print_user_files($user->id); - echo '
'; - - if (!$disabled and $this->usehtmleditor) { - use_html_editor(); - } - - print_footer('none'); - } - - /** - * Preprocess submission before grading - * - * Called by display_submission() - * The default type does nothing here. - * @param $submission object The submission object - */ - function preprocess_submission(&$submission) { - } - - /** - * Display all the submissions ready for grading - */ - function display_submissions($message='') { - global $CFG, $db, $USER; - require_once($CFG->libdir.'/gradelib.php'); - - /* first we check to see if the form has just been submitted - * to request user_preference updates - */ - - if (isset($_POST['updatepref'])){ - $perpage = optional_param('perpage', 10, PARAM_INT); - $perpage = ($perpage <= 0) ? 10 : $perpage ; - set_user_preference('assignment_perpage', $perpage); - set_user_preference('assignment_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL)); - } - - /* next we get perpage and quickgrade (allow quick grade) params - * from database - */ - $perpage = get_user_preferences('assignment_perpage', 10); - - $quickgrade = get_user_preferences('assignment_quickgrade', 0); - - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id); - - if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) { - $uses_outcomes = true; - } else { - $uses_outcomes = false; - } - - $page = optional_param('page', 0, PARAM_INT); - $strsaveallfeedback = get_string('saveallfeedback', 'assignment'); - - /// Some shortcuts to make the code read better - - $course = $this->course; - $assignment = $this->assignment; - $cm = $this->cm; - - $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet - add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id, $this->assignment->id, $this->cm->id); - $navigation = build_navigation($this->strsubmissions, $this->cm); - print_header_simple(format_string($this->assignment->name,true), "", $navigation, - '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm)); - - $course_context = get_context_instance(CONTEXT_COURSE, $course->id); - if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { - echo '
' - . get_string('seeallcoursegrades', 'grades') . '
'; - } - - if (!empty($message)) { - echo $message; // display messages here if any - } - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - /// Check to see if groups are being used in this assignment - - /// find out current groups mode - $groupmode = groups_get_activity_groupmode($cm); - $currentgroup = groups_get_activity_group($cm, true); - groups_print_activity_menu($cm, 'submissions.php?id=' . $this->cm->id); - - /// Get all ppl that are allowed to submit assignments - if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) { - $users = array_keys($users); - } - - // if groupmembersonly used, remove users who are not in any group - if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { - if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { - $users = array_intersect($users, array_keys($groupingusers)); - } - } - - $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade'); - if ($uses_outcomes) { - $tablecolumns[] = 'outcome'; // no sorting based on outcomes column - } - - $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'), - get_string('finalgrade', 'grades')); - if ($uses_outcomes) { - $tableheaders[] = get_string('outcome', 'grades'); - } - - require_once($CFG->libdir.'/tablelib.php'); - $table = new flexible_table('mod-assignment-submissions'); - - $table->define_columns($tablecolumns); - $table->define_headers($tableheaders); - $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id.'&currentgroup='.$currentgroup); - - $table->sortable(true, 'lastname');//sorted by lastname by default - $table->collapsible(true); - $table->initialbars(true); - - $table->column_suppress('picture'); - $table->column_suppress('fullname'); - - $table->column_class('picture', 'picture'); - $table->column_class('fullname', 'fullname'); - $table->column_class('grade', 'grade'); - $table->column_class('submissioncomment', 'comment'); - $table->column_class('timemodified', 'timemodified'); - $table->column_class('timemarked', 'timemarked'); - $table->column_class('status', 'status'); - $table->column_class('finalgrade', 'finalgrade'); - if ($uses_outcomes) { - $table->column_class('outcome', 'outcome'); - } - - $table->set_attribute('cellspacing', '0'); - $table->set_attribute('id', 'attempts'); - $table->set_attribute('class', 'submissions'); - $table->set_attribute('width', '100%'); - //$table->set_attribute('align', 'center'); - - $table->no_sorting('finalgrade'); - $table->no_sorting('outcome'); - - // Start working -- this is necessary as soon as the niceties are over - $table->setup(); - - if (empty($users)) { - print_heading(get_string('nosubmitusers','assignment')); - return true; - } - - /// Construct the SQL - - if ($where = $table->get_sql_where()) { - $where .= ' AND '; - } - - if ($sort = $table->get_sql_sort()) { - $sort = ' ORDER BY '.$sort; - } - - $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt, - s.id AS submissionid, s.grade, s.submissioncomment, - s.timemodified, s.timemarked, - COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status '; - $sql = 'FROM '.$CFG->prefix.'user u '. - 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid - AND s.assignment = '.$this->assignment->id.' '. - 'WHERE '.$where.'u.id IN ('.implode(',',$users).') '; - - $table->pagesize($perpage, count($users)); - - ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next - $offset = $page * $perpage; - - $strupdate = get_string('update'); - $strgrade = get_string('grade'); - $grademenu = make_grades_menu($this->assignment->grade); - - if (($ausers = get_records_sql($select.$sql.$sort, $table->get_page_start(), $table->get_page_size())) !== false) { - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers)); - foreach ($ausers as $auser) { - $final_grade = $grading_info->items[0]->grades[$auser->id]; - $grademax = $grading_info->items[0]->grademax; - $final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2); - $locked_overridden = 'locked'; - if ($final_grade->overridden) { - $locked_overridden = 'overridden'; - } - - /// Calculate user status - $auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified); - $picture = print_user_picture($auser, $course->id, $auser->picture, false, true); - - if (empty($auser->submissionid)) { - $auser->grade = -1; //no submission yet - } - - if (!empty($auser->submissionid)) { - ///Prints student answer and student modified date - ///attach file or print link to student answer, depending on the type of the assignment. - ///Refer to print_student_answer in inherited classes. - if ($auser->timemodified > 0) { - $studentmodified = '
'.$this->print_student_answer($auser->id) - . userdate($auser->timemodified).'
'; - } else { - $studentmodified = '
 
'; - } - ///Print grade, dropdown or text - if ($auser->timemarked > 0) { - $teachermodified = '
'.userdate($auser->timemarked).'
'; - - if ($final_grade->locked or $final_grade->overridden) { - $grade = '
'.$final_grade->formatted_grade.'
'; - } else if ($quickgrade) { - $menu = choose_from_menu(make_grades_menu($this->assignment->grade), - 'menu['.$auser->id.']', $auser->grade, - get_string('nograde'),'',-1,true,false,$tabindex++); - $grade = '
'. $menu .'
'; - } else { - $grade = '
'.$this->display_grade($auser->grade).'
'; - } - - } else { - $teachermodified = '
 
'; - if ($final_grade->locked or $final_grade->overridden) { - $grade = '
'.$final_grade->formatted_grade.'
'; - } else if ($quickgrade) { - $menu = choose_from_menu(make_grades_menu($this->assignment->grade), - 'menu['.$auser->id.']', $auser->grade, - get_string('nograde'),'',-1,true,false,$tabindex++); - $grade = '
'.$menu.'
'; - } else { - $grade = '
'.$this->display_grade($auser->grade).'
'; - } - } - ///Print Comment - if ($final_grade->locked or $final_grade->overridden) { - $comment = '
'.shorten_text(strip_tags($final_grade->str_feedback),15).'
'; - - } else if ($quickgrade) { - $comment = '
' - . '
'; - } else { - $comment = '
'.shorten_text(strip_tags($auser->submissioncomment),15).'
'; - } - } else { - $studentmodified = '
 
'; - $teachermodified = '
 
'; - $status = '
 
'; - - if ($final_grade->locked or $final_grade->overridden) { - $grade = '
'.$final_grade->formatted_grade . '
'; - } else if ($quickgrade) { // allow editing - $menu = choose_from_menu(make_grades_menu($this->assignment->grade), - 'menu['.$auser->id.']', $auser->grade, - get_string('nograde'),'',-1,true,false,$tabindex++); - $grade = '
'.$menu.'
'; - } else { - $grade = '
-
'; - } - - if ($final_grade->locked or $final_grade->overridden) { - $comment = '
'.$final_grade->str_feedback.'
'; - } else if ($quickgrade) { - $comment = '
' - . '
'; - } else { - $comment = '
 
'; - } - } - - if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1 - $auser->status = 0; - } else { - $auser->status = 1; - } - - $buttontext = ($auser->status == 1) ? $strupdate : $strgrade; - - ///No more buttons, we use popups ;-). - $popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id - . '&userid='.$auser->id.'&mode=single'.'&offset='.$offset++; - $button = link_to_popup_window ($popup_url, 'grade'.$auser->id, $buttontext, 600, 780, - $buttontext, 'none', true, 'button'.$auser->id); - - $status = '
'.$button.'
'; - - $finalgrade = ''.$final_grade->str_grade.''; - - $outcomes = ''; - - if ($uses_outcomes) { - - foreach($grading_info->outcomes as $n=>$outcome) { - $outcomes .= '
'; - $options = make_grades_menu(-$outcome->scaleid); - - if ($outcome->grades[$auser->id]->locked or !$quickgrade) { - $options[0] = get_string('nooutcome', 'grades'); - $outcomes .= ': '.$options[$outcome->grades[$auser->id]->grade].''; - } else { - $outcomes .= ' '; - $outcomes .= choose_from_menu($options, 'outcome_'.$n.'['.$auser->id.']', - $outcome->grades[$auser->id]->grade, get_string('nooutcome', 'grades'), '', 0, true, false, 0, 'outcome_'.$n.'_'.$auser->id); - } - $outcomes .= '
'; - } - } - - $userlink = '' . fullname($auser) . ''; - $row = array($picture, $userlink, $grade, $comment, $studentmodified, $teachermodified, $status, $finalgrade); - if ($uses_outcomes) { - $row[] = $outcomes; - } - - $table->add_data($row); - } - } - - /// Print quickgrade form around the table - if ($quickgrade){ - echo '
'; - echo '
'; - echo ''; - echo ''; - echo ''; - echo '
'; - } - - $table->print_html(); /// Print the whole table - - if ($quickgrade){ - $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : ''; - echo '
'; - echo '
'; - echo ''; - echo ''; - echo ''; - helpbutton('emailnotification', get_string('enableemailnotification', 'assignment'), 'assignment').'

'; - echo '
'; - echo '
'; - echo ''; - echo '
'; - } - /// End of fast grading form - - /// Mini form for setting user preference - echo '
'; - echo '
'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
'; - echo ''; - echo ''; - echo ''; - helpbutton('pagesize', get_string('pagesize','assignment'), 'assignment'); - echo '
'; - echo ''; - echo ''; - $checked = $quickgrade ? 'checked="checked"' : ''; - echo ''; - helpbutton('quickgrade', get_string('quickgrade', 'assignment'), 'assignment').'

'; - echo '
'; - echo ''; - echo '
'; - echo '
'; - ///End of mini form - print_footer($this->course); - } - - /** - * Process teacher feedback submission - * - * This is called by submissions() when a grading even has taken place. - * It gets its data from the submitted form. - * @return object The updated submission object - */ - function process_feedback() { - global $CFG, $USER; - require_once($CFG->libdir.'/gradelib.php'); - - if (!$feedback = data_submitted()) { // No incoming data? - return false; - } - - ///For save and next, we need to know the userid to save, and the userid to go - ///We use a new hidden field in the form, and set it to -1. If it's set, we use this - ///as the userid to store - if ((int)$feedback->saveuserid !== -1){ - $feedback->userid = $feedback->saveuserid; - } - - if (!empty($feedback->cancel)) { // User hit cancel button - return false; - } - - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $feedback->userid); - - // store outcomes if needed - $this->process_outcomes($feedback->userid); - - $submission = $this->get_submission($feedback->userid, true); // Get or make one - - if (!$grading_info->items[0]->grades[$feedback->userid]->locked and - !$grading_info->items[0]->grades[$feedback->userid]->overridden) { - - $submission->grade = $feedback->grade; - $submission->submissioncomment = $feedback->submissioncomment; - $submission->format = $feedback->format; - $submission->teacher = $USER->id; - $mailinfo = get_user_preferences('assignment_mailinfo', 0); - if (!$mailinfo) { - $submission->mailed = 1; // treat as already mailed - } else { - $submission->mailed = 0; // Make sure mail goes out (again, even) - } - $submission->timemarked = time(); - - unset($submission->data1); // Don't need to update this. - unset($submission->data2); // Don't need to update this. - - if (empty($submission->timemodified)) { // eg for offline assignments - // $submission->timemodified = time(); - } - - if (! update_record('assignment_submissions', $submission)) { - return false; - } - - // triger grade event - $this->update_grade($submission); - - add_to_log($this->course->id, 'assignment', 'update grades', - 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id); - } - - return $submission; - - } - - function process_outcomes($userid) { - global $CFG, $USER; - - if (empty($CFG->enableoutcomes)) { - return; - } - - require_once($CFG->libdir.'/gradelib.php'); - - if (!$formdata = data_submitted()) { - return; - } - - $data = array(); - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $userid); - - if (!empty($grading_info->outcomes)) { - foreach($grading_info->outcomes as $n=>$old) { - $name = 'outcome_'.$n; - if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) { - $data[$n] = $formdata->{$name}[$userid]; - } - } - } - if (count($data) > 0) { - grade_update_outcomes('mod/assignment', $this->course->id, 'mod', 'assignment', $this->assignment->id, $userid, $data); - } - - } - - /** - * Load the submission object for a particular user - * - * @param $userid int The id of the user whose submission we want or 0 in which case USER->id is used - * @param $createnew boolean optional Defaults to false. If set to true a new submission object will be created in the database - * @param bool $teachermodified student submission set if false - * @return object The submission - */ - function get_submission($userid=0, $createnew=false, $teachermodified=false) { - global $USER; - - if (empty($userid)) { - $userid = $USER->id; - } - - $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); - - if ($submission || !$createnew) { - return $submission; - } - $newsubmission = $this->prepare_new_submission($userid, $teachermodified); - if (!insert_record("assignment_submissions", $newsubmission)) { - error("Could not insert a new empty submission"); - } - - return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); - } - - /** - * Instantiates a new submission object for a given user - * - * Sets the assignment, userid and times, everything else is set to default values. - * @param $userid int The userid for which we want a submission object - * @param bool $teachermodified student submission set if false - * @return object The submission - */ - function prepare_new_submission($userid, $teachermodified=false) { - $submission = new Object; - $submission->assignment = $this->assignment->id; - $submission->userid = $userid; - //$submission->timecreated = time(); - $submission->timecreated = ''; - // teachers should not be modifying modified date, except offline assignments - if ($teachermodified) { - $submission->timemodified = 0; - } else { - $submission->timemodified = $submission->timecreated; - } - $submission->numfiles = 0; - $submission->data1 = ''; - $submission->data2 = ''; - $submission->grade = -1; - $submission->submissioncomment = ''; - $submission->format = 0; - $submission->teacher = 0; - $submission->timemarked = 0; - $submission->mailed = 0; - return $submission; - } - - /** - * Return all assignment submissions by ENROLLED students (even empty) - * - * @param $sort string optional field names for the ORDER BY in the sql query - * @param $dir string optional specifying the sort direction, defaults to DESC - * @return array The submission objects indexed by id - */ - function get_submissions($sort='', $dir='DESC') { - return assignment_get_all_submissions($this->assignment, $sort, $dir); - } - - /** - * Counts all real assignment submissions by ENROLLED students (not empty ones) - * - * @param $groupid int optional If nonzero then count is restricted to this group - * @return int The number of submissions - */ - function count_real_submissions($groupid=0) { - return assignment_count_real_submissions($this->cm, $groupid); - } - - /** - * Alerts teachers by email of new or changed assignments that need grading - * - * First checks whether the option to email teachers is set for this assignment. - * Sends an email to ALL teachers in the course (or in the group if using separate groups). - * Uses the methods email_teachers_text() and email_teachers_html() to construct the content. - * @param $submission object The submission that has changed - */ - function email_teachers($submission) { - global $CFG; - - if (empty($this->assignment->emailteachers)) { // No need to do anything - return; - } - - $user = get_record('user', 'id', $submission->userid); - - if ($teachers = $this->get_graders($user)) { - - $strassignments = get_string('modulenameplural', 'assignment'); - $strassignment = get_string('modulename', 'assignment'); - $strsubmitted = get_string('submitted', 'assignment'); - - foreach ($teachers as $teacher) { - $info = new object(); - $info->username = fullname($user, true); - $info->assignment = format_string($this->assignment->name,true); - $info->url = $CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id; - - $postsubject = $strsubmitted.': '.$info->username.' -> '.$this->assignment->name; - $posttext = $this->email_teachers_text($info); - $posthtml = ($teacher->mailformat == 1) ? $this->email_teachers_html($info) : ''; - - @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad. - } - } - } - - /** - * Returns a list of teachers that should be grading given submission - */ - function get_graders($user) { - //potential graders - $potgraders = get_users_by_capability($this->context, 'mod/assignment:grade', '', '', '', '', '', '', false, false); - - $graders = array(); - if (groups_get_activity_groupmode($this->cm) == SEPARATEGROUPS) { // Separate groups are being used - if ($groups = groups_get_all_groups($this->course->id, $user->id)) { // Try to find all groups - foreach ($groups as $group) { - foreach ($potgraders as $t) { - if ($t->id == $user->id) { - continue; // do not send self - } - if (groups_is_member($group->id, $t->id)) { - $graders[$t->id] = $t; - } - } - } - } else { - // user not in group, try to find graders without group - foreach ($potgraders as $t) { - if ($t->id == $user->id) { - continue; // do not send self - } - if (!groups_get_all_groups($this->course->id, $t->id)) { //ugly hack - $graders[$t->id] = $t; - } - } - } - } else { - foreach ($potgraders as $t) { - if ($t->id == $user->id) { - continue; // do not send self - } - $graders[$t->id] = $t; - } - } - return $graders; - } - - /** - * Creates the text content for emails to teachers - * - * @param $info object The info used by the 'emailteachermail' language string - * @return string - */ - function email_teachers_text($info) { - $posttext = format_string($this->course->shortname).' -> '.$this->strassignments.' -> '. - format_string($this->assignment->name)."\n"; - $posttext .= '---------------------------------------------------------------------'."\n"; - $posttext .= get_string("emailteachermail", "assignment", $info)."\n"; - $posttext .= "\n---------------------------------------------------------------------\n"; - return $posttext; - } - - /** - * Creates the html content for emails to teachers - * - * @param $info object The info used by the 'emailteachermailhtml' language string - * @return string - */ - function email_teachers_html($info) { - global $CFG; - $posthtml = '

'. - ''.format_string($this->course->shortname).' ->'. - ''.$this->strassignments.' ->'. - ''.format_string($this->assignment->name).'

'; - $posthtml .= '
'; - $posthtml .= '

'.get_string('emailteachermailhtml', 'assignment', $info).'

'; - $posthtml .= '

'; - return $posthtml; - } - - /** - * Produces a list of links to the files uploaded by a user - * - * @param $userid int optional id of the user. If 0 then $USER->id is used. - * @param $return boolean optional defaults to false. If true the list is returned rather than printed - * @return string optional - */ - function print_user_files($userid=0, $return=false) { - global $CFG, $USER; - - if (!$userid) { - if (!isloggedin()) { - return ''; - } - $userid = $USER->id; - } - - $filearea = $this->file_area_name($userid); - - $output = ''; - - if ($basedir = $this->file_area($userid)) { - if ($files = get_directory_list($basedir)) { - require_once($CFG->libdir.'/filelib.php'); - foreach ($files as $key => $file) { - - $icon = mimeinfo('icon', $file); - $ffurl = get_file_url("$filearea/$file", array('forcedownload'=>1)); - - $output .= ''.$icon.''. - ''.$file.'
'; - } - } - } - - $output = '
'.$output.'
'; - - if ($return) { - return $output; - } - echo $output; - } - - /** - * Count the files uploaded by a given user - * - * @param $userid int The user id - * @return int - */ - function count_user_files($userid) { - global $CFG; - - $filearea = $this->file_area_name($userid); - - if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { - if ($files = get_directory_list($basedir)) { - return count($files); - } - } - return 0; - } - - /** - * Creates a directory file name, suitable for make_upload_directory() - * - * @param $userid int The user id - * @return string path to file area - */ - function file_area_name($userid) { - global $CFG; - - return $this->course->id.'/'.$CFG->moddata.'/assignment/'.$this->assignment->id.'/'.$userid; - } - - /** - * Makes an upload directory - * - * @param $userid int The user id - * @return string path to file area. - */ - function file_area($userid) { - return make_upload_directory( $this->file_area_name($userid) ); - } - - /** - * Returns true if the student is allowed to submit - * - * Checks that the assignment has started and, if the option to prevent late - * submissions is set, also checks that the assignment has not yet closed. - * @return boolean - */ - function isopen() { - $time = time(); - if ($this->assignment->preventlate && $this->assignment->timedue) { - return ($this->assignment->timeavailable <= $time && $time <= $this->assignment->timedue); - } else { - return ($this->assignment->timeavailable <= $time); - } - } - - - /** - * Return true if is set description is hidden till available date - * - * This is needed by calendar so that hidden descriptions do not - * come up in upcoming events. - * - * Check that description is hidden till available date - * By default return false - * Assignments types should implement this method if needed - * @return boolen - */ - function description_is_hidden() { - return false; - } - - /** - * Return an outline of the user's interaction with the assignment - * - * The default method prints the grade and timemodified - * @param $user object - * @return object with properties ->info and ->time - */ - function user_outline($user) { - if ($submission = $this->get_submission($user->id)) { - - $result = new object(); - $result->info = get_string('grade').': '.$this->display_grade($submission->grade); - $result->time = $submission->timemodified; - return $result; - } - return NULL; - } - - /** - * Print complete information about the user's interaction with the assignment - * - * @param $user object - */ - function user_complete($user) { - if ($submission = $this->get_submission($user->id)) { - if ($basedir = $this->file_area($user->id)) { - if ($files = get_directory_list($basedir)) { - $countfiles = count($files)." ".get_string("uploadedfiles", "assignment"); - foreach ($files as $file) { - $countfiles .= "; $file"; - } - } - } - - print_simple_box_start(); - echo get_string("lastmodified").": "; - echo userdate($submission->timemodified); - echo $this->display_lateness($submission->timemodified); - - $this->print_user_files($user->id); - - echo '
'; - - if (empty($submission->timemarked)) { - print_string("notgradedyet", "assignment"); - } else { - $this->view_feedback($submission); - } - - print_simple_box_end(); - - } else { - print_string("notsubmittedyet", "assignment"); - } - } - - /** - * Return a string indicating how late a submission is - * - * @param $timesubmitted int - * @return string - */ - function display_lateness($timesubmitted) { - return assignment_display_lateness($timesubmitted, $this->assignment->timedue); - } - - /** - * Empty method stub for all delete actions. - */ - function delete() { - //nothing by default - redirect('view.php?id='.$this->cm->id); - } - - /** - * Empty custom feedback grading form. - */ - function custom_feedbackform($submission, $return=false) { - //nothing by default - return ''; - } - - /** - * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information - * for the course (see resource). - * - * Given a course_module object, this function returns any "extra" information that may be needed - * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. - * - * @param $coursemodule object The coursemodule object (record). - * @return object An object on information that the coures will know about (most noticeably, an icon). - * - */ - function get_coursemodule_info($coursemodule) { - return false; - } - - /** - * Plugin cron method - do not use $this here, create new assignment instances if needed. - * @return void - */ - function cron() { - //no plugin cron by default - override if needed - } - - /** - * Reset all submissions - */ - function reset_userdata($data) { - global $CFG; - require_once($CFG->libdir.'/filelib.php'); - - if (!count_records('assignment', 'course', $data->courseid, 'assignmenttype', $this->type)) { - return array(); // no assignments of this type present - } - - $componentstr = get_string('modulenameplural', 'assignment'); - $status = array(); - - $typestr = get_string('type'.$this->type, 'assignment'); - - if (!empty($data->reset_assignment_submissions)) { - $assignmentssql = "SELECT a.id - FROM {$CFG->prefix}assignment a - WHERE a.course={$data->courseid} AND a.assignmenttype='{$this->type}'"; - - delete_records_select('assignment_submissions', "assignment IN ($assignmentssql)"); - - if ($assignments = get_records_sql($assignmentssql)) { - foreach ($assignments as $assignmentid=>$unused) { - fulldelete($CFG->dataroot.'/'.$data->courseid.'/moddata/assignment/'.$assignmentid); - } - } - - $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallsubmissions','assignment').': '.$typestr, 'error'=>false); - - if (empty($data->reset_gradebook_grades)) { - // remove all grades from gradebook - assignment_reset_gradebook($data->courseid, $this->type); - } - } - - /// updating dates - shift may be negative too - if ($data->timeshift) { - shift_course_mod_dates('assignment', array('timedue', 'timeavailable'), $data->timeshift, $data->courseid); - $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged').': '.$typestr, 'error'=>false); - } - - return $status; - } -} ////// End of the assignment_base class - - - -/// OTHER STANDARD FUNCTIONS //////////////////////////////////////////////////////// - -/** - * Deletes an assignment instance - * - * This is done by calling the delete_instance() method of the assignment type class - */ -function assignment_delete_instance($id){ - global $CFG; - - if (! $assignment = get_record('assignment', 'id', $id)) { - return false; - } - - // fall back to base class if plugin missing - $classfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"; - if (file_exists($classfile)) { - require_once($classfile); - $assignmentclass = "assignment_$assignment->assignmenttype"; - - } else { - debugging("Missing assignment plug-in: {$assignment->assignmenttype}. Using base class for deleting instead."); - $assignmentclass = "assignment_base"; - } - - $ass = new $assignmentclass(); - return $ass->delete_instance($assignment); -} - - -/** - * Updates an assignment instance - * - * This is done by calling the update_instance() method of the assignment type class - */ -function assignment_update_instance($assignment){ - global $CFG; - - $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR); - - require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $ass = new $assignmentclass(); - return $ass->update_instance($assignment); -} - - -/** - * Adds an assignment instance - * - * This is done by calling the add_instance() method of the assignment type class - */ -function assignment_add_instance($assignment) { - global $CFG; - - $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR); - - require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $ass = new $assignmentclass(); - return $ass->add_instance($assignment); -} - - -/** - * Returns an outline of a user interaction with an assignment - * - * This is done by calling the user_outline() method of the assignment type class - */ -function assignment_user_outline($course, $user, $mod, $assignment) { - global $CFG; - - require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $ass = new $assignmentclass($mod->id, $assignment, $mod, $course); - return $ass->user_outline($user); -} - -/** - * Prints the complete info about a user's interaction with an assignment - * - * This is done by calling the user_complete() method of the assignment type class - */ -function assignment_user_complete($course, $user, $mod, $assignment) { - global $CFG; - - require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $ass = new $assignmentclass($mod->id, $assignment, $mod, $course); - return $ass->user_complete($user); -} - -/** - * Function to be run periodically according to the moodle cron - * - * Finds all assignment notifications that have yet to be mailed out, and mails them - */ -function assignment_cron () { - - global $CFG, $USER; - - /// first execute all crons in plugins - if ($plugins = get_list_of_plugins('mod/assignment/type')) { - foreach ($plugins as $plugin) { - require_once("$CFG->dirroot/mod/assignment/type/$plugin/assignment.class.php"); - $assignmentclass = "assignment_$plugin"; - $ass = new $assignmentclass(); - $ass->cron(); - } - } - - /// Notices older than 1 day will not be mailed. This is to avoid the problem where - /// cron has not been running for a long time, and then suddenly people are flooded - /// with mail from the past few weeks or months - - $timenow = time(); - $endtime = $timenow - $CFG->maxeditingtime; - $starttime = $endtime - 24 * 3600; /// One day earlier - - if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) { - - $realuser = clone($USER); - - foreach ($submissions as $key => $submission) { - if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) { - echo "Could not update the mailed field for id $submission->id. Not mailed.\n"; - unset($submissions[$key]); - } - } - - $timenow = time(); - - foreach ($submissions as $submission) { - - echo "Processing assignment submission $submission->id\n"; - - if (! $user = get_record("user", "id", "$submission->userid")) { - echo "Could not find user $post->userid\n"; - continue; - } - - if (! $course = get_record("course", "id", "$submission->course")) { - echo "Could not find course $submission->course\n"; - continue; - } - - /// Override the language and timezone of the "current" user, so that - /// mail is customised for the receiver. - $USER = $user; - course_setup($course); - - if (!has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $submission->course), $user->id)) { - echo fullname($user)." not an active participant in " . format_string($course->shortname) . "\n"; - continue; - } - - if (! $teacher = get_record("user", "id", "$submission->teacher")) { - echo "Could not find teacher $submission->teacher\n"; - continue; - } - - if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment, $course->id)) { - echo "Could not find course module for assignment id $submission->assignment\n"; - continue; - } - - if (! $mod->visible) { /// Hold mail notification for hidden assignments until later - continue; - } - - $strassignments = get_string("modulenameplural", "assignment"); - $strassignment = get_string("modulename", "assignment"); - - $assignmentinfo = new object(); - $assignmentinfo->teacher = fullname($teacher); - $assignmentinfo->assignment = format_string($submission->name,true); - $assignmentinfo->url = "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id"; - - $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true); - $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n"; - $posttext .= "---------------------------------------------------------------------\n"; - $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo)."\n"; - $posttext .= "---------------------------------------------------------------------\n"; - - if ($user->mailformat == 1) { // HTML - $posthtml = "

". - "wwwroot/course/view.php?id=$course->id\">$course->shortname ->". - "wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments ->". - "wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."

"; - $posthtml .= "
"; - $posthtml .= "

".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."

"; - $posthtml .= "

"; - } else { - $posthtml = ""; - } - - if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) { - echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n"; - } - } - - $USER = $realuser; - course_setup(SITEID); // reset cron user language, theme and timezone settings - - } - - return true; -} - -/** - * Return grade for given user or all users. - * - * @param int $assignmentid id of assignment - * @param int $userid optional user id, 0 means all users - * @return array array of grades, false if none - */ -function assignment_get_user_grades($assignment, $userid=0) { - global $CFG; - - $user = $userid ? "AND u.id = $userid" : ""; - - $sql = "SELECT u.id, u.id AS userid, s.grade AS rawgrade, s.submissioncomment AS feedback, s.format AS feedbackformat, - s.teacher AS usermodified, s.timemarked AS dategraded, s.timemodified AS datesubmitted - FROM {$CFG->prefix}user u, {$CFG->prefix}assignment_submissions s - WHERE u.id = s.userid AND s.assignment = $assignment->id - $user"; - - return get_records_sql($sql); -} - -/** - * Update grades by firing grade_updated event - * - * @param object $assignment null means all assignments - * @param int $userid specific user only, 0 mean all - */ -function assignment_update_grades($assignment=null, $userid=0, $nullifnone=true) { - global $CFG; - if (!function_exists('grade_update')) { //workaround for buggy PHP versions - require_once($CFG->libdir.'/gradelib.php'); - } - - if ($assignment != null) { - if ($grades = assignment_get_user_grades($assignment, $userid)) { - foreach($grades as $k=>$v) { - if ($v->rawgrade == -1) { - $grades[$k]->rawgrade = null; - } - } - assignment_grade_item_update($assignment, $grades); - } else { - assignment_grade_item_update($assignment); - } - - } else { - $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid - FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m - WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id"; - if ($rs = get_recordset_sql($sql)) { - while ($assignment = rs_fetch_next_record($rs)) { - if ($assignment->grade != 0) { - assignment_update_grades($assignment); - } else { - assignment_grade_item_update($assignment); - } - } - rs_close($rs); - } - } -} - -/** - * Create grade item for given assignment - * - * @param object $assignment object with extra cmidnumber - * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook - * @return int 0 if ok, error code otherwise - */ -function assignment_grade_item_update($assignment, $grades=NULL) { - global $CFG; - if (!function_exists('grade_update')) { //workaround for buggy PHP versions - require_once($CFG->libdir.'/gradelib.php'); - } - - if (!isset($assignment->courseid)) { - $assignment->courseid = $assignment->course; - } - - $params = array('itemname'=>$assignment->name, 'idnumber'=>$assignment->cmidnumber); - - if ($assignment->grade > 0) { - $params['gradetype'] = GRADE_TYPE_VALUE; - $params['grademax'] = $assignment->grade; - $params['grademin'] = 0; - - } else if ($assignment->grade < 0) { - $params['gradetype'] = GRADE_TYPE_SCALE; - $params['scaleid'] = -$assignment->grade; - - } else { - $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only - } - - if ($grades === 'reset') { - $params['reset'] = true; - $grades = NULL; - } - - return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, $grades, $params); -} - -/** - * Delete grade item for given assignment - * - * @param object $assignment object - * @return object assignment - */ -function assignment_grade_item_delete($assignment) { - global $CFG; - require_once($CFG->libdir.'/gradelib.php'); - - if (!isset($assignment->courseid)) { - $assignment->courseid = $assignment->course; - } - - return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, NULL, array('deleted'=>1)); -} - -/** - * Returns the users with data in one assignment (students and teachers) - * - * @param $assignmentid int - * @return array of user objects - */ -function assignment_get_participants($assignmentid) { - - global $CFG; - - //Get students - $students = get_records_sql("SELECT DISTINCT u.id, u.id - FROM {$CFG->prefix}user u, - {$CFG->prefix}assignment_submissions a - WHERE a.assignment = '$assignmentid' and - u.id = a.userid"); - //Get teachers - $teachers = get_records_sql("SELECT DISTINCT u.id, u.id - FROM {$CFG->prefix}user u, - {$CFG->prefix}assignment_submissions a - WHERE a.assignment = '$assignmentid' and - u.id = a.teacher"); - - //Add teachers to students - if ($teachers) { - foreach ($teachers as $teacher) { - $students[$teacher->id] = $teacher; - } - } - //Return students array (it contains an array of unique users) - return ($students); -} - -/** - * Checks if a scale is being used by an assignment - * - * This is used by the backup code to decide whether to back up a scale - * @param $assignmentid int - * @param $scaleid int - * @return boolean True if the scale is used by the assignment - */ -function assignment_scale_used($assignmentid, $scaleid) { - - $return = false; - - $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid); - - if (!empty($rec) && !empty($scaleid)) { - $return = true; - } - - return $return; -} - -/** - * Checks if scale is being used by any instance of assignment - * - * This is used to find out if scale used anywhere - * @param $scaleid int - * @return boolean True if the scale is used by any assignment - */ -function assignment_scale_used_anywhere($scaleid) { - if ($scaleid and record_exists('assignment', 'grade', -$scaleid)) { - return true; - } else { - return false; - } -} - -/** - * Make sure up-to-date events are created for all assignment instances - * - * This standard function will check all instances of this module - * and make sure there are up-to-date events created for each of them. - * If courseid = 0, then every assignment event in the site is checked, else - * only assignment events belonging to the course specified are checked. - * This function is used, in its new format, by restore_refresh_events() - * - * @param $courseid int optional If zero then all assignments for all courses are covered - * @return boolean Always returns true - */ -function assignment_refresh_events($courseid = 0) { - - if ($courseid == 0) { - if (! $assignments = get_records("assignment")) { - return true; - } - } else { - if (! $assignments = get_records("assignment", "course", $courseid)) { - return true; - } - } - $moduleid = get_field('modules', 'id', 'name', 'assignment'); - - foreach ($assignments as $assignment) { - $event = NULL; - $event->name = addslashes($assignment->name); - $event->description = addslashes($assignment->description); - $event->timestart = $assignment->timedue; - - if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) { - update_event($event); - - } else { - $event->courseid = $assignment->course; - $event->groupid = 0; - $event->userid = 0; - $event->modulename = 'assignment'; - $event->instance = $assignment->id; - $event->eventtype = 'due'; - $event->timeduration = 0; - $event->visible = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id); - add_event($event); - } - - } - return true; -} - -/** - * Print recent activity from all assignments in a given course - * - * This is used by the recent activity block - */ -function assignment_print_recent_activity($course, $viewfullnames, $timestart) { - global $CFG, $USER; - - // do not use log table if possible, it may be huge - - if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, asb.userid, - u.firstname, u.lastname, u.email, u.picture - FROM {$CFG->prefix}assignment_submissions asb - JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment - JOIN {$CFG->prefix}course_modules cm ON cm.instance = a.id - JOIN {$CFG->prefix}modules md ON md.id = cm.module - JOIN {$CFG->prefix}user u ON u.id = asb.userid - WHERE asb.timemodified > $timestart AND - a.course = {$course->id} AND - md.name = 'assignment' - ORDER BY asb.timemodified ASC")) { - return false; - } - - $modinfo =& get_fast_modinfo($course); // reference needed because we might load the groups - $show = array(); - $grader = array(); - - foreach($submissions as $submission) { - if (!array_key_exists($submission->cmid, $modinfo->cms)) { - continue; - } - $cm = $modinfo->cms[$submission->cmid]; - if (!$cm->uservisible) { - continue; - } - if ($submission->userid == $USER->id) { - $show[] = $submission; - continue; - } - - // the act of sumbitting of assignment may be considered private - only graders will see it if specified - if (empty($CFG->assignment_showrecentsubmissions)) { - if (!array_key_exists($cm->id, $grader)) { - $grader[$cm->id] = has_capability('moodle/grade:viewall', get_context_instance(CONTEXT_MODULE, $cm->id)); - } - if (!$grader[$cm->id]) { - continue; - } - } - - $groupmode = groups_get_activity_groupmode($cm, $course); - - if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) { - if (isguestuser()) { - // shortcut - guest user does not belong into any group - continue; - } - - if (is_null($modinfo->groups)) { - $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo - } - - // this will be slow - show only users that share group with me in this cm - if (empty($modinfo->groups[$cm->id])) { - continue; - } - $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid); - if (is_array($usersgroups)) { - $usersgroups = array_keys($usersgroups); - $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]); - if (empty($intersect)) { - continue; - } - } - } - $show[] = $submission; - } - - if (empty($show)) { - return false; - } - - print_headline(get_string('newsubmissions', 'assignment').':'); - - foreach ($show as $submission) { - $cm = $modinfo->cms[$submission->cmid]; - $link = $CFG->wwwroot.'/mod/assignment/view.php?id='.$cm->id; - print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames); - } - - return true; -} - - -/** - * Returns all assignments since a given time in specified forum. - */ -function assignment_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) { - - global $CFG, $COURSE, $USER; - - if ($COURSE->id == $courseid) { - $course = $COURSE; - } else { - $course = get_record('course', 'id', $courseid); - } - - $modinfo =& get_fast_modinfo($course); - - $cm = $modinfo->cms[$cmid]; - - if ($userid) { - $userselect = "AND u.id = $userid"; - } else { - $userselect = ""; - } - - if ($groupid) { - $groupselect = "AND gm.groupid = $groupid"; - $groupjoin = "JOIN {$CFG->prefix}groups_members gm ON gm.userid=u.id"; - } else { - $groupselect = ""; - $groupjoin = ""; - } - - if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, asb.userid, - u.firstname, u.lastname, u.email, u.picture - FROM {$CFG->prefix}assignment_submissions asb - JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment - JOIN {$CFG->prefix}user u ON u.id = asb.userid - $groupjoin - WHERE asb.timemodified > $timestart AND a.id = $cm->instance - $userselect $groupselect - ORDER BY asb.timemodified ASC")) { - return; - } - - $groupmode = groups_get_activity_groupmode($cm, $course); - $cm_context = get_context_instance(CONTEXT_MODULE, $cm->id); - $grader = has_capability('moodle/grade:viewall', $cm_context); - $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context); - $viewfullnames = has_capability('moodle/site:viewfullnames', $cm_context); - - if (is_null($modinfo->groups)) { - $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo - } - - $show = array(); - - foreach($submissions as $submission) { - if ($submission->userid == $USER->id) { - $show[] = $submission; - continue; - } - // the act of submitting of assignment may be considered private - only graders will see it if specified - if (empty($CFG->assignment_showrecentsubmissions)) { - if (!$grader) { - continue; - } - } - - if ($groupmode == SEPARATEGROUPS and !$accessallgroups) { - if (isguestuser()) { - // shortcut - guest user does not belong into any group - continue; - } - - // this will be slow - show only users that share group with me in this cm - if (empty($modinfo->groups[$cm->id])) { - continue; - } - $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid); - if (is_array($usersgroups)) { - $usersgroups = array_keys($usersgroups); - $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]); - if (empty($intersect)) { - continue; - } - } - } - $show[] = $submission; - } - - if (empty($show)) { - return; - } - - if ($grader) { - require_once($CFG->libdir.'/gradelib.php'); - $userids = array(); - foreach ($show as $id=>$submission) { - $userids[] = $submission->userid; - - } - $grades = grade_get_grades($courseid, 'mod', 'assignment', $cm->instance, $userids); - } - - $aname = format_string($cm->name,true); - foreach ($show as $submission) { - $tmpactivity = new object(); - - $tmpactivity->type = 'assignment'; - $tmpactivity->cmid = $cm->id; - $tmpactivity->name = $aname; - $tmpactivity->sectionnum = $cm->sectionnum; - $tmpactivity->timestamp = $submission->timemodified; - - if ($grader) { - $tmpactivity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade; - } - - $tmpactivity->user->userid = $submission->userid; - $tmpactivity->user->fullname = fullname($submission, $viewfullnames); - $tmpactivity->user->picture = $submission->picture; - - $activities[$index++] = $tmpactivity; - } - - return; -} - -/** - * Print recent activity from all assignments in a given course - * - * This is used by course/recent.php - */ -function assignment_print_recent_mod_activity($activity, $courseid, $detail, $modnames) { - global $CFG; - - echo ''; - - echo "
"; - print_user_picture($activity->user->userid, $courseid, $activity->user->picture); - echo ""; - - if ($detail) { - $modname = $modnames[$activity->type]; - echo '
'; - echo "modpixpath/assignment/icon.gif\" ". - "class=\"icon\" alt=\"$modname\">"; - echo "wwwroot/mod/assignment/view.php?id={$activity->cmid}\">{$activity->name}"; - echo '
'; - } - - if (isset($activity->grade)) { - echo '
'; - echo get_string('grade').': '; - echo $activity->grade; - echo '
'; - } - - echo ''; - - echo "
"; -} - -/// GENERIC SQL FUNCTIONS - -/** - * Fetch info from logs - * - * @param $log object with properties ->info (the assignment id) and ->userid - * @return array with assignment name and user firstname and lastname - */ -function assignment_log_info($log) { - global $CFG; - return get_record_sql("SELECT a.name, u.firstname, u.lastname - FROM {$CFG->prefix}assignment a, - {$CFG->prefix}user u - WHERE a.id = '$log->info' - AND u.id = '$log->userid'"); -} - -/** - * Return list of marked submissions that have not been mailed out for currently enrolled students - * - * @return array - */ -function assignment_get_unmailed_submissions($starttime, $endtime) { - - global $CFG; - - return get_records_sql("SELECT s.*, a.course, a.name - FROM {$CFG->prefix}assignment_submissions s, - {$CFG->prefix}assignment a - WHERE s.mailed = 0 - AND s.timemarked <= $endtime - AND s.timemarked >= $starttime - AND s.assignment = a.id"); - - /* return get_records_sql("SELECT s.*, a.course, a.name - FROM {$CFG->prefix}assignment_submissions s, - {$CFG->prefix}assignment a, - {$CFG->prefix}user_students us - WHERE s.mailed = 0 - AND s.timemarked <= $endtime - AND s.timemarked >= $starttime - AND s.assignment = a.id - AND s.userid = us.userid - AND a.course = us.course"); - */ -} - -/** - * Counts all real assignment submissions by ENROLLED students (not empty ones) - * - * There are also assignment type methods count_real_submissions() wich in the default - * implementation simply call this function. - * @param $groupid int optional If nonzero then count is restricted to this group - * @return int The number of submissions - */ -function assignment_count_real_submissions($cm, $groupid=0) { - global $CFG; - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - // this is all the users with this capability set, in this context or higher - if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $groupid, '', false)) { - $users = array_keys($users); - } - - // if groupmembersonly used, remove users who are not in any group - if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { - if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { - $users = array_intersect($users, array_keys($groupingusers)); - } - } - - if (empty($users)) { - return 0; - } - - $userlists = implode(',', $users); - - return count_records_sql("SELECT COUNT('x') - FROM {$CFG->prefix}assignment_submissions - WHERE assignment = $cm->instance AND - timemodified > 0 AND - userid IN ($userlists)"); -} - - -/** - * Return all assignment submissions by ENROLLED students (even empty) - * - * There are also assignment type methods get_submissions() wich in the default - * implementation simply call this function. - * @param $sort string optional field names for the ORDER BY in the sql query - * @param $dir string optional specifying the sort direction, defaults to DESC - * @return array The submission objects indexed by id - */ -function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") { -/// Return all assignment submissions by ENROLLED students (even empty) - global $CFG; - - if ($sort == "lastname" or $sort == "firstname") { - $sort = "u.$sort $dir"; - } else if (empty($sort)) { - $sort = "a.timemodified DESC"; - } else { - $sort = "a.$sort $dir"; - } - - /* not sure this is needed at all since assignmenet already has a course define, so this join? - $select = "s.course = '$assignment->course' AND"; - if ($assignment->course == SITEID) { - $select = ''; - }*/ - - return get_records_sql("SELECT a.* - FROM {$CFG->prefix}assignment_submissions a, - {$CFG->prefix}user u - WHERE u.id = a.userid - AND a.assignment = '$assignment->id' - ORDER BY $sort"); - - /* return get_records_sql("SELECT a.* - FROM {$CFG->prefix}assignment_submissions a, - {$CFG->prefix}user_students s, - {$CFG->prefix}user u - WHERE a.userid = s.userid - AND u.id = a.userid - AND $select a.assignment = '$assignment->id' - ORDER BY $sort"); - */ -} - -/** - * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information - * for the course (see resource). - * - * Given a course_module object, this function returns any "extra" information that may be needed - * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. - * - * @param $coursemodule object The coursemodule object (record). - * @return object An object on information that the coures will know about (most noticeably, an icon). - * - */ -function assignment_get_coursemodule_info($coursemodule) { - global $CFG; - - if (! $assignment = get_record('assignment', 'id', $coursemodule->instance, '', '', '', '', 'id, assignmenttype, name')) { - return false; - } - - $libfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"; - - if (file_exists($libfile)) { - require_once($libfile); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $ass = new $assignmentclass('staticonly'); - if ($result = $ass->get_coursemodule_info($coursemodule)) { - return $result; - } else { - $info = new object(); - $info->name = $assignment->name; - return $info; - } - - } else { - debugging('Incorrect assignment type: '.$assignment->assignmenttype); - return false; - } -} - - - -/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS /////////////////////////////////////// - -/** - * Returns an array of installed assignment types indexed and sorted by name - * - * @return array The index is the name of the assignment type, the value its full name from the language strings - */ -function assignment_types() { - $types = array(); - $names = get_list_of_plugins('mod/assignment/type'); - foreach ($names as $name) { - $types[$name] = get_string('type'.$name, 'assignment'); - } - asort($types); - return $types; -} - -/** - * Executes upgrade scripts for assignment types when necessary - */ -function assignment_upgrade_submodules() { - - global $CFG; - -/// Install/upgrade assignment types (it uses, simply, the standard plugin architecture) - upgrade_plugins('assignment_type', 'mod/assignment/type', "$CFG->wwwroot/$CFG->admin/index.php"); - -} - -function assignment_print_overview($courses, &$htmlarray) { - - global $USER, $CFG; - - if (empty($courses) || !is_array($courses) || count($courses) == 0) { - return array(); - } - - if (!$assignments = get_all_instances_in_courses('assignment',$courses)) { - return; - } - - $assignmentids = array(); - - // Do assignment_base::isopen() here without loading the whole thing for speed - foreach ($assignments as $key => $assignment) { - $time = time(); - if ($assignment->timedue) { - if ($assignment->preventlate) { - $isopen = ($assignment->timeavailable <= $time && $time <= $assignment->timedue); - } else { - $isopen = ($assignment->timeavailable <= $time); - } - } - if (empty($isopen) || empty($assignment->timedue)) { - unset($assignments[$key]); - }else{ - $assignmentids[] = $assignment->id; - } - } - - if(empty($assignmentids)){ - // no assigments to look at - we're done - return true; - } - - $strduedate = get_string('duedate', 'assignment'); - $strduedateno = get_string('duedateno', 'assignment'); - $strgraded = get_string('graded', 'assignment'); - $strnotgradedyet = get_string('notgradedyet', 'assignment'); - $strnotsubmittedyet = get_string('notsubmittedyet', 'assignment'); - $strsubmitted = get_string('submitted', 'assignment'); - $strassignment = get_string('modulename', 'assignment'); - $strreviewed = get_string('reviewed','assignment'); - - - // NOTE: we do all possible database work here *outside* of the loop to ensure this scales - - // build up and array of unmarked submissions indexed by assigment id/ userid - // for use where the user has grading rights on assigment - $rs = get_recordset_sql("SELECT id, assignment, userid - FROM {$CFG->prefix}assignment_submissions - WHERE teacher = 0 AND timemarked = 0 - AND assignment IN (". implode(',', $assignmentids).")"); - - $unmarkedsubmissions = array(); - while ($ra = rs_fetch_next_record($rs)) { - $unmarkedsubmissions[$ra->assignment][$ra->userid] = $ra->id; - } - rs_close($rs); - - - // get all user submissions, indexed by assigment id - $mysubmissions = get_records_sql("SELECT assignment, timemarked, teacher, grade - FROM {$CFG->prefix}assignment_submissions - WHERE userid = {$USER->id} AND - assignment IN (".implode(',', $assignmentids).")"); - - foreach ($assignments as $assignment) { - $str = '
'.$strassignment. ': '. - 'visible ? '':' class="dimmed"'). - 'title="'.$strassignment.'" href="'.$CFG->wwwroot. - '/mod/assignment/view.php?id='.$assignment->coursemodule.'">'. - $assignment->name.'
'; - if ($assignment->timedue) { - $str .= '
'.$strduedate.': '.userdate($assignment->timedue).'
'; - } else { - $str .= '
'.$strduedateno.'
'; - } - $context = get_context_instance(CONTEXT_MODULE, $assignment->coursemodule); - if (has_capability('mod/assignment:grade', $context)) { - - // count how many people can submit - $submissions = 0; // init - if ($students = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', 0, '', false)) { - foreach($students as $student){ - if(isset($unmarkedsubmissions[$assignment->id][$student->id])){ - $submissions++; - } - } - } - - if ($submissions) { - $str .= get_string('submissionsnotgraded', 'assignment', $submissions); - } - } else { - if(isset($mysubmissions[$assignment->id])){ - - $submission = $mysubmissions[$assignment->id]; - - if ($submission->teacher == 0 && $submission->timemarked == 0) { - $str .= $strsubmitted . ', ' . $strnotgradedyet; - } else if ($submission->grade <= 0) { - $str .= $strsubmitted . ', ' . $strreviewed; - } else { - $str .= $strsubmitted . ', ' . $strgraded; - } - } else { - $str .= $strnotsubmittedyet . ' ' . assignment_display_lateness(time(), $assignment->timedue); - } - } - $str .= '
'; - if (empty($htmlarray[$assignment->course]['assignment'])) { - $htmlarray[$assignment->course]['assignment'] = $str; - } else { - $htmlarray[$assignment->course]['assignment'] .= $str; - } - } -} - -function assignment_display_lateness($timesubmitted, $timedue) { - if (!$timedue) { - return ''; - } - $time = $timedue - $timesubmitted; - if ($time < 0) { - $timetext = get_string('late', 'assignment', format_time($time)); - return ' ('.$timetext.')'; - } else { - $timetext = get_string('early', 'assignment', format_time($time)); - return ' ('.$timetext.')'; - } -} - -function assignment_get_view_actions() { - return array('view'); -} - -function assignment_get_post_actions() { - return array('upload'); -} - -function assignment_get_types() { - global $CFG; - $types = array(); - - $type = new object(); - $type->modclass = MOD_CLASS_ACTIVITY; - $type->type = "assignment_group_start"; - $type->typestr = '--'.get_string('modulenameplural', 'assignment'); - $types[] = $type; - - $standardassignments = array('upload','online','uploadsingle','offline'); - foreach ($standardassignments as $assignmenttype) { - $type = new object(); - $type->modclass = MOD_CLASS_ACTIVITY; - $type->type = "assignment&type=$assignmenttype"; - $type->typestr = get_string("type$assignmenttype", 'assignment'); - $types[] = $type; - } - - /// Drop-in extra assignment types - $assignmenttypes = get_list_of_plugins('mod/assignment/type'); - foreach ($assignmenttypes as $assignmenttype) { - if (!empty($CFG->{'assignment_hide_'.$assignmenttype})) { // Not wanted - continue; - } - if (!in_array($assignmenttype, $standardassignments)) { - $type = new object(); - $type->modclass = MOD_CLASS_ACTIVITY; - $type->type = "assignment&type=$assignmenttype"; - $type->typestr = get_string("type$assignmenttype", 'assignment'); - $types[] = $type; - } - } - - $type = new object(); - $type->modclass = MOD_CLASS_ACTIVITY; - $type->type = "assignment_group_end"; - $type->typestr = '--'; - $types[] = $type; - - return $types; -} - -/** - * Removes all grades from gradebook - * @param int $courseid - * @param string optional type - */ -function assignment_reset_gradebook($courseid, $type='') { - global $CFG; - - $type = $type ? "AND a.assignmenttype='$type'" : ''; - - $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid - FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m - WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id AND a.course=$courseid $type"; - - if ($assignments = get_records_sql($sql)) { - foreach ($assignments as $assignment) { - assignment_grade_item_update($assignment, 'reset'); - } - } -} - -/** - * This function is used by the reset_course_userdata function in moodlelib. - * This function will remove all posts from the specified assignment - * and clean up any related data. - * @param $data the data submitted from the reset course. - * @return array status array - */ -function assignment_reset_userdata($data) { - global $CFG; - - $status = array(); - - foreach (get_list_of_plugins('mod/assignment/type') as $type) { - require_once("$CFG->dirroot/mod/assignment/type/$type/assignment.class.php"); - $assignmentclass = "assignment_$type"; - $ass = new $assignmentclass(); - $status = array_merge($status, $ass->reset_userdata($data)); - } - - return $status; -} - -/** - * Implementation of the function for printing the form elements that control - * whether the course reset functionality affects the assignment. - * @param $mform form passed by reference - */ -function assignment_reset_course_form_definition(&$mform) { - $mform->addElement('header', 'assignmentheader', get_string('modulenameplural', 'assignment')); - $mform->addElement('advcheckbox', 'reset_assignment_submissions', get_string('deleteallsubmissions','assignment')); -} - -/** - * Course reset form defaults. - */ -function assignment_reset_course_form_defaults($course) { - return array('reset_assignment_submissions'=>1); -} - -/** - * Returns all other caps used in module - */ -function assignment_get_extra_capabilities() { - return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames'); -} - -?> +cm = $cm; + } else if (! $this->cm = get_coursemodule_from_id('assignment', $cmid)) { + error('Course Module ID was incorrect'); + } + + $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id); + + if ($course) { + $this->course = $course; + } else if ($this->cm->course == $COURSE->id) { + $this->course = $COURSE; + } else if (! $this->course = get_record('course', 'id', $this->cm->course)) { + error('Course is misconfigured'); + } + + if ($assignment) { + $this->assignment = $assignment; + } else if (! $this->assignment = get_record('assignment', 'id', $this->cm->instance)) { + error('assignment ID was incorrect'); + } + + $this->assignment->cmidnumber = $this->cm->id; // compatibility with modedit assignment obj + $this->assignment->courseid = $this->course->id; // compatibility with modedit assignment obj + + $this->strassignment = get_string('modulename', 'assignment'); + $this->strassignments = get_string('modulenameplural', 'assignment'); + $this->strsubmissions = get_string('submissions', 'assignment'); + $this->strlastmodified = get_string('lastmodified'); + $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.format_string($this->assignment->name,true)); + + // visibility handled by require_login() with $cm parameter + // get current group only when really needed + + /// Set up things for a HTML editor if it's needed + if ($this->usehtmleditor = can_use_html_editor()) { + $this->defaultformat = FORMAT_HTML; + } else { + $this->defaultformat = FORMAT_MOODLE; + } + } + + /** + * Display the assignment, used by view.php + * + * This in turn calls the methods producing individual parts of the page + */ + function view() { + + $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); + require_capability('mod/assignment:view', $context); + + add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", + $this->assignment->id, $this->cm->id); + + $this->view_header(); + + $this->view_intro(); + + $this->view_dates(); + + $this->view_feedback(); + + $this->view_footer(); + } + + /** + * Display the header and top of a page + * + * (this doesn't change much for assignment types) + * This is used by the view() method to print the header of view.php but + * it can be used on other pages in which case the string to denote the + * page in the navigation trail should be passed as an argument + * + * @param $subpage string Description of subpage to be used in navigation trail + */ + function view_header($subpage='') { + + global $CFG; + + + if ($subpage) { + $navigation = build_navigation($subpage, $this->cm); + } else { + $navigation = build_navigation('', $this->cm); + } + + print_header($this->pagetitle, $this->course->fullname, $navigation, '', '', + true, update_module_button($this->cm->id, $this->course->id, $this->strassignment), + navmenu($this->course, $this->cm)); + + groups_print_activity_menu($this->cm, 'view.php?id=' . $this->cm->id); + + echo ''; + echo '
'; + } + + + /** + * Display the assignment intro + * + * This will most likely be extended by assignment type plug-ins + * The default implementation prints the assignment description in a box + */ + function view_intro() { + global $CFG; + + print_simple_box_start('center', '', '', 0, 'generalbox', 'intro'); + $formatoptions = new stdClass; + $formatoptions->noclean = true; + echo format_text($this->assignment->description, $this->assignment->format, $formatoptions); + + /* See if we can get a filename for assignment documents - redmorris 20090423 + * If we get one then display a link to the file with the description given and appropriate icon */ + if ($this->assignment->templatefile != '') { + $filename = $CFG->wwwroot.'/file.php/'.$this->course->id.'/'.$this->assignment->templatefile; + $filedescription = $this->assignment->templatetext; + if ($filedescription == '') { + $filedescription = get_string('assignmenttemplatetextdefault','assignment'); + } + $icon = mimeinfo('icon', substr(strrchr($filename, '/'),1)); + echo ''.get_string('file').' '.$filedescription.''; + } + print_simple_box_end(); + } + + /** + * Display the assignment dates + * + * Prints the assignment start and end dates in a box. + * This will be suitable for most assignment types + */ + function view_dates() { + if (!$this->assignment->timeavailable && !$this->assignment->timedue) { + return; + } + + print_simple_box_start('center', '', '', 0, 'generalbox', 'dates'); + echo ''; + if ($this->assignment->timeavailable) { + echo ''; + echo ' '; + } + if ($this->assignment->timedue) { + echo ''; + echo ' '; + } + echo '
'.get_string('availabledate','assignment').':'.userdate($this->assignment->timeavailable).'
'.get_string('duedate','assignment').':'.userdate($this->assignment->timedue).'
'; + print_simple_box_end(); + } + + + /** + * Display the bottom and footer of a page + * + * This default method just prints the footer. + * This will be suitable for most assignment types + */ + function view_footer() { + print_footer($this->course); + } + + /** + * Display the feedback to the student + * + * This default method prints the teacher picture and name, date when marked, + * grade and teacher submissioncomment. + * + * @param $submission object The submission object or NULL in which case it will be loaded + */ + function view_feedback($submission=NULL) { + global $USER, $CFG; + require_once($CFG->libdir.'/gradelib.php'); + + if (!has_capability('mod/assignment:submit', $this->context, $USER->id, false)) { + // can not submit assignments -> no feedback + return; + } + + if (!$submission) { /// Get submission for this assignment + $submission = $this->get_submission($USER->id); + } + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id); + $item = $grading_info->items[0]; + $grade = $item->grades[$USER->id]; + + if ($grade->hidden or $grade->grade === false) { // hidden or error + return; + } + + if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet + return; + } + + $graded_date = $grade->dategraded; + $graded_by = $grade->usermodified; + + /// We need the teacher info + if (!$teacher = get_record('user', 'id', $graded_by)) { + error('Could not find the teacher'); + } + + /// Print the feedback + print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher)); // TODO: fix teacher string + + echo ''; + + echo ''; + echo ''; + echo ''; + echo ''; + + echo ''; + echo ''; + echo ''; + + echo '
'; + if ($teacher) { + print_user_picture($teacher, $this->course->id, $teacher->picture); + } + echo ''; + echo '
'; + if ($teacher) { + echo '
'.fullname($teacher).'
'; + } + echo '
'.userdate($graded_date).'
'; + echo '
'; + echo '
 '; + echo '
'; + echo get_string("grade").': '.$grade->str_long_grade; + echo '
'; + echo '
'; + + echo '
'; + echo $grade->str_feedback; + echo '
'; + echo '
'; + } + + /** + * Returns a link with info about the state of the assignment submissions + * + * This is used by view_header to put this link at the top right of the page. + * For teachers it gives the number of submitted assignments with a link + * For students it gives the time of their submission. + * This will be suitable for most assignment types. + * @param bool $allgroup print all groups info if user can access all groups, suitable for index.php + * @return string + */ + function submittedlink($allgroups=false) { + global $USER; + + $submitted = ''; + + $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); + if (has_capability('mod/assignment:grade', $context)) { + if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) { + $group = 0; + } else { + $group = groups_get_activity_group($this->cm); + } + if ($count = $this->count_real_submissions($group)) { + $submitted = ''. + get_string('viewsubmissions', 'assignment', $count).''; + } else { + $submitted = ''. + get_string('noattempts', 'assignment').''; + } + } else { + if (!empty($USER->id)) { + if ($submission = $this->get_submission($USER->id)) { + if ($submission->timemodified) { + if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) { + $submitted = ''.userdate($submission->timemodified).''; + } else { + $submitted = ''.userdate($submission->timemodified).''; + } + } + } + } + } + + return $submitted; + } + + + function setup_elements(&$mform) { + + } + + /** + * Create a new assignment activity + * + * Given an object containing all the necessary data, + * (defined by the form in mod.html) this function + * will create a new instance and return the id number + * of the new instance. + * The due data is added to the calendar + * This is common to all assignment types. + * + * @param $assignment object The data from the form on mod.html + * @return int The id of the assignment + */ + function add_instance($assignment) { + global $COURSE; + + $assignment->timemodified = time(); + $assignment->courseid = $assignment->course; + + if ($returnid = insert_record("assignment", $assignment)) { + $assignment->id = $returnid; + + if ($assignment->timedue) { + $event = new object(); + $event->name = $assignment->name; + $event->description = $assignment->description; + $event->courseid = $assignment->course; + $event->groupid = 0; + $event->userid = 0; + $event->modulename = 'assignment'; + $event->instance = $returnid; + $event->eventtype = 'due'; + $event->timestart = $assignment->timedue; + $event->timeduration = 0; + + add_event($event); + } + + $assignment = stripslashes_recursive($assignment); + assignment_grade_item_update($assignment); + + } + + + return $returnid; + } + + /** + * Deletes an assignment activity + * + * Deletes all database records, files and calendar events for this assignment. + * @param $assignment object The assignment to be deleted + * @return boolean False indicates error + */ + function delete_instance($assignment) { + global $CFG; + + $assignment->courseid = $assignment->course; + + $result = true; + + if (! delete_records('assignment_submissions', 'assignment', $assignment->id)) { + $result = false; + } + + if (! delete_records('assignment', 'id', $assignment->id)) { + $result = false; + } + + if (! delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id)) { + $result = false; + } + + // delete file area with all attachments - ignore errors + require_once($CFG->libdir.'/filelib.php'); + fulldelete($CFG->dataroot.'/'.$assignment->course.'/'.$CFG->moddata.'/assignment/'.$assignment->id); + + assignment_grade_item_delete($assignment); + + return $result; + } + + /** + * Updates a new assignment activity + * + * Given an object containing all the necessary data, + * (defined by the form in mod.html) this function + * will update the assignment instance and return the id number + * The due date is updated in the calendar + * This is common to all assignment types. + * + * @param $assignment object The data from the form on mod.html + * @return int The assignment id + */ + function update_instance($assignment) { + global $COURSE; + + $assignment->timemodified = time(); + + $assignment->id = $assignment->instance; + $assignment->courseid = $assignment->course; + + if (!update_record('assignment', $assignment)) { + return false; + } + + if ($assignment->timedue) { + $event = new object(); + + if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) { + + $event->name = $assignment->name; + $event->description = $assignment->description; + $event->timestart = $assignment->timedue; + + update_event($event); + } else { + $event = new object(); + $event->name = $assignment->name; + $event->description = $assignment->description; + $event->courseid = $assignment->course; + $event->groupid = 0; + $event->userid = 0; + $event->modulename = 'assignment'; + $event->instance = $assignment->id; + $event->eventtype = 'due'; + $event->timestart = $assignment->timedue; + $event->timeduration = 0; + + add_event($event); + } + } else { + delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id); + } + + // get existing grade item + $assignment = stripslashes_recursive($assignment); + + assignment_grade_item_update($assignment); + + return true; + } + + /** + * Update grade item for this submission. + */ + function update_grade($submission) { + assignment_update_grades($this->assignment, $submission->userid); + } + + /** + * Top-level function for handling of submissions called by submissions.php + * + * This is for handling the teacher interaction with the grading interface + * This should be suitable for most assignment types. + * + * @param $mode string Specifies the kind of teacher interaction taking place + */ + function submissions($mode) { + ///The main switch is changed to facilitate + ///1) Batch fast grading + ///2) Skip to the next one on the popup + ///3) Save and Skip to the next one on the popup + + //make user global so we can use the id + global $USER; + + $mailinfo = optional_param('mailinfo', null, PARAM_BOOL); + if (is_null($mailinfo)) { + $mailinfo = get_user_preferences('assignment_mailinfo', 0); + } else { + set_user_preference('assignment_mailinfo', $mailinfo); + } + + switch ($mode) { + case 'grade': // We are in a popup window grading + if ($submission = $this->process_feedback()) { + //IE needs proper header with encoding + print_header(get_string('feedback', 'assignment').':'.format_string($this->assignment->name)); + print_heading(get_string('changessaved')); + print $this->update_main_listing($submission); + } + close_window(); + break; + + case 'single': // We are in a popup window displaying submission + $this->display_submission(); + break; + + case 'all': // Main window, display everything + $this->display_submissions(); + break; + + case 'fastgrade': + ///do the fast grading stuff - this process should work for all 3 subclasses + + $grading = false; + $commenting = false; + $col = false; + if (isset($_POST['submissioncomment'])) { + $col = 'submissioncomment'; + $commenting = true; + } + if (isset($_POST['menu'])) { + $col = 'menu'; + $grading = true; + } + if (!$col) { + //both submissioncomment and grade columns collapsed.. + $this->display_submissions(); + break; + } + + foreach ($_POST[$col] as $id => $unusedvalue){ + + $id = (int)$id; //clean parameter name + + $this->process_outcomes($id); + + if (!$submission = $this->get_submission($id)) { + $submission = $this->prepare_new_submission($id); + $newsubmission = true; + } else { + $newsubmission = false; + } + unset($submission->data1); // Don't need to update this. + unset($submission->data2); // Don't need to update this. + + //for fast grade, we need to check if any changes take place + $updatedb = false; + + if ($grading) { + $grade = $_POST['menu'][$id]; + $updatedb = $updatedb || ($submission->grade != $grade); + $submission->grade = $grade; + } else { + if (!$newsubmission) { + unset($submission->grade); // Don't need to update this. + } + } + if ($commenting) { + $commentvalue = trim($_POST['submissioncomment'][$id]); + $updatedb = $updatedb || ($submission->submissioncomment != stripslashes($commentvalue)); + $submission->submissioncomment = $commentvalue; + } else { + unset($submission->submissioncomment); // Don't need to update this. + } + + $submission->teacher = $USER->id; + if ($updatedb) { + $submission->mailed = (int)(!$mailinfo); + } + + $submission->timemarked = time(); + + //if it is not an update, we don't change the last modified time etc. + //this will also not write into database if no submissioncomment and grade is entered. + + if ($updatedb){ + if ($newsubmission) { + if (!isset($submission->submissioncomment)) { + $submission->submissioncomment = ''; + } + if (!$sid = insert_record('assignment_submissions', $submission)) { + return false; + } + $submission->id = $sid; + } else { + if (!update_record('assignment_submissions', $submission)) { + return false; + } + } + + // triger grade event + $this->update_grade($submission); + + //add to log only if updating + add_to_log($this->course->id, 'assignment', 'update grades', + 'submissions.php?id='.$this->assignment->id.'&user='.$submission->userid, + $submission->userid, $this->cm->id); + } + + } + + $message = notify(get_string('changessaved'), 'notifysuccess', 'center', true); + + $this->display_submissions($message); + break; + + + case 'next': + /// We are currently in pop up, but we want to skip to next one without saving. + /// This turns out to be similar to a single case + /// The URL used is for the next submission. + + $this->display_submission(); + break; + + case 'saveandnext': + ///We are in pop up. save the current one and go to the next one. + //first we save the current changes + if ($submission = $this->process_feedback()) { + //print_heading(get_string('changessaved')); + $extra_javascript = $this->update_main_listing($submission); + } + + //then we display the next submission + $this->display_submission($extra_javascript); + break; + + default: + echo "something seriously is wrong!!"; + break; + } + } + + /** + * Helper method updating the listing on the main script from popup using javascript + * + * @param $submission object The submission whose data is to be updated on the main page + */ + function update_main_listing($submission) { + global $SESSION, $CFG; + + $output = ''; + + $perpage = get_user_preferences('assignment_perpage', 10); + + $quickgrade = get_user_preferences('assignment_quickgrade', 0); + + /// Run some Javascript to try and update the parent page + $output .= '"; + return $output; + } + + /** + * Return a grade in user-friendly form, whether it's a scale or not + * + * @param $grade + * @return string User-friendly representation of grade + */ + function display_grade($grade) { + + static $scalegrades = array(); // Cache scales for each assignment - they might have different scales!! + + if ($this->assignment->grade >= 0) { // Normal number + if ($grade == -1) { + return '-'; + } else { + return $grade.' / '.$this->assignment->grade; + } + + } else { // Scale + if (empty($scalegrades[$this->assignment->id])) { + if ($scale = get_record('scale', 'id', -($this->assignment->grade))) { + $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale); + } else { + return '-'; + } + } + if (isset($scalegrades[$this->assignment->id][$grade])) { + return $scalegrades[$this->assignment->id][$grade]; + } + return '-'; + } + } + + /** + * Display a single submission, ready for grading on a popup window + * + * This default method prints the teacher info and submissioncomment box at the top and + * the student info and submission at the bottom. + * This method also fetches the necessary data in order to be able to + * provide a "Next submission" button. + * Calls preprocess_submission() to give assignment type plug-ins a chance + * to process submissions before they are graded + * This method gets its arguments from the page parameters userid and offset + */ + function display_submission($extra_javascript = '') { + + global $CFG; + require_once($CFG->libdir.'/gradelib.php'); + require_once($CFG->libdir.'/tablelib.php'); + + $userid = required_param('userid', PARAM_INT); + $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student. + + if (!$user = get_record('user', 'id', $userid)) { + error('No such user!'); + } + + if (!$submission = $this->get_submission($user->id)) { + $submission = $this->prepare_new_submission($userid); + } + if ($submission->timemodified > $submission->timemarked) { + $subtype = 'assignmentnew'; + } else { + $subtype = 'assignmentold'; + } + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array($user->id)); + $disabled = $grading_info->items[0]->grades[$userid]->locked || $grading_info->items[0]->grades[$userid]->overridden; + + /// construct SQL, using current offset to find the data of the next student + $course = $this->course; + $assignment = $this->assignment; + $cm = $this->cm; + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + /// Get all ppl that can submit assignments + + $currentgroup = groups_get_activity_group($cm); + if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) { + $users = array_keys($users); + } + + // if groupmembersonly used, remove users who are not in any group + if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { + if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { + $users = array_intersect($users, array_keys($groupingusers)); + } + } + + $nextid = 0; + + if ($users) { + $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt, + s.id AS submissionid, s.grade, s.submissioncomment, + s.timemodified, s.timemarked, + COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status '; + $sql = 'FROM '.$CFG->prefix.'user u '. + 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid + AND s.assignment = '.$this->assignment->id.' '. + 'WHERE u.id IN ('.implode(',', $users).') '; + + if ($sort = flexible_table::get_sql_sort('mod-assignment-submissions')) { + $sort = 'ORDER BY '.$sort.' '; + } + + if (($auser = get_records_sql($select.$sql.$sort, $offset+1, 1)) !== false) { + $nextuser = array_shift($auser); + /// Calculate user status + $nextuser->status = ($nextuser->timemarked > 0) && ($nextuser->timemarked >= $nextuser->timemodified); + $nextid = $nextuser->id; + } + } + + print_header(get_string('feedback', 'assignment').':'.fullname($user, true).':'.format_string($this->assignment->name)); + + /// Print any extra javascript needed for saveandnext + echo $extra_javascript; + + ///SOme javascript to help with setting up >.> + + echo ''."\n"; + echo ''; + + ///Start of teacher info row + + echo ''; + echo ''; + echo ''; + + ///End of teacher info row, Start of student info row + echo ''; + echo ''; + echo ''; + echo ''; + + ///End of student info row + + echo '
'; + if ($submission->teacher) { + $teacher = get_record('user', 'id', $submission->teacher); + } else { + global $USER; + $teacher = $USER; + } + print_user_picture($teacher, $this->course->id, $teacher->picture); + echo ''; + echo '
'; + echo '
'; // xhtml compatibility - invisiblefieldset was breaking layout here + echo ''; + echo ''; + echo ''; + echo ''; + echo '';//selected menu index + + //new hidden field, initialized to -1. + echo ''; + + if ($submission->timemarked) { + echo '
'; + echo '
'.fullname($teacher, true).'
'; + echo '
'.userdate($submission->timemarked).'
'; + echo '
'; + } + echo '
'; + choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', $submission->grade, get_string('nograde'), '', -1, false, $disabled); + echo '
'; + + echo '
'; + echo '
'.get_string('finalgrade', 'grades').': '.$grading_info->items[0]->grades[$userid]->str_grade.'
'; + echo '
'; + + if (!empty($CFG->enableoutcomes)) { + foreach($grading_info->outcomes as $n=>$outcome) { + echo '
'; + $options = make_grades_menu(-$outcome->scaleid); + if ($outcome->grades[$submission->userid]->locked) { + $options[0] = get_string('nooutcome', 'grades'); + echo $options[$outcome->grades[$submission->userid]->grade]; + } else { + choose_from_menu($options, 'outcome_'.$n.'['.$userid.']', $outcome->grades[$submission->userid]->grade, get_string('nooutcome', 'grades'), '', 0, false, false, 0, 'menuoutcome_'.$n); + } + echo '
'; + echo '
'; + } + } + + + $this->preprocess_submission($submission); + + if ($disabled) { + echo '
'.$grading_info->items[0]->grades[$userid]->str_feedback.'
'; + + } else { + print_textarea($this->usehtmleditor, 14, 58, 0, 0, 'submissioncomment', $submission->submissioncomment, $this->course->id); + if ($this->usehtmleditor) { + echo ''; + } else { + echo '
'; + choose_from_menu(format_text_menu(), "format", $submission->format, ""); + helpbutton("textformat", get_string("helpformatting")); + echo '
'; + } + } + + $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : ''; + + ///Print Buttons in Single View + echo ''; + echo ''; + echo '
'; + echo ''; + echo ''; + //if there are more to be graded. + if ($nextid) { + echo ''; + echo ''; + } + echo '
'; + echo '
'; + + $customfeedback = $this->custom_feedbackform($submission, true); + if (!empty($customfeedback)) { + echo $customfeedback; + } + + echo '
'; + print_user_picture($user, $this->course->id, $user->picture); + echo ''; + echo '
'; + echo '
'.fullname($user, true).'
'; + if ($submission->timemodified) { + echo '
'.userdate($submission->timemodified). + $this->display_lateness($submission->timemodified).'
'; + } + echo '
'; + $this->print_user_files($user->id); + echo '
'; + + if (!$disabled and $this->usehtmleditor) { + use_html_editor(); + } + + print_footer('none'); + } + + /** + * Preprocess submission before grading + * + * Called by display_submission() + * The default type does nothing here. + * @param $submission object The submission object + */ + function preprocess_submission(&$submission) { + } + + /** + * Display all the submissions ready for grading + */ + function display_submissions($message='') { + global $CFG, $db, $USER; + require_once($CFG->libdir.'/gradelib.php'); + + /* first we check to see if the form has just been submitted + * to request user_preference updates + */ + + if (isset($_POST['updatepref'])){ + $perpage = optional_param('perpage', 10, PARAM_INT); + $perpage = ($perpage <= 0) ? 10 : $perpage ; + set_user_preference('assignment_perpage', $perpage); + set_user_preference('assignment_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL)); + } + + /* next we get perpage and quickgrade (allow quick grade) params + * from database + */ + $perpage = get_user_preferences('assignment_perpage', 10); + + $quickgrade = get_user_preferences('assignment_quickgrade', 0); + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id); + + if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) { + $uses_outcomes = true; + } else { + $uses_outcomes = false; + } + + $page = optional_param('page', 0, PARAM_INT); + $strsaveallfeedback = get_string('saveallfeedback', 'assignment'); + + /// Some shortcuts to make the code read better + + $course = $this->course; + $assignment = $this->assignment; + $cm = $this->cm; + + $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet + add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id, $this->assignment->id, $this->cm->id); + $navigation = build_navigation($this->strsubmissions, $this->cm); + print_header_simple(format_string($this->assignment->name,true), "", $navigation, + '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm)); + + $course_context = get_context_instance(CONTEXT_COURSE, $course->id); + if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { + echo '
' + . get_string('seeallcoursegrades', 'grades') . '
'; + } + + if (!empty($message)) { + echo $message; // display messages here if any + } + + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + /// Check to see if groups are being used in this assignment + + /// find out current groups mode + $groupmode = groups_get_activity_groupmode($cm); + $currentgroup = groups_get_activity_group($cm, true); + groups_print_activity_menu($cm, 'submissions.php?id=' . $this->cm->id); + + /// Get all ppl that are allowed to submit assignments + if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) { + $users = array_keys($users); + } + + // if groupmembersonly used, remove users who are not in any group + if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { + if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { + $users = array_intersect($users, array_keys($groupingusers)); + } + } + + $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade'); + if ($uses_outcomes) { + $tablecolumns[] = 'outcome'; // no sorting based on outcomes column + } + + $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'), + get_string('finalgrade', 'grades')); + if ($uses_outcomes) { + $tableheaders[] = get_string('outcome', 'grades'); + } + + require_once($CFG->libdir.'/tablelib.php'); + $table = new flexible_table('mod-assignment-submissions'); + + $table->define_columns($tablecolumns); + $table->define_headers($tableheaders); + $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id.'&currentgroup='.$currentgroup); + + $table->sortable(true, 'lastname');//sorted by lastname by default + $table->collapsible(true); + $table->initialbars(true); + + $table->column_suppress('picture'); + $table->column_suppress('fullname'); + + $table->column_class('picture', 'picture'); + $table->column_class('fullname', 'fullname'); + $table->column_class('grade', 'grade'); + $table->column_class('submissioncomment', 'comment'); + $table->column_class('timemodified', 'timemodified'); + $table->column_class('timemarked', 'timemarked'); + $table->column_class('status', 'status'); + $table->column_class('finalgrade', 'finalgrade'); + if ($uses_outcomes) { + $table->column_class('outcome', 'outcome'); + } + + $table->set_attribute('cellspacing', '0'); + $table->set_attribute('id', 'attempts'); + $table->set_attribute('class', 'submissions'); + $table->set_attribute('width', '100%'); + //$table->set_attribute('align', 'center'); + + $table->no_sorting('finalgrade'); + $table->no_sorting('outcome'); + + // Start working -- this is necessary as soon as the niceties are over + $table->setup(); + + if (empty($users)) { + print_heading(get_string('nosubmitusers','assignment')); + return true; + } + + /// Construct the SQL + + if ($where = $table->get_sql_where()) { + $where .= ' AND '; + } + + if ($sort = $table->get_sql_sort()) { + $sort = ' ORDER BY '.$sort; + } + + $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt, + s.id AS submissionid, s.grade, s.submissioncomment, + s.timemodified, s.timemarked, + COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status '; + $sql = 'FROM '.$CFG->prefix.'user u '. + 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid + AND s.assignment = '.$this->assignment->id.' '. + 'WHERE '.$where.'u.id IN ('.implode(',',$users).') '; + + $table->pagesize($perpage, count($users)); + + ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next + $offset = $page * $perpage; + + $strupdate = get_string('update'); + $strgrade = get_string('grade'); + $grademenu = make_grades_menu($this->assignment->grade); + + if (($ausers = get_records_sql($select.$sql.$sort, $table->get_page_start(), $table->get_page_size())) !== false) { + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers)); + foreach ($ausers as $auser) { + $final_grade = $grading_info->items[0]->grades[$auser->id]; + $grademax = $grading_info->items[0]->grademax; + $final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2); + $locked_overridden = 'locked'; + if ($final_grade->overridden) { + $locked_overridden = 'overridden'; + } + + /// Calculate user status + $auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified); + $picture = print_user_picture($auser, $course->id, $auser->picture, false, true); + + if (empty($auser->submissionid)) { + $auser->grade = -1; //no submission yet + } + + if (!empty($auser->submissionid)) { + ///Prints student answer and student modified date + ///attach file or print link to student answer, depending on the type of the assignment. + ///Refer to print_student_answer in inherited classes. + if ($auser->timemodified > 0) { + $studentmodified = '
'.$this->print_student_answer($auser->id) + . userdate($auser->timemodified).'
'; + } else { + $studentmodified = '
 
'; + } + ///Print grade, dropdown or text + if ($auser->timemarked > 0) { + $teachermodified = '
'.userdate($auser->timemarked).'
'; + + if ($final_grade->locked or $final_grade->overridden) { + $grade = '
'.$final_grade->formatted_grade.'
'; + } else if ($quickgrade) { + $menu = choose_from_menu(make_grades_menu($this->assignment->grade), + 'menu['.$auser->id.']', $auser->grade, + get_string('nograde'),'',-1,true,false,$tabindex++); + $grade = '
'. $menu .'
'; + } else { + $grade = '
'.$this->display_grade($auser->grade).'
'; + } + + } else { + $teachermodified = '
 
'; + if ($final_grade->locked or $final_grade->overridden) { + $grade = '
'.$final_grade->formatted_grade.'
'; + } else if ($quickgrade) { + $menu = choose_from_menu(make_grades_menu($this->assignment->grade), + 'menu['.$auser->id.']', $auser->grade, + get_string('nograde'),'',-1,true,false,$tabindex++); + $grade = '
'.$menu.'
'; + } else { + $grade = '
'.$this->display_grade($auser->grade).'
'; + } + } + ///Print Comment + if ($final_grade->locked or $final_grade->overridden) { + $comment = '
'.shorten_text(strip_tags($final_grade->str_feedback),15).'
'; + + } else if ($quickgrade) { + $comment = '
' + . '
'; + } else { + $comment = '
'.shorten_text(strip_tags($auser->submissioncomment),15).'
'; + } + } else { + $studentmodified = '
 
'; + $teachermodified = '
 
'; + $status = '
 
'; + + if ($final_grade->locked or $final_grade->overridden) { + $grade = '
'.$final_grade->formatted_grade . '
'; + } else if ($quickgrade) { // allow editing + $menu = choose_from_menu(make_grades_menu($this->assignment->grade), + 'menu['.$auser->id.']', $auser->grade, + get_string('nograde'),'',-1,true,false,$tabindex++); + $grade = '
'.$menu.'
'; + } else { + $grade = '
-
'; + } + + if ($final_grade->locked or $final_grade->overridden) { + $comment = '
'.$final_grade->str_feedback.'
'; + } else if ($quickgrade) { + $comment = '
' + . '
'; + } else { + $comment = '
 
'; + } + } + + if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1 + $auser->status = 0; + } else { + $auser->status = 1; + } + + $buttontext = ($auser->status == 1) ? $strupdate : $strgrade; + + ///No more buttons, we use popups ;-). + $popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id + . '&userid='.$auser->id.'&mode=single'.'&offset='.$offset++; + $button = link_to_popup_window ($popup_url, 'grade'.$auser->id, $buttontext, 600, 780, + $buttontext, 'none', true, 'button'.$auser->id); + + $status = '
'.$button.'
'; + + $finalgrade = ''.$final_grade->str_grade.''; + + $outcomes = ''; + + if ($uses_outcomes) { + + foreach($grading_info->outcomes as $n=>$outcome) { + $outcomes .= '
'; + $options = make_grades_menu(-$outcome->scaleid); + + if ($outcome->grades[$auser->id]->locked or !$quickgrade) { + $options[0] = get_string('nooutcome', 'grades'); + $outcomes .= ': '.$options[$outcome->grades[$auser->id]->grade].''; + } else { + $outcomes .= ' '; + $outcomes .= choose_from_menu($options, 'outcome_'.$n.'['.$auser->id.']', + $outcome->grades[$auser->id]->grade, get_string('nooutcome', 'grades'), '', 0, true, false, 0, 'outcome_'.$n.'_'.$auser->id); + } + $outcomes .= '
'; + } + } + + $userlink = '' . fullname($auser) . ''; + $row = array($picture, $userlink, $grade, $comment, $studentmodified, $teachermodified, $status, $finalgrade); + if ($uses_outcomes) { + $row[] = $outcomes; + } + + $table->add_data($row); + } + } + + /// Print quickgrade form around the table + if ($quickgrade){ + echo '
'; + echo '
'; + echo ''; + echo ''; + echo ''; + echo '
'; + } + + $table->print_html(); /// Print the whole table + + if ($quickgrade){ + $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : ''; + echo '
'; + echo '
'; + echo ''; + echo ''; + echo ''; + helpbutton('emailnotification', get_string('enableemailnotification', 'assignment'), 'assignment').'

'; + echo '
'; + echo '
'; + echo ''; + echo '
'; + } + /// End of fast grading form + + /// Mini form for setting user preference + echo '
'; + echo '
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '
'; + echo ''; + echo ''; + echo ''; + helpbutton('pagesize', get_string('pagesize','assignment'), 'assignment'); + echo '
'; + echo ''; + echo ''; + $checked = $quickgrade ? 'checked="checked"' : ''; + echo ''; + helpbutton('quickgrade', get_string('quickgrade', 'assignment'), 'assignment').'

'; + echo '
'; + echo ''; + echo '
'; + echo '
'; + ///End of mini form + print_footer($this->course); + } + + /** + * Process teacher feedback submission + * + * This is called by submissions() when a grading even has taken place. + * It gets its data from the submitted form. + * @return object The updated submission object + */ + function process_feedback() { + global $CFG, $USER; + require_once($CFG->libdir.'/gradelib.php'); + + if (!$feedback = data_submitted()) { // No incoming data? + return false; + } + + ///For save and next, we need to know the userid to save, and the userid to go + ///We use a new hidden field in the form, and set it to -1. If it's set, we use this + ///as the userid to store + if ((int)$feedback->saveuserid !== -1){ + $feedback->userid = $feedback->saveuserid; + } + + if (!empty($feedback->cancel)) { // User hit cancel button + return false; + } + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $feedback->userid); + + // store outcomes if needed + $this->process_outcomes($feedback->userid); + + $submission = $this->get_submission($feedback->userid, true); // Get or make one + + if (!$grading_info->items[0]->grades[$feedback->userid]->locked and + !$grading_info->items[0]->grades[$feedback->userid]->overridden) { + + $submission->grade = $feedback->grade; + $submission->submissioncomment = $feedback->submissioncomment; + $submission->format = $feedback->format; + $submission->teacher = $USER->id; + $mailinfo = get_user_preferences('assignment_mailinfo', 0); + if (!$mailinfo) { + $submission->mailed = 1; // treat as already mailed + } else { + $submission->mailed = 0; // Make sure mail goes out (again, even) + } + $submission->timemarked = time(); + + unset($submission->data1); // Don't need to update this. + unset($submission->data2); // Don't need to update this. + + if (empty($submission->timemodified)) { // eg for offline assignments + // $submission->timemodified = time(); + } + + if (! update_record('assignment_submissions', $submission)) { + return false; + } + + // triger grade event + $this->update_grade($submission); + + add_to_log($this->course->id, 'assignment', 'update grades', + 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id); + } + + return $submission; + + } + + function process_outcomes($userid) { + global $CFG, $USER; + + if (empty($CFG->enableoutcomes)) { + return; + } + + require_once($CFG->libdir.'/gradelib.php'); + + if (!$formdata = data_submitted()) { + return; + } + + $data = array(); + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $userid); + + if (!empty($grading_info->outcomes)) { + foreach($grading_info->outcomes as $n=>$old) { + $name = 'outcome_'.$n; + if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) { + $data[$n] = $formdata->{$name}[$userid]; + } + } + } + if (count($data) > 0) { + grade_update_outcomes('mod/assignment', $this->course->id, 'mod', 'assignment', $this->assignment->id, $userid, $data); + } + + } + + /** + * Load the submission object for a particular user + * + * @param $userid int The id of the user whose submission we want or 0 in which case USER->id is used + * @param $createnew boolean optional Defaults to false. If set to true a new submission object will be created in the database + * @param bool $teachermodified student submission set if false + * @return object The submission + */ + function get_submission($userid=0, $createnew=false, $teachermodified=false) { + global $USER; + + if (empty($userid)) { + $userid = $USER->id; + } + + $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); + + if ($submission || !$createnew) { + return $submission; + } + $newsubmission = $this->prepare_new_submission($userid, $teachermodified); + if (!insert_record("assignment_submissions", $newsubmission)) { + error("Could not insert a new empty submission"); + } + + return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); + } + + /** + * Instantiates a new submission object for a given user + * + * Sets the assignment, userid and times, everything else is set to default values. + * @param $userid int The userid for which we want a submission object + * @param bool $teachermodified student submission set if false + * @return object The submission + */ + function prepare_new_submission($userid, $teachermodified=false) { + $submission = new Object; + $submission->assignment = $this->assignment->id; + $submission->userid = $userid; + //$submission->timecreated = time(); + $submission->timecreated = ''; + // teachers should not be modifying modified date, except offline assignments + if ($teachermodified) { + $submission->timemodified = 0; + } else { + $submission->timemodified = $submission->timecreated; + } + $submission->numfiles = 0; + $submission->data1 = ''; + $submission->data2 = ''; + $submission->grade = -1; + $submission->submissioncomment = ''; + $submission->format = 0; + $submission->teacher = 0; + $submission->timemarked = 0; + $submission->mailed = 0; + return $submission; + } + + /** + * Return all assignment submissions by ENROLLED students (even empty) + * + * @param $sort string optional field names for the ORDER BY in the sql query + * @param $dir string optional specifying the sort direction, defaults to DESC + * @return array The submission objects indexed by id + */ + function get_submissions($sort='', $dir='DESC') { + return assignment_get_all_submissions($this->assignment, $sort, $dir); + } + + /** + * Counts all real assignment submissions by ENROLLED students (not empty ones) + * + * @param $groupid int optional If nonzero then count is restricted to this group + * @return int The number of submissions + */ + function count_real_submissions($groupid=0) { + return assignment_count_real_submissions($this->cm, $groupid); + } + + /** + * Alerts teachers by email of new or changed assignments that need grading + * + * First checks whether the option to email teachers is set for this assignment. + * Sends an email to ALL teachers in the course (or in the group if using separate groups). + * Uses the methods email_teachers_text() and email_teachers_html() to construct the content. + * @param $submission object The submission that has changed + */ + function email_teachers($submission) { + global $CFG; + + if (empty($this->assignment->emailteachers)) { // No need to do anything + return; + } + + $user = get_record('user', 'id', $submission->userid); + + if ($teachers = $this->get_graders($user)) { + + $strassignments = get_string('modulenameplural', 'assignment'); + $strassignment = get_string('modulename', 'assignment'); + $strsubmitted = get_string('submitted', 'assignment'); + + foreach ($teachers as $teacher) { + $info = new object(); + $info->username = fullname($user, true); + $info->assignment = format_string($this->assignment->name,true); + $info->url = $CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id; + + $postsubject = $strsubmitted.': '.$info->username.' -> '.$this->assignment->name; + $posttext = $this->email_teachers_text($info); + $posthtml = ($teacher->mailformat == 1) ? $this->email_teachers_html($info) : ''; + + @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad. + } + } + } + + /** + * Returns a list of teachers that should be grading given submission + */ + function get_graders($user) { + //potential graders + $potgraders = get_users_by_capability($this->context, 'mod/assignment:grade', '', '', '', '', '', '', false, false); + + $graders = array(); + if (groups_get_activity_groupmode($this->cm) == SEPARATEGROUPS) { // Separate groups are being used + if ($groups = groups_get_all_groups($this->course->id, $user->id)) { // Try to find all groups + foreach ($groups as $group) { + foreach ($potgraders as $t) { + if ($t->id == $user->id) { + continue; // do not send self + } + if (groups_is_member($group->id, $t->id)) { + $graders[$t->id] = $t; + } + } + } + } else { + // user not in group, try to find graders without group + foreach ($potgraders as $t) { + if ($t->id == $user->id) { + continue; // do not send self + } + if (!groups_get_all_groups($this->course->id, $t->id)) { //ugly hack + $graders[$t->id] = $t; + } + } + } + } else { + foreach ($potgraders as $t) { + if ($t->id == $user->id) { + continue; // do not send self + } + $graders[$t->id] = $t; + } + } + return $graders; + } + + /** + * Creates the text content for emails to teachers + * + * @param $info object The info used by the 'emailteachermail' language string + * @return string + */ + function email_teachers_text($info) { + $posttext = format_string($this->course->shortname).' -> '.$this->strassignments.' -> '. + format_string($this->assignment->name)."\n"; + $posttext .= '---------------------------------------------------------------------'."\n"; + $posttext .= get_string("emailteachermail", "assignment", $info)."\n"; + $posttext .= "\n---------------------------------------------------------------------\n"; + return $posttext; + } + + /** + * Creates the html content for emails to teachers + * + * @param $info object The info used by the 'emailteachermailhtml' language string + * @return string + */ + function email_teachers_html($info) { + global $CFG; + $posthtml = '

'. + ''.format_string($this->course->shortname).' ->'. + ''.$this->strassignments.' ->'. + ''.format_string($this->assignment->name).'

'; + $posthtml .= '
'; + $posthtml .= '

'.get_string('emailteachermailhtml', 'assignment', $info).'

'; + $posthtml .= '

'; + return $posthtml; + } + + /** + * Produces a list of links to the files uploaded by a user + * + * @param $userid int optional id of the user. If 0 then $USER->id is used. + * @param $return boolean optional defaults to false. If true the list is returned rather than printed + * @return string optional + */ + function print_user_files($userid=0, $return=false) { + global $CFG, $USER; + + if (!$userid) { + if (!isloggedin()) { + return ''; + } + $userid = $USER->id; + } + + $filearea = $this->file_area_name($userid); + + $output = ''; + + if ($basedir = $this->file_area($userid)) { + if ($files = get_directory_list($basedir)) { + require_once($CFG->libdir.'/filelib.php'); + foreach ($files as $key => $file) { + + $icon = mimeinfo('icon', $file); + $ffurl = get_file_url("$filearea/$file", array('forcedownload'=>1)); + + $output .= ''.$icon.''. + ''.$file.'
'; + } + } + } + + $output = '
'.$output.'
'; + + if ($return) { + return $output; + } + echo $output; + } + + /** + * Count the files uploaded by a given user + * + * @param $userid int The user id + * @return int + */ + function count_user_files($userid) { + global $CFG; + + $filearea = $this->file_area_name($userid); + + if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { + if ($files = get_directory_list($basedir)) { + return count($files); + } + } + return 0; + } + + /** + * Creates a directory file name, suitable for make_upload_directory() + * + * @param $userid int The user id + * @return string path to file area + */ + function file_area_name($userid) { + global $CFG; + + return $this->course->id.'/'.$CFG->moddata.'/assignment/'.$this->assignment->id.'/'.$userid; + } + + /** + * Makes an upload directory + * + * @param $userid int The user id + * @return string path to file area. + */ + function file_area($userid) { + return make_upload_directory( $this->file_area_name($userid) ); + } + + /** + * Returns true if the student is allowed to submit + * + * Checks that the assignment has started and, if the option to prevent late + * submissions is set, also checks that the assignment has not yet closed. + * @return boolean + */ + function isopen() { + $time = time(); + if ($this->assignment->preventlate && $this->assignment->timedue) { + return ($this->assignment->timeavailable <= $time && $time <= $this->assignment->timedue); + } else { + return ($this->assignment->timeavailable <= $time); + } + } + + + /** + * Return true if is set description is hidden till available date + * + * This is needed by calendar so that hidden descriptions do not + * come up in upcoming events. + * + * Check that description is hidden till available date + * By default return false + * Assignments types should implement this method if needed + * @return boolen + */ + function description_is_hidden() { + return false; + } + + /** + * Return an outline of the user's interaction with the assignment + * + * The default method prints the grade and timemodified + * @param $user object + * @return object with properties ->info and ->time + */ + function user_outline($user) { + if ($submission = $this->get_submission($user->id)) { + + $result = new object(); + $result->info = get_string('grade').': '.$this->display_grade($submission->grade); + $result->time = $submission->timemodified; + return $result; + } + return NULL; + } + + /** + * Print complete information about the user's interaction with the assignment + * + * @param $user object + */ + function user_complete($user) { + if ($submission = $this->get_submission($user->id)) { + if ($basedir = $this->file_area($user->id)) { + if ($files = get_directory_list($basedir)) { + $countfiles = count($files)." ".get_string("uploadedfiles", "assignment"); + foreach ($files as $file) { + $countfiles .= "; $file"; + } + } + } + + print_simple_box_start(); + echo get_string("lastmodified").": "; + echo userdate($submission->timemodified); + echo $this->display_lateness($submission->timemodified); + + $this->print_user_files($user->id); + + echo '
'; + + if (empty($submission->timemarked)) { + print_string("notgradedyet", "assignment"); + } else { + $this->view_feedback($submission); + } + + print_simple_box_end(); + + } else { + print_string("notsubmittedyet", "assignment"); + } + } + + /** + * Return a string indicating how late a submission is + * + * @param $timesubmitted int + * @return string + */ + function display_lateness($timesubmitted) { + return assignment_display_lateness($timesubmitted, $this->assignment->timedue); + } + + /** + * Empty method stub for all delete actions. + */ + function delete() { + //nothing by default + redirect('view.php?id='.$this->cm->id); + } + + /** + * Empty custom feedback grading form. + */ + function custom_feedbackform($submission, $return=false) { + //nothing by default + return ''; + } + + /** + * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information + * for the course (see resource). + * + * Given a course_module object, this function returns any "extra" information that may be needed + * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. + * + * @param $coursemodule object The coursemodule object (record). + * @return object An object on information that the coures will know about (most noticeably, an icon). + * + */ + function get_coursemodule_info($coursemodule) { + return false; + } + + /** + * Plugin cron method - do not use $this here, create new assignment instances if needed. + * @return void + */ + function cron() { + //no plugin cron by default - override if needed + } + + /** + * Reset all submissions + */ + function reset_userdata($data) { + global $CFG; + require_once($CFG->libdir.'/filelib.php'); + + if (!count_records('assignment', 'course', $data->courseid, 'assignmenttype', $this->type)) { + return array(); // no assignments of this type present + } + + $componentstr = get_string('modulenameplural', 'assignment'); + $status = array(); + + $typestr = get_string('type'.$this->type, 'assignment'); + + if (!empty($data->reset_assignment_submissions)) { + $assignmentssql = "SELECT a.id + FROM {$CFG->prefix}assignment a + WHERE a.course={$data->courseid} AND a.assignmenttype='{$this->type}'"; + + delete_records_select('assignment_submissions', "assignment IN ($assignmentssql)"); + + if ($assignments = get_records_sql($assignmentssql)) { + foreach ($assignments as $assignmentid=>$unused) { + fulldelete($CFG->dataroot.'/'.$data->courseid.'/moddata/assignment/'.$assignmentid); + } + } + + $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallsubmissions','assignment').': '.$typestr, 'error'=>false); + + if (empty($data->reset_gradebook_grades)) { + // remove all grades from gradebook + assignment_reset_gradebook($data->courseid, $this->type); + } + } + + /// updating dates - shift may be negative too + if ($data->timeshift) { + shift_course_mod_dates('assignment', array('timedue', 'timeavailable'), $data->timeshift, $data->courseid); + $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged').': '.$typestr, 'error'=>false); + } + + return $status; + } +} ////// End of the assignment_base class + + + +/// OTHER STANDARD FUNCTIONS //////////////////////////////////////////////////////// + +/** + * Deletes an assignment instance + * + * This is done by calling the delete_instance() method of the assignment type class + */ +function assignment_delete_instance($id){ + global $CFG; + + if (! $assignment = get_record('assignment', 'id', $id)) { + return false; + } + + // fall back to base class if plugin missing + $classfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"; + if (file_exists($classfile)) { + require_once($classfile); + $assignmentclass = "assignment_$assignment->assignmenttype"; + + } else { + debugging("Missing assignment plug-in: {$assignment->assignmenttype}. Using base class for deleting instead."); + $assignmentclass = "assignment_base"; + } + + $ass = new $assignmentclass(); + return $ass->delete_instance($assignment); +} + + +/** + * Updates an assignment instance + * + * This is done by calling the update_instance() method of the assignment type class + */ +function assignment_update_instance($assignment){ + global $CFG; + + $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR); + + require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $ass = new $assignmentclass(); + return $ass->update_instance($assignment); +} + + +/** + * Adds an assignment instance + * + * This is done by calling the add_instance() method of the assignment type class + */ +function assignment_add_instance($assignment) { + global $CFG; + + $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR); + + require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $ass = new $assignmentclass(); + return $ass->add_instance($assignment); +} + + +/** + * Returns an outline of a user interaction with an assignment + * + * This is done by calling the user_outline() method of the assignment type class + */ +function assignment_user_outline($course, $user, $mod, $assignment) { + global $CFG; + + require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $ass = new $assignmentclass($mod->id, $assignment, $mod, $course); + return $ass->user_outline($user); +} + +/** + * Prints the complete info about a user's interaction with an assignment + * + * This is done by calling the user_complete() method of the assignment type class + */ +function assignment_user_complete($course, $user, $mod, $assignment) { + global $CFG; + + require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $ass = new $assignmentclass($mod->id, $assignment, $mod, $course); + return $ass->user_complete($user); +} + +/** + * Function to be run periodically according to the moodle cron + * + * Finds all assignment notifications that have yet to be mailed out, and mails them + */ +function assignment_cron () { + + global $CFG, $USER; + + /// first execute all crons in plugins + if ($plugins = get_list_of_plugins('mod/assignment/type')) { + foreach ($plugins as $plugin) { + require_once("$CFG->dirroot/mod/assignment/type/$plugin/assignment.class.php"); + $assignmentclass = "assignment_$plugin"; + $ass = new $assignmentclass(); + $ass->cron(); + } + } + + /// Notices older than 1 day will not be mailed. This is to avoid the problem where + /// cron has not been running for a long time, and then suddenly people are flooded + /// with mail from the past few weeks or months + + $timenow = time(); + $endtime = $timenow - $CFG->maxeditingtime; + $starttime = $endtime - 24 * 3600; /// One day earlier + + if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) { + + $realuser = clone($USER); + + foreach ($submissions as $key => $submission) { + if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) { + echo "Could not update the mailed field for id $submission->id. Not mailed.\n"; + unset($submissions[$key]); + } + } + + $timenow = time(); + + foreach ($submissions as $submission) { + + echo "Processing assignment submission $submission->id\n"; + + if (! $user = get_record("user", "id", "$submission->userid")) { + echo "Could not find user $post->userid\n"; + continue; + } + + if (! $course = get_record("course", "id", "$submission->course")) { + echo "Could not find course $submission->course\n"; + continue; + } + + /// Override the language and timezone of the "current" user, so that + /// mail is customised for the receiver. + $USER = $user; + course_setup($course); + + if (!has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $submission->course), $user->id)) { + echo fullname($user)." not an active participant in " . format_string($course->shortname) . "\n"; + continue; + } + + if (! $teacher = get_record("user", "id", "$submission->teacher")) { + echo "Could not find teacher $submission->teacher\n"; + continue; + } + + if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment, $course->id)) { + echo "Could not find course module for assignment id $submission->assignment\n"; + continue; + } + + if (! $mod->visible) { /// Hold mail notification for hidden assignments until later + continue; + } + + $strassignments = get_string("modulenameplural", "assignment"); + $strassignment = get_string("modulename", "assignment"); + + $assignmentinfo = new object(); + $assignmentinfo->teacher = fullname($teacher); + $assignmentinfo->assignment = format_string($submission->name,true); + $assignmentinfo->url = "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id"; + + $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true); + $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n"; + $posttext .= "---------------------------------------------------------------------\n"; + $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo)."\n"; + $posttext .= "---------------------------------------------------------------------\n"; + + if ($user->mailformat == 1) { // HTML + $posthtml = "

". + "wwwroot/course/view.php?id=$course->id\">$course->shortname ->". + "wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments ->". + "wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."

"; + $posthtml .= "
"; + $posthtml .= "

".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."

"; + $posthtml .= "

"; + } else { + $posthtml = ""; + } + + if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) { + echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n"; + } + } + + $USER = $realuser; + course_setup(SITEID); // reset cron user language, theme and timezone settings + + } + + return true; +} + +/** + * Return grade for given user or all users. + * + * @param int $assignmentid id of assignment + * @param int $userid optional user id, 0 means all users + * @return array array of grades, false if none + */ +function assignment_get_user_grades($assignment, $userid=0) { + global $CFG; + + $user = $userid ? "AND u.id = $userid" : ""; + + $sql = "SELECT u.id, u.id AS userid, s.grade AS rawgrade, s.submissioncomment AS feedback, s.format AS feedbackformat, + s.teacher AS usermodified, s.timemarked AS dategraded, s.timemodified AS datesubmitted + FROM {$CFG->prefix}user u, {$CFG->prefix}assignment_submissions s + WHERE u.id = s.userid AND s.assignment = $assignment->id + $user"; + + return get_records_sql($sql); +} + +/** + * Update grades by firing grade_updated event + * + * @param object $assignment null means all assignments + * @param int $userid specific user only, 0 mean all + */ +function assignment_update_grades($assignment=null, $userid=0, $nullifnone=true) { + global $CFG; + if (!function_exists('grade_update')) { //workaround for buggy PHP versions + require_once($CFG->libdir.'/gradelib.php'); + } + + if ($assignment != null) { + if ($grades = assignment_get_user_grades($assignment, $userid)) { + foreach($grades as $k=>$v) { + if ($v->rawgrade == -1) { + $grades[$k]->rawgrade = null; + } + } + assignment_grade_item_update($assignment, $grades); + } else { + assignment_grade_item_update($assignment); + } + + } else { + $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid + FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m + WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id"; + if ($rs = get_recordset_sql($sql)) { + while ($assignment = rs_fetch_next_record($rs)) { + if ($assignment->grade != 0) { + assignment_update_grades($assignment); + } else { + assignment_grade_item_update($assignment); + } + } + rs_close($rs); + } + } +} + +/** + * Create grade item for given assignment + * + * @param object $assignment object with extra cmidnumber + * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook + * @return int 0 if ok, error code otherwise + */ +function assignment_grade_item_update($assignment, $grades=NULL) { + global $CFG; + if (!function_exists('grade_update')) { //workaround for buggy PHP versions + require_once($CFG->libdir.'/gradelib.php'); + } + + if (!isset($assignment->courseid)) { + $assignment->courseid = $assignment->course; + } + + $params = array('itemname'=>$assignment->name, 'idnumber'=>$assignment->cmidnumber); + + if ($assignment->grade > 0) { + $params['gradetype'] = GRADE_TYPE_VALUE; + $params['grademax'] = $assignment->grade; + $params['grademin'] = 0; + + } else if ($assignment->grade < 0) { + $params['gradetype'] = GRADE_TYPE_SCALE; + $params['scaleid'] = -$assignment->grade; + + } else { + $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only + } + + if ($grades === 'reset') { + $params['reset'] = true; + $grades = NULL; + } + + return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, $grades, $params); +} + +/** + * Delete grade item for given assignment + * + * @param object $assignment object + * @return object assignment + */ +function assignment_grade_item_delete($assignment) { + global $CFG; + require_once($CFG->libdir.'/gradelib.php'); + + if (!isset($assignment->courseid)) { + $assignment->courseid = $assignment->course; + } + + return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, NULL, array('deleted'=>1)); +} + +/** + * Returns the users with data in one assignment (students and teachers) + * + * @param $assignmentid int + * @return array of user objects + */ +function assignment_get_participants($assignmentid) { + + global $CFG; + + //Get students + $students = get_records_sql("SELECT DISTINCT u.id, u.id + FROM {$CFG->prefix}user u, + {$CFG->prefix}assignment_submissions a + WHERE a.assignment = '$assignmentid' and + u.id = a.userid"); + //Get teachers + $teachers = get_records_sql("SELECT DISTINCT u.id, u.id + FROM {$CFG->prefix}user u, + {$CFG->prefix}assignment_submissions a + WHERE a.assignment = '$assignmentid' and + u.id = a.teacher"); + + //Add teachers to students + if ($teachers) { + foreach ($teachers as $teacher) { + $students[$teacher->id] = $teacher; + } + } + //Return students array (it contains an array of unique users) + return ($students); +} + +/** + * Checks if a scale is being used by an assignment + * + * This is used by the backup code to decide whether to back up a scale + * @param $assignmentid int + * @param $scaleid int + * @return boolean True if the scale is used by the assignment + */ +function assignment_scale_used($assignmentid, $scaleid) { + + $return = false; + + $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid); + + if (!empty($rec) && !empty($scaleid)) { + $return = true; + } + + return $return; +} + +/** + * Checks if scale is being used by any instance of assignment + * + * This is used to find out if scale used anywhere + * @param $scaleid int + * @return boolean True if the scale is used by any assignment + */ +function assignment_scale_used_anywhere($scaleid) { + if ($scaleid and record_exists('assignment', 'grade', -$scaleid)) { + return true; + } else { + return false; + } +} + +/** + * Make sure up-to-date events are created for all assignment instances + * + * This standard function will check all instances of this module + * and make sure there are up-to-date events created for each of them. + * If courseid = 0, then every assignment event in the site is checked, else + * only assignment events belonging to the course specified are checked. + * This function is used, in its new format, by restore_refresh_events() + * + * @param $courseid int optional If zero then all assignments for all courses are covered + * @return boolean Always returns true + */ +function assignment_refresh_events($courseid = 0) { + + if ($courseid == 0) { + if (! $assignments = get_records("assignment")) { + return true; + } + } else { + if (! $assignments = get_records("assignment", "course", $courseid)) { + return true; + } + } + $moduleid = get_field('modules', 'id', 'name', 'assignment'); + + foreach ($assignments as $assignment) { + $event = NULL; + $event->name = addslashes($assignment->name); + $event->description = addslashes($assignment->description); + $event->timestart = $assignment->timedue; + + if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) { + update_event($event); + + } else { + $event->courseid = $assignment->course; + $event->groupid = 0; + $event->userid = 0; + $event->modulename = 'assignment'; + $event->instance = $assignment->id; + $event->eventtype = 'due'; + $event->timeduration = 0; + $event->visible = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id); + add_event($event); + } + + } + return true; +} + +/** + * Print recent activity from all assignments in a given course + * + * This is used by the recent activity block + */ +function assignment_print_recent_activity($course, $viewfullnames, $timestart) { + global $CFG, $USER; + + // do not use log table if possible, it may be huge + + if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, asb.userid, + u.firstname, u.lastname, u.email, u.picture + FROM {$CFG->prefix}assignment_submissions asb + JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment + JOIN {$CFG->prefix}course_modules cm ON cm.instance = a.id + JOIN {$CFG->prefix}modules md ON md.id = cm.module + JOIN {$CFG->prefix}user u ON u.id = asb.userid + WHERE asb.timemodified > $timestart AND + a.course = {$course->id} AND + md.name = 'assignment' + ORDER BY asb.timemodified ASC")) { + return false; + } + + $modinfo =& get_fast_modinfo($course); // reference needed because we might load the groups + $show = array(); + $grader = array(); + + foreach($submissions as $submission) { + if (!array_key_exists($submission->cmid, $modinfo->cms)) { + continue; + } + $cm = $modinfo->cms[$submission->cmid]; + if (!$cm->uservisible) { + continue; + } + if ($submission->userid == $USER->id) { + $show[] = $submission; + continue; + } + + // the act of sumbitting of assignment may be considered private - only graders will see it if specified + if (empty($CFG->assignment_showrecentsubmissions)) { + if (!array_key_exists($cm->id, $grader)) { + $grader[$cm->id] = has_capability('moodle/grade:viewall', get_context_instance(CONTEXT_MODULE, $cm->id)); + } + if (!$grader[$cm->id]) { + continue; + } + } + + $groupmode = groups_get_activity_groupmode($cm, $course); + + if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) { + if (isguestuser()) { + // shortcut - guest user does not belong into any group + continue; + } + + if (is_null($modinfo->groups)) { + $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo + } + + // this will be slow - show only users that share group with me in this cm + if (empty($modinfo->groups[$cm->id])) { + continue; + } + $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid); + if (is_array($usersgroups)) { + $usersgroups = array_keys($usersgroups); + $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]); + if (empty($intersect)) { + continue; + } + } + } + $show[] = $submission; + } + + if (empty($show)) { + return false; + } + + print_headline(get_string('newsubmissions', 'assignment').':'); + + foreach ($show as $submission) { + $cm = $modinfo->cms[$submission->cmid]; + $link = $CFG->wwwroot.'/mod/assignment/view.php?id='.$cm->id; + print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames); + } + + return true; +} + + +/** + * Returns all assignments since a given time in specified forum. + */ +function assignment_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) { + + global $CFG, $COURSE, $USER; + + if ($COURSE->id == $courseid) { + $course = $COURSE; + } else { + $course = get_record('course', 'id', $courseid); + } + + $modinfo =& get_fast_modinfo($course); + + $cm = $modinfo->cms[$cmid]; + + if ($userid) { + $userselect = "AND u.id = $userid"; + } else { + $userselect = ""; + } + + if ($groupid) { + $groupselect = "AND gm.groupid = $groupid"; + $groupjoin = "JOIN {$CFG->prefix}groups_members gm ON gm.userid=u.id"; + } else { + $groupselect = ""; + $groupjoin = ""; + } + + if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, asb.userid, + u.firstname, u.lastname, u.email, u.picture + FROM {$CFG->prefix}assignment_submissions asb + JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment + JOIN {$CFG->prefix}user u ON u.id = asb.userid + $groupjoin + WHERE asb.timemodified > $timestart AND a.id = $cm->instance + $userselect $groupselect + ORDER BY asb.timemodified ASC")) { + return; + } + + $groupmode = groups_get_activity_groupmode($cm, $course); + $cm_context = get_context_instance(CONTEXT_MODULE, $cm->id); + $grader = has_capability('moodle/grade:viewall', $cm_context); + $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context); + $viewfullnames = has_capability('moodle/site:viewfullnames', $cm_context); + + if (is_null($modinfo->groups)) { + $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo + } + + $show = array(); + + foreach($submissions as $submission) { + if ($submission->userid == $USER->id) { + $show[] = $submission; + continue; + } + // the act of submitting of assignment may be considered private - only graders will see it if specified + if (empty($CFG->assignment_showrecentsubmissions)) { + if (!$grader) { + continue; + } + } + + if ($groupmode == SEPARATEGROUPS and !$accessallgroups) { + if (isguestuser()) { + // shortcut - guest user does not belong into any group + continue; + } + + // this will be slow - show only users that share group with me in this cm + if (empty($modinfo->groups[$cm->id])) { + continue; + } + $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid); + if (is_array($usersgroups)) { + $usersgroups = array_keys($usersgroups); + $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]); + if (empty($intersect)) { + continue; + } + } + } + $show[] = $submission; + } + + if (empty($show)) { + return; + } + + if ($grader) { + require_once($CFG->libdir.'/gradelib.php'); + $userids = array(); + foreach ($show as $id=>$submission) { + $userids[] = $submission->userid; + + } + $grades = grade_get_grades($courseid, 'mod', 'assignment', $cm->instance, $userids); + } + + $aname = format_string($cm->name,true); + foreach ($show as $submission) { + $tmpactivity = new object(); + + $tmpactivity->type = 'assignment'; + $tmpactivity->cmid = $cm->id; + $tmpactivity->name = $aname; + $tmpactivity->sectionnum = $cm->sectionnum; + $tmpactivity->timestamp = $submission->timemodified; + + if ($grader) { + $tmpactivity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade; + } + + $tmpactivity->user->userid = $submission->userid; + $tmpactivity->user->fullname = fullname($submission, $viewfullnames); + $tmpactivity->user->picture = $submission->picture; + + $activities[$index++] = $tmpactivity; + } + + return; +} + +/** + * Print recent activity from all assignments in a given course + * + * This is used by course/recent.php + */ +function assignment_print_recent_mod_activity($activity, $courseid, $detail, $modnames) { + global $CFG; + + echo ''; + + echo "
"; + print_user_picture($activity->user->userid, $courseid, $activity->user->picture); + echo ""; + + if ($detail) { + $modname = $modnames[$activity->type]; + echo '
'; + echo "modpixpath/assignment/icon.gif\" ". + "class=\"icon\" alt=\"$modname\">"; + echo "wwwroot/mod/assignment/view.php?id={$activity->cmid}\">{$activity->name}"; + echo '
'; + } + + if (isset($activity->grade)) { + echo '
'; + echo get_string('grade').': '; + echo $activity->grade; + echo '
'; + } + + echo ''; + + echo "
"; +} + +/// GENERIC SQL FUNCTIONS + +/** + * Fetch info from logs + * + * @param $log object with properties ->info (the assignment id) and ->userid + * @return array with assignment name and user firstname and lastname + */ +function assignment_log_info($log) { + global $CFG; + return get_record_sql("SELECT a.name, u.firstname, u.lastname + FROM {$CFG->prefix}assignment a, + {$CFG->prefix}user u + WHERE a.id = '$log->info' + AND u.id = '$log->userid'"); +} + +/** + * Return list of marked submissions that have not been mailed out for currently enrolled students + * + * @return array + */ +function assignment_get_unmailed_submissions($starttime, $endtime) { + + global $CFG; + + return get_records_sql("SELECT s.*, a.course, a.name + FROM {$CFG->prefix}assignment_submissions s, + {$CFG->prefix}assignment a + WHERE s.mailed = 0 + AND s.timemarked <= $endtime + AND s.timemarked >= $starttime + AND s.assignment = a.id"); + + /* return get_records_sql("SELECT s.*, a.course, a.name + FROM {$CFG->prefix}assignment_submissions s, + {$CFG->prefix}assignment a, + {$CFG->prefix}user_students us + WHERE s.mailed = 0 + AND s.timemarked <= $endtime + AND s.timemarked >= $starttime + AND s.assignment = a.id + AND s.userid = us.userid + AND a.course = us.course"); + */ +} + +/** + * Counts all real assignment submissions by ENROLLED students (not empty ones) + * + * There are also assignment type methods count_real_submissions() wich in the default + * implementation simply call this function. + * @param $groupid int optional If nonzero then count is restricted to this group + * @return int The number of submissions + */ +function assignment_count_real_submissions($cm, $groupid=0) { + global $CFG; + + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + // this is all the users with this capability set, in this context or higher + if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $groupid, '', false)) { + $users = array_keys($users); + } + + // if groupmembersonly used, remove users who are not in any group + if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) { + if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { + $users = array_intersect($users, array_keys($groupingusers)); + } + } + + if (empty($users)) { + return 0; + } + + $userlists = implode(',', $users); + + return count_records_sql("SELECT COUNT('x') + FROM {$CFG->prefix}assignment_submissions + WHERE assignment = $cm->instance AND + timemodified > 0 AND + userid IN ($userlists)"); +} + + +/** + * Return all assignment submissions by ENROLLED students (even empty) + * + * There are also assignment type methods get_submissions() wich in the default + * implementation simply call this function. + * @param $sort string optional field names for the ORDER BY in the sql query + * @param $dir string optional specifying the sort direction, defaults to DESC + * @return array The submission objects indexed by id + */ +function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") { +/// Return all assignment submissions by ENROLLED students (even empty) + global $CFG; + + if ($sort == "lastname" or $sort == "firstname") { + $sort = "u.$sort $dir"; + } else if (empty($sort)) { + $sort = "a.timemodified DESC"; + } else { + $sort = "a.$sort $dir"; + } + + /* not sure this is needed at all since assignmenet already has a course define, so this join? + $select = "s.course = '$assignment->course' AND"; + if ($assignment->course == SITEID) { + $select = ''; + }*/ + + return get_records_sql("SELECT a.* + FROM {$CFG->prefix}assignment_submissions a, + {$CFG->prefix}user u + WHERE u.id = a.userid + AND a.assignment = '$assignment->id' + ORDER BY $sort"); + + /* return get_records_sql("SELECT a.* + FROM {$CFG->prefix}assignment_submissions a, + {$CFG->prefix}user_students s, + {$CFG->prefix}user u + WHERE a.userid = s.userid + AND u.id = a.userid + AND $select a.assignment = '$assignment->id' + ORDER BY $sort"); + */ +} + +/** + * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information + * for the course (see resource). + * + * Given a course_module object, this function returns any "extra" information that may be needed + * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. + * + * @param $coursemodule object The coursemodule object (record). + * @return object An object on information that the coures will know about (most noticeably, an icon). + * + */ +function assignment_get_coursemodule_info($coursemodule) { + global $CFG; + + if (! $assignment = get_record('assignment', 'id', $coursemodule->instance, '', '', '', '', 'id, assignmenttype, name')) { + return false; + } + + $libfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"; + + if (file_exists($libfile)) { + require_once($libfile); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $ass = new $assignmentclass('staticonly'); + if ($result = $ass->get_coursemodule_info($coursemodule)) { + return $result; + } else { + $info = new object(); + $info->name = $assignment->name; + return $info; + } + + } else { + debugging('Incorrect assignment type: '.$assignment->assignmenttype); + return false; + } +} + + + +/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS /////////////////////////////////////// + +/** + * Returns an array of installed assignment types indexed and sorted by name + * + * @return array The index is the name of the assignment type, the value its full name from the language strings + */ +function assignment_types() { + $types = array(); + $names = get_list_of_plugins('mod/assignment/type'); + foreach ($names as $name) { + $types[$name] = get_string('type'.$name, 'assignment'); + } + asort($types); + return $types; +} + +/** + * Executes upgrade scripts for assignment types when necessary + */ +function assignment_upgrade_submodules() { + + global $CFG; + +/// Install/upgrade assignment types (it uses, simply, the standard plugin architecture) + upgrade_plugins('assignment_type', 'mod/assignment/type', "$CFG->wwwroot/$CFG->admin/index.php"); + +} + +function assignment_print_overview($courses, &$htmlarray) { + + global $USER, $CFG; + + if (empty($courses) || !is_array($courses) || count($courses) == 0) { + return array(); + } + + if (!$assignments = get_all_instances_in_courses('assignment',$courses)) { + return; + } + + $assignmentids = array(); + + // Do assignment_base::isopen() here without loading the whole thing for speed + foreach ($assignments as $key => $assignment) { + $time = time(); + if ($assignment->timedue) { + if ($assignment->preventlate) { + $isopen = ($assignment->timeavailable <= $time && $time <= $assignment->timedue); + } else { + $isopen = ($assignment->timeavailable <= $time); + } + } + if (empty($isopen) || empty($assignment->timedue)) { + unset($assignments[$key]); + }else{ + $assignmentids[] = $assignment->id; + } + } + + if(empty($assignmentids)){ + // no assigments to look at - we're done + return true; + } + + $strduedate = get_string('duedate', 'assignment'); + $strduedateno = get_string('duedateno', 'assignment'); + $strgraded = get_string('graded', 'assignment'); + $strnotgradedyet = get_string('notgradedyet', 'assignment'); + $strnotsubmittedyet = get_string('notsubmittedyet', 'assignment'); + $strsubmitted = get_string('submitted', 'assignment'); + $strassignment = get_string('modulename', 'assignment'); + $strreviewed = get_string('reviewed','assignment'); + + + // NOTE: we do all possible database work here *outside* of the loop to ensure this scales + + // build up and array of unmarked submissions indexed by assigment id/ userid + // for use where the user has grading rights on assigment + $rs = get_recordset_sql("SELECT id, assignment, userid + FROM {$CFG->prefix}assignment_submissions + WHERE teacher = 0 AND timemarked = 0 + AND assignment IN (". implode(',', $assignmentids).")"); + + $unmarkedsubmissions = array(); + while ($ra = rs_fetch_next_record($rs)) { + $unmarkedsubmissions[$ra->assignment][$ra->userid] = $ra->id; + } + rs_close($rs); + + + // get all user submissions, indexed by assigment id + $mysubmissions = get_records_sql("SELECT assignment, timemarked, teacher, grade + FROM {$CFG->prefix}assignment_submissions + WHERE userid = {$USER->id} AND + assignment IN (".implode(',', $assignmentids).")"); + + foreach ($assignments as $assignment) { + $str = '
'.$strassignment. ': '. + 'visible ? '':' class="dimmed"'). + 'title="'.$strassignment.'" href="'.$CFG->wwwroot. + '/mod/assignment/view.php?id='.$assignment->coursemodule.'">'. + $assignment->name.'
'; + if ($assignment->timedue) { + $str .= '
'.$strduedate.': '.userdate($assignment->timedue).'
'; + } else { + $str .= '
'.$strduedateno.'
'; + } + $context = get_context_instance(CONTEXT_MODULE, $assignment->coursemodule); + if (has_capability('mod/assignment:grade', $context)) { + + // count how many people can submit + $submissions = 0; // init + if ($students = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', 0, '', false)) { + foreach($students as $student){ + if(isset($unmarkedsubmissions[$assignment->id][$student->id])){ + $submissions++; + } + } + } + + if ($submissions) { + $str .= get_string('submissionsnotgraded', 'assignment', $submissions); + } + } else { + if(isset($mysubmissions[$assignment->id])){ + + $submission = $mysubmissions[$assignment->id]; + + if ($submission->teacher == 0 && $submission->timemarked == 0) { + $str .= $strsubmitted . ', ' . $strnotgradedyet; + } else if ($submission->grade <= 0) { + $str .= $strsubmitted . ', ' . $strreviewed; + } else { + $str .= $strsubmitted . ', ' . $strgraded; + } + } else { + $str .= $strnotsubmittedyet . ' ' . assignment_display_lateness(time(), $assignment->timedue); + } + } + $str .= '
'; + if (empty($htmlarray[$assignment->course]['assignment'])) { + $htmlarray[$assignment->course]['assignment'] = $str; + } else { + $htmlarray[$assignment->course]['assignment'] .= $str; + } + } +} + +function assignment_display_lateness($timesubmitted, $timedue) { + if (!$timedue) { + return ''; + } + $time = $timedue - $timesubmitted; + if ($time < 0) { + $timetext = get_string('late', 'assignment', format_time($time)); + return ' ('.$timetext.')'; + } else { + $timetext = get_string('early', 'assignment', format_time($time)); + return ' ('.$timetext.')'; + } +} + +function assignment_get_view_actions() { + return array('view'); +} + +function assignment_get_post_actions() { + return array('upload'); +} + +function assignment_get_types() { + global $CFG; + $types = array(); + + $type = new object(); + $type->modclass = MOD_CLASS_ACTIVITY; + $type->type = "assignment_group_start"; + $type->typestr = '--'.get_string('modulenameplural', 'assignment'); + $types[] = $type; + + $standardassignments = array('upload','online','uploadsingle','offline'); + foreach ($standardassignments as $assignmenttype) { + $type = new object(); + $type->modclass = MOD_CLASS_ACTIVITY; + $type->type = "assignment&type=$assignmenttype"; + $type->typestr = get_string("type$assignmenttype", 'assignment'); + $types[] = $type; + } + + /// Drop-in extra assignment types + $assignmenttypes = get_list_of_plugins('mod/assignment/type'); + foreach ($assignmenttypes as $assignmenttype) { + if (!empty($CFG->{'assignment_hide_'.$assignmenttype})) { // Not wanted + continue; + } + if (!in_array($assignmenttype, $standardassignments)) { + $type = new object(); + $type->modclass = MOD_CLASS_ACTIVITY; + $type->type = "assignment&type=$assignmenttype"; + $type->typestr = get_string("type$assignmenttype", 'assignment'); + $types[] = $type; + } + } + + $type = new object(); + $type->modclass = MOD_CLASS_ACTIVITY; + $type->type = "assignment_group_end"; + $type->typestr = '--'; + $types[] = $type; + + return $types; +} + +/** + * Removes all grades from gradebook + * @param int $courseid + * @param string optional type + */ +function assignment_reset_gradebook($courseid, $type='') { + global $CFG; + + $type = $type ? "AND a.assignmenttype='$type'" : ''; + + $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid + FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m + WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id AND a.course=$courseid $type"; + + if ($assignments = get_records_sql($sql)) { + foreach ($assignments as $assignment) { + assignment_grade_item_update($assignment, 'reset'); + } + } +} + +/** + * This function is used by the reset_course_userdata function in moodlelib. + * This function will remove all posts from the specified assignment + * and clean up any related data. + * @param $data the data submitted from the reset course. + * @return array status array + */ +function assignment_reset_userdata($data) { + global $CFG; + + $status = array(); + + foreach (get_list_of_plugins('mod/assignment/type') as $type) { + require_once("$CFG->dirroot/mod/assignment/type/$type/assignment.class.php"); + $assignmentclass = "assignment_$type"; + $ass = new $assignmentclass(); + $status = array_merge($status, $ass->reset_userdata($data)); + } + + return $status; +} + +/** + * Implementation of the function for printing the form elements that control + * whether the course reset functionality affects the assignment. + * @param $mform form passed by reference + */ +function assignment_reset_course_form_definition(&$mform) { + $mform->addElement('header', 'assignmentheader', get_string('modulenameplural', 'assignment')); + $mform->addElement('advcheckbox', 'reset_assignment_submissions', get_string('deleteallsubmissions','assignment')); +} + +/** + * Course reset form defaults. + */ +function assignment_reset_course_form_defaults($course) { + return array('reset_assignment_submissions'=>1); +} + +/** + * Returns all other caps used in module + */ +function assignment_get_extra_capabilities() { + return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames'); +} + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/restorelib.php moodle_assignment_work_1.9.4_Modified/mod/assignment/restorelib.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/restorelib.php 2008-12-12 07:03:28.000000000 +0000 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/restorelib.php 2009-04-23 15:56:42.000000000 +0100 @@ -1,504 +1,539 @@ -id) - // | - // | - // | - // assignment_submisions - // (UL,pk->id, fk->assignment,files) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // nt->nested field (recursive data) - // CL->course level info - // UL->user level info - // files->table may have files) - // - //----------------------------------------------------------- - - //This function executes all the restore procedure about this mod - function assignment_restore_mods($mod,$restore) { - - global $CFG; - - $status = true; - - //Get record from backup_ids - $data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id); - - if ($data) { - //Now get completed xmlized object - $info = $data->info; - //if necessary, write to restorelog and adjust date/time fields - if ($restore->course_startdateoffset) { - restore_log_date_changes('Assignment', $restore, $info['MOD']['#'], array('TIMEDUE', 'TIMEAVAILABLE')); - } - //traverse_xmlize($info); //Debug - //print_object ($GLOBALS['traverse_array']); //Debug - //$GLOBALS['traverse_array']=""; //Debug - - //Now, build the ASSIGNMENT record structure - $assignment->course = $restore->course_id; - $assignment->name = backup_todb($info['MOD']['#']['NAME']['0']['#']); - $assignment->description = backup_todb($info['MOD']['#']['DESCRIPTION']['0']['#']); - $assignment->format = backup_todb($info['MOD']['#']['FORMAT']['0']['#']); - $assignment->resubmit = backup_todb($info['MOD']['#']['RESUBMIT']['0']['#']); - $assignment->preventlate = backup_todb($info['MOD']['#']['PREVENTLATE']['0']['#']); - $assignment->emailteachers = backup_todb($info['MOD']['#']['EMAILTEACHERS']['0']['#']); - $assignment->var1 = backup_todb($info['MOD']['#']['VAR1']['0']['#']); - $assignment->var2 = backup_todb($info['MOD']['#']['VAR2']['0']['#']); - $assignment->var3 = backup_todb($info['MOD']['#']['VAR3']['0']['#']); - $assignment->var4 = backup_todb($info['MOD']['#']['VAR4']['0']['#']); - $assignment->var5 = backup_todb($info['MOD']['#']['VAR5']['0']['#']); - $assignment->type = isset($info['MOD']['#']['TYPE']['0']['#'])?backup_todb($info['MOD']['#']['TYPE']['0']['#']):''; - $assignment->assignmenttype = backup_todb($info['MOD']['#']['ASSIGNMENTTYPE']['0']['#']); - $assignment->maxbytes = backup_todb($info['MOD']['#']['MAXBYTES']['0']['#']); - $assignment->timedue = backup_todb($info['MOD']['#']['TIMEDUE']['0']['#']); - $assignment->timeavailable = backup_todb($info['MOD']['#']['TIMEAVAILABLE']['0']['#']); - $assignment->grade = backup_todb($info['MOD']['#']['GRADE']['0']['#']); - $assignment->timemodified = backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']); - - //We have to recode the grade field if it is <0 (scale) - if ($assignment->grade < 0) { - $scale = backup_getid($restore->backup_unique_code,"scale",abs($assignment->grade)); - if ($scale) { - $assignment->grade = -($scale->new_id); - } - } - - if (empty($assignment->assignmenttype)) { /// Pre 1.5 assignment - if ($assignment->type == 1) { - $assignment->assignmenttype = 'uploadsingle'; - } else { - $assignment->assignmenttype = 'offline'; - } - } - - // skip restore of plugins that are not installed - static $plugins; - if (!isset($plugins)) { - $plugins = get_list_of_plugins('mod/assignment/type'); - } - - if (!in_array($assignment->assignmenttype, $plugins)) { - if (!defined('RESTORE_SILENTLY')) { - echo "
  • ".get_string("modulename","assignment")." \"".format_string(stripslashes($assignment->name),true)."\" - plugin '{$assignment->assignmenttype}' not available!
  • "; - } - return true; // do not fail the restore - } - - //The structure is equal to the db, so insert the assignment - $newid = insert_record ("assignment",$assignment); - - //Do some output - if (!defined('RESTORE_SILENTLY')) { - echo "
  • ".get_string("modulename","assignment")." \"".format_string(stripslashes($assignment->name),true)."\"
  • "; - } - backup_flush(300); - - if ($newid) { - //We have the newid, update backup_ids - backup_putid($restore->backup_unique_code,$mod->modtype, - $mod->id, $newid); - //Now check if want to restore user data and do it. - if (restore_userdata_selected($restore,'assignment',$mod->id)) { - //Restore assignmet_submissions - $status = assignment_submissions_restore_mods($mod->id, $newid,$info,$restore) && $status; - } - } else { - $status = false; - } - } else { - $status = false; - } - - return $status; - } - - //This function restores the assignment_submissions - function assignment_submissions_restore_mods($old_assignment_id, $new_assignment_id,$info,$restore) { - - global $CFG; - - $status = true; - - //Get the submissions array - it might not be present - if (isset($info['MOD']['#']['SUBMISSIONS']['0']['#']['SUBMISSION'])) { - $submissions = $info['MOD']['#']['SUBMISSIONS']['0']['#']['SUBMISSION']; - } else { - $submissions = array(); - } - - //Iterate over submissions - for($i = 0; $i < sizeof($submissions); $i++) { - $sub_info = $submissions[$i]; - //traverse_xmlize($sub_info); //Debug - //print_object ($GLOBALS['traverse_array']); //Debug - //$GLOBALS['traverse_array']=""; //Debug - - //We'll need this later!! - $oldid = backup_todb($sub_info['#']['ID']['0']['#']); - $olduserid = backup_todb($sub_info['#']['USERID']['0']['#']); - - //Now, build the ASSIGNMENT_SUBMISSIONS record structure - $submission->assignment = $new_assignment_id; - $submission->userid = backup_todb($sub_info['#']['USERID']['0']['#']); - $submission->timecreated = backup_todb($sub_info['#']['TIMECREATED']['0']['#']); - $submission->timemodified = backup_todb($sub_info['#']['TIMEMODIFIED']['0']['#']); - $submission->numfiles = backup_todb($sub_info['#']['NUMFILES']['0']['#']); - $submission->data1 = backup_todb($sub_info['#']['DATA1']['0']['#']); - $submission->data2 = backup_todb($sub_info['#']['DATA2']['0']['#']); - $submission->grade = backup_todb($sub_info['#']['GRADE']['0']['#']); - if (isset($sub_info['#']['COMMENT']['0']['#'])) { - $submission->submissioncomment = backup_todb($sub_info['#']['COMMENT']['0']['#']); - } else { - $submission->submissioncomment = backup_todb($sub_info['#']['SUBMISSIONCOMMENT']['0']['#']); - } - $submission->format = backup_todb($sub_info['#']['FORMAT']['0']['#']); - $submission->teacher = backup_todb($sub_info['#']['TEACHER']['0']['#']); - $submission->timemarked = backup_todb($sub_info['#']['TIMEMARKED']['0']['#']); - $submission->mailed = backup_todb($sub_info['#']['MAILED']['0']['#']); - - //We have to recode the userid field - $user = backup_getid($restore->backup_unique_code,"user",$submission->userid); - if ($user) { - $submission->userid = $user->new_id; - } - - //We have to recode the teacher field - $user = backup_getid($restore->backup_unique_code,"user",$submission->teacher); - if ($user) { - $submission->teacher = $user->new_id; - } - - //The structure is equal to the db, so insert the assignment_submission - $newid = insert_record ("assignment_submissions",$submission); - - //Do some output - if (($i+1) % 50 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo "."; - if (($i+1) % 1000 == 0) { - echo "
    "; - } - } - backup_flush(300); - } - - if ($newid) { - //We have the newid, update backup_ids - backup_putid($restore->backup_unique_code,"assignment_submission",$oldid, - $newid); - - //Now copy moddata associated files - $status = assignment_restore_files ($old_assignment_id, $new_assignment_id, - $olduserid, $submission->userid, $restore); - - } else { - $status = false; - } - } - - return $status; - } - - //This function copies the assignment related info from backup temp dir to course moddata folder, - //creating it if needed and recoding everything (assignment id and user id) - function assignment_restore_files ($oldassid, $newassid, $olduserid, $newuserid, $restore) { - - global $CFG; - - $status = true; - $todo = false; - $moddata_path = ""; - $assignment_path = ""; - $temp_path = ""; - - //First, we check to "course_id" exists and create is as necessary - //in CFG->dataroot - $dest_dir = $CFG->dataroot."/".$restore->course_id; - $status = check_dir_exists($dest_dir,true); - - //Now, locate course's moddata directory - $moddata_path = $CFG->dataroot."/".$restore->course_id."/".$CFG->moddata; - - //Check it exists and create it - $status = check_dir_exists($moddata_path,true); - - //Now, locate assignment directory - if ($status) { - $assignment_path = $moddata_path."/assignment"; - //Check it exists and create it - $status = check_dir_exists($assignment_path,true); - } - - //Now locate the temp dir we are gong to restore - if ($status) { - $temp_path = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code. - "/moddata/assignment/".$oldassid."/".$olduserid; - //Check it exists - if (is_dir($temp_path)) { - $todo = true; - } - } - - //If todo, we create the neccesary dirs in course moddata/assignment - if ($status and $todo) { - //First this assignment id - $this_assignment_path = $assignment_path."/".$newassid; - $status = check_dir_exists($this_assignment_path,true); - //Now this user id - $user_assignment_path = $this_assignment_path."/".$newuserid; - //And now, copy temp_path to user_assignment_path - $status = backup_copy_file($temp_path, $user_assignment_path); - } - - return $status; - } - - //Return a content decoded to support interactivities linking. Every module - //should have its own. They are called automatically from - //assignment_decode_content_links_caller() function in each module - //in the restore process - function assignment_decode_content_links ($content,$restore) { - - global $CFG; - - $result = $content; - - //Link to the list of assignments - - $searchstring='/\$@(ASSIGNMENTINDEX)\*([0-9]+)@\$/'; - //We look for it - preg_match_all($searchstring,$content,$foundset); - //If found, then we are going to look for its new id (in backup tables) - if ($foundset[0]) { - //print_object($foundset); //Debug - //Iterate over foundset[2]. They are the old_ids - foreach($foundset[2] as $old_id) { - //We get the needed variables here (course id) - $rec = backup_getid($restore->backup_unique_code,"course",$old_id); - //Personalize the searchstring - $searchstring='/\$@(ASSIGNMENTINDEX)\*('.$old_id.')@\$/'; - //If it is a link to this course, update the link to its new location - if($rec->new_id) { - //Now replace it - $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/assignment/index.php?id='.$rec->new_id,$result); - } else { - //It's a foreign link so leave it as original - $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/assignment/index.php?id='.$old_id,$result); - } - } - } - - //Link to assignment view by moduleid - - $searchstring='/\$@(ASSIGNMENTVIEWBYID)\*([0-9]+)@\$/'; - //We look for it - preg_match_all($searchstring,$result,$foundset); - //If found, then we are going to look for its new id (in backup tables) - if ($foundset[0]) { - //print_object($foundset); //Debug - //Iterate over foundset[2]. They are the old_ids - foreach($foundset[2] as $old_id) { - //We get the needed variables here (course_modules id) - $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id); - //Personalize the searchstring - $searchstring='/\$@(ASSIGNMENTVIEWBYID)\*('.$old_id.')@\$/'; - //If it is a link to this course, update the link to its new location - if($rec->new_id) { - //Now replace it - $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/assignment/view.php?id='.$rec->new_id,$result); - } else { - //It's a foreign link so leave it as original - $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/assignment/view.php?id='.$old_id,$result); - } - } - } - - return $result; - } - - //This function makes all the necessary calls to xxxx_decode_content_links() - //function in each module, passing them the desired contents to be decoded - //from backup format to destination site/course in order to mantain inter-activities - //working in the backup/restore process. It's called from restore_decode_content_links() - //function in restore process - function assignment_decode_content_links_caller($restore) { - global $CFG; - $status = true; - - if ($assignments = get_records_sql ("SELECT a.id, a.description - FROM {$CFG->prefix}assignment a - WHERE a.course = $restore->course_id")) { - //Iterate over each assignment->description - $i = 0; //Counter to send some output to the browser to avoid timeouts - foreach ($assignments as $assignment) { - //Increment counter - $i++; - $content = $assignment->description; - $result = restore_decode_content_links_worker($content,$restore); - if ($result != $content) { - //Update record - $assignment->description = addslashes($result); - $status = update_record("assignment",$assignment); - if (debugging()) { - if (!defined('RESTORE_SILENTLY')) { - echo '

    '.s($content).'
    changed to
    '.s($result).'

    '; - } - } - } - //Do some output - if (($i+1) % 5 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo "."; - if (($i+1) % 100 == 0) { - echo "
    "; - } - } - backup_flush(300); - } - } - } - return $status; - } - - //This function converts texts in FORMAT_WIKI to FORMAT_MARKDOWN for - //some texts in the module - function assignment_restore_wiki2markdown ($restore) { - - global $CFG; - - $status = true; - - //Convert assignment->description - if ($records = get_records_sql ("SELECT a.id, a.description, a.format - FROM {$CFG->prefix}assignment a, - {$CFG->prefix}backup_ids b - WHERE a.course = $restore->course_id AND - a.format = ".FORMAT_WIKI. " AND - b.backup_code = $restore->backup_unique_code AND - b.table_name = 'assignment' AND - b.new_id = a.id")) { - foreach ($records as $record) { - //Rebuild wiki links - $record->description = restore_decode_wiki_content($record->description, $restore); - //Convert to Markdown - $wtm = new WikiToMarkdown(); - $record->description = $wtm->convert($record->description, $restore->course_id); - $record->format = FORMAT_MARKDOWN; - $status = update_record('assignment', addslashes_object($record)); - //Do some output - $i++; - if (($i+1) % 1 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo "."; - if (($i+1) % 20 == 0) { - echo "
    "; - } - } - backup_flush(300); - } - } - - } - return $status; - } - - //This function returns a log record with all the necessay transformations - //done. It's used by restore_log_module() to restore modules log. - function assignment_restore_logs($restore,$log) { - - $status = false; - - //Depending of the action, we recode different things - switch ($log->action) { - case "add": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "view.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "update": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "view.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "view": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "view.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "view all": - $log->url = "index.php?id=".$log->course; - $status = true; - break; - case "upload": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "view.php?a=".$mod->new_id; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "view submission": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "submissions.php?id=".$mod->new_id; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "update grades": - if ($log->cmid) { - //Extract the assignment id from the url field - $assid = substr(strrchr($log->url,"="),1); - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$assid); - if ($mod) { - $log->url = "submissions.php?id=".$mod->new_id; - $status = true; - } - } - break; - default: - if (!defined('RESTORE_SILENTLY')) { - echo "action (".$log->module."-".$log->action.") unknown. Not restored
    "; //Debug - } - break; - } - - if ($status) { - $status = $log; - } - return $status; - } -?> +id) + // | + // | + // | + // assignment_submisions + // (UL,pk->id, fk->assignment,files) + // + // Meaning: pk->primary key field of the table + // fk->foreign key to link with parent + // nt->nested field (recursive data) + // CL->course level info + // UL->user level info + // files->table may have files) + // + //----------------------------------------------------------- + + //This function executes all the restore procedure about this mod + function assignment_restore_mods($mod,$restore) { + + global $CFG; + + $status = true; + + //Get record from backup_ids + $data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id); + + if ($data) { + //Now get completed xmlized object + $info = $data->info; + //if necessary, write to restorelog and adjust date/time fields + if ($restore->course_startdateoffset) { + restore_log_date_changes('Assignment', $restore, $info['MOD']['#'], array('TIMEDUE', 'TIMEAVAILABLE')); + } + //traverse_xmlize($info); //Debug + //print_object ($GLOBALS['traverse_array']); //Debug + //$GLOBALS['traverse_array']=""; //Debug + + //Now, build the ASSIGNMENT record structure + $assignment->course = $restore->course_id; + $assignment->name = backup_todb($info['MOD']['#']['NAME']['0']['#']); + $assignment->description = backup_todb($info['MOD']['#']['DESCRIPTION']['0']['#']); + $assignment->format = backup_todb($info['MOD']['#']['FORMAT']['0']['#']); + $assignment->resubmit = backup_todb($info['MOD']['#']['RESUBMIT']['0']['#']); + $assignment->preventlate = backup_todb($info['MOD']['#']['PREVENTLATE']['0']['#']); + $assignment->emailteachers = backup_todb($info['MOD']['#']['EMAILTEACHERS']['0']['#']); + $assignment->var1 = backup_todb($info['MOD']['#']['VAR1']['0']['#']); + $assignment->var2 = backup_todb($info['MOD']['#']['VAR2']['0']['#']); + $assignment->var3 = backup_todb($info['MOD']['#']['VAR3']['0']['#']); + $assignment->var4 = backup_todb($info['MOD']['#']['VAR4']['0']['#']); + $assignment->var5 = backup_todb($info['MOD']['#']['VAR5']['0']['#']); + $assignment->type = isset($info['MOD']['#']['TYPE']['0']['#'])?backup_todb($info['MOD']['#']['TYPE']['0']['#']):''; + $assignment->assignmenttype = backup_todb($info['MOD']['#']['ASSIGNMENTTYPE']['0']['#']); + $assignment->maxbytes = backup_todb($info['MOD']['#']['MAXBYTES']['0']['#']); + $assignment->timedue = backup_todb($info['MOD']['#']['TIMEDUE']['0']['#']); + $assignment->timeavailable = backup_todb($info['MOD']['#']['TIMEAVAILABLE']['0']['#']); + $assignment->grade = backup_todb($info['MOD']['#']['GRADE']['0']['#']); + $assignment->timemodified = backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']); + $assignment->templatetext = backup_todb($info['MOD']['#']['TEMPLATETEXT']['0']['#']); + $assignment->templatefile = backup_todb($info['MOD']['#']['TEMPLATEFILE']['0']['#']); + + if ($assignment->templatefile != '') { + $status = restore_template_file($assignment->templatefile, $restore); + } + + //We have to recode the grade field if it is <0 (scale) + if ($assignment->grade < 0) { + $scale = backup_getid($restore->backup_unique_code,"scale",abs($assignment->grade)); + if ($scale) { + $assignment->grade = -($scale->new_id); + } + } + + if (empty($assignment->assignmenttype)) { /// Pre 1.5 assignment + if ($assignment->type == 1) { + $assignment->assignmenttype = 'uploadsingle'; + } else { + $assignment->assignmenttype = 'offline'; + } + } + + // skip restore of plugins that are not installed + static $plugins; + if (!isset($plugins)) { + $plugins = get_list_of_plugins('mod/assignment/type'); + } + + if (!in_array($assignment->assignmenttype, $plugins)) { + if (!defined('RESTORE_SILENTLY')) { + echo "
  • ".get_string("modulename","assignment")." \"".format_string(stripslashes($assignment->name),true)."\" - plugin '{$assignment->assignmenttype}' not available!
  • "; + } + return true; // do not fail the restore + } + + //The structure is equal to the db, so insert the assignment + $newid = insert_record ("assignment",$assignment); + + //Do some output + if (!defined('RESTORE_SILENTLY')) { + echo "
  • ".get_string("modulename","assignment")." \"".format_string(stripslashes($assignment->name),true)."\"
  • "; + } + backup_flush(300); + + if ($newid) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,$mod->modtype, + $mod->id, $newid); + //Now check if want to restore user data and do it. + if (restore_userdata_selected($restore,'assignment',$mod->id)) { + //Restore assignmet_submissions + $status = assignment_submissions_restore_mods($mod->id, $newid,$info,$restore) && $status; + } + } else { + $status = false; + } + } else { + $status = false; + } + + return $status; + } + + function restore_template_file($filelocation, $restore) { + + global $CFG; + $status = true; + + $intPos = 0; + $intLastPos = 0; + $intCount = 0; + + $status = check_dir_exists($CFG->dataroot.'/'.$restore->course_id, true); + + while ($status) { + $intPos = strpos($filelocation, '/', $intLastPos); + if ($intPos == 0 || $intCount > 20) { + break; + } + $strDirs = substr($filelocation, 0, strpos($filelocation, '/', $intPos) + 1); + $status = check_dir_exists($CFG->dataroot.'/'.$restore->course_id.'/'.$strDirs, true); + $intLastPos = $intPos+1; + $intCount = $intCount + 1; + } + + if ($status) { + $status = backup_copy_file($CFG->dataroot."/temp/backup/".$restore->backup_unique_code.'/'.$filelocation, $CFG->dataroot."/".$restore->course_id."/".$filelocation); + } + + return $status; + } + + //This function restores the assignment_submissions + function assignment_submissions_restore_mods($old_assignment_id, $new_assignment_id,$info,$restore) { + + global $CFG; + + $status = true; + + //Get the submissions array - it might not be present + if (isset($info['MOD']['#']['SUBMISSIONS']['0']['#']['SUBMISSION'])) { + $submissions = $info['MOD']['#']['SUBMISSIONS']['0']['#']['SUBMISSION']; + } else { + $submissions = array(); + } + + //Iterate over submissions + for($i = 0; $i < sizeof($submissions); $i++) { + $sub_info = $submissions[$i]; + //traverse_xmlize($sub_info); //Debug + //print_object ($GLOBALS['traverse_array']); //Debug + //$GLOBALS['traverse_array']=""; //Debug + + //We'll need this later!! + $oldid = backup_todb($sub_info['#']['ID']['0']['#']); + $olduserid = backup_todb($sub_info['#']['USERID']['0']['#']); + + //Now, build the ASSIGNMENT_SUBMISSIONS record structure + $submission->assignment = $new_assignment_id; + $submission->userid = backup_todb($sub_info['#']['USERID']['0']['#']); + $submission->timecreated = backup_todb($sub_info['#']['TIMECREATED']['0']['#']); + $submission->timemodified = backup_todb($sub_info['#']['TIMEMODIFIED']['0']['#']); + $submission->numfiles = backup_todb($sub_info['#']['NUMFILES']['0']['#']); + $submission->data1 = backup_todb($sub_info['#']['DATA1']['0']['#']); + $submission->data2 = backup_todb($sub_info['#']['DATA2']['0']['#']); + $submission->grade = backup_todb($sub_info['#']['GRADE']['0']['#']); + if (isset($sub_info['#']['COMMENT']['0']['#'])) { + $submission->submissioncomment = backup_todb($sub_info['#']['COMMENT']['0']['#']); + } else { + $submission->submissioncomment = backup_todb($sub_info['#']['SUBMISSIONCOMMENT']['0']['#']); + } + $submission->format = backup_todb($sub_info['#']['FORMAT']['0']['#']); + $submission->teacher = backup_todb($sub_info['#']['TEACHER']['0']['#']); + $submission->timemarked = backup_todb($sub_info['#']['TIMEMARKED']['0']['#']); + $submission->mailed = backup_todb($sub_info['#']['MAILED']['0']['#']); + + //We have to recode the userid field + $user = backup_getid($restore->backup_unique_code,"user",$submission->userid); + if ($user) { + $submission->userid = $user->new_id; + } + + //We have to recode the teacher field + $user = backup_getid($restore->backup_unique_code,"user",$submission->teacher); + if ($user) { + $submission->teacher = $user->new_id; + } + + //The structure is equal to the db, so insert the assignment_submission + $newid = insert_record ("assignment_submissions",$submission); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
    "; + } + } + backup_flush(300); + } + + if ($newid) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,"assignment_submission",$oldid, + $newid); + + //Now copy moddata associated files + $status = assignment_restore_files ($old_assignment_id, $new_assignment_id, + $olduserid, $submission->userid, $restore); + + } else { + $status = false; + } + } + + return $status; + } + + //This function copies the assignment related info from backup temp dir to course moddata folder, + //creating it if needed and recoding everything (assignment id and user id) + function assignment_restore_files ($oldassid, $newassid, $olduserid, $newuserid, $restore) { + + global $CFG; + + $status = true; + $todo = false; + $moddata_path = ""; + $assignment_path = ""; + $temp_path = ""; + + //First, we check to "course_id" exists and create is as necessary + //in CFG->dataroot + $dest_dir = $CFG->dataroot."/".$restore->course_id; + $status = check_dir_exists($dest_dir,true); + + //Now, locate course's moddata directory + $moddata_path = $CFG->dataroot."/".$restore->course_id."/".$CFG->moddata; + + //Check it exists and create it + $status = check_dir_exists($moddata_path,true); + + //Now, locate assignment directory + if ($status) { + $assignment_path = $moddata_path."/assignment"; + //Check it exists and create it + $status = check_dir_exists($assignment_path,true); + } + + //Now locate the temp dir we are gong to restore + if ($status) { + $temp_path = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code. + "/moddata/assignment/".$oldassid."/".$olduserid; + //Check it exists + if (is_dir($temp_path)) { + $todo = true; + } + } + + //If todo, we create the neccesary dirs in course moddata/assignment + if ($status and $todo) { + //First this assignment id + $this_assignment_path = $assignment_path."/".$newassid; + $status = check_dir_exists($this_assignment_path,true); + //Now this user id + $user_assignment_path = $this_assignment_path."/".$newuserid; + //And now, copy temp_path to user_assignment_path + $status = backup_copy_file($temp_path, $user_assignment_path); + } + + return $status; + } + + //Return a content decoded to support interactivities linking. Every module + //should have its own. They are called automatically from + //assignment_decode_content_links_caller() function in each module + //in the restore process + function assignment_decode_content_links ($content,$restore) { + + global $CFG; + + $result = $content; + + //Link to the list of assignments + + $searchstring='/\$@(ASSIGNMENTINDEX)\*([0-9]+)@\$/'; + //We look for it + preg_match_all($searchstring,$content,$foundset); + //If found, then we are going to look for its new id (in backup tables) + if ($foundset[0]) { + //print_object($foundset); //Debug + //Iterate over foundset[2]. They are the old_ids + foreach($foundset[2] as $old_id) { + //We get the needed variables here (course id) + $rec = backup_getid($restore->backup_unique_code,"course",$old_id); + //Personalize the searchstring + $searchstring='/\$@(ASSIGNMENTINDEX)\*('.$old_id.')@\$/'; + //If it is a link to this course, update the link to its new location + if($rec->new_id) { + //Now replace it + $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/assignment/index.php?id='.$rec->new_id,$result); + } else { + //It's a foreign link so leave it as original + $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/assignment/index.php?id='.$old_id,$result); + } + } + } + + //Link to assignment view by moduleid + + $searchstring='/\$@(ASSIGNMENTVIEWBYID)\*([0-9]+)@\$/'; + //We look for it + preg_match_all($searchstring,$result,$foundset); + //If found, then we are going to look for its new id (in backup tables) + if ($foundset[0]) { + //print_object($foundset); //Debug + //Iterate over foundset[2]. They are the old_ids + foreach($foundset[2] as $old_id) { + //We get the needed variables here (course_modules id) + $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id); + //Personalize the searchstring + $searchstring='/\$@(ASSIGNMENTVIEWBYID)\*('.$old_id.')@\$/'; + //If it is a link to this course, update the link to its new location + if($rec->new_id) { + //Now replace it + $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/assignment/view.php?id='.$rec->new_id,$result); + } else { + //It's a foreign link so leave it as original + $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/assignment/view.php?id='.$old_id,$result); + } + } + } + + return $result; + } + + //This function makes all the necessary calls to xxxx_decode_content_links() + //function in each module, passing them the desired contents to be decoded + //from backup format to destination site/course in order to mantain inter-activities + //working in the backup/restore process. It's called from restore_decode_content_links() + //function in restore process + function assignment_decode_content_links_caller($restore) { + global $CFG; + $status = true; + + if ($assignments = get_records_sql ("SELECT a.id, a.description + FROM {$CFG->prefix}assignment a + WHERE a.course = $restore->course_id")) { + //Iterate over each assignment->description + $i = 0; //Counter to send some output to the browser to avoid timeouts + foreach ($assignments as $assignment) { + //Increment counter + $i++; + $content = $assignment->description; + $result = restore_decode_content_links_worker($content,$restore); + if ($result != $content) { + //Update record + $assignment->description = addslashes($result); + $status = update_record("assignment",$assignment); + if (debugging()) { + if (!defined('RESTORE_SILENTLY')) { + echo '

    '.s($content).'
    changed to
    '.s($result).'

    '; + } + } + } + //Do some output + if (($i+1) % 5 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 100 == 0) { + echo "
    "; + } + } + backup_flush(300); + } + } + } + return $status; + } + + //This function converts texts in FORMAT_WIKI to FORMAT_MARKDOWN for + //some texts in the module + function assignment_restore_wiki2markdown ($restore) { + + global $CFG; + + $status = true; + + //Convert assignment->description + if ($records = get_records_sql ("SELECT a.id, a.description, a.format + FROM {$CFG->prefix}assignment a, + {$CFG->prefix}backup_ids b + WHERE a.course = $restore->course_id AND + a.format = ".FORMAT_WIKI. " AND + b.backup_code = $restore->backup_unique_code AND + b.table_name = 'assignment' AND + b.new_id = a.id")) { + foreach ($records as $record) { + //Rebuild wiki links + $record->description = restore_decode_wiki_content($record->description, $restore); + //Convert to Markdown + $wtm = new WikiToMarkdown(); + $record->description = $wtm->convert($record->description, $restore->course_id); + $record->format = FORMAT_MARKDOWN; + $status = update_record('assignment', addslashes_object($record)); + //Do some output + $i++; + if (($i+1) % 1 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 20 == 0) { + echo "
    "; + } + } + backup_flush(300); + } + } + + } + return $status; + } + + //This function returns a log record with all the necessay transformations + //done. It's used by restore_log_module() to restore modules log. + function assignment_restore_logs($restore,$log) { + + $status = false; + + //Depending of the action, we recode different things + switch ($log->action) { + case "add": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "view.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "update": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "view.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "view": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "view.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "view all": + $log->url = "index.php?id=".$log->course; + $status = true; + break; + case "upload": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "view.php?a=".$mod->new_id; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "view submission": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "submissions.php?id=".$mod->new_id; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "update grades": + if ($log->cmid) { + //Extract the assignment id from the url field + $assid = substr(strrchr($log->url,"="),1); + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$assid); + if ($mod) { + $log->url = "submissions.php?id=".$mod->new_id; + $status = true; + } + } + break; + default: + if (!defined('RESTORE_SILENTLY')) { + echo "action (".$log->module."-".$log->action.") unknown. Not restored
    "; //Debug + } + break; + } + + if ($status) { + $status = $log; + } + return $status; + } +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/type/upload/assignment.class.php moodle_assignment_work_1.9.4_Modified/mod/assignment/type/upload/assignment.class.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/type/upload/assignment.class.php 2008-10-10 08:19:46.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/type/upload/assignment.class.php 2009-04-24 09:43:14.000000000 +0100 @@ -1,1079 +1,1084 @@ -libdir.'/formslib.php'); - -define('ASSIGNMENT_STATUS_SUBMITTED', 'submitted'); // student thinks it is finished -define('ASSIGNMENT_STATUS_CLOSED', 'closed'); // teacher prevents more submissions - -/** - * Extend the base assignment class for assignments where you upload a single file - * - */ -class assignment_upload extends assignment_base { - - function assignment_upload($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) { - parent::assignment_base($cmid, $assignment, $cm, $course); - $this->type = 'upload'; - } - - function view() { - global $USER; - - require_capability('mod/assignment:view', $this->context); - - add_to_log($this->course->id, 'assignment', 'view', "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id); - - $this->view_header(); - - if ($this->assignment->timeavailable > time() - and !has_capability('mod/assignment:grade', $this->context) // grading user can see it anytime - and $this->assignment->var3) { // force hiding before available date - print_simple_box_start('center', '', '', 0, 'generalbox', 'intro'); - print_string('notavailableyet', 'assignment'); - print_simple_box_end(); - } else { - $this->view_intro(); - } - - $this->view_dates(); - - if (has_capability('mod/assignment:submit', $this->context)) { - $filecount = $this->count_user_files($USER->id); - $submission = $this->get_submission($USER->id); - - $this->view_feedback(); - - if (!$this->drafts_tracked() or !$this->isopen() or $this->is_finalized($submission)) { - print_heading(get_string('submission', 'assignment'), '', 3); - } else { - print_heading(get_string('submissiondraft', 'assignment'), '', 3); - } - - if ($filecount and $submission) { - print_simple_box($this->print_user_files($USER->id, true), 'center'); - } else { - if (!$this->isopen() or $this->is_finalized($submission)) { - print_simple_box(get_string('nofiles', 'assignment'), 'center'); - } else { - print_simple_box(get_string('nofilesyet', 'assignment'), 'center'); - } - } - - $this->view_upload_form(); - - if ($this->notes_allowed()) { - print_heading(get_string('notes', 'assignment'), '', 3); - $this->view_notes(); - } - - $this->view_final_submission(); - } - $this->view_footer(); - } - - - function view_feedback($submission=NULL) { - global $USER, $CFG; - require_once($CFG->libdir.'/gradelib.php'); - - if (!$submission) { /// Get submission for this assignment - $submission = $this->get_submission($USER->id); - } - - if (empty($submission->timemarked)) { /// Nothing to show, so print nothing - if ($this->count_responsefiles($USER->id)) { - print_heading(get_string('responsefiles', 'assignment', $this->course->teacher), '', 3); - $responsefiles = $this->print_responsefiles($USER->id, true); - print_simple_box($responsefiles, 'center'); - } - return; - } - - $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id); - $item = $grading_info->items[0]; - $grade = $item->grades[$USER->id]; - - if ($grade->hidden or $grade->grade === false) { // hidden or error - return; - } - - if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet - return; - } - - $graded_date = $grade->dategraded; - $graded_by = $grade->usermodified; - - /// We need the teacher info - if (!$teacher = get_record('user', 'id', $graded_by)) { - error('Could not find the teacher'); - } - - /// Print the feedback - print_heading(get_string('submissionfeedback', 'assignment'), '', 3); - - echo ''; - - echo ''; - echo ''; - echo ''; - echo ''; - - echo ''; - echo ''; - echo ''; - - echo ''; - echo ''; - echo ''; - - echo '
    '; - print_user_picture($teacher, $this->course->id, $teacher->picture); - echo ''; - echo '
    '; - echo '
    '.fullname($teacher).'
    '; - echo '
    '.userdate($graded_date).'
    '; - echo '
    '; - echo '
     '; - if ($this->assignment->grade) { - echo '
    '; - echo get_string("grade").': '.$grade->str_long_grade; - echo '
    '; - echo '
    '; - } - - echo '
    '; - echo $grade->str_feedback; - echo '
    '; - echo '
     '; - echo $this->print_responsefiles($USER->id, true); - echo '
    '; - } - - - function view_upload_form() { - global $CFG, $USER; - - $submission = $this->get_submission($USER->id); - - $struploadafile = get_string('uploadafile'); - $maxbytes = $this->assignment->maxbytes == 0 ? $this->course->maxbytes : $this->assignment->maxbytes; - $strmaxsize = get_string('maxsize', '', display_size($maxbytes)); - - if ($this->is_finalized($submission)) { - // no uploading - return; - } - - if ($this->can_upload_file($submission)) { - echo '
    '; - echo '
    '; - echo '
    '; - echo "

    $struploadafile ($strmaxsize)

    "; - echo ''; - echo ''; - require_once($CFG->libdir.'/uploadlib.php'); - upload_print_form_fragment(1,array('newfile'),null,false,null,0,$this->assignment->maxbytes,false); - echo ''; - echo '
    '; - echo '
    '; - echo '
    '; - echo '
    '; - } - - } - - function view_notes() { - global $USER; - - if ($submission = $this->get_submission($USER->id) - and !empty($submission->data1)) { - print_simple_box(format_text($submission->data1, FORMAT_HTML), 'center', '630px'); - } else { - print_simple_box(get_string('notesempty', 'assignment'), 'center'); - } - if ($this->can_update_notes($submission)) { - $options = array ('id'=>$this->cm->id, 'action'=>'editnotes'); - echo '
    '; - print_single_button('upload.php', $options, get_string('edit'), 'post', '_self', false); - echo '
    '; - } - } - - function view_final_submission() { - global $CFG, $USER; - - $submission = $this->get_submission($USER->id); - - if ($this->isopen() and $this->can_finalize($submission)) { - //print final submit button - print_heading(get_string('submitformarking','assignment'), '', 3); - echo '
    '; - echo '
    '; - echo '
    '; - echo ''; - echo ''; - echo ''; - echo '
    '; - echo '
    '; - echo '
    '; - } else if (!$this->isopen()) { - print_heading(get_string('nomoresubmissions','assignment'), '', 3); - - } else if ($this->drafts_tracked() and $state = $this->is_finalized($submission)) { - if ($state == ASSIGNMENT_STATUS_SUBMITTED) { - print_heading(get_string('submitedformarking','assignment'), '', 3); - } else { - print_heading(get_string('nomoresubmissions','assignment'), '', 3); - } - } else { - //no submission yet - } - } - - - /** - * Return true if var3 == hide description till available day - * - *@return boolean - */ - function description_is_hidden() { - return ($this->assignment->var3 && (time() <= $this->assignment->timeavailable)); - } - - function custom_feedbackform($submission, $return=false) { - global $CFG; - - $mode = optional_param('mode', '', PARAM_ALPHA); - $offset = optional_param('offset', 0, PARAM_INT); - $forcerefresh = optional_param('forcerefresh', 0, PARAM_BOOL); - - $output = get_string('responsefiles', 'assignment').': '; - - $output .= '
    wwwroot/mod/assignment/upload.php\">"; - $output .= '
    '; - $output .= ''; - $output .= ''; - $output .= ''; - $output .= ''; - $output .= ''; - require_once($CFG->libdir.'/uploadlib.php'); - $output .= upload_print_form_fragment(1,array('newfile'),null,false,null,0,0,true); - $output .= ''; - $output .= '
    '; - $output .= '
    '; - - if ($forcerefresh) { - $output .= $this->update_main_listing($submission); - } - - $responsefiles = $this->print_responsefiles($submission->userid, true); - if (!empty($responsefiles)) { - $output .= $responsefiles; - } - - if ($return) { - return $output; - } - echo $output; - return; - } - - - function print_student_answer($userid, $return=false){ - global $CFG; - - $filearea = $this->file_area_name($userid); - $submission = $this->get_submission($userid); - - $output = ''; - - if ($basedir = $this->file_area($userid)) { - if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission)) { - $output .= ''.get_string('draft', 'assignment').': '; - } - - if ($this->notes_allowed() and !empty($submission->data1)) { - $output .= link_to_popup_window ('/mod/assignment/type/upload/notes.php?id='.$this->cm->id.'&userid='.$userid, - 'notes'.$userid, get_string('notes', 'assignment'), 500, 780, get_string('notes', 'assignment'), 'none', true, 'notesbutton'.$userid); - $output .= ' '; - } - - if ($files = get_directory_list($basedir, 'responses')) { - require_once($CFG->libdir.'/filelib.php'); - foreach ($files as $key => $file) { - $icon = mimeinfo('icon', $file); - $ffurl = get_file_url("$filearea/$file"); - $output .= ''.$icon.''.$file.' '; - } - } - } - $output = '
    '.$output.'
    '; - $output .= '
    '; - - return $output; - } - - - /** - * Produces a list of links to the files uploaded by a user - * - * @param $userid int optional id of the user. If 0 then $USER->id is used. - * @param $return boolean optional defaults to false. If true the list is returned rather than printed - * @return string optional - */ - function print_user_files($userid=0, $return=false) { - global $CFG, $USER; - - $mode = optional_param('mode', '', PARAM_ALPHA); - $offset = optional_param('offset', 0, PARAM_INT); - - if (!$userid) { - if (!isloggedin()) { - return ''; - } - $userid = $USER->id; - } - - $filearea = $this->file_area_name($userid); - - $output = ''; - - $submission = $this->get_submission($userid); - - $candelete = $this->can_delete_files($submission); - $strdelete = get_string('delete'); - - if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission) and !empty($mode)) { // only during grading - $output .= ''.get_string('draft', 'assignment').':
    '; - } - - if ($this->notes_allowed() and !empty($submission->data1) and !empty($mode)) { // only during grading - - $npurl = $CFG->wwwroot."/mod/assignment/type/upload/notes.php?id={$this->cm->id}&userid=$userid&offset=$offset&mode=single"; - $output .= ''.get_string('notes', 'assignment').'
    '; - - } - - if ($basedir = $this->file_area($userid)) { - if ($files = get_directory_list($basedir, 'responses')) { - require_once($CFG->libdir.'/filelib.php'); - foreach ($files as $key => $file) { - - $icon = mimeinfo('icon', $file); - $ffurl = get_file_url("$filearea/$file"); - - $output .= ''.$icon.''.$file.''; - - if ($candelete) { - $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&file=$file&userid={$submission->userid}&mode=$mode&offset=$offset"; - - $output .= ' ' - .' '; - } - - $output .= '
    '; - } - } - } - - if ($this->drafts_tracked() and $this->isopen() and has_capability('mod/assignment:grade', $this->context) and $mode != '') { // we do not want it on view.php page - if ($this->can_unfinalize($submission)) { - $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'unfinalize', 'mode'=>$mode, 'offset'=>$offset); - $output .= print_single_button('upload.php', $options, get_string('unfinalize', 'assignment'), 'post', '_self', true); - } else if ($this->can_finalize($submission)) { - $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'finalizeclose', 'mode'=>$mode, 'offset'=>$offset); - $output .= print_single_button('upload.php', $options, get_string('finalize', 'assignment'), 'post', '_self', true); - } - } - - $output = '
    '.$output.'
    '; - - if ($return) { - return $output; - } - echo $output; - } - - function print_responsefiles($userid, $return=false) { - global $CFG, $USER; - - $mode = optional_param('mode', '', PARAM_ALPHA); - $offset = optional_param('offset', 0, PARAM_INT); - - $filearea = $this->file_area_name($userid).'/responses'; - - $output = ''; - - $candelete = $this->can_manage_responsefiles(); - $strdelete = get_string('delete'); - - if ($basedir = $this->file_area($userid)) { - $basedir .= '/responses'; - - if ($files = get_directory_list($basedir)) { - require_once($CFG->libdir.'/filelib.php'); - foreach ($files as $key => $file) { - - $icon = mimeinfo('icon', $file); - - $ffurl = get_file_url("$filearea/$file"); - - $output .= ''.$icon.''.$file.''; - - if ($candelete) { - $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&file=$file&userid=$userid&mode=$mode&offset=$offset&action=response"; - - $output .= ' ' - .' '; - } - - $output .= ' '; - } - } - - - $output = '
    '.$output.'
    '; - - } - - if ($return) { - return $output; - } - echo $output; - } - - - function upload() { - $action = required_param('action', PARAM_ALPHA); - - switch ($action) { - case 'finalize': - $this->finalize(); - break; - case 'finalizeclose': - $this->finalizeclose(); - break; - case 'unfinalize': - $this->unfinalize(); - break; - case 'uploadresponse': - $this->upload_responsefile(); - break; - case 'uploadfile': - $this->upload_file(); - case 'savenotes': - case 'editnotes': - $this->upload_notes(); - default: - error('Error: Unknow upload action ('.$action.').'); - } - } - - function upload_notes() { - global $CFG, $USER; - - $action = required_param('action', PARAM_ALPHA); - - $returnurl = 'view.php?id='.$this->cm->id; - - $mform = new mod_assignment_upload_notes_form(); - - $defaults = new object(); - $defaults->id = $this->cm->id; - - if ($submission = $this->get_submission($USER->id)) { - $defaults->text = $submission->data1; - } else { - $defaults->text = ''; - } - - $mform->set_data($defaults); - - if ($mform->is_cancelled()) { - redirect('view.php?id='.$this->cm->id); - } - - if (!$this->can_update_notes($submission)) { - $this->view_header(get_string('upload')); - notify(get_string('uploaderror', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - - if ($data = $mform->get_data() and $action == 'savenotes') { - $submission = $this->get_submission($USER->id, true); // get or create submission - $updated = new object(); - $updated->id = $submission->id; - $updated->timemodified = time(); - $updated->data1 = $data->text; - - if (update_record('assignment_submissions', $updated)) { - add_to_log($this->course->id, 'assignment', 'upload', 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - redirect($returnurl); - $submission = $this->get_submission($USER->id); - $this->update_grade($submission); - - } else { - $this->view_header(get_string('notes', 'assignment')); - notify(get_string('notesupdateerror', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - } - - /// show notes edit form - $this->view_header(get_string('notes', 'assignment')); - - print_heading(get_string('notes', 'assignment'), ''); - - $mform->display(); - - $this->view_footer(); - die; - } - - function upload_responsefile() { - global $CFG; - - $userid = required_param('userid', PARAM_INT); - $mode = required_param('mode', PARAM_ALPHA); - $offset = required_param('offset', PARAM_INT); - - $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset"; - - if (data_submitted('nomatch') and $this->can_manage_responsefiles()) { - $dir = $this->file_area_name($userid).'/responses'; - check_dir_exists($CFG->dataroot.'/'.$dir, true, true); - - require_once($CFG->dirroot.'/lib/uploadlib.php'); - $um = new upload_manager('newfile',false,true,$this->course,false,0,true); - - if (!$um->process_file_uploads($dir)) { - print_header(get_string('upload')); - notify(get_string('uploaderror', 'assignment')); - echo $um->get_errors(); - print_continue($returnurl); - print_footer('none'); - die; - } - } - redirect($returnurl); - } - - function upload_file() { - global $CFG, $USER; - - $mode = optional_param('mode', '', PARAM_ALPHA); - $offset = optional_param('offset', 0, PARAM_INT); - - $returnurl = 'view.php?id='.$this->cm->id; - - $filecount = $this->count_user_files($USER->id); - $submission = $this->get_submission($USER->id); - - if (!$this->can_upload_file($submission)) { - $this->view_header(get_string('upload')); - notify(get_string('uploaderror', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - - $dir = $this->file_area_name($USER->id); - check_dir_exists($CFG->dataroot.'/'.$dir, true, true); // better to create now so that student submissions do not block it later - - require_once($CFG->dirroot.'/lib/uploadlib.php'); - $um = new upload_manager('newfile',false,true,$this->course,false,$this->assignment->maxbytes,true); - - if ($um->process_file_uploads($dir)) { - $submission = $this->get_submission($USER->id, true); //create new submission if needed - $updated = new object(); - $updated->id = $submission->id; - $updated->timemodified = time(); - - if (update_record('assignment_submissions', $updated)) { - add_to_log($this->course->id, 'assignment', 'upload', - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($USER->id); - $this->update_grade($submission); - if (!$this->drafts_tracked()) { - $this->email_teachers($submission); - } - } else { - $new_filename = $um->get_new_filename(); - $this->view_header(get_string('upload')); - notify(get_string('uploadnotregistered', 'assignment', $new_filename)); - print_continue($returnurl); - $this->view_footer(); - die; - } - redirect('view.php?id='.$this->cm->id); - } - $this->view_header(get_string('upload')); - notify(get_string('uploaderror', 'assignment')); - echo $um->get_errors(); - print_continue($returnurl); - $this->view_footer(); - die; - } - - function finalize() { - global $USER; - - $confirm = optional_param('confirm', 0, PARAM_BOOL); - $returnurl = 'view.php?id='.$this->cm->id; - $submission = $this->get_submission($USER->id); - - if (!$this->can_finalize($submission)) { - redirect($returnurl); // probably already graded, redirect to assignment page, the reason should be obvious - } - - if (!data_submitted() or !$confirm) { - $optionsno = array('id'=>$this->cm->id); - $optionsyes = array ('id'=>$this->cm->id, 'confirm'=>1, 'action'=>'finalize'); - $this->view_header(get_string('submitformarking', 'assignment')); - print_heading(get_string('submitformarking', 'assignment')); - notice_yesno(get_string('onceassignmentsent', 'assignment'), 'upload.php', 'view.php', $optionsyes, $optionsno, 'post', 'get'); - $this->view_footer(); - die; - - } - $updated = new object(); - $updated->id = $submission->id; - $updated->data2 = ASSIGNMENT_STATUS_SUBMITTED; - $updated->timemodified = time(); - - if (update_record('assignment_submissions', $updated)) { - add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($USER->id); - $this->update_grade($submission); - $this->email_teachers($submission); - } else { - $this->view_header(get_string('submitformarking', 'assignment')); - notify(get_string('finalizeerror', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - redirect($returnurl); - } - - function finalizeclose() { - $userid = optional_param('userid', 0, PARAM_INT); - $mode = required_param('mode', PARAM_ALPHA); - $offset = required_param('offset', PARAM_INT); - $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset&forcerefresh=1"; - - // create but do not add student submission date - $submission = $this->get_submission($userid, true, true); - - if (!data_submitted() or !$this->can_finalize($submission)) { - redirect($returnurl); // probably closed already - } - - $updated = new object(); - $updated->id = $submission->id; - $updated->data2 = ASSIGNMENT_STATUS_CLOSED; - - if (update_record('assignment_submissions', $updated)) { - add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($userid, false, true); - $this->update_grade($submission); - } - redirect($returnurl); - } - - function unfinalize() { - - $userid = required_param('userid', PARAM_INT); - $mode = required_param('mode', PARAM_ALPHA); - $offset = required_param('offset', PARAM_INT); - - $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset&forcerefresh=1"; - - if (data_submitted('nomatch') - and $submission = $this->get_submission($userid) - and $this->can_unfinalize($submission)) { - - $updated = new object(); - $updated->id = $submission->id; - $updated->data2 = ''; - if (update_record('assignment_submissions', $updated)) { - //TODO: add unfinalize action to log - add_to_log($this->course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($userid); - $this->update_grade($submission); - } else { - $this->view_header(get_string('submitformarking', 'assignment')); - notify(get_string('unfinalizeerror', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - } - redirect($returnurl); - } - - - function delete() { - $action = optional_param('action', '', PARAM_ALPHA); - - switch ($action) { - case 'response': - $this->delete_responsefile(); - break; - default: - $this->delete_file(); - } - die; - } - - - function delete_responsefile() { - global $CFG; - - $file = required_param('file', PARAM_FILE); - $userid = required_param('userid', PARAM_INT); - $mode = required_param('mode', PARAM_ALPHA); - $offset = required_param('offset', PARAM_INT); - $confirm = optional_param('confirm', 0, PARAM_BOOL); - - $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset"; - - if (!$this->can_manage_responsefiles()) { - redirect($returnurl); - } - - $urlreturn = 'submissions.php'; - $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid); - - if (!data_submitted('nomatch') or !$confirm) { - $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'action'=>'response', 'mode'=>$mode, 'offset'=>$offset); - print_header(get_string('delete')); - print_heading(get_string('delete')); - notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get'); - print_footer('none'); - die; - } - - $dir = $this->file_area_name($userid).'/responses'; - $filepath = $CFG->dataroot.'/'.$dir.'/'.$file; - if (file_exists($filepath)) { - if (@unlink($filepath)) { - redirect($returnurl); - } - } - - // print delete error - print_header(get_string('delete')); - notify(get_string('deletefilefailed', 'assignment')); - print_continue($returnurl); - print_footer('none'); - die; - - } - - - function delete_file() { - global $CFG; - - $file = required_param('file', PARAM_FILE); - $userid = required_param('userid', PARAM_INT); - $confirm = optional_param('confirm', 0, PARAM_BOOL); - $mode = optional_param('mode', '', PARAM_ALPHA); - $offset = optional_param('offset', 0, PARAM_INT); - - require_login($this->course->id, false, $this->cm); - - if (empty($mode)) { - $urlreturn = 'view.php'; - $optionsreturn = array('id'=>$this->cm->id); - $returnurl = 'view.php?id='.$this->cm->id; - } else { - $urlreturn = 'submissions.php'; - $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid); - $returnurl = "submissions.php?id={$this->cm->id}&offset=$offset&mode=$mode&userid=$userid"; - } - - if (!$submission = $this->get_submission($userid) // incorrect submission - or !$this->can_delete_files($submission)) { // can not delete - $this->view_header(get_string('delete')); - notify(get_string('cannotdeletefiles', 'assignment')); - print_continue($returnurl); - $this->view_footer(); - die; - } - $dir = $this->file_area_name($userid); - - if (!data_submitted('nomatch') or !$confirm) { - $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'sesskey'=>sesskey(), 'mode'=>$mode, 'offset'=>$offset); - if (empty($mode)) { - $this->view_header(get_string('delete')); - } else { - print_header(get_string('delete')); - } - print_heading(get_string('delete')); - notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get'); - if (empty($mode)) { - $this->view_footer(); - } else { - print_footer('none'); - } - die; - } - - $filepath = $CFG->dataroot.'/'.$dir.'/'.$file; - if (file_exists($filepath)) { - if (@unlink($filepath)) { - $updated = new object(); - $updated->id = $submission->id; - $updated->timemodified = time(); - if (update_record('assignment_submissions', $updated)) { - add_to_log($this->course->id, 'assignment', 'upload', //TODO: add delete action to log - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($userid); - $this->update_grade($submission); - } - redirect($returnurl); - } - } - - // print delete error - if (empty($mode)) { - $this->view_header(get_string('delete')); - } else { - print_header(get_string('delete')); - } - notify(get_string('deletefilefailed', 'assignment')); - print_continue($returnurl); - if (empty($mode)) { - $this->view_footer(); - } else { - print_footer('none'); - } - die; - } - - - function can_upload_file($submission) { - global $USER; - - if (has_capability('mod/assignment:submit', $this->context) // can submit - and $this->isopen() // assignment not closed yet - and (empty($submission) or $submission->userid == $USER->id) // his/her own submission - and $this->count_user_files($USER->id) < $this->assignment->var1 // file limit not reached - and !$this->is_finalized($submission)) { // no uploading after final submission - return true; - } else { - return false; - } - } - - function can_manage_responsefiles() { - if (has_capability('mod/assignment:grade', $this->context)) { - return true; - } else { - return false; - } - } - - function can_delete_files($submission) { - global $USER; - - if (has_capability('mod/assignment:grade', $this->context)) { - return true; - } - - if (has_capability('mod/assignment:submit', $this->context) - and $this->isopen() // assignment not closed yet - and $this->assignment->resubmit // deleting allowed - and $USER->id == $submission->userid // his/her own submission - and !$this->is_finalized($submission)) { // no deleting after final submission - return true; - } else { - return false; - } - } - - function drafts_tracked() { - return !empty($this->assignment->var4); - } - - /** - * Returns submission status - * @param object $submission - may be empty - * @return string submission state - empty, ASSIGNMENT_STATUS_SUBMITTED or ASSIGNMENT_STATUS_CLOSED - */ - function is_finalized($submission) { - if (!$this->drafts_tracked()) { - return ''; - - } else if (empty($submission)) { - return ''; - - } else if ($submission->data2 == ASSIGNMENT_STATUS_SUBMITTED or $submission->data2 == ASSIGNMENT_STATUS_CLOSED) { - return $submission->data2; - - } else { - return ''; - } - } - - function can_unfinalize($submission) { - if (!$this->drafts_tracked()) { - return false; - } - if (has_capability('mod/assignment:grade', $this->context) - and $this->isopen() - and $this->is_finalized($submission)) { - return true; - } else { - return false; - } - } - - function can_finalize($submission) { - global $USER; - if (!$this->drafts_tracked()) { - return false; - } - - if ($this->is_finalized($submission)) { - return false; - } - - if (has_capability('mod/assignment:grade', $this->context)) { - return true; - - } else if (has_capability('mod/assignment:submit', $this->context) // can submit - and $this->isopen() // assignment not closed yet - and !empty($submission) // submission must exist - and $submission->userid == $USER->id // his/her own submission - and ($this->count_user_files($USER->id) - or ($this->notes_allowed() and !empty($submission->data1)))) { // something must be submitted - - return true; - } else { - return false; - } - } - - function can_update_notes($submission) { - global $USER; - - if (has_capability('mod/assignment:submit', $this->context) - and $this->notes_allowed() // notesd must be allowed - and $this->isopen() // assignment not closed yet - and (empty($submission) or $USER->id == $submission->userid) // his/her own submission - and !$this->is_finalized($submission)) { // no updateingafter final submission - return true; - } else { - return false; - } - } - - function notes_allowed() { - return (boolean)$this->assignment->var2; - } - - /** - * Count the files uploaded by a given user - * - * @param $userid int The user id - * @return int - */ - function count_user_files($userid) { - global $CFG; - - $filearea = $this->file_area_name($userid); - - if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { - if ($files = get_directory_list($basedir, 'responses')) { - return count($files); - } - } - return 0; - } - - function count_responsefiles($userid) { - global $CFG; - - $filearea = $this->file_area_name($userid).'/responses'; - - if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { - $basedir .= '/responses'; - if ($files = get_directory_list($basedir)) { - return count($files); - } - } - return 0; - } - - function setup_elements(&$mform) { - global $CFG, $COURSE; - - $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); - - $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); - $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')'; - $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices); - $mform->setDefault('maxbytes', $CFG->assignment_maxbytes); - - $mform->addElement('select', 'resubmit', get_string("allowdeleting", "assignment"), $ynoptions); - $mform->setHelpButton('resubmit', array('allowdeleting', get_string('allowdeleting', 'assignment'), 'assignment')); - $mform->setDefault('resubmit', 1); - - $options = array(); - for($i = 1; $i <= 20; $i++) { - $options[$i] = $i; - } - $mform->addElement('select', 'var1', get_string("allowmaxfiles", "assignment"), $options); - $mform->setHelpButton('var1', array('allowmaxfiles', get_string('allowmaxfiles', 'assignment'), 'assignment')); - $mform->setDefault('var1', 3); - - $mform->addElement('select', 'var2', get_string("allownotes", "assignment"), $ynoptions); - $mform->setHelpButton('var2', array('allownotes', get_string('allownotes', 'assignment'), 'assignment')); - $mform->setDefault('var2', 0); - - $mform->addElement('select', 'var3', get_string("hideintro", "assignment"), $ynoptions); - $mform->setHelpButton('var3', array('hideintro', get_string('hideintro', 'assignment'), 'assignment')); - $mform->setDefault('var3', 0); - - $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions); - $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment')); - $mform->setDefault('emailteachers', 0); - - $mform->addElement('select', 'var4', get_string("trackdrafts", "assignment"), $ynoptions); - $mform->setHelpButton('var4', array('trackdrafts', get_string('trackdrafts', 'assignment'), 'assignment')); - $mform->setDefault('var4', 1); - - } - -} - -class mod_assignment_upload_notes_form extends moodleform { - function definition() { - $mform =& $this->_form; - - // visible elements - $mform->addElement('htmleditor', 'text', get_string('notes', 'assignment'), array('cols'=>85, 'rows'=>30)); - $mform->setType('text', PARAM_RAW); // to be cleaned before display - $mform->setHelpButton('text', array('reading', 'writing'), false, 'editorhelpbutton'); - - // hidden params - $mform->addElement('hidden', 'id', 0); - $mform->setType('id', PARAM_INT); - $mform->addElement('hidden', 'action', 'savenotes'); - $mform->setType('id', PARAM_ALPHA); - - // buttons - $this->add_action_buttons(); - } -} - -?> +libdir.'/formslib.php'); + +define('ASSIGNMENT_STATUS_SUBMITTED', 'submitted'); // student thinks it is finished +define('ASSIGNMENT_STATUS_CLOSED', 'closed'); // teacher prevents more submissions + +/** + * Extend the base assignment class for assignments where you upload a single file + * + */ +class assignment_upload extends assignment_base { + + function assignment_upload($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) { + parent::assignment_base($cmid, $assignment, $cm, $course); + $this->type = 'upload'; + } + + function view() { + global $USER; + + require_capability('mod/assignment:view', $this->context); + + add_to_log($this->course->id, 'assignment', 'view', "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id); + + $this->view_header(); + + if ($this->assignment->timeavailable > time() + and !has_capability('mod/assignment:grade', $this->context) // grading user can see it anytime + and $this->assignment->var3) { // force hiding before available date + print_simple_box_start('center', '', '', 0, 'generalbox', 'intro'); + print_string('notavailableyet', 'assignment'); + print_simple_box_end(); + } else { + $this->view_intro(); + } + + $this->view_dates(); + + if (has_capability('mod/assignment:submit', $this->context)) { + $filecount = $this->count_user_files($USER->id); + $submission = $this->get_submission($USER->id); + + $this->view_feedback(); + + if (!$this->drafts_tracked() or !$this->isopen() or $this->is_finalized($submission)) { + print_heading(get_string('submission', 'assignment'), '', 3); + } else { + print_heading(get_string('submissiondraft', 'assignment'), '', 3); + } + + if ($filecount and $submission) { + print_simple_box($this->print_user_files($USER->id, true), 'center'); + } else { + if (!$this->isopen() or $this->is_finalized($submission)) { + print_simple_box(get_string('nofiles', 'assignment'), 'center'); + } else { + print_simple_box(get_string('nofilesyet', 'assignment'), 'center'); + } + } + + $this->view_upload_form(); + + if ($this->notes_allowed()) { + print_heading(get_string('notes', 'assignment'), '', 3); + $this->view_notes(); + } + + $this->view_final_submission(); + } + $this->view_footer(); + } + + + function view_feedback($submission=NULL) { + global $USER, $CFG; + require_once($CFG->libdir.'/gradelib.php'); + + if (!$submission) { /// Get submission for this assignment + $submission = $this->get_submission($USER->id); + } + + if (empty($submission->timemarked)) { /// Nothing to show, so print nothing + if ($this->count_responsefiles($USER->id)) { + print_heading(get_string('responsefiles', 'assignment', $this->course->teacher), '', 3); + $responsefiles = $this->print_responsefiles($USER->id, true); + print_simple_box($responsefiles, 'center'); + } + return; + } + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id); + $item = $grading_info->items[0]; + $grade = $item->grades[$USER->id]; + + if ($grade->hidden or $grade->grade === false) { // hidden or error + return; + } + + if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet + return; + } + + $graded_date = $grade->dategraded; + $graded_by = $grade->usermodified; + + /// We need the teacher info + if (!$teacher = get_record('user', 'id', $graded_by)) { + error('Could not find the teacher'); + } + + /// Print the feedback + print_heading(get_string('submissionfeedback', 'assignment'), '', 3); + + echo ''; + + echo ''; + echo ''; + echo ''; + echo ''; + + echo ''; + echo ''; + echo ''; + + echo ''; + echo ''; + echo ''; + + echo '
    '; + print_user_picture($teacher, $this->course->id, $teacher->picture); + echo ''; + echo '
    '; + echo '
    '.fullname($teacher).'
    '; + echo '
    '.userdate($graded_date).'
    '; + echo '
    '; + echo '
     '; + if ($this->assignment->grade) { + echo '
    '; + echo get_string("grade").': '.$grade->str_long_grade; + echo '
    '; + echo '
    '; + } + + echo '
    '; + echo $grade->str_feedback; + echo '
    '; + echo '
     '; + echo $this->print_responsefiles($USER->id, true); + echo '
    '; + } + + + function view_upload_form() { + global $CFG, $USER; + + $submission = $this->get_submission($USER->id); + + $struploadafile = get_string('uploadafile'); + $maxbytes = $this->assignment->maxbytes == 0 ? $this->course->maxbytes : $this->assignment->maxbytes; + $strmaxsize = get_string('maxsize', '', display_size($maxbytes)); + + if ($this->is_finalized($submission)) { + // no uploading + return; + } + + if ($this->can_upload_file($submission)) { + echo '
    '; + echo '
    '; + echo '
    '; + echo "

    $struploadafile ($strmaxsize)

    "; + echo ''; + echo ''; + require_once($CFG->libdir.'/uploadlib.php'); + upload_print_form_fragment(1,array('newfile'),null,false,null,0,$this->assignment->maxbytes,false); + echo ''; + echo '
    '; + echo '
    '; + echo '
    '; + echo '
    '; + } + + } + + function view_notes() { + global $USER; + + if ($submission = $this->get_submission($USER->id) + and !empty($submission->data1)) { + print_simple_box(format_text($submission->data1, FORMAT_HTML), 'center', '630px'); + } else { + print_simple_box(get_string('notesempty', 'assignment'), 'center'); + } + if ($this->can_update_notes($submission)) { + $options = array ('id'=>$this->cm->id, 'action'=>'editnotes'); + echo '
    '; + print_single_button('upload.php', $options, get_string('edit'), 'post', '_self', false); + echo '
    '; + } + } + + function view_final_submission() { + global $CFG, $USER; + + $submission = $this->get_submission($USER->id); + + if ($this->isopen() and $this->can_finalize($submission)) { + //print final submit button + print_heading(get_string('submitformarking','assignment'), '', 3); + echo '
    '; + echo '
    '; + echo '
    '; + echo ''; + echo ''; + echo ''; + echo '
    '; + echo '
    '; + echo '
    '; + } else if (!$this->isopen()) { + print_heading(get_string('nomoresubmissions','assignment'), '', 3); + + } else if ($this->drafts_tracked() and $state = $this->is_finalized($submission)) { + if ($state == ASSIGNMENT_STATUS_SUBMITTED) { + print_heading(get_string('submitedformarking','assignment'), '', 3); + } else { + print_heading(get_string('nomoresubmissions','assignment'), '', 3); + } + } else { + //no submission yet + } + } + + + /** + * Return true if var3 == hide description till available day + * + *@return boolean + */ + function description_is_hidden() { + return ($this->assignment->var3 && (time() <= $this->assignment->timeavailable)); + } + + function custom_feedbackform($submission, $return=false) { + global $CFG; + + $mode = optional_param('mode', '', PARAM_ALPHA); + $offset = optional_param('offset', 0, PARAM_INT); + $forcerefresh = optional_param('forcerefresh', 0, PARAM_BOOL); + + $output = get_string('responsefiles', 'assignment').': '; + + $output .= '
    wwwroot/mod/assignment/upload.php\">"; + $output .= '
    '; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + require_once($CFG->libdir.'/uploadlib.php'); + $output .= upload_print_form_fragment(1,array('newfile'),null,false,null,0,0,true); + $output .= ''; + $output .= '
    '; + $output .= '
    '; + + if ($forcerefresh) { + $output .= $this->update_main_listing($submission); + } + + $responsefiles = $this->print_responsefiles($submission->userid, true); + if (!empty($responsefiles)) { + $output .= $responsefiles; + } + + if ($return) { + return $output; + } + echo $output; + return; + } + + + function print_student_answer($userid, $return=false){ + global $CFG; + + $filearea = $this->file_area_name($userid); + $submission = $this->get_submission($userid); + + $output = ''; + + if ($basedir = $this->file_area($userid)) { + if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission)) { + $output .= ''.get_string('draft', 'assignment').': '; + } + + if ($this->notes_allowed() and !empty($submission->data1)) { + $output .= link_to_popup_window ('/mod/assignment/type/upload/notes.php?id='.$this->cm->id.'&userid='.$userid, + 'notes'.$userid, get_string('notes', 'assignment'), 500, 780, get_string('notes', 'assignment'), 'none', true, 'notesbutton'.$userid); + $output .= ' '; + } + + if ($files = get_directory_list($basedir, 'responses')) { + require_once($CFG->libdir.'/filelib.php'); + foreach ($files as $key => $file) { + $icon = mimeinfo('icon', $file); + $ffurl = get_file_url("$filearea/$file"); + $output .= ''.$icon.''.$file.' '; + } + } + } + $output = '
    '.$output.'
    '; + $output .= '
    '; + + return $output; + } + + + /** + * Produces a list of links to the files uploaded by a user + * + * @param $userid int optional id of the user. If 0 then $USER->id is used. + * @param $return boolean optional defaults to false. If true the list is returned rather than printed + * @return string optional + */ + function print_user_files($userid=0, $return=false) { + global $CFG, $USER; + + $mode = optional_param('mode', '', PARAM_ALPHA); + $offset = optional_param('offset', 0, PARAM_INT); + + if (!$userid) { + if (!isloggedin()) { + return ''; + } + $userid = $USER->id; + } + + $filearea = $this->file_area_name($userid); + + $output = ''; + + $submission = $this->get_submission($userid); + + $candelete = $this->can_delete_files($submission); + $strdelete = get_string('delete'); + + if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission) and !empty($mode)) { // only during grading + $output .= ''.get_string('draft', 'assignment').':
    '; + } + + if ($this->notes_allowed() and !empty($submission->data1) and !empty($mode)) { // only during grading + + $npurl = $CFG->wwwroot."/mod/assignment/type/upload/notes.php?id={$this->cm->id}&userid=$userid&offset=$offset&mode=single"; + $output .= ''.get_string('notes', 'assignment').'
    '; + + } + + if ($basedir = $this->file_area($userid)) { + if ($files = get_directory_list($basedir, 'responses')) { + require_once($CFG->libdir.'/filelib.php'); + foreach ($files as $key => $file) { + + $icon = mimeinfo('icon', $file); + $ffurl = get_file_url("$filearea/$file"); + + $output .= ''.$icon.''.$file.''; + + if ($candelete) { + $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&file=$file&userid={$submission->userid}&mode=$mode&offset=$offset"; + + $output .= ' ' + .' '; + } + + $output .= '
    '; + } + } + } + + if ($this->drafts_tracked() and $this->isopen() and has_capability('mod/assignment:grade', $this->context) and $mode != '') { // we do not want it on view.php page + if ($this->can_unfinalize($submission)) { + $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'unfinalize', 'mode'=>$mode, 'offset'=>$offset); + $output .= print_single_button('upload.php', $options, get_string('unfinalize', 'assignment'), 'post', '_self', true); + } else if ($this->can_finalize($submission)) { + $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'finalizeclose', 'mode'=>$mode, 'offset'=>$offset); + $output .= print_single_button('upload.php', $options, get_string('finalize', 'assignment'), 'post', '_self', true); + } + } + + $output = '
    '.$output.'
    '; + + if ($return) { + return $output; + } + echo $output; + } + + function print_responsefiles($userid, $return=false) { + global $CFG, $USER; + + $mode = optional_param('mode', '', PARAM_ALPHA); + $offset = optional_param('offset', 0, PARAM_INT); + + $filearea = $this->file_area_name($userid).'/responses'; + + $output = ''; + + $candelete = $this->can_manage_responsefiles(); + $strdelete = get_string('delete'); + + if ($basedir = $this->file_area($userid)) { + $basedir .= '/responses'; + + if ($files = get_directory_list($basedir)) { + require_once($CFG->libdir.'/filelib.php'); + foreach ($files as $key => $file) { + + $icon = mimeinfo('icon', $file); + + $ffurl = get_file_url("$filearea/$file"); + + $output .= ''.$icon.''.$file.''; + + if ($candelete) { + $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&file=$file&userid=$userid&mode=$mode&offset=$offset&action=response"; + + $output .= ' ' + .' '; + } + + $output .= ' '; + } + } + + + $output = '
    '.$output.'
    '; + + } + + if ($return) { + return $output; + } + echo $output; + } + + + function upload() { + $action = required_param('action', PARAM_ALPHA); + + switch ($action) { + case 'finalize': + $this->finalize(); + break; + case 'finalizeclose': + $this->finalizeclose(); + break; + case 'unfinalize': + $this->unfinalize(); + break; + case 'uploadresponse': + $this->upload_responsefile(); + break; + case 'uploadfile': + $this->upload_file(); + case 'savenotes': + case 'editnotes': + $this->upload_notes(); + default: + error('Error: Unknow upload action ('.$action.').'); + } + } + + function upload_notes() { + global $CFG, $USER; + + $action = required_param('action', PARAM_ALPHA); + + $returnurl = 'view.php?id='.$this->cm->id; + + $mform = new mod_assignment_upload_notes_form(); + + $defaults = new object(); + $defaults->id = $this->cm->id; + + if ($submission = $this->get_submission($USER->id)) { + $defaults->text = $submission->data1; + } else { + $defaults->text = ''; + } + + $mform->set_data($defaults); + + if ($mform->is_cancelled()) { + redirect('view.php?id='.$this->cm->id); + } + + if (!$this->can_update_notes($submission)) { + $this->view_header(get_string('upload')); + notify(get_string('uploaderror', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + + if ($data = $mform->get_data() and $action == 'savenotes') { + $submission = $this->get_submission($USER->id, true); // get or create submission + $updated = new object(); + $updated->id = $submission->id; + $updated->timemodified = time(); + $updated->data1 = $data->text; + + if (update_record('assignment_submissions', $updated)) { + add_to_log($this->course->id, 'assignment', 'upload', 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + redirect($returnurl); + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + + } else { + $this->view_header(get_string('notes', 'assignment')); + notify(get_string('notesupdateerror', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + } + + /// show notes edit form + $this->view_header(get_string('notes', 'assignment')); + + print_heading(get_string('notes', 'assignment'), ''); + + $mform->display(); + + $this->view_footer(); + die; + } + + function upload_responsefile() { + global $CFG; + + $userid = required_param('userid', PARAM_INT); + $mode = required_param('mode', PARAM_ALPHA); + $offset = required_param('offset', PARAM_INT); + + $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset"; + + if (data_submitted('nomatch') and $this->can_manage_responsefiles()) { + $dir = $this->file_area_name($userid).'/responses'; + check_dir_exists($CFG->dataroot.'/'.$dir, true, true); + + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newfile',false,true,$this->course,false,0,true); + + if (!$um->process_file_uploads($dir)) { + print_header(get_string('upload')); + notify(get_string('uploaderror', 'assignment')); + echo $um->get_errors(); + print_continue($returnurl); + print_footer('none'); + die; + } + } + redirect($returnurl); + } + + function upload_file() { + global $CFG, $USER; + + $mode = optional_param('mode', '', PARAM_ALPHA); + $offset = optional_param('offset', 0, PARAM_INT); + + $returnurl = 'view.php?id='.$this->cm->id; + + $filecount = $this->count_user_files($USER->id); + $submission = $this->get_submission($USER->id); + + if (!$this->can_upload_file($submission)) { + $this->view_header(get_string('upload')); + notify(get_string('uploaderror', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + + $dir = $this->file_area_name($USER->id); + check_dir_exists($CFG->dataroot.'/'.$dir, true, true); // better to create now so that student submissions do not block it later + + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newfile',false,true,$this->course,false,$this->assignment->maxbytes,true); + + if ($um->process_file_uploads($dir)) { + $submission = $this->get_submission($USER->id, true); //create new submission if needed + $updated = new object(); + $updated->id = $submission->id; + $updated->timemodified = time(); + + if (update_record('assignment_submissions', $updated)) { + add_to_log($this->course->id, 'assignment', 'upload', + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + if (!$this->drafts_tracked()) { + $this->email_teachers($submission); + } + } else { + $new_filename = $um->get_new_filename(); + $this->view_header(get_string('upload')); + notify(get_string('uploadnotregistered', 'assignment', $new_filename)); + print_continue($returnurl); + $this->view_footer(); + die; + } + redirect('view.php?id='.$this->cm->id); + } + $this->view_header(get_string('upload')); + notify(get_string('uploaderror', 'assignment')); + echo $um->get_errors(); + print_continue($returnurl); + $this->view_footer(); + die; + } + + function finalize() { + global $USER; + + $confirm = optional_param('confirm', 0, PARAM_BOOL); + $returnurl = 'view.php?id='.$this->cm->id; + $submission = $this->get_submission($USER->id); + + if (!$this->can_finalize($submission)) { + redirect($returnurl); // probably already graded, redirect to assignment page, the reason should be obvious + } + + if (!data_submitted() or !$confirm) { + $optionsno = array('id'=>$this->cm->id); + $optionsyes = array ('id'=>$this->cm->id, 'confirm'=>1, 'action'=>'finalize'); + $this->view_header(get_string('submitformarking', 'assignment')); + print_heading(get_string('submitformarking', 'assignment')); + notice_yesno(get_string('onceassignmentsent', 'assignment'), 'upload.php', 'view.php', $optionsyes, $optionsno, 'post', 'get'); + $this->view_footer(); + die; + + } + $updated = new object(); + $updated->id = $submission->id; + $updated->data2 = ASSIGNMENT_STATUS_SUBMITTED; + $updated->timemodified = time(); + + if (update_record('assignment_submissions', $updated)) { + add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + $this->email_teachers($submission); + } else { + $this->view_header(get_string('submitformarking', 'assignment')); + notify(get_string('finalizeerror', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + redirect($returnurl); + } + + function finalizeclose() { + $userid = optional_param('userid', 0, PARAM_INT); + $mode = required_param('mode', PARAM_ALPHA); + $offset = required_param('offset', PARAM_INT); + $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset&forcerefresh=1"; + + // create but do not add student submission date + $submission = $this->get_submission($userid, true, true); + + if (!data_submitted() or !$this->can_finalize($submission)) { + redirect($returnurl); // probably closed already + } + + $updated = new object(); + $updated->id = $submission->id; + $updated->data2 = ASSIGNMENT_STATUS_CLOSED; + + if (update_record('assignment_submissions', $updated)) { + add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($userid, false, true); + $this->update_grade($submission); + } + redirect($returnurl); + } + + function unfinalize() { + + $userid = required_param('userid', PARAM_INT); + $mode = required_param('mode', PARAM_ALPHA); + $offset = required_param('offset', PARAM_INT); + + $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset&forcerefresh=1"; + + if (data_submitted('nomatch') + and $submission = $this->get_submission($userid) + and $this->can_unfinalize($submission)) { + + $updated = new object(); + $updated->id = $submission->id; + $updated->data2 = ''; + if (update_record('assignment_submissions', $updated)) { + //TODO: add unfinalize action to log + add_to_log($this->course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($userid); + $this->update_grade($submission); + } else { + $this->view_header(get_string('submitformarking', 'assignment')); + notify(get_string('unfinalizeerror', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + } + redirect($returnurl); + } + + + function delete() { + $action = optional_param('action', '', PARAM_ALPHA); + + switch ($action) { + case 'response': + $this->delete_responsefile(); + break; + default: + $this->delete_file(); + } + die; + } + + + function delete_responsefile() { + global $CFG; + + $file = required_param('file', PARAM_FILE); + $userid = required_param('userid', PARAM_INT); + $mode = required_param('mode', PARAM_ALPHA); + $offset = required_param('offset', PARAM_INT); + $confirm = optional_param('confirm', 0, PARAM_BOOL); + + $returnurl = "submissions.php?id={$this->cm->id}&userid=$userid&mode=$mode&offset=$offset"; + + if (!$this->can_manage_responsefiles()) { + redirect($returnurl); + } + + $urlreturn = 'submissions.php'; + $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid); + + if (!data_submitted('nomatch') or !$confirm) { + $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'action'=>'response', 'mode'=>$mode, 'offset'=>$offset); + print_header(get_string('delete')); + print_heading(get_string('delete')); + notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get'); + print_footer('none'); + die; + } + + $dir = $this->file_area_name($userid).'/responses'; + $filepath = $CFG->dataroot.'/'.$dir.'/'.$file; + if (file_exists($filepath)) { + if (@unlink($filepath)) { + redirect($returnurl); + } + } + + // print delete error + print_header(get_string('delete')); + notify(get_string('deletefilefailed', 'assignment')); + print_continue($returnurl); + print_footer('none'); + die; + + } + + + function delete_file() { + global $CFG; + + $file = required_param('file', PARAM_FILE); + $userid = required_param('userid', PARAM_INT); + $confirm = optional_param('confirm', 0, PARAM_BOOL); + $mode = optional_param('mode', '', PARAM_ALPHA); + $offset = optional_param('offset', 0, PARAM_INT); + + require_login($this->course->id, false, $this->cm); + + if (empty($mode)) { + $urlreturn = 'view.php'; + $optionsreturn = array('id'=>$this->cm->id); + $returnurl = 'view.php?id='.$this->cm->id; + } else { + $urlreturn = 'submissions.php'; + $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid); + $returnurl = "submissions.php?id={$this->cm->id}&offset=$offset&mode=$mode&userid=$userid"; + } + + if (!$submission = $this->get_submission($userid) // incorrect submission + or !$this->can_delete_files($submission)) { // can not delete + $this->view_header(get_string('delete')); + notify(get_string('cannotdeletefiles', 'assignment')); + print_continue($returnurl); + $this->view_footer(); + die; + } + $dir = $this->file_area_name($userid); + + if (!data_submitted('nomatch') or !$confirm) { + $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'sesskey'=>sesskey(), 'mode'=>$mode, 'offset'=>$offset); + if (empty($mode)) { + $this->view_header(get_string('delete')); + } else { + print_header(get_string('delete')); + } + print_heading(get_string('delete')); + notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get'); + if (empty($mode)) { + $this->view_footer(); + } else { + print_footer('none'); + } + die; + } + + $filepath = $CFG->dataroot.'/'.$dir.'/'.$file; + if (file_exists($filepath)) { + if (@unlink($filepath)) { + $updated = new object(); + $updated->id = $submission->id; + $updated->timemodified = time(); + if (update_record('assignment_submissions', $updated)) { + add_to_log($this->course->id, 'assignment', 'upload', //TODO: add delete action to log + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($userid); + $this->update_grade($submission); + } + redirect($returnurl); + } + } + + // print delete error + if (empty($mode)) { + $this->view_header(get_string('delete')); + } else { + print_header(get_string('delete')); + } + notify(get_string('deletefilefailed', 'assignment')); + print_continue($returnurl); + if (empty($mode)) { + $this->view_footer(); + } else { + print_footer('none'); + } + die; + } + + + function can_upload_file($submission) { + global $USER; + + if (has_capability('mod/assignment:submit', $this->context) // can submit + and $this->isopen() // assignment not closed yet + and (empty($submission) or $submission->userid == $USER->id) // his/her own submission + and $this->count_user_files($USER->id) < $this->assignment->var1 // file limit not reached + and !$this->is_finalized($submission)) { // no uploading after final submission + return true; + } else { + return false; + } + } + + function can_manage_responsefiles() { + if (has_capability('mod/assignment:grade', $this->context)) { + return true; + } else { + return false; + } + } + + function can_delete_files($submission) { + global $USER; + + if (has_capability('mod/assignment:grade', $this->context)) { + return true; + } + + if (has_capability('mod/assignment:submit', $this->context) + and $this->isopen() // assignment not closed yet + and $this->assignment->resubmit // deleting allowed + and $USER->id == $submission->userid // his/her own submission + and !$this->is_finalized($submission)) { // no deleting after final submission + return true; + } else { + return false; + } + } + + function drafts_tracked() { + return !empty($this->assignment->var4); + } + + /** + * Returns submission status + * @param object $submission - may be empty + * @return string submission state - empty, ASSIGNMENT_STATUS_SUBMITTED or ASSIGNMENT_STATUS_CLOSED + */ + function is_finalized($submission) { + if (!$this->drafts_tracked()) { + return ''; + + } else if (empty($submission)) { + return ''; + + } else if ($submission->data2 == ASSIGNMENT_STATUS_SUBMITTED or $submission->data2 == ASSIGNMENT_STATUS_CLOSED) { + return $submission->data2; + + } else { + return ''; + } + } + + function can_unfinalize($submission) { + if (!$this->drafts_tracked()) { + return false; + } + if (has_capability('mod/assignment:grade', $this->context) + and $this->isopen() + and $this->is_finalized($submission)) { + return true; + } else { + return false; + } + } + + function can_finalize($submission) { + global $USER; + if (!$this->drafts_tracked()) { + return false; + } + + if ($this->is_finalized($submission)) { + return false; + } + + if (has_capability('mod/assignment:grade', $this->context)) { + return true; + + } else if (has_capability('mod/assignment:submit', $this->context) // can submit + and $this->isopen() // assignment not closed yet + and !empty($submission) // submission must exist + and $submission->userid == $USER->id // his/her own submission + and ($this->count_user_files($USER->id) + or ($this->notes_allowed() and !empty($submission->data1)))) { // something must be submitted + + return true; + } else { + return false; + } + } + + function can_update_notes($submission) { + global $USER; + + if (has_capability('mod/assignment:submit', $this->context) + and $this->notes_allowed() // notesd must be allowed + and $this->isopen() // assignment not closed yet + and (empty($submission) or $USER->id == $submission->userid) // his/her own submission + and !$this->is_finalized($submission)) { // no updateingafter final submission + return true; + } else { + return false; + } + } + + function notes_allowed() { + return (boolean)$this->assignment->var2; + } + + /** + * Count the files uploaded by a given user + * + * @param $userid int The user id + * @return int + */ + function count_user_files($userid) { + global $CFG; + + $filearea = $this->file_area_name($userid); + + if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { + if ($files = get_directory_list($basedir, 'responses')) { + return count($files); + } + } + return 0; + } + + function count_responsefiles($userid) { + global $CFG; + + $filearea = $this->file_area_name($userid).'/responses'; + + if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) { + $basedir .= '/responses'; + if ($files = get_directory_list($basedir)) { + return count($files); + } + } + return 0; + } + + function setup_elements(&$mform) { + global $CFG, $COURSE; + + $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); + + $mform->addElement('text', 'templatetext', get_string('assignmenttemplatetext', 'assignment'), array('size'=>'64')); + $mform->setHelpButton('templatetext', array('template', get_string('assignmenttemplatetext', 'assignment'), 'assignment')); + $mform->addElement('choosecoursefile', 'templatefile', get_string('assignmenttemplatefile', 'assignment')); + $mform->setHelpButton('templatefile', array('template', get_string('assignmenttemplatefile', 'assignment'), 'assignment')); + + $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); + $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')'; + $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices); + $mform->setDefault('maxbytes', $CFG->assignment_maxbytes); + + $mform->addElement('select', 'resubmit', get_string("allowdeleting", "assignment"), $ynoptions); + $mform->setHelpButton('resubmit', array('allowdeleting', get_string('allowdeleting', 'assignment'), 'assignment')); + $mform->setDefault('resubmit', 1); + + $options = array(); + for($i = 1; $i <= 20; $i++) { + $options[$i] = $i; + } + $mform->addElement('select', 'var1', get_string("allowmaxfiles", "assignment"), $options); + $mform->setHelpButton('var1', array('allowmaxfiles', get_string('allowmaxfiles', 'assignment'), 'assignment')); + $mform->setDefault('var1', 3); + + $mform->addElement('select', 'var2', get_string("allownotes", "assignment"), $ynoptions); + $mform->setHelpButton('var2', array('allownotes', get_string('allownotes', 'assignment'), 'assignment')); + $mform->setDefault('var2', 0); + + $mform->addElement('select', 'var3', get_string("hideintro", "assignment"), $ynoptions); + $mform->setHelpButton('var3', array('hideintro', get_string('hideintro', 'assignment'), 'assignment')); + $mform->setDefault('var3', 0); + + $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions); + $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment')); + $mform->setDefault('emailteachers', 0); + + $mform->addElement('select', 'var4', get_string("trackdrafts", "assignment"), $ynoptions); + $mform->setHelpButton('var4', array('trackdrafts', get_string('trackdrafts', 'assignment'), 'assignment')); + $mform->setDefault('var4', 1); + + } + +} + +class mod_assignment_upload_notes_form extends moodleform { + function definition() { + $mform =& $this->_form; + + // visible elements + $mform->addElement('htmleditor', 'text', get_string('notes', 'assignment'), array('cols'=>85, 'rows'=>30)); + $mform->setType('text', PARAM_RAW); // to be cleaned before display + $mform->setHelpButton('text', array('reading', 'writing'), false, 'editorhelpbutton'); + + // hidden params + $mform->addElement('hidden', 'id', 0); + $mform->setType('id', PARAM_INT); + $mform->addElement('hidden', 'action', 'savenotes'); + $mform->setType('id', PARAM_ALPHA); + + // buttons + $this->add_action_buttons(); + } +} + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/type/uploadsingle/assignment.class.php moodle_assignment_work_1.9.4_Modified/mod/assignment/type/uploadsingle/assignment.class.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/type/uploadsingle/assignment.class.php 2008-04-09 08:16:44.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/type/uploadsingle/assignment.class.php 2009-04-24 09:44:14.000000000 +0100 @@ -1,185 +1,190 @@ -file_area_name($userid); - - $output = ''; - - if ($basedir = $this->file_area($userid)) { - if ($files = get_directory_list($basedir)) { - require_once($CFG->libdir.'/filelib.php'); - foreach ($files as $key => $file) { - - $icon = mimeinfo('icon', $file); - $ffurl = get_file_url("$filearea/$file"); - - //died right here - //require_once($ffurl); - $output = ''.$icon.''. - ''.$file.'
    '; - } - } - } - - $output = '
    '.$output.'
    '; - return $output; - } - - function assignment_uploadsingle($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) { - parent::assignment_base($cmid, $assignment, $cm, $course); - $this->type = 'uploadsingle'; - } - - function view() { - - global $USER; - - $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); - require_capability('mod/assignment:view', $context); - - add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id); - - $this->view_header(); - - $this->view_intro(); - - $this->view_dates(); - - $filecount = $this->count_user_files($USER->id); - - if ($submission = $this->get_submission()) { - if ($submission->timemarked) { - $this->view_feedback(); - } - if ($filecount) { - print_simple_box($this->print_user_files($USER->id, true), 'center'); - } - } - - if (has_capability('mod/assignment:submit', $context) && $this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) { - $this->view_upload_form(); - } - - $this->view_footer(); - } - - - function view_upload_form() { - global $CFG; - $struploadafile = get_string("uploadafile"); - - $maxbytes = $this->assignment->maxbytes == 0 ? $this->course->maxbytes : $this->assignment->maxbytes; - $strmaxsize = get_string('maxsize', '', display_size($maxbytes)); - - echo '
    '; - echo '
    wwwroot/mod/assignment/upload.php\">"; - echo '
    '; - echo "

    $struploadafile ($strmaxsize)

    "; - echo ''; - require_once($CFG->libdir.'/uploadlib.php'); - upload_print_form_fragment(1,array('newfile'),false,null,0,$this->assignment->maxbytes,false); - echo ''; - echo '
    '; - echo '
    '; - echo '
    '; - } - - - function upload() { - - global $CFG, $USER; - - require_capability('mod/assignment:submit', get_context_instance(CONTEXT_MODULE, $this->cm->id)); - - $this->view_header(get_string('upload')); - - $filecount = $this->count_user_files($USER->id); - $submission = $this->get_submission($USER->id); - if ($this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) { - if ($submission = $this->get_submission($USER->id)) { - //TODO: change later to ">= 0", to prevent resubmission when graded 0 - if (($submission->grade > 0) and !$this->assignment->resubmit) { - notify(get_string('alreadygraded', 'assignment')); - } - } - - $dir = $this->file_area_name($USER->id); - - require_once($CFG->dirroot.'/lib/uploadlib.php'); - $um = new upload_manager('newfile',true,false,$this->course,false,$this->assignment->maxbytes); - if ($um->process_file_uploads($dir)) { - $newfile_name = $um->get_new_filename(); - if ($submission) { - $submission->timemodified = time(); - $submission->numfiles = 1; - $submission->submissioncomment = addslashes($submission->submissioncomment); - unset($submission->data1); // Don't need to update this. - unset($submission->data2); // Don't need to update this. - if (update_record("assignment_submissions", $submission)) { - add_to_log($this->course->id, 'assignment', 'upload', - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($USER->id); - $this->update_grade($submission); - $this->email_teachers($submission); - print_heading(get_string('uploadedfile')); - } else { - notify(get_string("uploadfailnoupdate", "assignment")); - } - } else { - $newsubmission = $this->prepare_new_submission($USER->id); - $newsubmission->timemodified = time(); - $newsubmission->numfiles = 1; - if (insert_record('assignment_submissions', $newsubmission)) { - add_to_log($this->course->id, 'assignment', 'upload', - 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); - $submission = $this->get_submission($USER->id); - $this->update_grade($submission); - $this->email_teachers($newsubmission); - print_heading(get_string('uploadedfile')); - } else { - notify(get_string("uploadnotregistered", "assignment", $newfile_name) ); - } - } - } - } else { - notify(get_string("uploaderror", "assignment")); //submitting not allowed! - } - - print_continue('view.php?id='.$this->cm->id); - - $this->view_footer(); - } - - function setup_elements(&$mform) { - global $CFG, $COURSE; - - $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); - - $mform->addElement('select', 'resubmit', get_string("allowresubmit", "assignment"), $ynoptions); - $mform->setHelpButton('resubmit', array('resubmit', get_string('allowresubmit', 'assignment'), 'assignment')); - $mform->setDefault('resubmit', 0); - - $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions); - $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment')); - $mform->setDefault('emailteachers', 0); - - $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); - $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')'; - $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices); - $mform->setDefault('maxbytes', $CFG->assignment_maxbytes); - - } - -} - -?> +file_area_name($userid); + + $output = ''; + + if ($basedir = $this->file_area($userid)) { + if ($files = get_directory_list($basedir)) { + require_once($CFG->libdir.'/filelib.php'); + foreach ($files as $key => $file) { + + $icon = mimeinfo('icon', $file); + $ffurl = get_file_url("$filearea/$file"); + + //died right here + //require_once($ffurl); + $output = ''.$icon.''. + ''.$file.'
    '; + } + } + } + + $output = '
    '.$output.'
    '; + return $output; + } + + function assignment_uploadsingle($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) { + parent::assignment_base($cmid, $assignment, $cm, $course); + $this->type = 'uploadsingle'; + } + + function view() { + + global $USER; + + $context = get_context_instance(CONTEXT_MODULE,$this->cm->id); + require_capability('mod/assignment:view', $context); + + add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id); + + $this->view_header(); + + $this->view_intro(); + + $this->view_dates(); + + $filecount = $this->count_user_files($USER->id); + + if ($submission = $this->get_submission()) { + if ($submission->timemarked) { + $this->view_feedback(); + } + if ($filecount) { + print_simple_box($this->print_user_files($USER->id, true), 'center'); + } + } + + if (has_capability('mod/assignment:submit', $context) && $this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) { + $this->view_upload_form(); + } + + $this->view_footer(); + } + + + function view_upload_form() { + global $CFG; + $struploadafile = get_string("uploadafile"); + + $maxbytes = $this->assignment->maxbytes == 0 ? $this->course->maxbytes : $this->assignment->maxbytes; + $strmaxsize = get_string('maxsize', '', display_size($maxbytes)); + + echo '
    '; + echo '
    wwwroot/mod/assignment/upload.php\">"; + echo '
    '; + echo "

    $struploadafile ($strmaxsize)

    "; + echo ''; + require_once($CFG->libdir.'/uploadlib.php'); + upload_print_form_fragment(1,array('newfile'),false,null,0,$this->assignment->maxbytes,false); + echo ''; + echo '
    '; + echo '
    '; + echo '
    '; + } + + + function upload() { + + global $CFG, $USER; + + require_capability('mod/assignment:submit', get_context_instance(CONTEXT_MODULE, $this->cm->id)); + + $this->view_header(get_string('upload')); + + $filecount = $this->count_user_files($USER->id); + $submission = $this->get_submission($USER->id); + if ($this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) { + if ($submission = $this->get_submission($USER->id)) { + //TODO: change later to ">= 0", to prevent resubmission when graded 0 + if (($submission->grade > 0) and !$this->assignment->resubmit) { + notify(get_string('alreadygraded', 'assignment')); + } + } + + $dir = $this->file_area_name($USER->id); + + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newfile',true,false,$this->course,false,$this->assignment->maxbytes); + if ($um->process_file_uploads($dir)) { + $newfile_name = $um->get_new_filename(); + if ($submission) { + $submission->timemodified = time(); + $submission->numfiles = 1; + $submission->submissioncomment = addslashes($submission->submissioncomment); + unset($submission->data1); // Don't need to update this. + unset($submission->data2); // Don't need to update this. + if (update_record("assignment_submissions", $submission)) { + add_to_log($this->course->id, 'assignment', 'upload', + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + $this->email_teachers($submission); + print_heading(get_string('uploadedfile')); + } else { + notify(get_string("uploadfailnoupdate", "assignment")); + } + } else { + $newsubmission = $this->prepare_new_submission($USER->id); + $newsubmission->timemodified = time(); + $newsubmission->numfiles = 1; + if (insert_record('assignment_submissions', $newsubmission)) { + add_to_log($this->course->id, 'assignment', 'upload', + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + $this->email_teachers($newsubmission); + print_heading(get_string('uploadedfile')); + } else { + notify(get_string("uploadnotregistered", "assignment", $newfile_name) ); + } + } + } + } else { + notify(get_string("uploaderror", "assignment")); //submitting not allowed! + } + + print_continue('view.php?id='.$this->cm->id); + + $this->view_footer(); + } + + function setup_elements(&$mform) { + global $CFG, $COURSE; + + $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); + + $mform->addElement('text', 'templatetext', get_string('assignmenttemplatetext', 'assignment'), array('size'=>'64')); + $mform->setHelpButton('templatetext', array('template', get_string('assignmenttemplatetext', 'assignment'), 'assignment')); + $mform->addElement('choosecoursefile', 'templatefile', get_string('assignmenttemplatefile', 'assignment')); + $mform->setHelpButton('templatefile', array('template', get_string('assignmenttemplatefile', 'assignment'), 'assignment')); + + $mform->addElement('select', 'resubmit', get_string("allowresubmit", "assignment"), $ynoptions); + $mform->setHelpButton('resubmit', array('resubmit', get_string('allowresubmit', 'assignment'), 'assignment')); + $mform->setDefault('resubmit', 0); + + $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions); + $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment')); + $mform->setDefault('emailteachers', 0); + + $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); + $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')'; + $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices); + $mform->setDefault('maxbytes', $CFG->assignment_maxbytes); + + } + +} + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/version.php moodle_assignment_work_1.9.4_Modified/mod/assignment/version.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/version.php 2008-03-20 10:14:02.000000000 +0000 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/version.php 2009-04-23 15:37:58.000000000 +0100 @@ -1,12 +1,12 @@ -version = 2007101511; -$module->requires = 2007101509; // Requires this Moodle version -$module->cron = 60; - -?> +version = 2009042301; +$module->requires = 2007101509; // Requires this Moodle version +$module->cron = 60; + +?> diff -Naur moodle_assignment_work_1.9.4_Pure/mod/assignment/view.php moodle_assignment_work_1.9.4_Modified/mod/assignment/view.php --- moodle_assignment_work_1.9.4_Pure/mod/assignment/view.php 2007-08-18 10:06:24.000000000 +0100 +++ moodle_assignment_work_1.9.4_Modified/mod/assignment/view.php 2009-04-23 15:49:42.000000000 +0100 @@ -1,41 +1,42 @@ -instance)) { - error("assignment ID was incorrect"); - } - - if (! $course = get_record("course", "id", $assignment->course)) { - error("Course is misconfigured"); - } - } else { - if (!$assignment = get_record("assignment", "id", $a)) { - error("Course module is incorrect"); - } - if (! $course = get_record("course", "id", $assignment->course)) { - error("Course is misconfigured"); - } - if (! $cm = get_coursemodule_from_instance("assignment", $assignment->id, $course->id)) { - error("Course Module ID was incorrect"); - } - } - - require_login($course, true, $cm); - - require ("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); - $assignmentclass = "assignment_$assignment->assignmenttype"; - $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course); - - $assignmentinstance->view(); // Actually display the assignment! - -?> +instance)) { + error("assignment ID was incorrect"); + } + + if (! $course = get_record("course", "id", $assignment->course)) { + error("Course is misconfigured"); + } + } else { + if (!$assignment = get_record("assignment", "id", $a)) { + error("Course module is incorrect"); + } + if (! $course = get_record("course", "id", $assignment->course)) { + error("Course is misconfigured"); + } + if (! $cm = get_coursemodule_from_instance("assignment", $assignment->id, $course->id)) { + error("Course Module ID was incorrect"); + } + } + + require_login($course, true, $cm); + + require ("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); + $assignmentclass = "assignment_$assignment->assignmenttype"; + $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course); + + $assignmentinstance->view(); // Actually display the assignment! + +?>