Search moodle.org's
Developer Documentation

  • 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 37 and 311]

       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   * Defines restore_plugin class
      20   *
      21   * @package     core_backup
      22   * @subpackage  moodle2
      23   * @category    backup
      24   * @copyright   2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
      25   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      26   */
      27  
      28  defined('MOODLE_INTERNAL') || die();
      29  
      30  /**
      31   * Class implementing the plugins support for moodle2 restore
      32   *
      33   * TODO: Finish phpdocs
      34   */
      35  abstract class restore_plugin {
      36  
      37      /** @var string */
      38      protected $plugintype;
      39      /** @var string */
      40      protected $pluginname;
      41      /** @var string */
      42      protected $connectionpoint;
      43      /** @var restore_structure_step */
      44      protected $step;
      45      /** @var restore_course_task|restore_activity_task */
      46      protected $task;
      47  
      48      /**
      49       * restore_plugin constructor.
      50       *
      51       * @param string $plugintype
      52       * @param string $pluginname
      53       * @param restore_structure_step $step
      54       */
      55      public function __construct($plugintype, $pluginname, $step) {
      56          $this->plugintype = $plugintype;
      57          $this->pluginname = $pluginname;
      58          $this->step          = $step;
      59          $this->task          = $step->get_task();
      60          $this->connectionpoint = '';
      61      }
      62  
      63      public function define_plugin_structure($connectionpoint) {
      64          if (!$connectionpoint instanceof restore_path_element) {
      65              throw new restore_step_exception('restore_path_element_required', $connectionpoint);
      66          }
      67  
      68          $paths = array();
      69          $this->connectionpoint = $connectionpoint;
      70          $methodname = 'define_' . basename($this->connectionpoint->get_path()) . '_plugin_structure';
      71  
      72          if (method_exists($this, $methodname)) {
      73              if ($pluginpaths = $this->$methodname()) {
      74                  foreach ($pluginpaths as $path) {
      75                      if ($path->get_processing_object() === null && !$this->step->grouped_parent_exists($path, $paths)) {
      76                          $path->set_processing_object($this);
      77                      }
      78                      $paths[] = $path;
      79                  }
      80              }
      81          }
      82          return $paths;
      83      }
      84  
      85      /**
      86       * after_execute dispatcher for any restore_plugin class
      87       *
      88       * This method will dispatch execution to the corresponding
      89       * after_execute_xxx() method when available, with xxx
      90       * being the connection point of the instance, so plugin
      91       * classes with multiple connection points will support
      92       * multiple after_execute methods, one for each connection point
      93       */
      94      public function launch_after_execute_methods() {
      95          // Check if the after_execute method exists and launch it
      96          $afterexecute = 'after_execute_' . basename($this->connectionpoint->get_path());
      97          if (method_exists($this, $afterexecute)) {
      98              $this->$afterexecute();
      99          }
     100      }
     101  
     102      /**
     103       * after_restore dispatcher for any restore_plugin class
     104       *
     105       * This method will dispatch execution to the corresponding
     106       * after_restore_xxx() method when available, with xxx
     107       * being the connection point of the instance, so plugin
     108       * classes with multiple connection points will support
     109       * multiple after_restore methods, one for each connection point
     110       */
     111      public function launch_after_restore_methods() {
     112          // Check if the after_restore method exists and launch it
     113          $afterrestore = 'after_restore_' . basename($this->connectionpoint->get_path());
     114          if (method_exists($this, $afterrestore)) {
     115              $this->$afterrestore();
     116          }
     117      }
     118  
     119      /**
     120       * Returns one array with all the decode contents
     121       * to be processed by the links decoder
     122       *
     123       * This method, given one plugin type, returns one
     124       * array of {@link restore_decode_content} objects
     125       * that will be added to the restore decoder in order
     126       * to perform modifications under the plugin contents.
     127       *
     128       * The objects are retrieved by calling to the {@link define_decode_contents}
     129       * method (when available), first in the main restore_xxxx_plugin class
     130       * and later on each of the available subclasses
     131       */
     132      static public function get_restore_decode_contents($plugintype) {
     133          $decodecontents = array();
     134          // Check the requested plugintype is a valid one
     135          if (!array_key_exists($plugintype, core_component::get_plugin_types($plugintype))) {
     136               throw new backup_step_exception('incorrect_plugin_type', $plugintype);
     137          }
     138          // Check the base plugin class exists
     139          $classname = 'restore_' . $plugintype . '_plugin';
     140          if (!class_exists($classname)) {
     141               throw new backup_step_exception('plugin_class_not_found', $classname);
     142          }
     143          // First, call to the define_plugin_decode_contents in the base plugin class
     144          // (must exist by design in all the plugin base classes)
     145          if (method_exists($classname, 'define_plugin_decode_contents')) {
     146              $decodecontents = array_merge($decodecontents, call_user_func(array($classname, 'define_plugin_decode_contents')));
     147          }
     148          // Now, iterate over all the possible plugins available
     149          // (only the needed ones have been loaded, so they will
     150          // be the ones being asked here). Fetch their restore contents
     151          // by calling (if exists) to their define_decode_contents() method
     152          $plugins = core_component::get_plugin_list($plugintype);
     153          foreach ($plugins as $plugin => $plugindir) {
     154              $classname = 'restore_' . $plugintype . '_' . $plugin . '_plugin';
     155              if (class_exists($classname)) {
     156                  if (method_exists($classname, 'define_decode_contents')) {
     157                      $decodecontents = array_merge($decodecontents, call_user_func(array($classname, 'define_decode_contents')));
     158                  }
     159              }
     160          }
     161          return $decodecontents;
     162      }
     163  
     164      /**
     165       * Define the contents in the plugin that must be
     166       * processed by the link decoder
     167       */
     168      static public function define_plugin_decode_contents() {
     169          throw new coding_exception('define_plugin_decode_contents() method needs to be overridden in each subclass of restore_plugin');
     170      }
     171  
     172  // Protected API starts here
     173  
     174  // restore_step/structure_step/task wrappers
     175  
     176      protected function get_restoreid() {
     177          if (is_null($this->task)) {
     178              throw new restore_step_exception('not_specified_restore_task');
     179          }
     180          return $this->task->get_restoreid();
     181      }
     182  
     183      /**
     184       * To send ids pairs to backup_ids_table and to store them into paths
     185       *
     186       * This method will send the given itemname and old/new ids to the
     187       * backup_ids_temp table, and, at the same time, will save the new id
     188       * into the corresponding restore_path_element for easier access
     189       * by children. Also will inject the known old context id for the task
     190       * in case it's going to be used for restoring files later
     191       */
     192      protected function set_mapping($itemname, $oldid, $newid, $restorefiles = false, $filesctxid = null, $parentid = null) {
     193          $this->step->set_mapping($itemname, $oldid, $newid, $restorefiles, $filesctxid, $parentid);
     194      }
     195  
     196      /**
     197       * Returns the latest (parent) old id mapped by one pathelement
     198       */
     199      protected function get_old_parentid($itemname) {
     200          return $this->step->get_old_parentid($itemname);
     201      }
     202  
     203      /**
     204       * Returns the latest (parent) new id mapped by one pathelement
     205       */
     206      protected function get_new_parentid($itemname) {
     207          return $this->step->get_new_parentid($itemname);
     208      }
     209  
     210      /**
     211       * Return the new id of a mapping for the given itemname
     212       *
     213       * @param string $itemname the type of item
     214       * @param int $oldid the item ID from the backup
     215       * @param mixed $ifnotfound what to return if $oldid wasnt found. Defaults to false
     216       */
     217      protected function get_mappingid($itemname, $oldid, $ifnotfound = false) {
     218          return $this->step->get_mappingid($itemname, $oldid, $ifnotfound);
     219      }
     220  
     221      /**
     222       * Return the complete mapping from the given itemname, itemid
     223       */
     224      protected function get_mapping($itemname, $oldid) {
     225          return $this->step->get_mapping($itemname, $oldid);
     226      }
     227  
     228      /**
     229       * Add all the existing file, given their component and filearea and one backup_ids itemname to match with
     230       */
     231      protected function add_related_files($component, $filearea, $mappingitemname, $filesctxid = null, $olditemid = null) {
     232          $this->step->add_related_files($component, $filearea, $mappingitemname, $filesctxid, $olditemid);
     233      }
     234  
     235      /**
     236       * Apply course startdate offset based in original course startdate and course_offset_startdate setting
     237       * Note we are using one static cache here, but *by restoreid*, so it's ok for concurrence/multiple
     238       * executions in the same request
     239       */
     240      protected function apply_date_offset($value) {
     241          return $this->step->apply_date_offset($value);
     242      }
     243  
     244      /**
     245       * Returns the value of one (task/plan) setting
     246       */
     247      protected function get_setting_value($name) {
     248          if (is_null($this->task)) {
     249              throw new restore_step_exception('not_specified_restore_task');
     250          }
     251          return $this->task->get_setting_value($name);
     252      }
     253  
     254  // end of restore_step/structure_step/task wrappers
     255  
     256      /**
     257       * Simple helper function that returns the name for the restore_path_element
     258       * It's not mandatory to use it but recommended ;-)
     259       */
     260      protected function get_namefor($name = '') {
     261          $name = $name !== '' ? '_' . $name : '';
     262          return $this->plugintype . '_' . $this->pluginname . $name;
     263      }
     264  
     265      /**
     266       * Simple helper function that returns the base (prefix) of the path for the restore_path_element
     267       * Useful if we used get_recommended_name() in backup. It's not mandatory to use it but recommended ;-)
     268       */
     269      protected function get_pathfor($path = '') {
     270          $path = trim($path, '/') !== '' ? '/' . trim($path, '/') : '';
     271          return $this->connectionpoint->get_path() . '/' .
     272                 'plugin_' . $this->plugintype . '_' .
     273                 $this->pluginname . '_' . basename($this->connectionpoint->get_path()) . $path;
     274      }
     275  
     276      /**
     277       * Get the task we are part of.
     278       *
     279       * @return restore_activity_task|restore_course_task the task.
     280       */
     281      protected function get_task() {
     282          return $this->task;
     283      }
     284  }