PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.12
VikBooking Hotel Booking Engine & PMS v1.8.12
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 1.7.4 All 35 releases
vikbooking / vikbooking.php

vikbooking.php in VikBooking Hotel Booking Engine & PMS 1.8.12, at vikbooking.php

1,002 lines 28.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: VikBooking
4 Plugin URI: https://vikwp.com/plugin/vikbooking
5 Description: Certified Booking Engine for Hotels and Accommodations.
6 Version: 1.8.12
7 Author: E4J s.r.l.
8 Author URI: https://vikwp.com
9 License: GPL2
10 License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 Text Domain: vikbooking
12 Domain Path: /languages
13 */
14
15 // No direct access
16 defined('ABSPATH') or die('No script kiddies please!');
17
18 // autoload dependencies
19 require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'autoload.php';
20
21 // handle install/uninstall
22 register_activation_hook(__FILE__, array('VikBookingInstaller', 'activate'));
23 register_deactivation_hook(__FILE__, array('VikBookingInstaller', 'deactivate'));
24 register_uninstall_hook(__FILE__, array('VikBookingInstaller', 'delete'));
25
26 // init Installer
27 add_action('init', array('VikBookingInstaller', 'onInit'));
28
29 /**
30 * Fires after all automatic updates have run.
31 * Completes the update scheduled in background.
32 *
33 * @param array $results The results of all attempted updates.
34 *
35 * @since 1.3.12
36 */
37 add_action('automatic_updates_complete', array('VikBookingInstaller', 'automaticUpdate'));
38
39 /**
40 * Filters whether to automatically update core, a plugin, a theme, or a language.
41 * Used to automatically turn off the update in case a PRO version expired.
42 *
43 * @param bool|null $update Whether to update. The value of null is internally used
44 * to detect whether nothing has hooked into this filter.
45 * @param object $item The update offer.
46 *
47 * @since 1.3.12
48 */
49 add_filter('auto_update_plugin', array('VikBookingInstaller', 'useAutoUpdate'), 10, 2);
50
51 /**
52 * Fires at the end of the update message container in each
53 * row of the plugins list table.
54 *
55 * The dynamic portion of the hook name, `$file`, refers to the path
56 * of the plugin's primary file relative to the plugins directory.
57 *
58 * @link https://developer.wordpress.org/reference/hooks/in_plugin_update_message-file/
59 *
60 * @param array $data An array of plugin metadata.
61 * @param array $response An array of metadata about the available plugin update.
62 *
63 * @since 1.3.12
64 */
65 add_action('in_plugin_update_message-vikbooking/vikbooking.php', array('VikBookingInstaller', 'getUpdateMessage'), 10, 2);
66
67 // init pagination layout
68 VikBookingBuilder::setupPaginationLayout();
69 // init html helpers
70 VikBookingBuilder::setupHtmlHelpers();
71 // init payment framework
72 VikBookingBuilder::configurePaymentFramework();
73 // setup hooks to extend the backup functionalities
74 VikBookingBuilder::setupBackupSystem();
75
76 // setup plugin overrides management
77 add_action('plugins_loaded', array('VikBookingBuilder', 'setupOverridesManager'));
78
79 // setup lite system
80 add_action('plugins_loaded', array('VikBookingLiteManager', 'setup'));
81 add_action('plugins_loaded', array('VikChannelManagerLiteManager', 'setup'));
82
83 /**
84 * Added support for screen options.
85 * Parameters such as the list limit can be changed from there.
86 *
87 * @since 1.2.5
88 */
89 add_action('current_screen', array('VikBookingScreen', 'options'));
90 add_filter('set-screen-option', array('VikBookingScreen', 'saveOption'), 10, 3);
91 /**
92 * Due to WordPress 5.4.2 changes, we need to attach
93 * VikBooking to a dedicated hook in order to
94 * allow the update of the list limit.
95 *
96 * @since 1.3.5
97 */
98 add_filter('set_screen_option_vikbooking_list_limit', array('VikBookingScreen', 'saveOption'), 10, 3);
99
100 // init Session
101 add_action('init', array('JSessionHandler', 'start'), 1);
102 add_action('wp_logout', array('JSessionHandler', 'destroy'));
103
104 // filter page link to rewrite URI
105 add_action('plugins_loaded', function()
106 {
107 // installer class will check the update status
108 VikBookingInstaller::update();
109
110 global $pagenow;
111
112 $app = JFactory::getApplication();
113 $input = $app->input;
114
115 // check if the URI contains option=com_vikbooking
116 if ($input->get('option') == 'com_vikbooking')
117 {
118 // make sure we are not contacting the AJAX and POST end-points
119 if (!wp_doing_ajax() && $pagenow != 'admin-post.php')
120 {
121 /**
122 * Include page in query string only if we are in the back-end,
123 * because WordPress 5.5 seems to break the page loading in case
124 * that argument has been included in query string.
125 *
126 * It is not needed to include this argument in the front-end
127 * as the page should lean on the reached shortcode only.
128 *
129 * @since 1.3.7
130 */
131 if ($app->isAdmin())
132 {
133 // inject page=vikbooking in GET superglobal
134 $input->get->set('page', 'vikbooking');
135 }
136 }
137 else
138 {
139 // inject action=vikbooking in GET superglobal for AJAX and POST requests
140 $_GET['action'] = 'vikbooking';
141 }
142 }
143 elseif ($input->get('page') == 'vikbooking' || $input->get('action') == 'vikbooking')
144 {
145 // inject option=com_vikbooking in GET superglobal
146 $_GET['option'] = 'com_vikbooking';
147 }
148 });
149
150 // process the request and obtain the response
151 add_action('init', function()
152 {
153 /**
154 * Language files should no longer be loaded during 'plugins_loaded'.
155 *
156 * @since 1.7.6
157 */
158 VikBookingBuilder::loadLanguage();
159
160 $app = JFactory::getApplication();
161 $input = $app->input;
162
163 // if we are in the front-end, try to parse the URL to inject
164 // option, view and args in the input request
165 if ($app->isSite() && VIKBOOKING_SITE_PREPROCESS)
166 {
167 // get post ID from current URL
168 $id = url_to_postid(JUri::current());
169
170 if ($id)
171 {
172 // get shortcode admin model
173 $model = JModel::getInstance('vikbooking', 'shortcode', 'admin');
174 // get shortcode searching by post ID (false to avoid returning a new item)
175 $shortcode = $model->getItem(array('post_id' => $id), false);
176
177 if ($shortcode)
178 {
179 // build args array using the shortcode attributes
180 $args = (array) json_decode($shortcode->json, true);
181 $args['view'] = $shortcode->type;
182 $args['option'] = 'com_vikbooking';
183
184 // inject the shortcode args into the input request
185 foreach ($args as $k => $v)
186 {
187 // inject only if not defined
188 $input->def($k, $v);
189 }
190 }
191 }
192 }
193
194 // process VikBooking only if it has been requested via GET or POST
195 if ($input->get('option') == 'com_vikbooking' || $input->get('page') == 'vikbooking')
196 {
197 VikBookingBody::process();
198 }
199 });
200
201 // handle AJAX requests
202 add_action('wp_ajax_vikbooking', 'handle_vikbooking_ajax');
203 add_action('wp_ajax_nopriv_vikbooking', 'handle_vikbooking_ajax');
204
205 function handle_vikbooking_ajax()
206 {
207 VikBookingBody::getHtml();
208
209 // die to get a valid response
210 wp_die();
211 }
212
213 // setup admin menu
214 add_action('admin_menu', array('VikBookingBuilder', 'setupAdminMenu'));
215
216 // register widgets
217 add_action('widgets_init', array('VikBookingBuilder', 'setupWidgets'));
218
219 /**
220 * Load plugin language when registering the widgets as well.
221 * Since translations are now loaded at "init", they might not be available yet.
222 *
223 * @since 1.8.4
224 */
225 add_action('widgets_init', ['VikBookingBuilder', 'loadLanguage'], 1);
226
227 // handle shortcodes (SITE controller dispatcher)
228 add_shortcode('vikbooking', function($atts, $content = null)
229 {
230 $app = JFactory::getApplication();
231
232 /**
233 * Force the application client to "site" every time a shortcode is executed.
234 *
235 * @since 1.5.5
236 */
237 $app->setClient('site');
238
239 // wrap attributes in a registry
240 $args = new JObject($atts);
241
242 // get the VIEW (empty if not set)
243 $view = $args->get('view', '');
244
245 // load the FORM of the view
246 JLoader::import('adapter.form.form');
247 $path = implode(DIRECTORY_SEPARATOR, array(VBO_SITE_PATH, 'views', $view, 'tmpl', 'default.xml'));
248 // raises an exception if the VIEW is not set
249 $form = JForm::getInstance($view, $path);
250
251 // get all the XML form fields
252 $fields = $form->getFields();
253
254 // filter the fields to get a list of allowed names
255 $fields = array_map(function($f)
256 {
257 return (string) $f->attributes()->name;
258 }, $fields);
259
260 // inject query vars
261 $input = $app->input;
262 // since we are going to render the controller manually,
263 // we don't need to push the option into $_REQUEST pool.
264 // $input->set('option', 'com_vikbooking');
265
266 // Inject shortcode vars only if they are not set
267 // in the request. This is used to allow the navigation
268 // between the pages.
269 $input->def('view', $view);
270
271 foreach ($fields as $k)
272 {
273 $input->def($k, $args->get($k));
274 }
275
276 /**
277 * When saving a shortcode block through Gutenberg,
278 * WordPress tries to reach the page to check what happens.
279 * Some views of VikBooking may immediately redirect the users to
280 * another page URI.
281 * This redirect breaks the request made by WordPress for the
282 * validation of the page, which follows the new location.
283 * The code below prevents the execution of the controller
284 * in case the URI matches the REST API end-point.
285 *
286 * @since 1.7
287 */
288 $rest_prefix = trailingslashit(rest_get_url_prefix());
289 $is_rest_api = strpos($input->server->getString('REQUEST_URI', ''), $rest_prefix) !== false
290 || JUri::getInstance($input->server->getString('REQUEST_URI', ''))->hasVar('rest_route')
291 || strpos($input->server->getString('REQUEST_URI', ''), '/wp-admin/') !== false;
292
293 if ($is_rest_api && in_array($input->get('view'), ['tinyurl']))
294 {
295 // return an empty string to prevent any redirects
296 return '';
297 }
298
299 // dispatch the controller
300 return VikBookingBody::getHtml(true);
301 });
302
303 // the callback is fired before the VBO controller is dispatched
304 add_action('vikbooking_before_dispatch', function()
305 {
306 $app = JFactory::getApplication();
307 $user = Jfactory::getUser();
308
309 // initialize timezone handler
310 JDate::getDefaultTimezone();
311 date_default_timezone_set($app->get('offset', 'UTC'));
312
313 // check if the user is authorised to access the back-end (only if the client is 'admin')
314 if ($app->isAdmin() && !$user->authorise('core.manage', 'com_vikbooking'))
315 {
316 if ($user->guest)
317 {
318 // if the user is not logged, redirect to login page
319 $app->redirect('index.php');
320 exit;
321 }
322 else
323 {
324 // otherwise raise an exception
325 wp_die(
326 '<h1>' . JText::translate('FATAL_ERROR') . '</h1>' .
327 '<p>' . JText::translate('RESOURCE_AUTH_ERROR') . '</p>',
328 403
329 );
330 }
331 }
332
333 // main library
334 require_once VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikbooking.php';
335
336 if ($app->isAdmin())
337 {
338 require_once VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'vikbooking.php';
339 require_once VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'jv_helper.php';
340 }
341 else
342 {
343 // Invoke VCM before the rendering
344 VikBooking::detectUserAgent();
345 VikBooking::invokeChannelManager();
346 VikBooking::getTracker();
347 VikBooking::loadPreferredColorStyles();
348 }
349
350 /**
351 * Prevent some pages from performing an auto-redirect when running
352 * the Bricks plugin preview.
353 *
354 * @since 1.7.7
355 */
356 if ($app->input->get('bricks') === 'run' && in_array($app->input->get('view'), ['tinyurl']))
357 {
358 $app->input->set('view', '');
359 }
360 });
361
362 // instead using the default server timezone, try to use the one
363 // specified within the WordPress configuration
364 add_filter('vik_date_default_timezone', function($timezone)
365 {
366 return JFactory::getApplication()->get('offset', $timezone);
367 });
368
369 // the callback is fired once the VBO controller has been dispatched
370 add_action('vikbooking_after_dispatch', function()
371 {
372 // load assets after dispatching the controller to avoid
373 // including JS and CSS when an AJAX function exits or dies
374 VikBookingAssets::load();
375
376 /**
377 * Load javascript core.
378 *
379 * @since 1.1.8
380 */
381 JHtml::fetch('behavior.core');
382
383 // restore standard timezone
384 date_default_timezone_set(JDate::getDefaultTimezone());
385
386 /**
387 * @note when the headers have been sent or when
388 * the request is AJAX, the assets (CSS and JS) are
389 * appended to the document after the
390 * response dispatched by the controller.
391 */
392 });
393
394 // End-point for front-end post actions.
395 // The end-point URL must be built as .../wp-admin/admin-post.php
396 // and requires $_POST['action'] == 'vikbooking' to be submitted through a form or GET.
397 add_action('admin_post_vikbooking', 'handle_vikbooking_endpoint'); // if the user is logged in
398 add_action('admin_post_nopriv_vikbooking', 'handle_vikbooking_endpoint'); // if the user in not logged in
399
400 // handle POST end-point
401 function handle_vikbooking_endpoint()
402 {
403 // get PLAIN response
404 echo VikBookingBody::getResponse();
405 }
406
407 // Hook used to access the PAGE details when a user is
408 // creating or updating it. This is helpful to make a relation
409 // between the page and the injected shortcode.
410 add_action('save_post', function($post_id)
411 {
412 // get model to access all the existing shortcodes
413 $model = JModel::getInstance('vikbooking', 'shortcodes', 'admin');
414 $shortcodes = $model->all(array('id', 'shortcode', 'post_id'));
415
416 // get post data
417 $post = get_post($post_id);
418
419 /**
420 * Check if we are editing a child post as Gutenberg
421 * seems to use always the inherit status, which
422 * refers to a post parent.
423 *
424 * @since 1.0.17
425 */
426 if ($post->post_status != 'publish' && !empty($post->post_parent) && $post->post_parent != $post_id)
427 {
428 // fallback to obtain parent post data
429 $post = get_post($post->post_parent);
430
431 /**
432 * Use new post ID.
433 *
434 * @since 1.2.7 Fixed post ID property name.
435 */
436 $post_id = $post->ID;
437 }
438
439 if ($post->post_status != 'publish')
440 {
441 // ignore drafts auto-save
442 return;
443 }
444
445 // get shortcode model
446 $shortcodeModel = JModel::getInstance('vikbooking', 'shortcode', 'admin');
447
448 /**
449 * Since we need unique post IDs, all the shortcodes
450 * that are assigned to the specified $post_id should
451 * be detached.
452 *
453 * @since 1.0.17
454 */
455 foreach ($shortcodes as $data)
456 {
457 if ($data->post_id == $post_id)
458 {
459 // The post is already assigned to a shortcode.
460 // Unset it to avoid duplicated.
461 $data->post_id = 0;
462 $shortcodeModel->save($data);
463 }
464 }
465
466 // iterate the shortcodes
467 foreach ($shortcodes as $data)
468 {
469 // check if the content of the post contains the shortcode
470 if (strpos($post->post_content, html_entity_decode($data->shortcode)) !== false)
471 {
472 // inject the POST ID
473 $data->post_id = $post_id;
474
475 // update shortcode
476 $shortcodeModel->save($data);
477
478 // stop iterating
479 return;
480 }
481 }
482 });
483
484 // Hook used to unset temporarily the relationship
485 // between the trashed post and the shortcode.
486 add_action('trashed_post', function($post_id)
487 {
488 // get shortcode model
489 $model = JModel::getInstance('vikbooking', 'shortcode', 'admin');
490
491 // get the shortcode attached to the trashed post ID
492 $item = $model->getItem(array('post_id' => $post_id), false);
493
494 // if the item exists, temporarily detach the relationship
495 if ($item)
496 {
497 $item->post_id = 0;
498 $item->tmp_post_id = $post_id;
499
500 $model->save($item);
501 }
502 });
503
504 // Hook used to restore permanently the relationship
505 // between the untrashed post and the shortcode.
506 add_action('untrashed_post', function($post_id)
507 {
508 // get shortcode model
509 $model = JModel::getInstance('vikbooking', 'shortcode', 'admin');
510
511 // get the shortcode attached to the untrashed post ID
512 $item = $model->getItem(array('tmp_post_id' => $post_id), false);
513
514 // if the item exists, re-attach the relationship
515 if ($item)
516 {
517 $item->post_id = $post_id;
518 $item->tmp_post_id = 0;
519
520 $model->save($item);
521 }
522 });
523
524 // Hook used to temporarily detach the relationship
525 // between the deleted post and the shortcode.
526 add_action('deleted_post', function($post_id)
527 {
528 // get shortcode model
529 $model = JModel::getInstance('vikbooking', 'shortcode', 'admin');
530
531 // get the shortcode attached to the trashed post ID
532 $item = $model->getItem(array('tmp_post_id' => $post_id), false);
533
534 // If no item found, the "trash" feature is probably disabled.
535 // Try to take a look for a shortcode with an active relationship.
536 if (!$item)
537 {
538 $item = $model->getItem(array('post_id' => $post_id), false);
539 }
540
541 // if the item exists, permanently detach the relationship
542 if ($item)
543 {
544 $item->post_id = 0;
545 $item->tmp_post_id = 0;
546
547 $model->save($item);
548 }
549 });
550
551 if (JFactory::getApplication()->isAdmin() && !wp_doing_ajax())
552 {
553 /**
554 * @todo should we restrict these filters to the post managements pages only?
555 */
556
557 VikBookingLoader::import('system.mce');
558
559 // add new buttons
560 add_filter('mce_buttons', array('VikBookingTinyMCE', 'addShortcodesButton'));
561
562 // load the button handlers
563 add_filter('mce_external_plugins', array('VikBookingTinyMCE', 'registerShortcodesScript'));
564 }
565
566 /**
567 * Always load the Gutenberg shortcodes block to support the preview rendering.
568 *
569 * @since 1.6.7
570 */
571 VikBookingLoader::import('system.gutenberg');
572 add_action('init', ['VikBookingGutenberg', 'registerShortcodesScript']);
573
574 /**
575 * Dispatch the uninstallation of VikBooking
576 * every time a new blog (multisite) is deleted.
577 *
578 * Fires after the site is deleted from the network (WP 4.8.0 or higher).
579 *
580 * @param integer $blog_id The site ID.
581 * @param boolean $drop True if site's tables should be dropped. Default is false.
582 *
583 * @since 1.0.6
584 */
585 add_action('deleted_blog', function($blog_id, $drop)
586 {
587 VikBookingInstaller::uninstall($drop);
588 }, 10, 2);
589
590 /**
591 * Once the plugins have been loaded, evaluates to execute the
592 * scheduled cron jobs.
593 *
594 * Scheduling is processed in case a cron job is hitting wp-cron file
595 * or in case a user is visiting the website.
596 *
597 * @since 1.5.10 Schedules a different hook for each cron.
598 * @since 1.6.5 Added priority to PHP_INT_MAX - 1 to allow Vik Channel Manager
599 * to have all the intervals scheduled by Vik Booking.
600 */
601 add_action('plugins_loaded', array('VikBookingCron', 'setup'), (PHP_INT_MAX - 1));
602
603 /**
604 * Action used to register a periodic check of the automatic payments scheduled.
605 * This hook will be called by a scheduled event in WP-Cron.
606 *
607 * @since 1.6.10
608 */
609 add_action('vikbooking_cron_payments_scheduled', function()
610 {
611 // watch the automatic payments scheduled, if any
612 VBOModelPayschedules::getInstance()->watch();
613 });
614
615 /**
616 * Action used to register a periodic performance cleaning check.
617 * This hook will be called by a scheduled event in WP-Cron.
618 *
619 * @since 1.7.2
620 * @since 1.8.7 scheduled DAC expired passcodes cleaning.
621 */
622 add_action('vikbooking_cron_performance_cleaner', function()
623 {
624 // performance cleaning check
625 VBOPerformanceCleaner::runCheck();
626 // clean up expired passcodes from smart locks
627 VBOFactory::getDoorAccessControl()->cleanExpiredPasscodes();
628 });
629
630 /**
631 * Action used to register a periodic check of door-access-control framework.
632 * This hook will be called by a scheduled event in WP-Cron.
633 *
634 * @since 1.8.4
635 * @since 1.8.6 added support to watch the devices first access.
636 */
637 add_action('vikbooking_cron_door_access_control', function()
638 {
639 // watch if any booking is approaching the check-in date
640 VBOFactory::getDoorAccessControl()->handleUpcomingArrivals();
641 // watch if passcodes get used for the first time
642 VBOFactory::getDoorAccessControl()->watchFirstAccess();
643 });
644
645 /**
646 * Action used to register a periodic database cleaning check.
647 * This hook will be called by a scheduled event in WP-Cron.
648 *
649 * @since 1.8.5
650 */
651 add_action('vikbooking_cron_db_optimization', ['VBOPerformanceCleaner', 'optimizeDatabase']);
652
653 /**
654 * Install the scheduling of the hook within WP-Cron needed
655 * to watch and process the automatic payments scheduled.
656 *
657 * @since 1.6.10
658 * @since 1.7.2 registered "vikbooking_cron_performance_cleaner".
659 * @since 1.8.4 registered "vikbooking_cron_door_access_control".
660 * @since 1.8.5 registered "vikbooking_cron_db_optimization".
661 */
662 add_action('plugins_loaded', function()
663 {
664 // make sure the cron event hasn't been yet scheduled.
665 if (!wp_next_scheduled('vikbooking_cron_payments_scheduled'))
666 {
667 // schedule event starting from the current time for "every half hour"
668 // such interval will be installed by VikBookingCron::setup()
669 wp_schedule_event(time(), 'half_hour', 'vikbooking_cron_payments_scheduled');
670 }
671
672 // make sure the cron event hasn't been yet scheduled.
673 if (!wp_next_scheduled('vikbooking_cron_performance_cleaner'))
674 {
675 // schedule event starting from the current time for "every week"
676 wp_schedule_event(time(), 'weekly', 'vikbooking_cron_performance_cleaner');
677 }
678
679 // make sure the cron event hasn't been yet scheduled.
680 if (!wp_next_scheduled('vikbooking_cron_door_access_control'))
681 {
682 // schedule event starting from the current time for "every hour"
683 wp_schedule_event(time(), 'hourly', 'vikbooking_cron_door_access_control');
684 }
685
686 // make sure the cron event hasn't been yet scheduled.
687 if (!wp_next_scheduled('vikbooking_cron_db_optimization'))
688 {
689 // schedule event starting from the current time for "every hour"
690 wp_schedule_event(time(), 'hourly', 'vikbooking_cron_db_optimization');
691 }
692 }, (PHP_INT_MAX - 1));
693
694 /**
695 * Filters the action links displayed for each plugin in the Plugins list table.
696 * Hook used to filter the "deactivation" link and ask a feedback every time that
697 * button is clicked.
698 *
699 * @param array $actions An array of plugin action links. By default this can include 'activate',
700 * 'deactivate', and 'delete'. With Multisite active this can also include
701 * 'network_active' and 'network_only' items.
702 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
703 * @param array $plugin_data An array of plugin data. See `get_plugin_data()`.
704 * @param string $context The plugin context. By default this can include 'all', 'active', 'inactive',
705 * 'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
706 *
707 * @since 1.2.13
708 */
709 add_filter('plugin_action_links', array('VikBookingFeedback', 'deactivate'), 10, 4);
710
711 /**
712 * Adjusts the timezone of the website before dispatching
713 * a widget as we are currently outside of the main plugin and
714 * the timezone have probably been restored to the default one.
715 *
716 * @param string $id The widget ID (path name).
717 * @param JObject &$params The widget configuration registry.
718 *
719 * @since 1.2.10
720 */
721 add_action('vik_widget_before_dispatch_site', function($id, &$params)
722 {
723 // initialize timezone handler
724 JDate::getDefaultTimezone();
725 date_default_timezone_set(JFactory::getApplication()->get('offset', 'UTC'));
726 }, 10, 2);
727
728 /**
729 * Restores the timezone of the website after dispatching
730 * a widget in order to avoid strange behaviors with other plugins.
731 *
732 * @param string $id The widget ID (path name).
733 * @param string &$html The HTML of the widget to display.
734 *
735 * @since 1.2.10
736 */
737 add_action('vik_widget_after_dispatch_site', function($id, &$html)
738 {
739 // restore standard timezone
740 date_default_timezone_set(JDate::getDefaultTimezone());
741 }, 10, 2);
742
743 /**
744 * Added support for Loco Translate.
745 * In case some translations have been edited by using this plugin,
746 * we should look within the Loco Translate folder to check whether
747 * the requested translation is available.
748 *
749 * @param boolean $loaded True if the translation has been already loaded.
750 * @param string $domain The plugin text domain to load.
751 *
752 * @return boolean True if a new translation is loaded.
753 *
754 * @since 1.6.0
755 */
756 add_filter('vik_plugin_load_language', function($loaded, $domain)
757 {
758 // proceed only in case the translation hasn't been loaded
759 // and Loco Translate plugin is installed
760 if (!$loaded && is_dir(WP_LANG_DIR . DIRECTORY_SEPARATOR . 'loco'))
761 {
762 // Build LOCO path.
763 // Since load_plugin_textdomain accepts only relative paths,
764 // we should go back to the /wp-contents/ folder first.
765 $loco = implode(DIRECTORY_SEPARATOR, array('..', 'languages', 'loco', 'plugins'));
766
767 // try to load the plugin translation from Loco folder
768 $loaded = load_plugin_textdomain($domain, false, $loco);
769 }
770
771 return $loaded;
772 }, 10, 2);
773
774 /**
775 * Display notice messages in third party plugins
776 * to suggest the import of the reservations.
777 *
778 * @since 1.3.5
779 */
780 add_action('admin_notices', function()
781 {
782 // main library
783 require_once VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikbooking.php';
784
785 // load supported plugins
786 $supported_plugins = VikBooking::canImportBookingsFromThirdPartyPlugins();
787
788 if (wp_doing_ajax() || $supported_plugins === false)
789 {
790 return;
791 }
792
793 $lookup = array(
794 'admin.php' => 'page',
795 'edit.php' => 'post_type',
796 );
797
798 global $pagenow;
799
800 if (!isset($lookup[$pagenow]))
801 {
802 // page not observed
803 return;
804 }
805
806 $input = JFactory::getApplication()->input;
807
808 if (!preg_match("/^mphb_/i", $input->get($lookup[$pagenow])))
809 {
810 return;
811 }
812
813 // get logo URI
814 $backlogo = VikBooking::getBackendLogo();
815 ?>
816 <style>
817 #mphb-vbo-import-notice {
818 display: inline-block;
819 width: 100%;
820 box-sizing: border-box;
821 border-left-color: #cc9907;
822 box-shadow: 0 5px 10px rgba(0,0,0,.05);
823 }
824 #mphb-vbo-import-notice a.vbo-import-button {
825 float: right;
826 border: none;
827 font-size: 14px;
828 margin: 18px 10px;
829 padding: 12px 29px;
830 color: #FFF;
831 text-shadow: none;
832 font-weight: bold;
833 background: #3AA03C;
834 -moz-border-radius: 3px;
835 border-radius: 3px;
836 -webkit-border-radius: 3px;
837 text-decoration: none;
838 height: 50px;
839 text-align: center;
840 text-transform: uppercase;
841 box-shadow: none;
842 line-height: 26px;
843 }
844 a.vbo-import-button:hover {
845 background: #43BD45 !important;
846 }
847 .vbo-import-logo {
848 display: inline-block;
849 margin-top: 21px;
850 max-width: 49px;
851 }
852 .vbo-import-text {
853 font-size: 18px;
854 display: inline-block;
855 vertical-align: top;
856 margin: 31px 10px 10px 10px;
857 }
858 </style>
859
860 <div class="notice is-dismissible notice-info" id="mphb-vbo-import-notice">
861 <div class="vbo-import-wrap">
862 <p>
863 <span class="vbo-import-logo">
864 <img src="<?php echo VBO_ADMIN_URI . (!empty($backlogo) ? "resources/{$backlogo}" : 'vikbooking.png'); ?>" alt="VikBooking Logo" />
865 </span>
866 <span class="vbo-import-text"><?php echo JText::sprintf('VBO_IMPBFROM_INTO_VBO', $supported_plugins['mphb']); ?></span>
867 <a class="button vbo-import-button" href="admin.php?option=com_vikbooking&view=importbftpp"><?php echo JText::translate('VBO_IMPBFTPP_DOIMPORT_SHORT'); ?></a>
868 </p>
869 </div>
870 </div>
871 <?php
872 });
873
874 /**
875 * Downloads the RSS feeds after loading the dashboard of VikBooking.
876 *
877 * @since 1.3.9
878 */
879 add_action('vikbooking_after_display_dashboard', array('VikBookingRssFeeds', 'download'));
880
881 /**
882 * Trigger event to allow the plugins to include custom HTML within the view.
883 * It is possible to return an associative array to group the HTML strings
884 * under different fieldsets. Plain/html string will be always pushed within
885 * the "custom" fieldset instead.
886 *
887 * Displays the RSS configuration.
888 *
889 * @param mixed $forms The HTML to display.
890 * @param mixed $view The current view instance.
891 *
892 * @return mixed The HTML to display.
893 *
894 * @since 1.3.9
895 */
896 add_filter('vikbooking_display_view_config_global', array('VikBookingRssFeeds', 'config'), 10, 2);
897
898 /**
899 * Save the RSS configuration every time "saveconfig" task is reached.
900 *
901 * @since 1.3.9
902 */
903 add_action('vikbooking_before_dispatch', function()
904 {
905 $input = JFactory::getApplication()->input;
906
907 if ($input->get('task') == 'saveconfig')
908 {
909 VikBookingRssFeeds::save();
910 }
911 });
912
913 /**
914 * Hook used to manipulate the RSS channels to which the plugin is subscribed.
915 *
916 * @param array $channels A list of RSS permalinks.
917 * @param boolean $status True to return only the published channels.
918 *
919 * @return array A list of supported channels.
920 *
921 * @since 1.3.9
922 */
923 add_filter('vikbooking_fetch_rss_channels', array('VikBookingRssFeeds', 'getChannels'), 10, 2);
924
925 /**
926 * Hook used to apply some stuff before returning the RSS reader.
927 *
928 * @param JRssReader &$rss The RSS reader handler.
929 *
930 * @since 1.3.9
931 */
932 add_action('vikbooking_before_use_rss', array('VikBookingRssFeeds', 'ready'));
933
934 /**
935 * Hook used to support browser notifications on any /wp-admin
936 * page that doesn't belong to Vik Booking. Note that the hook
937 * should be 'admin_footer' and not 'admin_print_footer_scripts'.
938 *
939 * @since 1.5.0
940 */
941 add_action('admin_footer', function()
942 {
943 $app = JFactory::getApplication();
944 $input = $app->input;
945
946 // make sure we are not inside Vik Booking
947 if ($input->get('option') == 'com_vikbooking' || $input->get('page') == 'vikbooking' || $input->get('action') == 'vikbooking')
948 {
949 return;
950 }
951
952 /**
953 * Avoid conflicts with third-party page-builder plugins that may simulate the front-end.
954 *
955 * @since 1.8.1
956 */
957 if (!$app->isClient('administrator'))
958 {
959 return;
960 }
961
962 /**
963 * Let third party plugins stop Vik Booking from loading assets on other wp-admin pages.
964 *
965 * @since 1.6.1
966 */
967 $allowed = apply_filters('vikbooking_load_external_assets', true);
968 if (!$allowed)
969 {
970 return;
971 }
972
973 // initialize timezone handler
974 JDate::getDefaultTimezone();
975 date_default_timezone_set($app->get('offset', 'UTC'));
976
977 // load the necessary assets for external pages
978 VikBookingAssets::loadForExternal();
979
980 // restore standard timezone
981 date_default_timezone_set(JDate::getDefaultTimezone());
982
983 /**
984 * Reload system configuration scripts to allow
985 * Vik Booking to preload texts also on VCM.
986 *
987 * @since 1.6.0
988 */
989 JHtml::fetch('behavior.core');
990 });
991
992 /**
993 * Prevent WordPress Themes from running wptexturize() that may erroneously
994 * detect HTML tags among raw JavaScript code, by encoding ampersand symbols.
995 *
996 * @since 1.6.9
997 */
998 add_filter('run_wptexturize', function($run_texturize)
999 {
1000 return is_admin() ? $run_texturize : false;
1001 }, PHP_INT_MAX);
1002