PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / helpers / src / backup / import / director.php

director.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/src/backup/import/director.php

362 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Wraps the instructions used to restore a backup.
16 *
17 * @since 1.5
18 */
19 class VBOBackupImportDirector
20 {
21 /**
22 * The path of the backup (folder).
23 *
24 * @var string
25 */
26 private $path;
27
28 /**
29 * The minimum requireed version to use while restoring a backup.
30 *
31 * @var string
32 */
33 private $version;
34
35 /**
36 * Class constructor.
37 *
38 * @param string $path The archive path.
39 */
40 public function __construct($path)
41 {
42 $this->path = rtrim($path, DIRECTORY_SEPARATOR);
43 }
44
45 /**
46 * Sets the version of the manifest.
47 *
48 * @param string $version
49 *
50 * @return self This object to support chaining.
51 */
52 public function setVersion($version)
53 {
54 $this->version = $version;
55
56 return $this;
57 }
58
59 /**
60 * Executes the restore process.
61 *
62 * @return void
63 *
64 * @throws Exception
65 */
66 public function process()
67 {
68 // obtain manifest object
69 $manifest = $this->parseManifest();
70
71 // make sure the backup version is compatible with the current one
72 $this->validateVersion($manifest);
73
74 /** @var VBOPlatformDispatcherInterface */
75 $dispatcher = VBOFactory::getPlatform()->getDispatcher();
76
77 /**
78 * Trigger event to allow third party plugins to extend the backup import.
79 * This hook triggers before processing the import of an existing backup.
80 *
81 * It is possible to throw an exception to prevent the import process.
82 *
83 * @param object $manifest The backup manifest.
84 * @param string $path The path of the backup archive (uncompressed).
85 *
86 * @return void
87 *
88 * @since 1.5
89 *
90 * @throws Exception
91 */
92 $dispatcher->trigger('onBeforeImportBackupVikBooking', [$manifest, $this->path]);
93
94 // execute the uninstallation rules
95 $this->uninstall($manifest);
96
97 // execute the installation rules
98 $this->install($manifest);
99
100 /**
101 * Trigger event to allow third party plugins to extend the backup import.
102 * This hook triggers after processing the import of an existing backup.
103 *
104 * It is possible to throw an exception to prevent the import process.
105 *
106 * @param object $manifest The backup manifest.
107 * @param string $path The path of the backup archive (uncompressed).
108 *
109 * @return void
110 *
111 * @since 1.5
112 *
113 * @throws Exception
114 */
115 $dispatcher->trigger('onAfterImportBackupVikBooking', [$manifest, $this->path]);
116 }
117
118 /**
119 * Helper method used to parse the manifest file contained
120 * within the backup archive.
121 *
122 * @return object
123 *
124 * @throws Exception
125 */
126 protected function parseManifest()
127 {
128 // create file
129 $file = $this->path . DIRECTORY_SEPARATOR . 'manifest.json';
130
131 if (!JFile::exists($file))
132 {
133 $path_folders = JFolder::folders($this->path);
134 if ($path_folders)
135 {
136 // update path to manifest file
137 $this->path .= DIRECTORY_SEPARATOR . $path_folders[0];
138 $file = $this->path . DIRECTORY_SEPARATOR . 'manifest.json';
139 }
140 }
141
142 // make sure the manifest exists
143 if (!JFile::exists($file))
144 {
145 // manifest not found
146 throw new Exception('The backup does not include a manifest file', 404);
147 }
148
149 $manifest = '';
150
151 // open file pointer
152 $fp = fopen($file, 'r');
153
154 while (!feof($fp))
155 {
156 // read buffer
157 $manifest .= fread($fp, 8192);
158 }
159
160 // close file pointer
161 fclose($fp);
162
163 // decode the manifest
164 $manifest = json_decode($manifest);
165
166 if (!is_object($manifest))
167 {
168 throw new Exception('The backup manifest is not valid', 500);
169 }
170
171 return $manifest;
172 }
173
174 /**
175 * Checks whether the version of the backup is compatible with the current
176 * version of the software.
177 *
178 * @param object $manifest The backup manifest.
179 *
180 * @return boolean True if compatible.
181 *
182 * @throws Exception
183 */
184 protected function validateVersion($manifest)
185 {
186 if (empty($manifest->application) || $manifest->application !== 'Vik Booking')
187 {
188 // application is missing
189 throw new Exception("Application is missing", 500);
190 }
191
192 $application = $manifest->application;
193
194 // get the identifier of the current platform
195 $platform = defined('ABSPATH') ? 'wordpress' : 'joomla';
196
197 // check whether the manifest specifies a custom version for the current platform
198 if (isset($manifest->platforms->{$platform}))
199 {
200 // append platform to program name
201 $application .= ' ' . $platform;
202
203 // override manifest with specific instructions for the current platform
204 $manifest = $manifest->platforms->{$platform};
205 }
206
207 if (empty($manifest->version))
208 {
209 // version not found
210 throw new Exception("Version not found", 500);
211 }
212
213 // check whether the version signature has been specified by the backup
214 if (isset($manifest->signature))
215 {
216 // validate version integrity
217 $signature = md5($application . ' ' . $manifest->version);
218
219 if ($signature !== $manifest->signature)
220 {
221 // the signature doesn't matche
222 throw new Exception('Signature mismatch', 500);
223 }
224 }
225
226 // first of all, make sure the backup version is equals or higher than the
227 // minimum required version
228 if (version_compare($manifest->version, $this->version, '<'))
229 {
230 // the manifest version is lower than the minimum required version
231 throw new Exception(sprintf('The backup version (%s) is not compatible with the minimum required version (%s)', $manifest->version, $this->version), 500);
232 }
233
234 // then check whether the current version is equals of higher than the backup version
235 if (version_compare(VIKBOOKING_SOFTWARE_VERSION, $manifest->version, '<')) {
236 // the software version is lower than the backup version
237 throw new Exception(sprintf('The software version (%s) is not compatible with the backup version (%s)', VIKBOOKING_SOFTWARE_VERSION, $manifest->version), 500);
238 }
239
240 return true;
241 }
242
243 /**
244 * Executes the uninstallation queries.
245 *
246 * @param object $manifest The backup manifest.
247 *
248 * @return void
249 */
250 protected function uninstall($manifest)
251 {
252 // look for uninstall queries
253 if (!isset($manifest->uninstall))
254 {
255 // nothing to execute
256 return;
257 }
258
259 $dbo = JFactory::getDbo();
260
261 // iterate queries to clean any existing records
262 foreach ((array) $manifest->uninstall as $q)
263 {
264 // launch query
265 $dbo->setQuery($q);
266 $dbo->execute();
267 }
268 }
269
270 /**
271 * Executes the installation rules.
272 *
273 * @param object $manifest The backup manifest.
274 *
275 * @return void
276 */
277 protected function install($manifest)
278 {
279 // look for installers
280 if (!isset($manifest->installers))
281 {
282 // nothing to install...
283 return;
284 }
285
286 $dispatcher = VBOFactory::getPlatform()->getDispatcher();
287
288 // iterate installers
289 foreach ((array) $manifest->installers as $install)
290 {
291 if (empty($install->role))
292 {
293 // install role not found, cannot proceed
294 throw new Exception('Missing import backup role', 500);
295 }
296
297 // extract import data from rule
298 $data = isset($install->data) ? $install->data : null;
299
300 /**
301 * Trigger event to allow third party plugins to implement at runtime new import backup rules.
302 *
303 * It is possible to throw an exception to abort the import process.
304 *
305 * @param string $role The identifier of the import rule.
306 * @param mixed $options The instructions of the backup import rule.
307 *
308 * @return boolean True in case the rule has been dispatched, false (or null) to let the
309 * system uses one of the pre-installed rules.
310 *
311 * @since 1.5
312 *
313 * @throws Exception
314 */
315 $executed = $dispatcher->filter('onExecuteImportBackupRuleVikBooking', [$install->role, $data]);
316
317 // check whether the rule has been already dispatched by a plugin
318 if (!in_array(true, $executed))
319 {
320 // dispatch one of the system rules
321 $this->loadRule($install->role)->execute($data);
322 }
323 }
324 }
325
326 /**
327 * Creates a new import rule.
328 *
329 * @param string $rule The identifier of the rule to create.
330 *
331 * @return VBOBackupImportRule
332 *
333 * @throws Exception
334 */
335 public function loadRule($rule)
336 {
337 // build class name
338 $classname = preg_replace("/_/", ' ', $rule);
339 $classname = preg_replace("/\s+/", '', ucwords($classname));
340 $classname = 'VBOBackupImportRule' . $classname;
341
342 // make sure the rule class exists
343 if (!class_exists($classname))
344 {
345 // class not found
346 throw new Exception(sprintf('Cannot find [%s] import rule class', $classname), 404);
347 }
348
349 // create new rule
350 $rule = new $classname($this->path);
351
352 // make sure we have a valid instance
353 if (!$rule instanceof VBOBackupImportRule)
354 {
355 throw new Exception(sprintf('The import rule [%s] is not a valid instance', $classname), 500);
356 }
357
358 // create the rule
359 return $rule;
360 }
361 }
362