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 / libraries / system / install.php

install.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/system/install.php

702 lines 18.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking - Libraries
4 * @subpackage system
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2018 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 VikBookingLoader::import('update.manager');
15 VikBookingLoader::import('update.license');
16
17 /**
18 * Class used to handle the activation, deactivation and
19 * uninstallation of VikBooking plugin.
20 *
21 * @since 1.0
22 */
23 class VikBookingInstaller
24 {
25 /**
26 * Flag used to init the class only once.
27 *
28 * @var boolean
29 */
30 protected static $init = false;
31
32 /**
33 * Initialize the class attaching wp actions.
34 *
35 * @return void
36 */
37 public static function onInit()
38 {
39 // init only if not done yet
40 if (static::$init === false)
41 {
42 // handle installation message
43 add_action('admin_notices', array('VikBookingInstaller', 'handleMessage'));
44
45 /**
46 * Register hooks and actions here
47 */
48
49 // mark flag as true to avoid init it again
50 static::$init = true;
51 }
52
53 /**
54 * Check whether the Pro license has expired.
55 *
56 * @since 1.2.8
57 */
58 add_action('admin_notices', array('VikBookingInstaller', 'handleUpdateWarning'));
59 }
60
61 /**
62 * Handles the activation of the plugin.
63 *
64 * @param boolean $message True to display the activation message,
65 * false to ignore it.
66 *
67 * @return void
68 */
69 public static function activate($message = true)
70 {
71 // get installed software version
72 $version = get_option('vikbooking_software_version', null);
73
74 // check if the plugin has been already installed
75 if (is_null($version))
76 {
77 // dispatch UPDATER to launch installation queries
78 VikBookingUpdateManager::install();
79
80 // mark the plugin has installed to avoid duplicated installation queries
81 update_option('vikbooking_software_version', VIKBOOKING_SOFTWARE_VERSION);
82 }
83
84 if ($message)
85 {
86 // set activation flag to display a message
87 add_option('vikbooking_onactivate', 1);
88 }
89 }
90
91 /**
92 * Handles the deactivation of the plugin.
93 *
94 * @return void
95 */
96 public static function deactivate()
97 {
98 // do nothing for the moment
99 }
100
101 /**
102 * Handles the uninstallation of the plugin.
103 *
104 * @param boolean $drop True to drop the tables of VikBooking from the database.
105 *
106 * @return void
107 */
108 public static function uninstall($drop = true)
109 {
110 // dispatch UPDATER to drop database tables
111 VikBookingUpdateManager::uninstall($drop);
112
113 // delete installation flag
114 delete_option('vikbooking_software_version');
115 }
116
117 /**
118 * Handles the uninstallation of the plugin.
119 * Proxy for uninstall method which always force database drop.
120 *
121 * @return void
122 *
123 * @uses uninstall()
124 *
125 * @since 1.2.6
126 */
127 public static function delete()
128 {
129 // complete uninstallation by dropping the database
130 static::uninstall(true);
131 }
132
133 /**
134 * Checks if the current version should be updated
135 * and, eventually, processes it.
136 *
137 * @return void
138 */
139 public static function update()
140 {
141 // get installed software version
142 $version = get_option('vikbooking_software_version', null);
143
144 $app = JFactory::getApplication();
145
146 // check if we are running an older version
147 if (VikBookingUpdateManager::shouldUpdate($version))
148 {
149 /**
150 * Avoid useless redirections if doing ajax.
151 *
152 * @since 1.1.6
153 */
154 if (!wp_doing_ajax() && $app->isAdmin())
155 {
156 // Turn on maintenance mode before running the update.
157 // In case the maintenance mode was already active, then
158 // an error message will be thrown.
159 static::setMaintenance(true);
160
161 // process the update (we don't need to raise an error)
162 VikBookingUpdateManager::update($version);
163
164 // update cached plugin version
165 update_option('vikbooking_software_version', VIKBOOKING_SOFTWARE_VERSION);
166
167 // deactivate the maintenance mode on update completion
168 static::setMaintenance(false);
169
170 /**
171 * Check if pro version, but attempt to re-download the Pro settings
172 * within the current loading flow rather than redirecting. In case
173 * something goes wrong, fallback to the old "get pro" redirect method.
174 *
175 * @since 1.5.11
176 */
177 if (VikBookingLicense::isPro())
178 {
179 // load license model
180 $model = JModel::getInstance('vikbooking', 'license', 'admin');
181
182 // download PRO version hoping that all will go fine
183 $result = $model->download(VikBookingLicense::getKey());
184
185 if ($result === false)
186 {
187 // an error occurred, retrieve it as exception
188 $error = $model->getError(null, $toString = true);
189
190 // display exception error
191 $app->enqueueMessage($error, 'error');
192
193 // fallback to the pro-package download page (old method)
194 $app->redirect('index.php?option=com_vikbooking&view=getpro&version=' . $version);
195 $app->close();
196 }
197 }
198 }
199 }
200 // check if the current instance is a new blog of a network
201 else if (is_null($version))
202 {
203 /**
204 * The version is NULL, vikbooking_software_version doesn't
205 * exist as an option of this blog.
206 * We need to launch the installation manually.
207 *
208 * @see activate()
209 *
210 * @since 1.0.6
211 */
212
213 // Use FALSE to ignore the activation message
214 static::activate(false);
215 }
216 }
217
218 /**
219 * Callback used to complete the update of the plugin
220 * made after a scheduled event.
221 *
222 * @param array $results The results of all attempted updates.
223 *
224 * @return void
225 *
226 * @since 1.3.12
227 */
228 public static function automaticUpdate($results)
229 {
230 // create log trace
231 $trace = '### VikBooking Automatic Update | ' . JHtml::fetch('date', new JDate(), 'Y-m-d H:i:s') . "\n\n";
232 $trace .= "```json\n" . json_encode($results, JSON_PRETTY_PRINT) . "\n```\n\n";
233
234 if (empty($results['plugin']))
235 {
236 $results['plugin'] = [];
237 }
238
239 // iterate all plugins
240 foreach ($results['plugin'] as $plugin)
241 {
242 if (!empty($plugin->item->slug))
243 {
244 // register check trace
245 $trace .= "Does `{$plugin->item->slug}` match `vikbooking`?\n\n";
246
247 // make sure the plugin slug matches this one
248 if ($plugin->item->slug == 'vikbooking')
249 {
250 // register status trace
251 $trace .= "Did WP complete the update without errors? [" . ($plugin->result ? 'Y' : 'N') . "]\n\n";
252
253 // plugin found, make sure the update was successful
254 if ($plugin->result)
255 {
256 try
257 {
258 // register version trace
259 $trace .= sprintf("Updating from [%s] to [%s]...\n\n", VIKBOOKING_SOFTWARE_VERSION, $plugin->item->new_version);
260
261 // complete the update in background
262 static::backgroundUpdate($plugin->item->new_version);
263
264 // update completed without errors
265 $trace .= "Background update completed\n\n";
266 }
267 catch (Exception $e)
268 {
269 // something went wrong, register error within the trace
270 $trace .= sprintf(
271 "An error occurred while trying to finalize the update (%d):\n> %s\n\n",
272 $e->getCode(),
273 $e->getMessage()
274 );
275
276 /**
277 * @todo An error occurred while trying to download the PRO version,
278 * evaluate to send an e-mail to the administrator.
279 */
280 }
281 }
282 }
283 }
284 }
285
286 // register debug trace within a log file
287 JLoader::import('adapter.filesystem.file');
288 JFile::write(VIKBOOKING_BASE . DIRECTORY_SEPARATOR . 'au-log.md', $trace . "---\n\n");
289 }
290
291 /**
292 * Same as update task, but all made in background.
293 *
294 * @param string $new_version The new version of the plugin.
295 *
296 * @return void
297 *
298 * @since 1.3.12
299 */
300 protected static function backgroundUpdate($new_version)
301 {
302 // get installed software version
303 $version = get_option('vikbooking_software_version', null);
304
305 // DO NOT use shouldUpdate method because, since we are always within
306 // the same flow, the version constant is still referring to the previous
307 // version. So, always assume to proceed with the update of the plugin.
308
309 // Turn on maintenance mode before running the update.
310 // In case the maintenance mode was already active, then
311 // an error message will be thrown.
312 static::setMaintenance(true);
313
314 // process the update (we don't need to raise an error)
315 VikBookingUpdateManager::update($version);
316
317 // update cached plugin version
318 update_option('vikbooking_software_version', $new_version);
319
320 // deactivate the maintenance mode on update completion
321 static::setMaintenance(false);
322
323 // check if pro version
324 if (VikBookingLicense::isPro())
325 {
326 // load license model
327 $model = JModel::getInstance('vikbooking', 'license', 'admin');
328
329 // download PRO version hoping that all will go fine
330 $result = $model->download(VikBookingLicense::getKey());
331
332 if ($result === false)
333 {
334 // an error occurred, retrieve it as exception
335 $error = $model->getError(null, $toString = false);
336
337 // propagate exception
338 throw $error;
339 }
340 }
341 }
342
343 /**
344 * Checks whether the automatic updates should be turned off.
345 * This is useful to prevent auto-updates for those customers
346 * that are running an expired PRO version. This will avoid
347 * losing the files after an unexpected update.
348 *
349 * @param boolean $update The current auto-update choice.
350 * @param object $item The plugin offer.
351 *
352 * @return mixed Null to let WP decides, false to always deny it.
353 *
354 * @since 1.3.12
355 */
356 public static function useAutoUpdate($update, $item)
357 {
358 // make sure we are fetching VikBooking
359 if (!empty($item->slug) && $item->slug == 'vikbooking')
360 {
361 // plugin found, lets check whether the user is
362 // not running the PRO version
363 if (!VikBookingLicense::isPro())
364 {
365 // not a PRO version, check whether a license
366 // key was registered
367 if (VikBookingLicense::getKey())
368 {
369 // The plugin registered a key; the customer
370 // chose to let the license expires...
371 // We need to prevent auto-updates.
372 $update = false;
373 }
374 }
375 }
376
377 return $update;
378 }
379
380 /**
381 * Toggle maintenance mode for the site.
382 * Creates/deletes the maintenance file to enable/disable maintenance mode.
383 *
384 * @param boolean $enable True to enable maintenance mode, false to disable.
385 *
386 * @return void
387 *
388 * @since 1.4.4
389 * @since 1.4.7 the maintenance mode also relies on database options, not only on a file.
390 * we also allow to turn off/skip maintenance mode by passing a value in query string.
391 */
392 protected static function setMaintenance($enable)
393 {
394 $maintenance_file_path = VIKBOOKING_BASE . '/maintenance.txt';
395 $maintenance_db_option = 'vikbooking_maintenance';
396
397 if ($enable)
398 {
399 // check if we are in maintenance mode
400 if (JFile::exists($maintenance_file_path) && get_option($maintenance_db_option, null) !== null)
401 {
402 // allow to skip maintenance mode via query string
403 if (JFactory::getApplication()->input->getInt('skip_maintenance', 0))
404 {
405 // turn off maintenance mode
406 return static::setMaintenance(false);
407 }
408
409 // raise error message in case the update process is currently running
410 $skip_maintenance_url = JUri::current();
411 $skip_maintenance_url .= (strpos($skip_maintenance_url, '?') === false ? '?' : '&') . 'skip_maintenance=1';
412 wp_die(
413 // message to be displayed
414 '<h1>Maintenance</h1>' .
415 '<p>VikBooking is in maintenance mode. Please wait a minute for the update to complete.</p>',
416 // page title to set
417 'Maintenance',
418 // arguments to control behavior
419 array(
420 // set link for the message to be displayed
421 'link_url' => $skip_maintenance_url,
422 'link_text' => 'Skip Maintenance',
423 // HTTP error code "locked"
424 'code' => 423,
425 )
426 );
427 }
428
429 // make sure no time limits will impact the process to restore the necessary files
430 ignore_user_abort(true);
431 set_time_limit(0);
432
433 // enter maintenance mode for the current version
434 JFile::write($maintenance_file_path, VIKBOOKING_SOFTWARE_VERSION);
435 update_option($maintenance_db_option, VIKBOOKING_SOFTWARE_VERSION);
436 }
437 else
438 {
439 // turn off maintenance mode
440 JFile::delete($maintenance_file_path);
441 delete_option($maintenance_db_option);
442 }
443 }
444
445 /**
446 * In case of an expired PRO version, prompts a message informing
447 * the user that it is going to lose the PRO features.
448 *
449 * @param array $data An array of plugin metadata.
450 * @param array $response An array of metadata about the available plugin update.
451 *
452 * @return void
453 *
454 * @since 1.3.12
455 */
456 public static function getUpdateMessage($data, $response)
457 {
458 // check whether the user is not running the PRO version
459 if (!VikBookingLicense::isPro())
460 {
461 // not a PRO version, check whether a license
462 // key was registered
463 if (VikBookingLicense::getKey())
464 {
465 // The plugin registered a key; the customer
466 // chose to let the license expires...
467 // We need to display an alert.
468 add_action('admin_footer', function() use ($data, $response)
469 {
470 // display layout
471 echo JLayoutHelper::render(
472 'html.license.update',
473 array($data, $response),
474 null,
475 array('component' => 'com_vikbooking')
476 );
477 });
478 }
479 }
480 }
481
482 /**
483 * Helper method used to obtain the list of breaking
484 * changes registered within the wordpress options.
485 *
486 * @return array
487 *
488 * @since 1.6.5
489 */
490 public static function getBreakingChanges()
491 {
492 // get existing breaking changes
493 $files = get_option('vikbooking_breaking_changes');
494 // decode from JSON
495 return (array) ($files ? json_decode($files, true) : null);
496 }
497
498 /**
499 * Helper method used to register a list of breaking
500 * changes within the wordpress options.
501 *
502 * @param array $files The files to register.
503 *
504 * @return void
505 *
506 * @since 1.6.5
507 */
508 public static function registerBreakingChanges(array $files)
509 {
510 if ($files)
511 {
512 // get existing files
513 $existing = static::getBreakingChanges();
514
515 foreach ($files as $client => $list)
516 {
517 if (!$list)
518 {
519 // ignore in case the list is empty
520 continue;
521 }
522
523 if (!isset($existing[$client]))
524 {
525 // no client set, register it right now
526 $existing[$client] = (array) $list;
527 }
528 else
529 {
530 // client already set, merge existing with new ones (get rid of duplicates)
531 $existing[$client] = array_values(array_unique(array_merge($existing[$client], (array) $list)));
532 }
533 }
534
535 // register within an option the breaking changes
536 update_option('vikbooking_breaking_changes', json_encode($existing));
537 }
538 }
539
540 /**
541 * Helper method used to unregister a list of breaking
542 * changes within the wordpress options.
543 *
544 * @param string|array|null $files The file(s) to unregister.
545 * Leave empty to clear all the files.
546 *
547 * @return void
548 *
549 * @since 1.6.5
550 */
551 public static function unregisterBreakingChanges($files = null)
552 {
553 if ($files)
554 {
555 $existing = static::getBreakingChanges();
556
557 // scan all the provided files
558 foreach ((array) $files as $file)
559 {
560 // search path under each client
561 foreach ($existing as $client => $list)
562 {
563 // get index of the specified file
564 $index = array_search($file, $list);
565
566 if ($index === false)
567 {
568 // path not found, ignore
569 continue;
570 }
571
572 // remove path at the specified index
573 array_splice($existing[$client], $index, 1);
574
575 if (!$existing[$client])
576 {
577 // remove client as there are no more pending overrides
578 unset($existing[$client]);
579 }
580 }
581 }
582
583 if ($existing)
584 {
585 // update breaking changes in case the list is not empty
586 update_option('vikbooking_breaking_changes', json_encode($existing));
587 }
588 else
589 {
590 // directly delete the breaking changes option otherwise
591 static::unregisterBreakingChanges();
592 }
593 }
594 else
595 {
596 // clear breaking changes
597 delete_option('vikbooking_breaking_changes');
598 }
599 }
600
601 /**
602 * Helper method used to show the breaking changes to
603 * the administrator. This method will have no effect
604 * in case the logged-in user is not an administrator.
605 *
606 * @return void
607 *
608 * @since 1.6.5
609 */
610 public static function showBreakingChanges()
611 {
612 // make sure the user is an administrator
613 if (JFactory::getUser()->authorise('core.admin', 'com_vikbooking'))
614 {
615 // retieve breaking changes list, if any
616 $bc = static::getBreakingChanges();
617
618 if ($bc)
619 {
620 // use layout to render the warning message
621 $warn = JLayoutHelper::render(
622 'html.overrides.bc',
623 ['files' => $bc],
624 null,
625 ['component' => 'com_vikbooking']
626 );
627
628 // enqueue warning to be displayed
629 JFactory::getApplication()->enqueueMessage($warn, 'warning');
630 }
631 }
632 }
633
634 /**
635 * Method used to check for any installation message to show.
636 *
637 * @return void
638 */
639 public static function handleMessage()
640 {
641 $app = JFactory::getApplication();
642
643 // if we are in the admin section and the plugin has been activated
644 if ($app->isAdmin() && get_option('vikbooking_onactivate') == 1)
645 {
646 // delete the activation flag to avoid displaying the message more than once
647 delete_option('vikbooking_onactivate');
648
649 ?>
650 <div class="notice is-dismissible notice-success">
651 <p>
652 <strong>Thanks for activating our plugin!</strong>
653 <a href="https://vikwp.com" target="_blank">https://vikwp.com</a>
654 </p>
655 </div>
656 <?php
657 }
658 }
659
660 /**
661 * Check if the Pro version has expired to alert the user that an
662 * update would actually mean downgrading to the free version.
663 *
664 * @since 1.2.8
665 */
666 public static function handleUpdateWarning()
667 {
668 global $pagenow;
669
670 if ($pagenow == 'plugins.php' && VikBookingLicense::isExpired() && !VikBookingLicense::hasVcm())
671 {
672 if (!JFactory::getApplication()->input->cookie->getInt('vbo_update_warning_hide', 0))
673 {
674 ?>
675 <div class="notice is-dismissible notice-warning" id="vbo-update-warning">
676 <p>
677 <strong><?php echo JText::translate('VBOPROVEXPWARNUPD'); ?></strong>
678 </p>
679 </div>
680
681 <script type="text/javascript">
682 jQuery(function() {
683 jQuery('#vbo-update-warning').on('click', '.notice-dismiss', function(event, el) {
684 var numWeeks = 1;
685 if (typeof localStorage !== 'undefined') {
686 numWeeks = localStorage.getItem('vbo_update_warning_hide_count');
687 numWeeks = !numWeeks ? 0 : parseInt(numWeeks);
688 numWeeks++;
689 localStorage.setItem('vbo_update_warning_hide_count', numWeeks);
690 }
691 var nd = new Date();
692 nd.setDate(nd.getDate() + (7 * numWeeks));
693 document.cookie = 'vbo_update_warning_hide=1; expires=' + nd.toUTCString() + '; path=/; SameSite=Lax';
694 });
695 });
696 </script>
697 <?php
698 }
699 }
700 }
701 }
702