Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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-plan 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 /** 26 * Abstract class defining the needed stuff to backup one @backup_structure 27 * 28 * TODO: Finish phpdocs 29 */ 30 abstract class backup_structure_step extends backup_step { 31 32 /** 33 * Name of the file to be generated 34 * @var string 35 */ 36 protected $filename; 37 38 /** 39 * xml content transformer being used (need it here, apart from xml_writer, 40 * thanks to serialized data to process - say thanks to blocks!) 41 * @var backup_xml_transformer|null 42 */ 43 protected $contenttransformer; 44 45 /** 46 * Constructor - instantiates one object of this class 47 */ 48 public function __construct($name, $filename, $task = null) { 49 if (!is_null($task) && !($task instanceof backup_task)) { 50 throw new backup_step_exception('wrong_backup_task_specified'); 51 } 52 $this->filename = $filename; 53 $this->contenttransformer = null; 54 parent::__construct($name, $task); 55 } 56 57 public function execute() { 58 59 if (!$this->execute_condition()) { // Check any condition to execute this 60 return; 61 } 62 63 $fullpath = $this->task->get_taskbasepath(); 64 65 // We MUST have one fullpath here, else, error 66 if (empty($fullpath)) { 67 throw new backup_step_exception('backup_structure_step_undefined_fullpath'); 68 } 69 70 // Append the filename to the fullpath 71 $fullpath = rtrim($fullpath, '/') . '/' . $this->filename; 72 73 // Create output, transformer, writer, processor 74 $xo = new file_xml_output($fullpath); 75 $xt = null; 76 if (class_exists('backup_xml_transformer')) { 77 $xt = new backup_xml_transformer($this->get_courseid()); 78 $this->contenttransformer = $xt; // Save the reference to the transformer 79 // as far as we are going to need it out 80 // from xml_writer (blame serialized data!) 81 } 82 $xw = new xml_writer($xo, $xt); 83 $progress = $this->task->get_progress(); 84 $progress->start_progress($this->get_name()); 85 $pr = new backup_structure_processor($xw, $progress); 86 87 // Set processor variables from settings 88 foreach ($this->get_settings() as $setting) { 89 $pr->set_var($setting->get_name(), $setting->get_value()); 90 } 91 // Add backupid as one more var for processor 92 $pr->set_var(backup::VAR_BACKUPID, $this->get_backupid()); 93 94 // Get structure definition 95 $structure = $this->define_structure(); 96 if (! $structure instanceof backup_nested_element) { 97 throw new backup_step_exception('backup_structure_step_wrong_structure'); 98 } 99 100 // Start writer 101 $xw->start(); 102 103 // Process structure definition 104 $structure->process($pr); 105 106 // Get the results from the nested elements 107 $results = $structure->get_results(); 108 109 // Get the log messages to append to the log 110 $logs = $structure->get_logs(); 111 foreach ($logs as $log) { 112 $this->log($log->message, $log->level, $log->a, $log->depth, $log->display); 113 } 114 115 // Close everything 116 $xw->stop(); 117 $progress->end_progress(); 118 119 // Destroy the structure. It helps PHP 5.2 memory a lot! 120 $structure->destroy(); 121 122 return $results; 123 } 124 125 /** 126 * As far as backup structure steps are implementing backup_plugin stuff, they need to 127 * have the parent task available for wrapping purposes (get course/context....) 128 */ 129 public function get_task() { 130 return $this->task; 131 } 132 133 // Protected API starts here 134 135 /** 136 * Add plugin structure to any element in the structure backup tree 137 * 138 * @param string $plugintype type of plugin as defined by core_component::get_plugin_types() 139 * @param backup_nested_element $element element in the structure backup tree that 140 * we are going to add plugin information to 141 * @param bool $multiple to define if multiple plugins can produce information 142 * for each instance of $element (true) or no (false) 143 */ 144 protected function add_plugin_structure($plugintype, $element, $multiple) { 145 146 global $CFG; 147 148 // Check the requested plugintype is a valid one 149 if (!array_key_exists($plugintype, core_component::get_plugin_types($plugintype))) { 150 throw new backup_step_exception('incorrect_plugin_type', $plugintype); 151 } 152 153 // Arrived here, plugin is correct, let's create the optigroup 154 $optigroupname = $plugintype . '_' . $element->get_name() . '_plugin'; 155 $optigroup = new backup_optigroup($optigroupname, null, $multiple); 156 $element->add_child($optigroup); // Add optigroup to stay connected since beginning 157 158 // Get all the optigroup_elements, looking across all the plugin dirs 159 $pluginsdirs = core_component::get_plugin_list($plugintype); 160 foreach ($pluginsdirs as $name => $plugindir) { 161 $classname = 'backup_' . $plugintype . '_' . $name . '_plugin'; 162 $backupfile = $plugindir . '/backup/moodle2/' . $classname . '.class.php'; 163 if (file_exists($backupfile)) { 164 require_once($backupfile); 165 $backupplugin = new $classname($plugintype, $name, $optigroup, $this); 166 // Add plugin returned structure to optigroup 167 $backupplugin->define_plugin_structure($element->get_name()); 168 } 169 } 170 } 171 172 /** 173 * Add subplugin structure for a given plugin to any element in the structure backup tree. 174 * 175 * This method allows the injection of subplugins (of a specified plugin) data to any 176 * element in any backup structure. 177 * 178 * NOTE: Initially subplugins were only available for activities (mod), so only the 179 * {@link backup_activity_structure_step} class had support for them, always 180 * looking for /mod/modulenanme subplugins. This new method is a generalization of the 181 * existing one for activities, supporting all subplugins injecting information everywhere. 182 * 183 * @param string $subplugintype type of subplugin as defined in plugin's db/subplugins.json. 184 * @param backup_nested_element $element element in the backup tree (anywhere) that 185 * we are going to add subplugin information to. 186 * @param bool $multiple to define if multiple subplugins can produce information 187 * for each instance of $element (true) or no (false). 188 * @param string $plugintype type of the plugin. 189 * @param string $pluginname name of the plugin. 190 * @return void 191 */ 192 protected function add_subplugin_structure($subplugintype, $element, $multiple, $plugintype = null, $pluginname = null) { 193 global $CFG; 194 // This global declaration is required, because where we do require_once($backupfile); 195 // That file may in turn try to do require_once($CFG->dirroot ...). 196 // That worked in the past, we should keep it working. 197 198 // Verify if this is a BC call for an activity backup. See NOTE above for this special case. 199 if ($plugintype === null and $pluginname === null) { 200 $plugintype = 'mod'; 201 $pluginname = $this->task->get_modulename(); 202 // TODO: Once all the calls have been changed to add both not null plugintype and pluginname, add a debugging here. 203 } 204 205 // Check the requested plugintype is a valid one. 206 if (!array_key_exists($plugintype, core_component::get_plugin_types())) { 207 throw new backup_step_exception('incorrect_plugin_type', $plugintype); 208 } 209 210 // Check the requested pluginname, for the specified plugintype, is a valid one. 211 if (!array_key_exists($pluginname, core_component::get_plugin_list($plugintype))) { 212 throw new backup_step_exception('incorrect_plugin_name', array($plugintype, $pluginname)); 213 } 214 215 // Check the requested subplugintype is a valid one. 216 $subplugins = core_component::get_subplugins("{$plugintype}_{$pluginname}"); 217 if (null === $subplugins) { 218 throw new backup_step_exception('plugin_missing_subplugins_configuration', [$plugintype, $pluginname]); 219 } 220 if (!array_key_exists($subplugintype, $subplugins)) { 221 throw new backup_step_exception('incorrect_subplugin_type', $subplugintype); 222 } 223 224 // Arrived here, subplugin is correct, let's create the optigroup. 225 $optigroupname = $subplugintype . '_' . $element->get_name() . '_subplugin'; 226 $optigroup = new backup_optigroup($optigroupname, null, $multiple); 227 $element->add_child($optigroup); // Add optigroup to stay connected since beginning. 228 229 // Every subplugin optionally can have a common/parent subplugin 230 // class for shared stuff. 231 $parentclass = 'backup_' . $plugintype . '_' . $pluginname . '_' . $subplugintype . '_subplugin'; 232 $parentfile = core_component::get_component_directory($plugintype . '_' . $pluginname) . 233 '/backup/moodle2/' . $parentclass . '.class.php'; 234 if (file_exists($parentfile)) { 235 require_once($parentfile); 236 } 237 238 // Get all the optigroup_elements, looking over all the subplugin dirs. 239 $subpluginsdirs = core_component::get_plugin_list($subplugintype); 240 foreach ($subpluginsdirs as $name => $subpluginsdir) { 241 $classname = 'backup_' . $subplugintype . '_' . $name . '_subplugin'; 242 $backupfile = $subpluginsdir . '/backup/moodle2/' . $classname . '.class.php'; 243 if (file_exists($backupfile)) { 244 require_once($backupfile); 245 $backupsubplugin = new $classname($subplugintype, $name, $optigroup, $this); 246 // Add subplugin returned structure to optigroup. 247 $backupsubplugin->define_subplugin_structure($element->get_name()); 248 } 249 } 250 } 251 252 /** 253 * To conditionally decide if one step will be executed or no 254 * 255 * For steps needing to be executed conditionally, based in dynamic 256 * conditions (at execution time vs at declaration time) you must 257 * override this function. It will return true if the step must be 258 * executed and false if not 259 */ 260 protected function execute_condition() { 261 return true; 262 } 263 264 /** 265 * Define the structure to be processed by this backup step. 266 * 267 * @return backup_nested_element 268 */ 269 abstract protected function define_structure(); 270 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body