Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 38 and 311] [Versions 39 and 311]

   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  // File areas for file feedback assignment.
  29  define('ASSIGNFEEDBACK_FILE_FILEAREA', 'feedback_files');
  30  define('ASSIGNFEEDBACK_FILE_BATCH_FILEAREA', 'feedback_files_batch');
  31  define('ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA', 'feedback_files_import');
  32  define('ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES', 5);
  33  define('ASSIGNFEEDBACK_FILE_MAXSUMMARYUSERS', 5);
  34  define('ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME', 120);
  35  
  36  /**
  37   * Library class for file feedback plugin extending feedback plugin base class.
  38   *
  39   * @package   assignfeedback_file
  40   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  41   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class assign_feedback_file extends assign_feedback_plugin {
  44  
  45      /**
  46       * Get the name of the file feedback plugin.
  47       *
  48       * @return string
  49       */
  50      public function get_name() {
  51          return get_string('file', 'assignfeedback_file');
  52      }
  53  
  54      /**
  55       * Get file feedback information from the database.
  56       *
  57       * @param int $gradeid
  58       * @return mixed
  59       */
  60      public function get_file_feedback($gradeid) {
  61          global $DB;
  62          return $DB->get_record('assignfeedback_file', array('grade'=>$gradeid));
  63      }
  64  
  65      /**
  66       * File format options.
  67       *
  68       * @return array
  69       */
  70      private function get_file_options() {
  71          global $COURSE;
  72  
  73          $fileoptions = array('subdirs'=>1,
  74                               'maxbytes'=>$COURSE->maxbytes,
  75                               'accepted_types'=>'*',
  76                               'return_types'=>FILE_INTERNAL);
  77          return $fileoptions;
  78      }
  79  
  80      /**
  81       * Has the feedback file been modified?
  82       *
  83       * @param stdClass $grade Grade object.
  84       * @param stdClass $data Form data.
  85       * @return boolean True if the file area has been modified, else false.
  86       */
  87      public function is_feedback_modified(stdClass $grade, stdClass $data) {
  88          global $USER;
  89  
  90          $filekey = null;
  91          $draftareainfo = null;
  92          foreach ($data as $key => $value) {
  93              if (strpos($key, 'files_') === 0 && strpos($key, '_filemanager')) {
  94                  $filekey = $key;
  95              }
  96          }
  97          if (isset($filekey)) {
  98              $draftareainfo = file_get_draft_area_info($data->$filekey);
  99              $filecount = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA);
 100              if ($filecount != $draftareainfo['filecount']) {
 101                  return true;
 102              } else {
 103                  // We need to check that the files in the draft area are the same as in the file area.
 104                  $usercontext = context_user::instance($USER->id);
 105                  $fs = get_file_storage();
 106                  $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $data->$filekey, 'id', true);
 107                  $files = $fs->get_area_files($this->assignment->get_context()->id,
 108                                       'assignfeedback_file',
 109                                       ASSIGNFEEDBACK_FILE_FILEAREA,
 110                                       $grade->id,
 111                                       'id',
 112                                       false);
 113                  foreach ($files as $key => $file) {
 114                      // Flag for recording if we have a matching file.
 115                      $matchflag = false;
 116                      foreach ($draftfiles as $draftkey => $draftfile) {
 117                          if (!$file->is_directory()) {
 118                              // File name is the same, but it could be a different file with the same name.
 119                              if ($draftfile->get_filename() == $file->get_filename()) {
 120                                  // If the file name is the same but the content hash is different, or
 121                                  // The file path for the file has changed, then we have a modification.
 122                                  if ($draftfile->get_contenthash() != $file->get_contenthash() ||
 123                                          $draftfile->get_filepath() != $file->get_filepath()) {
 124                                      return true;
 125                                  }
 126                                  // These files match. Check the next file.
 127                                  $matchflag = true;
 128                                  // We have a match on the file name so we can move to the next file and not
 129                                  // proceed through the other draftfiles.
 130                                  break;
 131                              }
 132                          }
 133                      }
 134                      // If the file does not match then there has been a modification.
 135                      if (!$matchflag) {
 136                          return true;
 137                      }
 138                  }
 139              }
 140          }
 141          return false;
 142      }
 143  
 144      /**
 145       * Copy all the files from one file area to another.
 146       *
 147       * @param file_storage $fs - The source context id
 148       * @param int $fromcontextid - The source context id
 149       * @param string $fromcomponent - The source component
 150       * @param string $fromfilearea - The source filearea
 151       * @param int $fromitemid - The source item id
 152       * @param int $tocontextid - The destination context id
 153       * @param string $tocomponent - The destination component
 154       * @param string $tofilearea - The destination filearea
 155       * @param int $toitemid - The destination item id
 156       * @return boolean
 157       */
 158      private function copy_area_files(file_storage $fs,
 159                                       $fromcontextid,
 160                                       $fromcomponent,
 161                                       $fromfilearea,
 162                                       $fromitemid,
 163                                       $tocontextid,
 164                                       $tocomponent,
 165                                       $tofilearea,
 166                                       $toitemid) {
 167  
 168          $newfilerecord = new stdClass();
 169          $newfilerecord->contextid = $tocontextid;
 170          $newfilerecord->component = $tocomponent;
 171          $newfilerecord->filearea = $tofilearea;
 172          $newfilerecord->itemid = $toitemid;
 173  
 174          if ($files = $fs->get_area_files($fromcontextid, $fromcomponent, $fromfilearea, $fromitemid)) {
 175              foreach ($files as $file) {
 176                  if ($file->is_directory() and $file->get_filepath() === '/') {
 177                      // We need a way to mark the age of each draft area.
 178                      // By not copying the root dir we force it to be created
 179                      // automatically with current timestamp.
 180                      continue;
 181                  }
 182  
 183                  $existingfile = $fs->get_file(
 184                      $newfilerecord->contextid,
 185                      $newfilerecord->component,
 186                      $newfilerecord->filearea,
 187                      $newfilerecord->itemid,
 188                      $file->get_filepath(),
 189                      $file->get_filename()
 190                  );
 191                  if ($existingfile) {
 192                      // If the file already exists, remove it so it can be updated.
 193                      $existingfile->delete();
 194                  }
 195  
 196                  $newfile = $fs->create_file_from_storedfile($newfilerecord, $file);
 197              }
 198          }
 199          return true;
 200      }
 201  
 202      /**
 203       * Get form elements for grading form.
 204       *
 205       * @param stdClass $grade
 206       * @param MoodleQuickForm $mform
 207       * @param stdClass $data
 208       * @param int $userid The userid we are currently grading
 209       * @return bool true if elements were added to the form
 210       */
 211      public function get_form_elements_for_user($grade, MoodleQuickForm $mform, stdClass $data, $userid) {
 212  
 213          $fileoptions = $this->get_file_options();
 214          $gradeid = $grade ? $grade->id : 0;
 215          $elementname = 'files_' . $userid;
 216  
 217          $data = file_prepare_standard_filemanager($data,
 218                                                    $elementname,
 219                                                    $fileoptions,
 220                                                    $this->assignment->get_context(),
 221                                                    'assignfeedback_file',
 222                                                    ASSIGNFEEDBACK_FILE_FILEAREA,
 223                                                    $gradeid);
 224          $mform->addElement('filemanager', $elementname . '_filemanager', $this->get_name(), null, $fileoptions);
 225  
 226          return true;
 227      }
 228  
 229      /**
 230       * Count the number of files.
 231       *
 232       * @param int $gradeid
 233       * @param string $area
 234       * @return int
 235       */
 236      private function count_files($gradeid, $area) {
 237  
 238          $fs = get_file_storage();
 239          $files = $fs->get_area_files($this->assignment->get_context()->id,
 240                                       'assignfeedback_file',
 241                                       $area,
 242                                       $gradeid,
 243                                       'id',
 244                                       false);
 245  
 246          return count($files);
 247      }
 248  
 249      /**
 250       * Update the number of files in the file area.
 251       *
 252       * @param stdClass $grade The grade record
 253       * @return bool - true if the value was saved
 254       */
 255      public function update_file_count($grade) {
 256          global $DB;
 257  
 258          $filefeedback = $this->get_file_feedback($grade->id);
 259          if ($filefeedback) {
 260              $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA);
 261              return $DB->update_record('assignfeedback_file', $filefeedback);
 262          } else {
 263              $filefeedback = new stdClass();
 264              $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA);
 265              $filefeedback->grade = $grade->id;
 266              $filefeedback->assignment = $this->assignment->get_instance()->id;
 267              return $DB->insert_record('assignfeedback_file', $filefeedback) > 0;
 268          }
 269      }
 270  
 271      /**
 272       * Save the feedback files.
 273       *
 274       * @param stdClass $grade
 275       * @param stdClass $data
 276       * @return bool
 277       */
 278      public function save(stdClass $grade, stdClass $data) {
 279          $fileoptions = $this->get_file_options();
 280  
 281          // The element name may have been for a different user.
 282          foreach ($data as $key => $value) {
 283              if (strpos($key, 'files_') === 0 && strpos($key, '_filemanager')) {
 284                  $elementname = substr($key, 0, strpos($key, '_filemanager'));
 285              }
 286          }
 287  
 288          $data = file_postupdate_standard_filemanager($data,
 289                                                       $elementname,
 290                                                       $fileoptions,
 291                                                       $this->assignment->get_context(),
 292                                                       'assignfeedback_file',
 293                                                       ASSIGNFEEDBACK_FILE_FILEAREA,
 294                                                       $grade->id);
 295  
 296          return $this->update_file_count($grade);
 297      }
 298  
 299      /**
 300       * Display the list of files in the feedback status table.
 301       *
 302       * @param stdClass $grade
 303       * @param bool $showviewlink - Set to true to show a link to see the full list of files
 304       * @return string
 305       */
 306      public function view_summary(stdClass $grade, & $showviewlink) {
 307  
 308          $count = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA);
 309  
 310          // Show a view all link if the number of files is over this limit.
 311          $showviewlink = $count > ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES;
 312  
 313          if ($count <= ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES) {
 314              return $this->assignment->render_area_files('assignfeedback_file',
 315                                                          ASSIGNFEEDBACK_FILE_FILEAREA,
 316                                                          $grade->id);
 317          } else {
 318              return get_string('countfiles', 'assignfeedback_file', $count);
 319          }
 320      }
 321  
 322      /**
 323       * Display the list of files in the feedback status table.
 324       *
 325       * @param stdClass $grade
 326       * @return string
 327       */
 328      public function view(stdClass $grade) {
 329          return $this->assignment->render_area_files('assignfeedback_file',
 330                                                      ASSIGNFEEDBACK_FILE_FILEAREA,
 331                                                      $grade->id);
 332      }
 333  
 334      /**
 335       * The assignment has been deleted - cleanup.
 336       *
 337       * @return bool
 338       */
 339      public function delete_instance() {
 340          global $DB;
 341          // Will throw exception on failure.
 342          $DB->delete_records('assignfeedback_file',
 343                              array('assignment'=>$this->assignment->get_instance()->id));
 344  
 345          return true;
 346      }
 347  
 348      /**
 349       * Return true if there are no feedback files.
 350       *
 351       * @param stdClass $grade
 352       */
 353      public function is_empty(stdClass $grade) {
 354          return $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA) == 0;
 355      }
 356  
 357      /**
 358       * Get file areas returns a list of areas this plugin stores files.
 359       *
 360       * @return array - An array of fileareas (keys) and descriptions (values)
 361       */
 362      public function get_file_areas() {
 363          return array(ASSIGNFEEDBACK_FILE_FILEAREA=>$this->get_name());
 364      }
 365  
 366      /**
 367       * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
 368       * and version.
 369       *
 370       * @param string $type old assignment subtype
 371       * @param int $version old assignment version
 372       * @return bool True if upgrade is possible
 373       */
 374      public function can_upgrade($type, $version) {
 375          if (($type == 'upload' || $type == 'uploadsingle') && $version >= 2011112900) {
 376              return true;
 377          }
 378          return false;
 379      }
 380  
 381      /**
 382       * Upgrade the settings from the old assignment to the new plugin based one.
 383       *
 384       * @param context $oldcontext - the context for the old assignment
 385       * @param stdClass $oldassignment - the data for the old assignment
 386       * @param string $log - can be appended to by the upgrade
 387       * @return bool was it a success? (false will trigger a rollback)
 388       */
 389      public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
 390          // First upgrade settings (nothing to do).
 391          return true;
 392      }
 393  
 394      /**
 395       * Upgrade the feedback from the old assignment to the new one.
 396       *
 397       * @param context $oldcontext - the database for the old assignment context
 398       * @param stdClass $oldassignment The data record for the old assignment
 399       * @param stdClass $oldsubmission The data record for the old submission
 400       * @param stdClass $grade The data record for the new grade
 401       * @param string $log Record upgrade messages in the log
 402       * @return bool true or false - false will trigger a rollback
 403       */
 404      public function upgrade(context $oldcontext,
 405                              stdClass $oldassignment,
 406                              stdClass $oldsubmission,
 407                              stdClass $grade,
 408                              & $log) {
 409          global $DB;
 410  
 411          // Now copy the area files.
 412          $this->assignment->copy_area_files_for_upgrade($oldcontext->id,
 413                                                          'mod_assignment',
 414                                                          'response',
 415                                                          $oldsubmission->id,
 416                                                          $this->assignment->get_context()->id,
 417                                                          'assignfeedback_file',
 418                                                          ASSIGNFEEDBACK_FILE_FILEAREA,
 419                                                          $grade->id);
 420  
 421          // Now count them!
 422          $filefeedback = new stdClass();
 423          $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA);
 424          $filefeedback->grade = $grade->id;
 425          $filefeedback->assignment = $this->assignment->get_instance()->id;
 426          if (!$DB->insert_record('assignfeedback_file', $filefeedback) > 0) {
 427              $log .= get_string('couldnotconvertgrade', 'mod_assign', $grade->userid);
 428              return false;
 429          }
 430          return true;
 431      }
 432  
 433      /**
 434       * Return a list of the batch grading operations performed by this plugin.
 435       * This plugin supports batch upload files and upload zip.
 436       *
 437       * @return array The list of batch grading operations
 438       */
 439      public function get_grading_batch_operations() {
 440          return array('uploadfiles'=>get_string('uploadfiles', 'assignfeedback_file'));
 441      }
 442  
 443      /**
 444       * Upload files and send them to multiple users.
 445       *
 446       * @param array $users - An array of user ids
 447       * @return string - The response html
 448       */
 449      public function view_batch_upload_files($users) {
 450          global $CFG, $DB, $USER;
 451  
 452          require_capability('mod/assign:grade', $this->assignment->get_context());
 453          require_once($CFG->dirroot . '/mod/assign/feedback/file/batchuploadfilesform.php');
 454          require_once($CFG->dirroot . '/mod/assign/renderable.php');
 455  
 456          $formparams = array('cm'=>$this->assignment->get_course_module()->id,
 457                              'users'=>$users,
 458                              'context'=>$this->assignment->get_context());
 459  
 460          $usershtml = '';
 461  
 462          $usercount = 0;
 463          foreach ($users as $userid) {
 464              if ($usercount >= ASSIGNFEEDBACK_FILE_MAXSUMMARYUSERS) {
 465                  $moreuserscount = count($users) - ASSIGNFEEDBACK_FILE_MAXSUMMARYUSERS;
 466                  $usershtml .= get_string('moreusers', 'assignfeedback_file', $moreuserscount);
 467                  break;
 468              }
 469              $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
 470  
 471              $usersummary = new assign_user_summary($user,
 472                                                     $this->assignment->get_course()->id,
 473                                                     has_capability('moodle/site:viewfullnames',
 474                                                     $this->assignment->get_course_context()),
 475                                                     $this->assignment->is_blind_marking(),
 476                                                     $this->assignment->get_uniqueid_for_user($user->id),
 477                                                     // TODO Does not support custom user profile fields (MDL-70456).
 478                                                     \core_user\fields::get_identity_fields($this->assignment->get_context(), false));
 479              $usershtml .= $this->assignment->get_renderer()->render($usersummary);
 480              $usercount += 1;
 481          }
 482  
 483          $formparams['usershtml'] = $usershtml;
 484  
 485          $mform = new assignfeedback_file_batch_upload_files_form(null, $formparams);
 486  
 487          if ($mform->is_cancelled()) {
 488              redirect(new moodle_url('view.php',
 489                                      array('id'=>$this->assignment->get_course_module()->id,
 490                                            'action'=>'grading')));
 491              return;
 492          } else if ($data = $mform->get_data()) {
 493              // Copy the files from the draft area to a temporary import area.
 494              $data = file_postupdate_standard_filemanager($data,
 495                                                           'files',
 496                                                           $this->get_file_options(),
 497                                                           $this->assignment->get_context(),
 498                                                           'assignfeedback_file',
 499                                                           ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 500                                                           $USER->id);
 501              $fs = get_file_storage();
 502  
 503              // Now copy each of these files to the users feedback file area.
 504              foreach ($users as $userid) {
 505                  $grade = $this->assignment->get_user_grade($userid, true);
 506                  $this->assignment->notify_grade_modified($grade);
 507  
 508                  $this->copy_area_files($fs,
 509                                         $this->assignment->get_context()->id,
 510                                         'assignfeedback_file',
 511                                         ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 512                                         $USER->id,
 513                                         $this->assignment->get_context()->id,
 514                                         'assignfeedback_file',
 515                                         ASSIGNFEEDBACK_FILE_FILEAREA,
 516                                         $grade->id);
 517  
 518                  $filefeedback = $this->get_file_feedback($grade->id);
 519                  if ($filefeedback) {
 520                      $filefeedback->numfiles = $this->count_files($grade->id,
 521                                                                   ASSIGNFEEDBACK_FILE_FILEAREA);
 522                      $DB->update_record('assignfeedback_file', $filefeedback);
 523                  } else {
 524                      $filefeedback = new stdClass();
 525                      $filefeedback->numfiles = $this->count_files($grade->id,
 526                                                                   ASSIGNFEEDBACK_FILE_FILEAREA);
 527                      $filefeedback->grade = $grade->id;
 528                      $filefeedback->assignment = $this->assignment->get_instance()->id;
 529                      $DB->insert_record('assignfeedback_file', $filefeedback);
 530                  }
 531              }
 532  
 533              // Now delete the temporary import area.
 534              $fs->delete_area_files($this->assignment->get_context()->id,
 535                                     'assignfeedback_file',
 536                                     ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 537                                     $USER->id);
 538  
 539              redirect(new moodle_url('view.php',
 540                                      array('id'=>$this->assignment->get_course_module()->id,
 541                                            'action'=>'grading')));
 542              return;
 543          } else {
 544  
 545              $header = new assign_header($this->assignment->get_instance(),
 546                                          $this->assignment->get_context(),
 547                                          false,
 548                                          $this->assignment->get_course_module()->id,
 549                                          get_string('batchuploadfiles', 'assignfeedback_file'));
 550              $o = '';
 551              $o .= $this->assignment->get_renderer()->render($header);
 552              $o .= $this->assignment->get_renderer()->render(new assign_form('batchuploadfiles', $mform));
 553              $o .= $this->assignment->get_renderer()->render_footer();
 554          }
 555  
 556          return $o;
 557      }
 558  
 559      /**
 560       * User has chosen a custom grading batch operation and selected some users.
 561       *
 562       * @param string $action - The chosen action
 563       * @param array $users - An array of user ids
 564       * @return string - The response html
 565       */
 566      public function grading_batch_operation($action, $users) {
 567  
 568          if ($action == 'uploadfiles') {
 569              return $this->view_batch_upload_files($users);
 570          }
 571          return '';
 572      }
 573  
 574      /**
 575       * View the upload zip form.
 576       *
 577       * @return string - The html response
 578       */
 579      public function view_upload_zip() {
 580          global $CFG, $USER;
 581  
 582          require_capability('mod/assign:grade', $this->assignment->get_context());
 583          require_once($CFG->dirroot . '/mod/assign/feedback/file/uploadzipform.php');
 584          require_once($CFG->dirroot . '/mod/assign/feedback/file/importziplib.php');
 585          require_once($CFG->dirroot . '/mod/assign/feedback/file/importzipform.php');
 586  
 587          $formparams = array('context'=>$this->assignment->get_context(),
 588                              'cm'=>$this->assignment->get_course_module()->id);
 589          $mform = new assignfeedback_file_upload_zip_form(null, $formparams);
 590  
 591          $o = '';
 592  
 593          $confirm = optional_param('confirm', 0, PARAM_BOOL);
 594          $renderer = $this->assignment->get_renderer();
 595  
 596          // Delete any existing files.
 597          $importer = new assignfeedback_file_zip_importer();
 598          $contextid = $this->assignment->get_context()->id;
 599  
 600          if ($mform->is_cancelled()) {
 601              $importer->delete_import_files($contextid);
 602              $urlparams = array('id'=>$this->assignment->get_course_module()->id,
 603                                 'action'=>'grading');
 604              $url = new moodle_url('view.php', $urlparams);
 605              redirect($url);
 606              return;
 607          } else if ($confirm) {
 608              $params = array('assignment'=>$this->assignment, 'importer'=>$importer);
 609  
 610              $mform = new assignfeedback_file_import_zip_form(null, $params);
 611              if ($mform->is_cancelled()) {
 612                  $importer->delete_import_files($contextid);
 613                  $urlparams = array('id'=>$this->assignment->get_course_module()->id,
 614                                     'action'=>'grading');
 615                  $url = new moodle_url('view.php', $urlparams);
 616                  redirect($url);
 617                  return;
 618              }
 619  
 620              $o .= $importer->import_zip_files($this->assignment, $this);
 621              $importer->delete_import_files($contextid);
 622          } else if (($data = $mform->get_data()) &&
 623                     ($zipfile = $mform->save_stored_file('feedbackzip',
 624                                                          $contextid,
 625                                                          'assignfeedback_file',
 626                                                          ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
 627                                                          $USER->id,
 628                                                          '/',
 629                                                          'import.zip',
 630                                                          true))) {
 631  
 632              $importer->extract_files_from_zip($zipfile, $contextid);
 633  
 634              $params = array('assignment'=>$this->assignment, 'importer'=>$importer);
 635  
 636              $mform = new assignfeedback_file_import_zip_form(null, $params);
 637  
 638              $header = new assign_header($this->assignment->get_instance(),
 639                                          $this->assignment->get_context(),
 640                                          false,
 641                                          $this->assignment->get_course_module()->id,
 642                                          get_string('confirmuploadzip', 'assignfeedback_file'));
 643              $o .= $renderer->render($header);
 644              $o .= $renderer->render(new assign_form('confirmimportzip', $mform));
 645              $o .= $renderer->render_footer();
 646  
 647          } else {
 648  
 649              $header = new assign_header($this->assignment->get_instance(),
 650                                          $this->assignment->get_context(),
 651                                          false,
 652                                          $this->assignment->get_course_module()->id,
 653                                          get_string('uploadzip', 'assignfeedback_file'));
 654              $o .= $renderer->render($header);
 655              $o .= $renderer->render(new assign_form('uploadfeedbackzip', $mform));
 656              $o .= $renderer->render_footer();
 657          }
 658  
 659          return $o;
 660      }
 661  
 662      /**
 663       * Called by the assignment module when someone chooses something from the
 664       * grading navigation or batch operations list.
 665       *
 666       * @param string $action - The page to view
 667       * @return string - The html response
 668       */
 669      public function view_page($action) {
 670          if ($action == 'uploadfiles') {
 671              $users = required_param('selectedusers', PARAM_SEQUENCE);
 672              return $this->view_batch_upload_files(explode(',', $users));
 673          }
 674          if ($action == 'uploadzip') {
 675              return $this->view_upload_zip();
 676          }
 677  
 678          return '';
 679      }
 680  
 681      /**
 682       * Return a list of the grading actions performed by this plugin.
 683       * This plugin supports upload zip.
 684       *
 685       * @return array The list of grading actions
 686       */
 687      public function get_grading_actions() {
 688          return array('uploadzip'=>get_string('uploadzip', 'assignfeedback_file'));
 689      }
 690  
 691      /**
 692       * Return a description of external params suitable for uploading a feedback file from a webservice.
 693       *
 694       * @return external_description|null
 695       */
 696      public function get_external_parameters() {
 697          return array(
 698              'files_filemanager' => new external_value(
 699                  PARAM_INT,
 700                  'The id of a draft area containing files for this feedback.',
 701                  VALUE_OPTIONAL
 702              )
 703          );
 704      }
 705  
 706      /**
 707       * Return the plugin configs for external functions.
 708       *
 709       * @return array the list of settings
 710       * @since Moodle 3.2
 711       */
 712      public function get_config_for_external() {
 713          return (array) $this->get_config();
 714      }
 715  }