Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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                                                     get_extra_user_fields($this->assignment->get_context()));
 478              $usershtml .= $this->assignment->get_renderer()->render($usersummary);
 479              $usercount += 1;
 480          }
 481  
 482          $formparams['usershtml'] = $usershtml;
 483  
 484          $mform = new assignfeedback_file_batch_upload_files_form(null, $formparams);
 485  
 486          if ($mform->is_cancelled()) {
 487              redirect(new moodle_url('view.php',
 488                                      array('id'=>$this->assignment->get_course_module()->id,
 489                                            'action'=>'grading')));
 490              return;
 491          } else if ($data = $mform->get_data()) {
 492              // Copy the files from the draft area to a temporary import area.
 493              $data = file_postupdate_standard_filemanager($data,
 494                                                           'files',
 495                                                           $this->get_file_options(),
 496                                                           $this->assignment->get_context(),
 497                                                           'assignfeedback_file',
 498                                                           ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 499                                                           $USER->id);
 500              $fs = get_file_storage();
 501  
 502              // Now copy each of these files to the users feedback file area.
 503              foreach ($users as $userid) {
 504                  $grade = $this->assignment->get_user_grade($userid, true);
 505                  $this->assignment->notify_grade_modified($grade);
 506  
 507                  $this->copy_area_files($fs,
 508                                         $this->assignment->get_context()->id,
 509                                         'assignfeedback_file',
 510                                         ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 511                                         $USER->id,
 512                                         $this->assignment->get_context()->id,
 513                                         'assignfeedback_file',
 514                                         ASSIGNFEEDBACK_FILE_FILEAREA,
 515                                         $grade->id);
 516  
 517                  $filefeedback = $this->get_file_feedback($grade->id);
 518                  if ($filefeedback) {
 519                      $filefeedback->numfiles = $this->count_files($grade->id,
 520                                                                   ASSIGNFEEDBACK_FILE_FILEAREA);
 521                      $DB->update_record('assignfeedback_file', $filefeedback);
 522                  } else {
 523                      $filefeedback = new stdClass();
 524                      $filefeedback->numfiles = $this->count_files($grade->id,
 525                                                                   ASSIGNFEEDBACK_FILE_FILEAREA);
 526                      $filefeedback->grade = $grade->id;
 527                      $filefeedback->assignment = $this->assignment->get_instance()->id;
 528                      $DB->insert_record('assignfeedback_file', $filefeedback);
 529                  }
 530              }
 531  
 532              // Now delete the temporary import area.
 533              $fs->delete_area_files($this->assignment->get_context()->id,
 534                                     'assignfeedback_file',
 535                                     ASSIGNFEEDBACK_FILE_BATCH_FILEAREA,
 536                                     $USER->id);
 537  
 538              redirect(new moodle_url('view.php',
 539                                      array('id'=>$this->assignment->get_course_module()->id,
 540                                            'action'=>'grading')));
 541              return;
 542          } else {
 543  
 544              $header = new assign_header($this->assignment->get_instance(),
 545                                          $this->assignment->get_context(),
 546                                          false,
 547                                          $this->assignment->get_course_module()->id,
 548                                          get_string('batchuploadfiles', 'assignfeedback_file'));
 549              $o = '';
 550              $o .= $this->assignment->get_renderer()->render($header);
 551              $o .= $this->assignment->get_renderer()->render(new assign_form('batchuploadfiles', $mform));
 552              $o .= $this->assignment->get_renderer()->render_footer();
 553          }
 554  
 555          return $o;
 556      }
 557  
 558      /**
 559       * User has chosen a custom grading batch operation and selected some users.
 560       *
 561       * @param string $action - The chosen action
 562       * @param array $users - An array of user ids
 563       * @return string - The response html
 564       */
 565      public function grading_batch_operation($action, $users) {
 566  
 567          if ($action == 'uploadfiles') {
 568              return $this->view_batch_upload_files($users);
 569          }
 570          return '';
 571      }
 572  
 573      /**
 574       * View the upload zip form.
 575       *
 576       * @return string - The html response
 577       */
 578      public function view_upload_zip() {
 579          global $CFG, $USER;
 580  
 581          require_capability('mod/assign:grade', $this->assignment->get_context());
 582          require_once($CFG->dirroot . '/mod/assign/feedback/file/uploadzipform.php');
 583          require_once($CFG->dirroot . '/mod/assign/feedback/file/importziplib.php');
 584          require_once($CFG->dirroot . '/mod/assign/feedback/file/importzipform.php');
 585  
 586          $formparams = array('context'=>$this->assignment->get_context(),
 587                              'cm'=>$this->assignment->get_course_module()->id);
 588          $mform = new assignfeedback_file_upload_zip_form(null, $formparams);
 589  
 590          $o = '';
 591  
 592          $confirm = optional_param('confirm', 0, PARAM_BOOL);
 593          $renderer = $this->assignment->get_renderer();
 594  
 595          // Delete any existing files.
 596          $importer = new assignfeedback_file_zip_importer();
 597          $contextid = $this->assignment->get_context()->id;
 598  
 599          if ($mform->is_cancelled()) {
 600              $importer->delete_import_files($contextid);
 601              $urlparams = array('id'=>$this->assignment->get_course_module()->id,
 602                                 'action'=>'grading');
 603              $url = new moodle_url('view.php', $urlparams);
 604              redirect($url);
 605              return;
 606          } else if ($confirm) {
 607              $params = array('assignment'=>$this->assignment, 'importer'=>$importer);
 608  
 609              $mform = new assignfeedback_file_import_zip_form(null, $params);
 610              if ($mform->is_cancelled()) {
 611                  $importer->delete_import_files($contextid);
 612                  $urlparams = array('id'=>$this->assignment->get_course_module()->id,
 613                                     'action'=>'grading');
 614                  $url = new moodle_url('view.php', $urlparams);
 615                  redirect($url);
 616                  return;
 617              }
 618  
 619              $o .= $importer->import_zip_files($this->assignment, $this);
 620              $importer->delete_import_files($contextid);
 621          } else if (($data = $mform->get_data()) &&
 622                     ($zipfile = $mform->save_stored_file('feedbackzip',
 623                                                          $contextid,
 624                                                          'assignfeedback_file',
 625                                                          ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
 626                                                          $USER->id,
 627                                                          '/',
 628                                                          'import.zip',
 629                                                          true))) {
 630  
 631              $importer->extract_files_from_zip($zipfile, $contextid);
 632  
 633              $params = array('assignment'=>$this->assignment, 'importer'=>$importer);
 634  
 635              $mform = new assignfeedback_file_import_zip_form(null, $params);
 636  
 637              $header = new assign_header($this->assignment->get_instance(),
 638                                          $this->assignment->get_context(),
 639                                          false,
 640                                          $this->assignment->get_course_module()->id,
 641                                          get_string('confirmuploadzip', 'assignfeedback_file'));
 642              $o .= $renderer->render($header);
 643              $o .= $renderer->render(new assign_form('confirmimportzip', $mform));
 644              $o .= $renderer->render_footer();
 645  
 646          } else {
 647  
 648              $header = new assign_header($this->assignment->get_instance(),
 649                                          $this->assignment->get_context(),
 650                                          false,
 651                                          $this->assignment->get_course_module()->id,
 652                                          get_string('uploadzip', 'assignfeedback_file'));
 653              $o .= $renderer->render($header);
 654              $o .= $renderer->render(new assign_form('uploadfeedbackzip', $mform));
 655              $o .= $renderer->render_footer();
 656          }
 657  
 658          return $o;
 659      }
 660  
 661      /**
 662       * Called by the assignment module when someone chooses something from the
 663       * grading navigation or batch operations list.
 664       *
 665       * @param string $action - The page to view
 666       * @return string - The html response
 667       */
 668      public function view_page($action) {
 669          if ($action == 'uploadfiles') {
 670              $users = required_param('selectedusers', PARAM_SEQUENCE);
 671              return $this->view_batch_upload_files(explode(',', $users));
 672          }
 673          if ($action == 'uploadzip') {
 674              return $this->view_upload_zip();
 675          }
 676  
 677          return '';
 678      }
 679  
 680      /**
 681       * Return a list of the grading actions performed by this plugin.
 682       * This plugin supports upload zip.
 683       *
 684       * @return array The list of grading actions
 685       */
 686      public function get_grading_actions() {
 687          return array('uploadzip'=>get_string('uploadzip', 'assignfeedback_file'));
 688      }
 689  
 690      /**
 691       * Return a description of external params suitable for uploading a feedback file from a webservice.
 692       *
 693       * @return external_description|null
 694       */
 695      public function get_external_parameters() {
 696          return array(
 697              'files_filemanager' => new external_value(
 698                  PARAM_INT,
 699                  'The id of a draft area containing files for this feedback.',
 700                  VALUE_OPTIONAL
 701              )
 702          );
 703      }
 704  
 705      /**
 706       * Return the plugin configs for external functions.
 707       *
 708       * @return array the list of settings
 709       * @since Moodle 3.2
 710       */
 711      public function get_config_for_external() {
 712          return (array) $this->get_config();
 713      }
 714  }