Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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   * Specialised restore for format_weeks
  19   *
  20   * @package   format_weeks
  21   * @category  backup
  22   * @copyright 2017 Marina Glancy
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Specialised restore for format_weeks
  30   *
  31   * Processes 'numsections' from the old backup files and hides sections that used to be "orphaned"
  32   *
  33   * @package   format_weeks
  34   * @category  backup
  35   * @copyright 2017 Marina Glancy
  36   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class restore_format_weeks_plugin extends restore_format_plugin {
  39  
  40      /** @var int */
  41      protected $originalnumsections = 0;
  42  
  43      /**
  44       * Checks if backup file was made on Moodle before 3.3 and we should respect the 'numsections'
  45       * and potential "orphaned" sections in the end of the course.
  46       *
  47       * @return bool
  48       */
  49      protected function is_pre_33_backup() {
  50          $backupinfo = $this->step->get_task()->get_info();
  51          $backuprelease = $backupinfo->backup_release; // The major version: 2.9, 3.0, 3.10...
  52          return version_compare($backuprelease, '3.3', '<');
  53      }
  54  
  55      /**
  56       * Handles setting the automatic end date for a restored course.
  57       *
  58       * @param int $enddate The end date in the backup file.
  59       */
  60      protected function update_automatic_end_date($enddate) {
  61          global $DB;
  62  
  63          // At this stage the 'course_format_options' table will already have a value set for this option as it is
  64          // part of the course format and the default will have been set.
  65          // Get the current course format option.
  66          $params = array(
  67              'courseid' => $this->step->get_task()->get_courseid(),
  68              'format' => 'weeks',
  69              'sectionid' => 0,
  70              'name' => 'automaticenddate'
  71          );
  72          $cfoid = $DB->get_field('course_format_options', 'id', $params);
  73  
  74          $update = new stdClass();
  75          $update->id = $cfoid;
  76          if (empty($enddate)) {
  77              $update->value = 1;
  78              $DB->update_record('course_format_options', $update);
  79  
  80              // Now, let's update the course end date.
  81              format_weeks::update_end_date($this->step->get_task()->get_courseid());
  82          } else {
  83              $update->value = 0;
  84              $DB->update_record('course_format_options', $update);
  85  
  86              // The end date may have been changed by observers during restore, ensure we set it back to what was in the backup.
  87              $DB->set_field('course', 'enddate', $enddate, array('id' => $this->step->get_task()->get_courseid()));
  88          }
  89      }
  90  
  91      /**
  92       * Handles updating the visibility of sections in the restored course.
  93       *
  94       * @param int $numsections The number of sections in the restored course.
  95       */
  96      protected function update_course_sections_visibility($numsections) {
  97          global $DB;
  98  
  99          $backupinfo = $this->step->get_task()->get_info();
 100          foreach ($backupinfo->sections as $key => $section) {
 101              // For each section from the backup file check if it was restored and if was "orphaned" in the original
 102              // course and mark it as hidden. This will leave all activities in it visible and available just as it was
 103              // in the original course.
 104              // Exception is when we restore with merging and the course already had a section with this section number,
 105              // in this case we don't modify the visibility.
 106              if ($this->step->get_task()->get_setting_value($key . '_included')) {
 107                  $sectionnum = (int)$section->title;
 108                  if ($sectionnum > $numsections && $sectionnum > $this->originalnumsections) {
 109                      $DB->execute("UPDATE {course_sections} SET visible = 0 WHERE course = ? AND section = ?",
 110                          [$this->step->get_task()->get_courseid(), $sectionnum]);
 111                  }
 112              }
 113          }
 114      }
 115  
 116      /**
 117       * Creates a dummy path element in order to be able to execute code after restore
 118       *
 119       * @return restore_path_element[]
 120       */
 121      public function define_course_plugin_structure() {
 122          global $DB;
 123  
 124          // Since this method is executed before the restore we can do some pre-checks here.
 125          // In case of merging backup into existing course find the current number of sections.
 126          $target = $this->step->get_task()->get_target();
 127          if (($target == backup::TARGET_CURRENT_ADDING || $target == backup::TARGET_EXISTING_ADDING) &&
 128                  $this->is_pre_33_backup()) {
 129              $maxsection = $DB->get_field_sql(
 130                  'SELECT max(section) FROM {course_sections} WHERE course = ?',
 131                  [$this->step->get_task()->get_courseid()]);
 132              $this->originalnumsections = (int)$maxsection;
 133          }
 134  
 135          // Dummy path element is needed in order for after_restore_course() to be called.
 136          return [new restore_path_element('dummy_course', $this->get_pathfor('/dummycourse'))];
 137      }
 138  
 139      /**
 140       * Dummy process method
 141       */
 142      public function process_dummy_course() {
 143  
 144      }
 145  
 146      /**
 147       * Executed after course restore is complete
 148       *
 149       * This method is only executed if course configuration was overridden
 150       */
 151      public function after_restore_course() {
 152          if (!$this->is_pre_33_backup()) {
 153              // Backup file was made in Moodle 3.3 or later, we don't need to process it.
 154              return;
 155          }
 156  
 157          $backupinfo = $this->step->get_task()->get_info();
 158          if ($backupinfo->original_course_format !== 'weeks') {
 159              // Backup from another course format.
 160              return;
 161          }
 162  
 163          $data = $this->connectionpoint->get_data();
 164  
 165          // Backup may not include the end date, so set it to 0.
 166          $enddate = isset($data['tags']['enddate']) ? $data['tags']['enddate'] : 0;
 167  
 168          // Set the automatic end date setting and the course end date (if applicable).
 169          $this->update_automatic_end_date($enddate);
 170  
 171          if (isset($data['tags']['numsections'])) {
 172              // Update course sections visibility.
 173              $numsections = (int)$data['tags']['numsections'];
 174              $this->update_course_sections_visibility($numsections);
 175          }
 176      }
 177  }