From b37ce778c69fe4baa99c9e756615e90f9362a0bb Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Thu, 22 Apr 2010 11:33:17 +0000 Subject: [PATCH] Assignment MDL-7206 - download all submissions as a zip - finally pushing this into head. --- mod/assignment/lang/en/assignment.php | 1 + mod/assignment/lib.php | 44 +++++++++++++++- mod/assignment/submissions.php | 7 ++- .../type/online/assignment.class.php | 45 +++++++++++++++++ .../type/upload/assignment.class.php | 50 +++++++++++++++++++ .../type/uploadsingle/assignment.class.php | 50 +++++++++++++++++++ 6 files changed, 195 insertions(+), 2 deletions(-) diff --git a/mod/assignment/lang/en/assignment.php b/mod/assignment/lang/en/assignment.php index 05f8591b333..2399ba96821 100644 --- a/mod/assignment/lang/en/assignment.php +++ b/mod/assignment/lang/en/assignment.php @@ -64,6 +64,7 @@ $string['coursemisconf'] = 'Course is misconfigured'; $string['deleteallsubmissions'] = 'Delete all submissions'; $string['deletefilefailed'] = 'Deleting of file failed.'; $string['description'] = 'Description'; +$string['downloadall'] = 'Download all assignments as a zip'; $string['draft'] = 'Draft'; $string['duedate'] = 'Due date'; $string['duedateno'] = 'No due date'; diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 8496fd75ead..d5a9fe1c78b 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -1208,7 +1208,9 @@ class assignment_base { echo $OUTPUT->heading(get_string('nosubmitusers','assignment')); return true; } - + if ($this->assignment->assignmenttype=='upload' || $this->assignment->assignmenttype=='online' || $this->assignment->assignmenttype=='uploadsingle') { + echo '
'.get_string('downloadall', 'assignment').'
'; + } /// Construct the SQL if ($where = $table->get_sql_where()) { @@ -3382,3 +3384,43 @@ function assignment_extend_settings_navigation(settings_navigation $settings, na $assignmentinstance->extend_settings_navigation($assignmentnode); } } + +/** + * generate zip file from array of given files + * @param array $filesforzipping - array of files to pass into archive_to_pathname + * @return path of temp file - note this returned file does not have a .zip extension - it is a temp file. + */ +function assignment_pack_files($filesforzipping) { + global $CFG; + //create path for new zip file. + $tempzip = tempnam($CFG->dataroot.'/temp/', 'assignment_'); + //zip files + $zipper = new zip_packer(); + if ($zipper->archive_to_pathname($filesforzipping, $tempzip)) { + return $tempzip; + } + return false; +} +//TODO - this is a copy of the function my_mktempdir in admin/uploadpicture.php - it would be good to have as a core function. +/** + * Create a unique temporary directory with a given prefix name, + * inside a given directory, with given permissions. Return the + * full path to the newly created temp directory. + * + * @param string $dir where to create the temp directory. + * @param string $prefix prefix for the temp directory name (default '') + * @param string $mode permissions for the temp directory (default 700) + * + * @return string The full path to the temp directory. + */ +function assignment_create_temp_dir($dir, $prefix='', $mode=0700) { + if (substr($dir, -1) != '/') { + $dir .= '/'; + } + + do { + $path = $dir.$prefix.mt_rand(0, 9999999); + } while (!mkdir($path, $mode)); + + return $path; +} \ No newline at end of file diff --git a/mod/assignment/submissions.php b/mod/assignment/submissions.php index c202574e74c..ee0168e4f1b 100644 --- a/mod/assignment/submissions.php +++ b/mod/assignment/submissions.php @@ -6,6 +6,7 @@ require_once("lib.php"); $id = optional_param('id', 0, PARAM_INT); // Course module ID $a = optional_param('a', 0, PARAM_INT); // Assignment ID $mode = optional_param('mode', 'all', PARAM_ALPHA); // What mode are we in? +$download = optional_param('download' , 'none', PARAM_ALPHA); //ZIP download asked for? $url = new moodle_url('/mod/assignment/submissions.php'); if ($id) { @@ -49,4 +50,8 @@ require($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assi $assignmentclass = 'assignment_'.$assignment->assignmenttype; $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course); -$assignmentinstance->submissions($mode); // Display or process the submissions \ No newline at end of file +if($download == "zip") { + $assignmentinstance->download_submissions(); +} else { + $assignmentinstance->submissions($mode); // Display or process the submissions +} \ No newline at end of file diff --git a/mod/assignment/type/online/assignment.class.php b/mod/assignment/type/online/assignment.class.php index 5f2af3ac640..236bcbf4230 100644 --- a/mod/assignment/type/online/assignment.class.php +++ b/mod/assignment/type/online/assignment.class.php @@ -384,6 +384,51 @@ class assignment_online extends assignment_base { session_get_instance()->write_close(); // unlock session during fileserving send_stored_file($file, 60*60, 0, true); } + + /** + * creates a zip of all assignment submissions and sends a zip to the browser + */ + public function download_submissions() { + global $CFG, $DB; + require_once($CFG->libdir.'/filelib.php'); + + $submissions = $this->get_submissions('',''); + if (empty($submissions)) { + error("there are no submissions to download"); + } + $filesforzipping = array(); + $tempdir = assignment_create_temp_dir($CFG->dataroot."/temp/", "assignment".$this->assignment->id); //location for temp files. + //online assignment can use html + $filextn=".html"; + + $groupmode = groupmode($this->course,$this->cm); + $groupid = 0; // All users + $groupname = ''; + if($groupmode) { + $group = get_current_group($this->course->id, true); + $groupid = $group->id; + $groupname = $group->name.'-'; + } + $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file. + foreach ($submissions as $submission) { + $a_userid = $submission->userid; //get userid + if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) { + $a_assignid = $submission->assignment; //get name of this assignment for use in the file names. + $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname + $submissioncontent = "". $submission->data1. ""; //fetched from database + //get file name.html + $fileforzipname = $a_user->username . "_" . clean_filename($this->assignment->name) . $filextn; + $fd = fopen($tempdir . $fileforzipname,'wb'); //create if not exist, write binary + fwrite( $fd, $submissioncontent); + fclose( $fd ); + $filesforzipping[$fileforzipname] = $tempdir.$fileforzipname; + } + } //end of foreach + if ($zipfile = assignment_pack_files($filesforzipping)) { + remove_dir($tempdir); //remove old tempdir with individual files. + send_temp_file($zipfile, $filename); //send file and delete after sending. + } + } } class mod_assignment_online_edit_form extends moodleform { diff --git a/mod/assignment/type/upload/assignment.class.php b/mod/assignment/type/upload/assignment.class.php index 4e4c0d6732f..d8fe8eff985 100644 --- a/mod/assignment/type/upload/assignment.class.php +++ b/mod/assignment/type/upload/assignment.class.php @@ -1119,6 +1119,56 @@ class assignment_upload extends assignment_base { $node->add(get_string('notes', 'assignment'), $link); } } + + /** + * creates a zip of all assignment submissions and sends a zip to the browser + */ + public function download_submissions() { + global $CFG,$DB; + require_once($CFG->libdir.'/filelib.php'); + + $submissions = $this->get_submissions('',''); + if (empty($submissions)) { + error("there are no submissions to download"); + } + $filesforzipping = array(); + $filenewname = clean_filename($this->assignment->name); //create prefix of individual files + $tempdir = assignment_create_temp_dir($CFG->dataroot."/temp/", "assignment".$this->assignment->id); //location for temp files. + $fs = get_file_storage(); + + $groupmode = groupmode($this->course,$this->cm); + $groupid = 0; // All users + $groupname = ''; + if($groupmode) { + $group = get_current_group($this->course->id, true); + $groupid = $group->id; + $groupname = $group->name.'-'; + } + $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file. + foreach ($submissions as $submission) { + $a_userid = $submission->userid; //get userid + if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) { + $a_assignid = $submission->assignment; //get name of this assignment for use in the file names. + $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname + + $files = $fs->get_area_files($this->context->id, 'assignment_submission', $a_userid, "timemodified", false); + foreach ($files as $file) { + //get files new name. + $fileforzipname = $a_user->username . "_" . $filenewname . "_" . $file->get_filename(); + //get files old name + if (!$file->copy_content_to($tempdir . $fileforzipname)) { + error ("failed to copy file
" .$tempdir. $fileforzipname); + } + //save file name to array for zipping. + $filesforzipping[$fileforzipname] = $tempdir.$fileforzipname; + } + } + } // end of foreach loop + if ($zipfile = assignment_pack_files($filesforzipping)) { + remove_dir($tempdir); //remove old tempdir with individual files. + send_temp_file($zipfile, $filename); //send file and delete after sending. + } + } } class mod_assignment_upload_notes_form extends moodleform { diff --git a/mod/assignment/type/uploadsingle/assignment.class.php b/mod/assignment/type/uploadsingle/assignment.class.php index a4c1cbeca60..1193721f7cc 100644 --- a/mod/assignment/type/uploadsingle/assignment.class.php +++ b/mod/assignment/type/uploadsingle/assignment.class.php @@ -229,6 +229,56 @@ class assignment_uploadsingle extends assignment_base { } } } + + /** + * creates a zip of all assignment submissions and sends a zip to the browser + */ + function download_submissions() { + global $CFG,$DB; + require_once($CFG->libdir.'/filelib.php'); + + $submissions = $this->get_submissions('',''); + if (empty($submissions)) { + error("there are no submissions to download"); + } + $filesforzipping = array(); + $filenewname = clean_filename($this->assignment->name); //create prefix of individual files + $tempdir = assignment_create_temp_dir($CFG->dataroot."/temp/", "assignment".$this->assignment->id); //location for temp files. + $fs = get_file_storage(); + + $groupmode = groupmode($this->course,$this->cm); + $groupid = 0; // All users + $groupname = ''; + if($groupmode) { + $group = get_current_group($this->course->id, true); + $groupid = $group->id; + $groupname = $group->name.'-'; + } + $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file. + foreach ($submissions as $submission) { + $a_userid = $submission->userid; //get userid + if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) { + $a_assignid = $submission->assignment; //get name of this assignment for use in the file names. + $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname + + $files = $fs->get_area_files($this->context->id, 'assignment_submission', $a_userid, "timemodified", false); + foreach ($files as $file) { + //get files new name. + $fileforzipname = $a_user->username . "_" . $filenewname . "_" . $file->get_filename(); + //get files old name + if (!$file->copy_content_to($tempdir . $fileforzipname)) { + error ("failed to copy file
" .$tempdir. $fileforzipname); + } + //save file name to array for zipping. + $filesforzipping[$fileforzipname] = $tempdir.$fileforzipname; + } + } + } // End of foreach + if ($zipfile = assignment_pack_files($filesforzipping)) { + remove_dir($tempdir); //remove old tempdir with individual files. + send_temp_file($zipfile, $filename); //send file and delete after sending. + } + } }