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 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]

   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          foreach ($this->contents as $content) {
  81              $content->process($this);
  82          }
  83      }
  84  
  85      /**
  86       * Receive content from restore_decode_content objects
  87       * and apply all the restore_decode_rules to them
  88       */
  89      public function decode_content($content) {
  90          if (!$content = $this->precheck_content($content)) { // Perform some prechecks
  91              return false;
  92          }
  93          // Iterate over all rules, chaining results
  94          foreach ($this->rules as $rule) {
  95              $content = $rule->decode($content);
  96          }
  97          return $content;
  98      }
  99  
 100      /**
 101       * Adds all the course/section/activity/block contents and rules
 102       */
 103      public static function register_link_decoders($processor) {
 104          $tasks = array(); // To get the list of tasks having decoders
 105  
 106          // Add the course task
 107          $tasks[] = 'restore_course_task';
 108  
 109          // Add the section task
 110          $tasks[] = 'restore_section_task';
 111  
 112          // Add the module tasks
 113          $mods = core_component::get_plugin_list('mod');
 114          foreach ($mods as $mod => $moddir) {
 115              if (class_exists('restore_' . $mod . '_activity_task')) {
 116                  $tasks[] = 'restore_' . $mod . '_activity_task';
 117              }
 118          }
 119  
 120          // Add the default block task
 121          $tasks[] = 'restore_default_block_task';
 122  
 123          // Add the custom block tasks
 124          $blocks = core_component::get_plugin_list('block');
 125          foreach ($blocks as $block => $blockdir) {
 126              if (class_exists('restore_' . $block . '_block_task')) {
 127                  $tasks[] = 'restore_' . $block . '_block_task';
 128              }
 129          }
 130  
 131          // We have all the tasks registered, let's iterate over them, getting
 132          // contents and rules and adding them to the processor
 133          foreach ($tasks as $classname) {
 134              // Get restore_decode_content array and add to processor
 135              $contents = call_user_func(array($classname, 'define_decode_contents'));
 136              if (!is_array($contents)) {
 137                  throw new restore_decode_processor_exception('define_decode_contents_not_array', $classname);
 138              }
 139              foreach ($contents as $content) {
 140                  $processor->add_content($content);
 141              }
 142              // Get restore_decode_rule array and add to processor
 143              $rules = call_user_func(array($classname, 'define_decode_rules'));
 144              if (!is_array($rules)) {
 145                  throw new restore_decode_processor_exception('define_decode_rules_not_array', $classname);
 146              }
 147              foreach ($rules as $rule) {
 148                  $processor->add_rule($rule);
 149              }
 150          }
 151  
 152          // Now process all the plugins contents (note plugins don't have support for rules)
 153          // TODO: Add other plugin types (course formats, local...) here if we add them to backup/restore
 154          $plugins = array('qtype');
 155          foreach ($plugins as $plugin) {
 156              $contents = restore_plugin::get_restore_decode_contents($plugin);
 157              if (!is_array($contents)) {
 158                  throw new restore_decode_processor_exception('get_restore_decode_contents_not_array', $plugin);
 159              }
 160              foreach ($contents as $content) {
 161                  $processor->add_content($content);
 162              }
 163          }
 164      }
 165  
 166  // Protected API starts here
 167  
 168      /**
 169       * Perform some general checks in content. Returning false rules processing is skipped
 170       */
 171      protected function precheck_content($content) {
 172          // Look for $@ in content (all interlinks contain that)
 173          return (strpos($content, '$@') === false) ? false : $content;
 174      }
 175  }
 176  
 177  /*
 178   * Exception class used by all the @restore_decode_content stuff
 179   */
 180  class restore_decode_processor_exception extends backup_exception {
 181  
 182      public function __construct($errorcode, $a=NULL, $debuginfo=null) {
 183          return parent::__construct($errorcode, $a, $debuginfo);
 184      }
 185  }