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.

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

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * @package moodlecore
  20   * @subpackage backup-helper
  21   * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Helper class that will perform all the necessary decoding tasks on restore
  29   *
  30   * This class will register all the restore_decode_content and
  31   * restore_decode_rule instances defined by the restore tasks
  32   * in order to perform the complete decoding of links in the
  33   * final task of the restore_plan execution.
  34   *
  35   * By visiting each content provider will apply all the defined rules
  36   *
  37   * TODO: Complete phpdocs
  38   */
  39  class restore_decode_processor {
  40  
  41      protected $contents;  // Array of restore_decode_content providers
  42      protected $rules;     // Array of restore_decode_rule workers
  43      protected $restoreid;   // The unique restoreid we are executing
  44      protected $sourcewwwroot; // The original wwwroot of the backup file
  45      protected $targetwwwroot; // The target wwwroot of the restore operation
  46  
  47      public function __construct($restoreid, $sourcewwwroot, $targetwwwroot) {
  48          $this->restoreid = $restoreid;
  49          $this->sourcewwwroot = $sourcewwwroot;
  50          $this->targetwwwroot = $targetwwwroot;
  51  
  52          $this->contents = array();
  53          $this->rules    = array();
  54      }
  55  
  56      public function add_content($content) {
  57          if (!$content instanceof restore_decode_content) {
  58              throw new restore_decode_processor_exception('incorrect_restore_decode_content', get_class($content));
  59          }
  60          $content->set_restoreid($this->restoreid);
  61          $this->contents[] = $content;
  62      }
  63  
  64      public function add_rule($rule) {
  65          if (!$rule instanceof restore_decode_rule) {
  66              throw new restore_decode_processor_exception('incorrect_restore_decode_rule', get_class($rule));
  67          }
  68          $rule->set_restoreid($this->restoreid);
  69          $rule->set_wwwroots($this->sourcewwwroot, $this->targetwwwroot);
  70          $this->rules[] = $rule;
  71      }
  72  
  73      /**
  74       * Visit all the restore_decode_content providers
  75       * that will cause decode_content() to be called
  76       * for each content
  77       */
  78      public function execute() {
  79          // Iterate over all contents, visiting them
  80          /** @var restore_decode_content $content */
  81          foreach ($this->contents as $content) {
  82              $content->process($this);
  83          }
  84      }
  85  
  86      /**
  87       * Receive content from restore_decode_content objects
  88       * and apply all the restore_decode_rules to them
  89       */
  90      public function decode_content($content) {
  91          if (!$content = $this->precheck_content($content)) { // Perform some prechecks
  92              return false;
  93          }
  94          // Iterate over all rules, chaining results
  95          foreach ($this->rules as $rule) {
  96              $content = $rule->decode($content);
  97          }
  98          return $content;
  99      }
 100  
 101      /**
 102       * Adds all the course/section/activity/block contents and rules
 103       */
 104      public static function register_link_decoders($processor) {
 105          $tasks = array(); // To get the list of tasks having decoders
 106  
 107          // Add the course task
 108          $tasks[] = 'restore_course_task';
 109  
 110          // Add the section task
 111          $tasks[] = 'restore_section_task';
 112  
 113          // Add the module tasks
 114          $mods = core_component::get_plugin_list('mod');
 115          foreach ($mods as $mod => $moddir) {
 116              if (class_exists('restore_' . $mod . '_activity_task')) {
 117                  $tasks[] = 'restore_' . $mod . '_activity_task';
 118              }
 119          }
 120  
 121          // Add the default block task
 122          $tasks[] = 'restore_default_block_task';
 123  
 124          // Add the custom block tasks
 125          $blocks = core_component::get_plugin_list('block');
 126          foreach ($blocks as $block => $blockdir) {
 127              if (class_exists('restore_' . $block . '_block_task')) {
 128                  $tasks[] = 'restore_' . $block . '_block_task';
 129              }
 130          }
 131  
 132          // We have all the tasks registered, let's iterate over them, getting
 133          // contents and rules and adding them to the processor
 134          foreach ($tasks as $classname) {
 135              // Get restore_decode_content array and add to processor
 136              $contents = call_user_func(array($classname, 'define_decode_contents'));
 137              if (!is_array($contents)) {
 138                  throw new restore_decode_processor_exception('define_decode_contents_not_array', $classname);
 139              }
 140              foreach ($contents as $content) {
 141                  $processor->add_content($content);
 142              }
 143              // Get restore_decode_rule array and add to processor
 144              $rules = call_user_func(array($classname, 'define_decode_rules'));
 145              if (!is_array($rules)) {
 146                  throw new restore_decode_processor_exception('define_decode_rules_not_array', $classname);
 147              }
 148              foreach ($rules as $rule) {
 149                  $processor->add_rule($rule);
 150              }
 151          }
 152  
 153          // Now process all the plugins contents (note plugins don't have support for rules)
 154          // TODO: Add other plugin types (course formats, local...) here if we add them to backup/restore
 155          $plugins = array('qtype');
 156          foreach ($plugins as $plugin) {
 157              $contents = restore_plugin::get_restore_decode_contents($plugin);
 158              if (!is_array($contents)) {
 159                  throw new restore_decode_processor_exception('get_restore_decode_contents_not_array', $plugin);
 160              }
 161              foreach ($contents as $content) {
 162                  $processor->add_content($content);
 163              }
 164          }
 165      }
 166  
 167  // Protected API starts here
 168  
 169      /**
 170       * Perform some general checks in content. Returning false rules processing is skipped
 171       */
 172      protected function precheck_content($content) {
 173          // Look for $@ in content (all interlinks contain that)
 174          return (strpos($content ?? '', '$@') === false) ? false : $content;
 175      }
 176  }
 177  
 178  /*
 179   * Exception class used by all the @restore_decode_content stuff
 180   */
 181  class restore_decode_processor_exception extends backup_exception {
 182  
 183      public function __construct($errorcode, $a=NULL, $debuginfo=null) {
 184          return parent::__construct($errorcode, $a, $debuginfo);
 185      }
 186  }