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 / builder.php

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

752 lines 20.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 /**
15 * Helper class to setup the plugin.
16 *
17 * @since 1.0
18 */
19 class VikBookingBuilder
20 {
21 /**
22 * Loads the .mo language related to the current locale.
23 *
24 * @return void
25 */
26 public static function loadLanguage()
27 {
28 static $loaded = false;
29
30 /**
31 * Do not load the languages more than once.
32 *
33 * @since 1.8.4
34 */
35 if ($loaded)
36 {
37 return;
38 }
39
40 $loaded = true;
41
42 $app = JFactory::getApplication();
43
44 /**
45 * @since 1.0.2 All the language files have been merged
46 * within a single file to be compliant with
47 * the Worpdress Translation Standards.
48 * The language file is located in /languages folder.
49 */
50 $path = VIKBOOKING_LANG;
51
52 $handler = VIKBOOKING_LIBRARIES . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
53 $domain = 'vikbooking';
54
55 // init language
56 $lang = JFactory::getLanguage();
57
58 $lang->attachHandler($handler . 'system.php', $domain);
59
60 if ($app->isAdmin())
61 {
62 $lang->attachHandler($handler . 'adminsys.php', $domain);
63 $lang->attachHandler($handler . 'admin.php', $domain);
64 }
65 else
66 {
67 $lang->attachHandler($handler . 'site.php', $domain);
68 }
69
70 $lang->load($domain, $path);
71 }
72
73 /**
74 * Setup the pagination layout to use.
75 *
76 * @return void
77 */
78 public static function setupPaginationLayout()
79 {
80 $layout = new JLayoutFile('html.system.pagination', null, array('component' => 'com_vikbooking'));
81
82 JLoader::import('adapter.pagination.pagination');
83 JPagination::setLayout($layout);
84 }
85
86 /**
87 * Pushes the plugin pages into the WP admin menu.
88 *
89 * @return void
90 *
91 * @link https://developer.wordpress.org/resource/dashicons/#star-filled
92 */
93 public static function setupAdminMenu()
94 {
95 JLoader::import('adapter.acl.access');
96 $capability = JAccess::adjustCapability('core.manage', 'com_vikbooking');
97
98 add_menu_page(
99 JText::translate('COM_VIKBOOKING'), // page title
100 JText::translate('COM_VIKBOOKING_MENU'), // menu title
101 $capability, // capability
102 'vikbooking', // slug
103 array('VikBookingBody', 'getHtml'), // callback
104 'dashicons-building', // icon
105 71 // ordering
106 );
107 }
108
109 /**
110 * Setup HTML helper classes.
111 * This method should be used to register custom function
112 * for example to render own layouts.
113 *
114 * @return void
115 */
116 public static function setupHtmlHelpers()
117 {
118 // helper method to render calendars layout
119 JHtml::register('renderCalendar', function($data)
120 {
121 JHtml::fetch('script', VBO_SITE_URI . 'resources/jquery-ui.min.js');
122 JHtml::fetch('stylesheet', VBO_SITE_URI . 'resources/jquery-ui.min.css');
123
124 $layout = new JLayoutFile('html.plugins.calendar', null, array('component' => 'com_vikbooking'));
125
126 return $layout->render($data);
127 });
128
129 // helper method to get the plugin layout file handler
130 JHtml::register('layoutfile', function($layoutId, $basePath = null, $options = array())
131 {
132 $input = JFactory::getApplication()->input;
133
134 if (!isset($options['component']) && !$input->getBool('option'))
135 {
136 // force layout file in case there is no active plugin
137 $options['component'] = 'com_vikbooking';
138 }
139
140 return new JLayoutFile($layoutId, $basePath, $options);
141 });
142
143 // helper method to include the system JS file
144 JHtml::register('system.js', function()
145 {
146 static $loaded = 0;
147
148 if (!$loaded)
149 {
150 // include only once
151 $loaded = 1;
152
153 $internalFilesOptions = array('version' => VIKBOOKING_SOFTWARE_VERSION);
154
155 JHtml::fetch('script', VBO_ADMIN_URI . 'resources/js/system.js', $internalFilesOptions, array('id' => 'vbo-sys-script'));
156 JHtml::fetch('stylesheet', VBO_ADMIN_URI . 'resources/css/system.css', $internalFilesOptions, array('id' => 'vbo-sys-style'));
157
158 /**
159 * The CSS/JS files of Bootstrap may disturb the styles of the Theme, and so
160 * we load it only within the back-end, or if the configuration setting is on.
161 *
162 * @since 1.3.0
163 */
164 if (JFactory::getApplication()->isAdmin() || (class_exists('VikBooking') && VikBooking::loadBootstrap()))
165 {
166 /**
167 * Prior the version 1.3.5 the file bootstrap.min.js was always loaded above and outside
168 * this IF statement. We now wrap all Bootstrap assets within the admin or setting enabled.
169 *
170 * @since 1.3.5
171 */
172 JHtml::fetch('script', VBO_ADMIN_URI . 'resources/js/bootstrap.min.js', $internalFilesOptions, array('id' => 'bootstrap-script'));
173
174 JHtml::fetch('stylesheet', VBO_ADMIN_URI . 'resources/css/bootstrap.lite.css', $internalFilesOptions, array('id' => 'bootstrap-lite-style'));
175 }
176 }
177 });
178
179 // helper method to include the select2 JS file
180 JHtml::register('select2', function()
181 {
182 /**
183 * Select2 is now loaded only when requested.
184 *
185 * @since 1.2.5
186 */
187 JHtml::fetch('script', VBO_ADMIN_URI . 'resources/select2.min.js');
188 JHtml::fetch('stylesheet', VBO_ADMIN_URI . 'resources/select2.min.css');
189 });
190
191 /**
192 * Register helper methods to sanitize attributes, html, JS and other elements.
193 */
194 JHtml::register('esc_attr', function($str)
195 {
196 return esc_attr($str);
197 });
198
199 JHtml::register('esc_html', function($str)
200 {
201 return esc_html($str);
202 });
203
204 JHtml::register('esc_js', function($str)
205 {
206 return esc_js($str);
207 });
208
209 JHtml::register('esc_textarea', function($str)
210 {
211 return esc_textarea($str);
212 });
213
214 /**
215 * Attempt to turn on the SQL_BIG_SELECTS setting at runtime, to avoid
216 * SQL errors like "The SELECT would examine more than MAX_JOIN_SIZE rows;".
217 * This has affected several clients with the Channel Manager for the Guest Messages
218 * downloaded by OTAs like Booking.com or Airbnb. Since we do this operation at runtime,
219 * we attempt to suppress the DB errors in case the user does not have enough permissions
220 * to run queries of type "SET". Once executed, we restore the original value for DB errors.
221 *
222 * @since 1.16.0 (J) - 1.6.0 (WP)
223 */
224 add_action('plugins_loaded', function()
225 {
226 $dbo = JFactory::getDbo();
227
228 // suppress temporarily any database error
229 $dbo->suppress_errors(true);
230
231 // turn on the required SQL setting
232 $dbo->setQuery('SET SQL_BIG_SELECTS=1');
233 $dbo->execute();
234
235 // restore the default SQL display errors setting
236 $dbo->suppress_errors(false);
237 });
238 }
239
240 /**
241 * This method is used to configure teh payments framework.
242 * Here should be registered all the default gateways supported
243 * by the plugin.
244 *
245 * @return void
246 *
247 * @since 1.0.5
248 */
249 public static function configurePaymentFramework()
250 {
251 // push the pre-installed gateways within the payment drivers list
252 add_filter('get_supported_payments_vikbooking', function($drivers)
253 {
254 $list = glob(VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'payments' . DIRECTORY_SEPARATOR . '*.php');
255
256 return array_merge($drivers, $list);
257 });
258
259 // load payment handlers when dispatched
260 add_action('load_payment_gateway_vikbooking', function(&$drivers, $payment)
261 {
262 $classname = null;
263
264 VikBookingLoader::import('admin.payments.' . $payment, VIKBOOKING_BASE);
265
266 switch ($payment)
267 {
268 case 'paypal':
269 $classname = 'VikBookingPayPalPayment';
270 break;
271
272 case 'paypal_checkout':
273 $classname = 'VikBookingPayPalCheckoutPayment';
274 break;
275
276 case 'offline_credit_card':
277 $classname = 'VikBookingOfflineCreditCardPayment';
278 break;
279
280 case 'bank_transfer':
281 $classname = 'VikBookingBankTransferPayment';
282 break;
283 }
284
285 if ($classname)
286 {
287 $drivers[] = $classname;
288 }
289 }, 10, 2);
290
291 // manipulate response to be compliant with notifypayment task
292 add_action('payment_after_validate_transaction_vikbooking', function(&$payment, &$status, &$response)
293 {
294 /**
295 * Transaction property can be used to perform refunds, and it's collected
296 * and returned during charge/capture transactions only.
297 *
298 * @since 1.4.0
299 * @since 1.6.9 added support for "tot_fees".
300 */
301
302 // manipulate the response to be compliant with the old payment system
303 $response = array(
304 'verified' => (int) $status->isVerified(),
305 'tot_paid' => $status->amount,
306 'tot_fees' => $status->fees,
307 'log' => $status->log,
308 'transaction' => $status->transaction,
309 );
310
311 if ($status->skip_email)
312 {
313 $response['skip_email'] = $status->skip_email;
314 }
315 }, 10, 3);
316
317 // manipulate response to be compliant with dorefund task
318 add_action('payment_after_refund_transaction_vikbooking', function(&$payment, &$status, &$response)
319 {
320 /**
321 * Transactions of type refund need to unify the response
322 * to be compliant with all platforms.
323 *
324 * @since 1.4.0
325 */
326
327 // manipulate the response to be compliant with the old payment system
328 $response = array(
329 'verified' => (int) $status->isVerified(),
330 'tot_refunded' => $status->amount,
331 'log' => $status->log,
332 );
333 }, 10, 3);
334
335 // manipulate response to be compliant with direct charge transaction
336 add_action('payment_after_direct_charge_vikbooking', function($payment, $status, &$response)
337 {
338 /**
339 * Transactions of type direct charge need to unify the response
340 * to be compliant with all platforms.
341 *
342 * @since 1.6.4
343 */
344
345 // manipulate the response to be compliant with any platform
346 $response = array(
347 'verified' => (int) $status->isVerified(),
348 'tot_paid' => $status->amount,
349 'log' => $status->log,
350 'transaction' => $status->transaction,
351 );
352 }, 10, 3);
353
354 // manipulate response to be compliant with the off-session capturing requests
355 add_action('payment_after_offsession_capture_vikbooking', function($payment, $status, &$response)
356 {
357 /**
358 * Transaction property can be used to perform refunds, and it's collected
359 * and returned during charge/capture transactions only.
360 *
361 * @since 1.8.0
362 */
363
364 // manipulate the response to be compliant with any platform
365 $response = array(
366 'verified' => (int) $status->isVerified(),
367 'tot_paid' => $status->amount,
368 'tot_fees' => $status->fees ?? null,
369 'log' => $status->log ?? null,
370 'transaction' => $status->transaction ?? null,
371 );
372 }, 10, 3);
373 }
374
375 /**
376 * Registers all the widget contained within the modules folder.
377 *
378 * @return void
379 */
380 public static function setupWidgets()
381 {
382 JLoader::import('adapter.module.factory');
383
384 // load all the modules
385 JModuleFactory::load(VIKBOOKING_BASE . DIRECTORY_SEPARATOR . 'modules');
386
387 /**
388 * Loads also the widgets to display within the
389 * admin dashboard of WordPress.
390 *
391 * @since 1.3.9
392 */
393 add_action('wp_dashboard_setup', function()
394 {
395 JLoader::import('adapter.dashboard.admin');
396
397 // set up folder containing the widget to load
398 $path = VIKBOOKING_LIBRARIES . DIRECTORY_SEPARATOR . 'dashboard';
399 // define the classname prefix
400 $prefix = 'JDashboardWidgetVikBooking';
401
402 try
403 {
404 // load and register widgets
405 JDashboardAdmin::load($path, $prefix);
406 }
407 catch (Exception $e)
408 {
409 // silently suppress exception to avoid breaking the website
410
411 if (VIKBOOKING_DEBUG)
412 {
413 // propagate error in case of debug enabled
414 throw $e;
415 }
416 }
417 });
418 }
419
420 /**
421 * Configures the RSS feeds reader.
422 *
423 * @return JRssReader
424 *
425 * @since 1.3.9
426 */
427 public static function setupRssReader()
428 {
429 // autoload RSS handler class
430 JLoader::import('adapter.rss.reader');
431
432 /**
433 * Hook used to manipulate the RSS channels to which the plugin is subscribed.
434 *
435 * @param array $channels A list of RSS permalinks.
436 * @param boolean $status True to return only the published channels.
437 *
438 * @return array A list of supported channels.
439 *
440 * @since 1.3.9
441 */
442 $channels = apply_filters('vikbooking_fetch_rss_channels', array(), true);
443
444 if (VIKBOOKING_DEBUG)
445 {
446 /**
447 * Filters the transient lifetime of the feed cache.
448 *
449 * @since 2.8.0
450 *
451 * @param integer $lifetime Cache duration in seconds. Default is 43200 seconds (12 hours).
452 * @param string $filename Unique identifier for the cache object.
453 */
454 add_filter('wp_feed_cache_transient_lifetime', function($time, $url) use ($channels)
455 {
456 // in case of debug enabled, cache the feeds only for 60 seconds
457 if ($url == $channels || in_array($url, $channels))
458 {
459 $time = 60;
460 }
461
462 return $time;
463 }, 10, 2);
464 }
465
466 // instantiate RSS reader
467 $rss = JRssReader::getInstance($channels, 'vikbooking');
468
469 /**
470 * Hook used to apply some stuff before returning the RSS reader.
471 *
472 * @param JRssReader &$rss The RSS reader handler.
473 *
474 * @return void
475 *
476 * @since 1.3.9
477 */
478 do_action_ref_array('vikbooking_before_use_rss', array(&$rss));
479
480 return $rss;
481 }
482
483 /**
484 * Extends the backup framework.
485 *
486 * @return void
487 *
488 * @since 1.5
489 */
490 public static function setupBackupSystem()
491 {
492 /**
493 * Anonymous function used to check whether the manifest includes the shortcodes import.
494 *
495 * @param object $manifest The backup manifest.
496 *
497 * @return boolean
498 */
499 $hasShortcodes = function($manifest)
500 {
501 // look for the uninstall directive inside the manifest, which is mainly
502 // used during the sample data installation
503 if (isset($manifest->uninstall))
504 {
505 // iterate all uninstall queries
506 foreach ((array) $manifest->uninstall as $query)
507 {
508 // look for a table that uninstall the shortcodes
509 if (preg_match("/#__vikbooking_wpshortcodes\b/", $query))
510 {
511 return true;
512 }
513 }
514 }
515
516 // look for the directive containing the installation rules
517 if (isset($manifest->installers))
518 {
519 // iterate all install rules
520 foreach ((array) $manifest->installers as $rule)
521 {
522 // detect SQL File role
523 if ($rule->role === 'sqlfile')
524 {
525 // check shortcodes into the file path
526 $target = [$rule->data->path];
527 }
528 else if ($rule->role === 'sql')
529 {
530 // search into all the provided queries
531 $target = (array) $rule->data;
532 }
533 else
534 {
535 // nothing to check
536 $target = [];
537 }
538
539 foreach ($target as $tmp)
540 {
541 // check whether the current target mentions the shortcodes database table
542 if (preg_match("/#__vikbooking_wpshortcodes\b/", $tmp))
543 {
544 return true;
545 }
546 }
547 }
548 }
549
550 return false;
551 };
552
553 /**
554 * Trigger event to allow third party plugins to extend the backup import.
555 * This hook triggers before processing the import of an existing backup.
556 *
557 * It is possible to throw an exception to prevent the import process.
558 *
559 * Uninstalls all the pages that have been assigned to the existing shortcodes.
560 *
561 * @param object $manifest The backup manifest.
562 * @param string $path The path of the backup archive (uncompressed).
563 *
564 * @since 1.5
565 *
566 * @throws Exception
567 */
568 add_action('vikbooking_before_import_backup', function($manifest, $path) use ($hasShortcodes)
569 {
570 if (!function_exists('is_plugin_active')) {
571 require_once ABSPATH . 'wp-admin/includes/plugin.php';
572 }
573
574 /**
575 * Abort the backup import process in case Rank Math SEO plugin is installed and active.
576 *
577 * @since 1.8
578 */
579 if (is_plugin_active('seo-by-rank-math/rank-math.php')) {
580 throw new Exception('The <strong>Rank Math SEO</strong> plugin appears to be installed on your website. Before proceeding with the restoration, it is necessary to deactivate this plugin. Once the data installation is complete, you will be able to re-enable it.', 409);
581 }
582
583 // check whether the manifest includes the shortcodes installation
584 $manifest->shortcodes = $hasShortcodes($manifest);
585
586 if (empty($manifest->shortcodes))
587 {
588 // shortcodes not included within the backup, do not uninstall
589 return;
590 }
591
592 // get shortcode admin model
593 $model = JModel::getInstance('vikbooking', 'shortcodes', 'admin');
594
595 // get all existing shortcodes
596 $shortcodes = $model->all(array('createdon', 'post_id'));
597
598 // iterate all shortcodes found
599 foreach ($shortcodes as $shortcode)
600 {
601 // make sure the shortcode has been assigned to a post
602 if ($shortcode->post_id)
603 {
604 // get post details
605 $post = get_post((int) $shortcode->post_id);
606
607 if (!$post)
608 {
609 continue;
610 }
611
612 // convert shortcode creation date
613 $shortcode->createdon = new JDate($shortcode->createdon);
614 // convert post creation date
615 $post->post_date_gmt = new JDate($post->post_date_gmt);
616
617 // compare ephocs and make sure the post was not created before the shortcode
618 if ((int) $shortcode->createdon->format('U') <= (int) $post->post_date_gmt->format('U'))
619 {
620 // permanently delete post
621 wp_delete_post($post->ID, $force_delete = true);
622 }
623 }
624 }
625 }, 10, 2);
626
627 /**
628 * Trigger event to allow third party plugins to extend the backup import.
629 * This hook triggers after processing the import of an existing backup.
630 *
631 * It is possible to throw an exception to prevent the import process.
632 *
633 * Assigns all the newly created shortcodes to new pages.
634 *
635 * @param object $manifest The backup manifest.
636 * @param string $path The path of the backup archive (uncompressed).
637 *
638 * @since 1.5
639 *
640 * @throws Exception
641 */
642 add_action('vikbooking_after_import_backup', function($manifest, $path)
643 {
644 if (!empty($manifest->shortcodes))
645 {
646 // get shortcodes admin model
647 $listModel = JModel::getInstance('vikbooking', 'shortcodes', 'admin');
648
649 // get all existing shortcodes
650 $shortcodes = $listModel->all('id');
651
652 // get shortcode admin model
653 $model = JModel::getInstance('vikbooking', 'shortcode', 'admin');
654
655 // iterate all shortcodes found
656 foreach ($shortcodes as $shortcode)
657 {
658 // assign the shortcode to a new page
659 $model->addPage($shortcode->id);
660 }
661 }
662
663 // trigger full files mirroring
664 VikBookingUpdateManager::triggerUploadFullMirroring();
665 }, 10, 2);
666
667 /**
668 * Trigger event to allow third party plugins to choose what are the columns to dump
669 * and whether the table should be skipped or not.
670 *
671 * Fires while attaching a rule to dump some SQL statements.
672 *
673 * Used to avoid dumping the post ID to which the shortcodes are attached
674 *
675 * @param boolean $include False to avoid including the table into the backup.
676 * @param array &$columns An associative array of supported database table columns,
677 * where the key is the column name and the value is a nested
678 * array holding the column information.
679 * @param string $table The name of the database table.
680 *
681 * @since 1.5
682 */
683 add_filter('vikbooking_before_backup_dump_sql', function($include, &$columns, $table)
684 {
685 if (is_null($include))
686 {
687 $include = true;
688 }
689
690 // check if we are exporting the shortcodes
691 if ($table === '#__vikbooking_wpshortcodes')
692 {
693 // avoid dumping the post ID column
694 unset($columns['post_id'], $columns['tmp_post_id']);
695 }
696
697 return $include;
698 }, 10, 3);
699 }
700
701 /**
702 * Implements the tools needed to manage the overrides
703 * without having to use a FTP client.
704 *
705 * @return void
706 *
707 * @since 1.6.5
708 */
709 public static function setupOverridesManager()
710 {
711 /**
712 * Trigger event to allow the plugins to include custom HTML within the view.
713 * It is possible to return an associative array to group the HTML strings
714 * under different fieldsets. Plain/html string will be always pushed within
715 * the "custom" fieldset instead.
716 *
717 * Displays the overrides configuration.
718 *
719 * @param mixed $forms The HTML to display.
720 * @param mixed $view The current view instance.
721 *
722 * @since 1.6.5
723 */
724 add_filter('vikbooking_display_view_config_global', function($forms, $view)
725 {
726 if (!$forms)
727 {
728 // init forms array
729 $forms = [];
730 }
731
732 // render configuration layout
733 $html = JLayoutHelper::render('html.overrides.config', [
734 'view' => $view,
735 ]);
736
737 // add fieldset to forms
738 $forms[__('Page Overrides', 'vikbooking')] = $html;
739
740 return $forms;
741 }, 8, 2);
742
743 /**
744 * Hook used to display a list of breaking changes after completing an update of the plugin.
745 * The message will be displayed only once within the dashboard of VikBooking.
746 *
747 * @since 1.6.5
748 */
749 add_action('vikbooking_before_display_dashboard', array('VikBookingInstaller', 'showBreakingChanges'));
750 }
751 }
752