[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/assign/feedback/file/ -> importziplib.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * This file contains the definition for the library class for file feedback plugin
  19   *
  20   *
  21   * @package   assignfeedback_file
  22   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * library class for importing feedback files from a zip
  30   *
  31   * @package   assignfeedback_file
  32   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  33   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class assignfeedback_file_zip_importer {
  36  
  37      /**
  38       * Is this filename valid (contains a unique participant ID) for import?
  39       *
  40       * @param assign $assignment - The assignment instance
  41       * @param stored_file $fileinfo - The fileinfo
  42       * @param array $participants - A list of valid participants for this module indexed by unique_id
  43       * @param stdClass $user - Set to the user that matches by participant id
  44       * @param assign_plugin $plugin - Set to the plugin that exported the file
  45       * @param string $filename - Set to truncated filename (prefix stripped)
  46       * @return true If the participant Id can be extracted and this is a valid user
  47       */
  48      public function is_valid_filename_for_import($assignment, $fileinfo, $participants, & $user, & $plugin, & $filename) {
  49          if ($fileinfo->is_directory()) {
  50              return false;
  51          }
  52  
  53          // Ignore hidden files.
  54          if (strpos($fileinfo->get_filename(), '.') === 0) {
  55              return false;
  56          }
  57          // Ignore hidden files.
  58          if (strpos($fileinfo->get_filename(), '~') === 0) {
  59              return false;
  60          }
  61  
  62          $info = explode('_', $fileinfo->get_filepath() . $fileinfo->get_filename(), 5);
  63  
  64          if (count($info) < 5) {
  65              return false;
  66          }
  67  
  68          $participantid = $info[1];
  69          $filename = $info[4];
  70          $plugin = $assignment->get_plugin_by_type($info[2], $info[3]);
  71  
  72          if (!is_numeric($participantid)) {
  73              return false;
  74          }
  75  
  76          if (!$plugin) {
  77              return false;
  78          }
  79  
  80          // Convert to int.
  81          $participantid += 0;
  82  
  83          if (empty($participants[$participantid])) {
  84              return false;
  85          }
  86  
  87          $user = $participants[$participantid];
  88          return true;
  89      }
  90  
  91      /**
  92       * Does this file exist in any of the current files supported by this plugin for this user?
  93       *
  94       * @param assign $assignment - The assignment instance
  95       * @param stdClass $user The user matching this uploaded file
  96       * @param assign_plugin $plugin The matching plugin from the filename
  97       * @param string $filename The parsed filename from the zip
  98       * @param stored_file $fileinfo The info about the extracted file from the zip
  99       * @return bool - True if the file has been modified or is new
 100       */
 101      public function is_file_modified($assignment, $user, $plugin, $filename, $fileinfo) {
 102          $sg = null;
 103  
 104          if ($plugin->get_subtype() == 'assignsubmission') {
 105              $sg = $assignment->get_user_submission($user->id, false);
 106          } else if ($plugin->get_subtype() == 'assignfeedback') {
 107              $sg = $assignment->get_user_grade($user->id, false);
 108          } else {
 109              return false;
 110          }
 111  
 112          if (!$sg) {
 113              return true;
 114          }
 115          foreach ($plugin->get_files($sg, $user) as $pluginfilename => $file) {
 116              if ($pluginfilename == $filename) {
 117                  // Extract the file and compare hashes.
 118                  $contenthash = '';
 119                  if (is_array($file)) {
 120                      $content = reset($file);
 121                      $contenthash = sha1($content);
 122                  } else {
 123                      $contenthash = $file->get_contenthash();
 124                  }
 125                  if ($contenthash != $fileinfo->get_contenthash()) {
 126                      return true;
 127                  } else {
 128                      return false;
 129                  }
 130              }
 131          }
 132          return true;
 133      }
 134  
 135      /**
 136       * Delete all temp files used when importing a zip
 137       *
 138       * @param int $contextid - The context id of this assignment instance
 139       * @return bool true if all files were deleted
 140       */
 141      public function delete_import_files($contextid) {
 142          global $USER;
 143  
 144          $fs = get_file_storage();
 145  
 146          return $fs->delete_area_files($contextid,
 147                                        'assignfeedback_file',
 148                                        ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
 149                                        $USER->id);
 150      }
 151  
 152      /**
 153       * Extract the uploaded zip to a temporary import area for this user
 154       *
 155       * @param stored_file $zipfile The uploaded file
 156       * @param int $contextid The context for this assignment
 157       * @return bool - True if the files were unpacked
 158       */
 159      public function extract_files_from_zip($zipfile, $contextid) {
 160          global $USER;
 161  
 162          $feedbackfilesupdated = 0;
 163          $feedbackfilesadded = 0;
 164          $userswithnewfeedback = array();
 165  
 166          // Unzipping a large zip file is memory intensive.
 167          raise_memory_limit(MEMORY_EXTRA);
 168  
 169          $packer = get_file_packer('application/zip');
 170          core_php_time_limit::raise(ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME);
 171  
 172          return $packer->extract_to_storage($zipfile,
 173                                      $contextid,
 174                                      'assignfeedback_file',
 175                                      ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
 176                                      $USER->id,
 177                                      'import');
 178  
 179      }
 180  
 181      /**
 182       * Get the list of files extracted from the uploaded zip
 183       *
 184       * @param int $contextid
 185       * @return array of stored_files
 186       */
 187      public function get_import_files($contextid) {
 188          global $USER;
 189  
 190          $fs = get_file_storage();
 191          $files = $fs->get_directory_files($contextid,
 192                                            'assignfeedback_file',
 193                                            ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
 194                                            $USER->id,
 195                                            '/import/', true); // Get files recursive (all levels).
 196  
 197          $keys = array_keys($files);
 198  
 199          return $files;
 200      }
 201  
 202      /**
 203       * Process an uploaded zip file
 204       *
 205       * @param assign $assignment - The assignment instance
 206       * @param assign_feedback_file $fileplugin - The file feedback plugin
 207       * @return string - The html response
 208       */
 209      public function import_zip_files($assignment, $fileplugin) {
 210          global $CFG, $PAGE, $DB;
 211  
 212          core_php_time_limit::raise(ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME);
 213          $packer = get_file_packer('application/zip');
 214  
 215          $feedbackfilesupdated = 0;
 216          $feedbackfilesadded = 0;
 217          $userswithnewfeedback = array();
 218          $contextid = $assignment->get_context()->id;
 219  
 220          $fs = get_file_storage();
 221          $files = $this->get_import_files($contextid);
 222  
 223          $currentgroup = groups_get_activity_group($assignment->get_course_module(), true);
 224          $allusers = $assignment->list_participants($currentgroup, false);
 225          $participants = array();
 226          foreach ($allusers as $user) {
 227              $participants[$assignment->get_uniqueid_for_user($user->id)] = $user;
 228          }
 229  
 230          foreach ($files as $unzippedfile) {
 231              // Set the timeout for unzipping each file.
 232              $user = null;
 233              $plugin = null;
 234              $filename = '';
 235  
 236              if ($this->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $user, $plugin, $filename)) {
 237                  if ($this->is_file_modified($assignment, $user, $plugin, $filename, $unzippedfile)) {
 238                      $grade = $assignment->get_user_grade($user->id, true);
 239  
 240                      // In 3.1 the download structure of the submission files changed so that each student had their own
 241                      // separate folder, the files were not renamed and the folder structure was kept. It is possible that
 242                      // a user downloaded the submission files in 3.0 (or earlier) and edited the zip to add feedback and
 243                      // in that time the site was updated to 3.1, the following code means that we will still support the
 244                      // old file structure. For more information please see - MDL-52489.
 245                      $path = pathinfo($filename);
 246                      if ($path['dirname'] == '.') { // Old structure as students are not in separate folders.
 247                          $basename = $filename;
 248                          $dirname = "/";
 249                          $dirnamewslash = "/";
 250                      } else {
 251                          $basename = $path['basename'];
 252                          $dirname = $path['dirname'];
 253                          $dirnamewslash = $dirname . "/";
 254                      }
 255  
 256                      if ($oldfile = $fs->get_file($contextid,
 257                                                   'assignfeedback_file',
 258                                                   ASSIGNFEEDBACK_FILE_FILEAREA,
 259                                                   $grade->id,
 260                                                   $dirname,
 261                                                   $basename)) {
 262                          // Update existing feedback file.
 263                          $oldfile->replace_file_with($unzippedfile);
 264                          $feedbackfilesupdated++;
 265                      } else {
 266                          // Create a new feedback file.
 267                          $newfilerecord = new stdClass();
 268                          $newfilerecord->contextid = $contextid;
 269                          $newfilerecord->component = 'assignfeedback_file';
 270                          $newfilerecord->filearea = ASSIGNFEEDBACK_FILE_FILEAREA;
 271                          $newfilerecord->filename = $basename;
 272                          $newfilerecord->filepath = $dirnamewslash;
 273                          $newfilerecord->itemid = $grade->id;
 274                          $fs->create_file_from_storedfile($newfilerecord, $unzippedfile);
 275                          $feedbackfilesadded++;
 276                      }
 277                      $userswithnewfeedback[$user->id] = 1;
 278  
 279                      // Update the number of feedback files for this user.
 280                      $fileplugin->update_file_count($grade);
 281  
 282                      // Update the last modified time on the grade which will trigger student notifications.
 283                      $assignment->notify_grade_modified($grade);
 284                  }
 285              }
 286          }
 287  
 288          require_once($CFG->dirroot . '/mod/assign/feedback/file/renderable.php');
 289          $importsummary = new assignfeedback_file_import_summary($assignment->get_course_module()->id,
 290                                                              count($userswithnewfeedback),
 291                                                              $feedbackfilesadded,
 292                                                              $feedbackfilesupdated);
 293  
 294          $assignrenderer = $assignment->get_renderer();
 295          $renderer = $PAGE->get_renderer('assignfeedback_file');
 296  
 297          $o = '';
 298  
 299          $o .= $assignrenderer->render(new assign_header($assignment->get_instance(),
 300                                                          $assignment->get_context(),
 301                                                          false,
 302                                                          $assignment->get_course_module()->id,
 303                                                          get_string('uploadzipsummary', 'assignfeedback_file')));
 304  
 305          $o .= $renderer->render($importsummary);
 306  
 307          $o .= $assignrenderer->render_footer();
 308          return $o;
 309      }
 310  
 311  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1