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_subplugin 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
28defined('MOODLE_INTERNAL') || die();
29
30/**
31 * Class implementing the subplugins support for moodle2 restore
32 *
33 * TODO: Finish phpdocs
34 * TODO: Make this subclass of restore_plugin
35 * TODO: Add support for declaring decode_contents (not decode_rules)
36 */
37abstract class restore_subplugin {
38
39    protected $subplugintype;
40    protected $subpluginname;
41    protected $connectionpoint;
42    protected $step;
43    protected $task;
44
45    public function __construct($subplugintype, $subpluginname, $step) {
46        $this->subplugintype = $subplugintype;
47        $this->subpluginname = $subpluginname;
48        $this->step          = $step;
49        $this->task          = $step->get_task();
50        $this->connectionpoint = '';
51    }
52
53    public function define_subplugin_structure($connectionpoint) {
54        if (!$connectionpoint instanceof restore_path_element) {
55            throw new restore_step_exception('restore_path_element_required', $connectionpoint);
56        }
57
58        $paths = array();
59        $this->connectionpoint = $connectionpoint;
60        $methodname = 'define_' . basename($this->connectionpoint->get_path()) . '_subplugin_structure';
61
62        if (method_exists($this, $methodname)) {
63            if ($subbluginpaths = $this->$methodname()) {
64                foreach ($subbluginpaths as $path) {
65                    $path->set_processing_object($this);
66                    $paths[] = $path;
67                }
68            }
69        }
70        return $paths;
71    }
72
73    /**
74     * after_execute dispatcher for any restore_subplugin class
75     *
76     * This method will dispatch execution to the corresponding
77     * after_execute_xxx() method when available, with xxx
78     * being the connection point of the instance, so subplugin
79     * classes with multiple connection points will support
80     * multiple after_execute methods, one for each connection point
81     */
82    public function launch_after_execute_methods() {
83        // Check if the after_execute method exists and launch it
84        $afterexecute = 'after_execute_' . basename($this->connectionpoint->get_path());
85        if (method_exists($this, $afterexecute)) {
86            $this->$afterexecute();
87        }
88    }
89
90    /**
91     * The after_restore dispatcher for any restore_subplugin class.
92     *
93     * This method will dispatch execution to the corresponding
94     * after_restore_xxx() method when available, with xxx
95     * being the connection point of the instance, so subplugin
96     * classes with multiple connection points will support
97     * multiple after_restore methods, one for each connection point.
98     */
99    public function launch_after_restore_methods() {
100        // Check if the after_restore method exists and launch it.
101        $afterestore = 'after_restore_' . basename($this->connectionpoint->get_path());
102        if (method_exists($this, $afterestore)) {
103            $this->$afterestore();
104        }
105    }
106
107// Protected API starts here
108
109// restore_step/structure_step/task wrappers
110
111    protected function get_restoreid() {
112        if (is_null($this->task)) {
113            throw new restore_step_exception('not_specified_restore_task');
114        }
115        return $this->task->get_restoreid();
116    }
117
118    /**
119     * To send ids pairs to backup_ids_table and to store them into paths
120     *
121     * This method will send the given itemname and old/new ids to the
122     * backup_ids_temp table, and, at the same time, will save the new id
123     * into the corresponding restore_path_element for easier access
124     * by children. Also will inject the known old context id for the task
125     * in case it's going to be used for restoring files later
126     */
127    protected function set_mapping($itemname, $oldid, $newid, $restorefiles = false, $filesctxid = null, $parentid = null) {
128        $this->step->set_mapping($itemname, $oldid, $newid, $restorefiles, $filesctxid, $parentid);
129    }
130
131    /**
132     * Returns the latest (parent) old id mapped by one pathelement
133     */
134    protected function get_old_parentid($itemname) {
135        return $this->step->get_old_parentid($itemname);
136    }
137
138    /**
139     * Returns the latest (parent) new id mapped by one pathelement
140     */
141    protected function get_new_parentid($itemname) {
142        return $this->step->get_new_parentid($itemname);
143    }
144
145    /**
146     * Return the new id of a mapping for the given itemname
147     *
148     * @param string $itemname the type of item
149     * @param int $oldid the item ID from the backup
150     * @param mixed $ifnotfound what to return if $oldid wasnt found. Defaults to false
151     */
152    protected function get_mappingid($itemname, $oldid, $ifnotfound = false) {
153        return $this->step->get_mappingid($itemname, $oldid, $ifnotfound);
154    }
155
156    /**
157     * Return the complete mapping from the given itemname, itemid
158     */
159    protected function get_mapping($itemname, $oldid) {
160        return $this->step->get_mapping($itemname, $oldid);
161    }
162
163    /**
164     * Add all the existing file, given their component and filearea and one backup_ids itemname to match with
165     */
166    protected function add_related_files($component, $filearea, $mappingitemname, $filesctxid = null, $olditemid = null) {
167        $this->step->add_related_files($component, $filearea, $mappingitemname, $filesctxid, $olditemid);
168    }
169
170    /**
171     * Apply course startdate offset based in original course startdate and course_offset_startdate setting
172     * Note we are using one static cache here, but *by restoreid*, so it's ok for concurrence/multiple
173     * executions in the same request
174     */
175    protected function apply_date_offset($value) {
176        return $this->step->apply_date_offset($value);
177    }
178
179    /**
180     * Call the log function from the step.
181     */
182    public function log($message, $level, $a = null, $depth = null, $display = false) {
183        return $this->step->log($message, $level, $a, $depth, $display);
184    }
185
186    /**
187     * Returns the value of one (task/plan) setting
188     */
189    protected function get_setting_value($name) {
190        if (is_null($this->task)) {
191            throw new restore_step_exception('not_specified_restore_task');
192        }
193        return $this->task->get_setting_value($name);
194    }
195
196// end of restore_step/structure_step/task wrappers
197
198    /**
199     * Simple helper function that returns the name for the restore_path_element
200     * It's not mandatory to use it but recommended ;-)
201     */
202    protected function get_namefor($name = '') {
203        $name = $name !== '' ? '_' . $name : '';
204        return $this->subplugintype . '_' . $this->subpluginname . $name;
205    }
206
207    /**
208     * Simple helper function that returns the base (prefix) of the path for the restore_path_element
209     * Useful if we used get_recommended_name() in backup. It's not mandatory to use it but recommended ;-)
210     */
211    protected function get_pathfor($path = '') {
212        $path = trim($path, '/') !== '' ? '/' . trim($path, '/') : '';
213        return $this->connectionpoint->get_path() . '/' .
214               'subplugin_' . $this->subplugintype . '_' .
215               $this->subpluginname . '_' . basename($this->connectionpoint->get_path()) . $path;
216    }
217}
218