PluginProbe
VikRestaurants Table Reservations and Take-Away / trunk
VikRestaurants Table Reservations and Take-Away vtrunk
trunk 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4
vikrestaurants / vikrestaurants.php

vikrestaurants.php in VikRestaurants Table Reservations and Take-Away trunk, at vikrestaurants.php

975 lines 30.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: VikRestaurants
4 Plugin URI: https://vikwp.com/plugin/vikrestaurants
5 Description: A professional tool for managing your restaurant reservations and take-away orders.
6 Version: 1.5.4
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: vikrestaurants
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('VikRestaurantsInstaller', 'activate'));
23 register_deactivation_hook(__FILE__, array('VikRestaurantsInstaller', 'deactivate'));
24 register_uninstall_hook(__FILE__, array('VikRestaurantsInstaller', 'delete'));
25
26 // init Installer
27 add_action('init', array('VikRestaurantsInstaller', 'update'));
28 add_action('init', array('VikRestaurantsInstaller', 'onInit'));
29
30 /**
31 * Fires after all automatic updates have run.
32 * Completes the update scheduled in background.
33 *
34 * @param array $results The results of all attempted updates.
35 *
36 * @since 1.2
37 */
38 add_action('automatic_updates_complete', array('VikRestaurantsInstaller', 'automaticUpdate'));
39
40 /**
41 * Filters whether to automatically update core, a plugin, a theme, or a language.
42 * Used to automatically turn off the update in case a PRO version expired.
43 *
44 * @param bool|null $update Whether to update. The value of null is internally used
45 * to detect whether nothing has hooked into this filter.
46 * @param object $item The update offer.
47 *
48 * @since 1.2
49 */
50 add_filter('auto_update_plugin', array('VikRestaurantsInstaller', 'useAutoUpdate'), 10, 2);
51
52 /**
53 * Fires at the end of the update message container in each
54 * row of the plugins list table.
55 *
56 * The dynamic portion of the hook name, `$file`, refers to the path
57 * of the plugin's primary file relative to the plugins directory.
58 *
59 * @link https://developer.wordpress.org/reference/hooks/in_plugin_update_message-file/
60 *
61 * @param array $data An array of plugin metadata.
62 * @param array $response An array of metadata about the available plugin update.
63 *
64 * @since 1.2
65 */
66 add_action('in_plugin_update_message-vikrestaurants/vikrestaurants.php', array('VikRestaurantsInstaller', 'getUpdateMessage'), 10, 2);
67
68 /**
69 * Hook used to display a list of breaking changes after completing an update of the plugin.
70 * The message will be displayed only once within the dashboard of VikRestaurants.
71 *
72 * @since 1.2
73 */
74 add_action('vikrestaurants_before_display_restaurant', array('VikRestaurantsInstaller', 'showBreakingChanges'));
75
76 /**
77 * Load plugin language only once all the plugins
78 * have been loaded, so that they are able to use
79 * the filters to extend the language functionalities.
80 *
81 * @since 1.4 Load language on init to prevent a WP warning.
82 */
83 add_action('init', array('VikRestaurantsBuilder', 'loadLanguage'));
84
85 // init html helpers
86 VikRestaurantsBuilder::setupHtmlHelpers();
87 // init payment framework
88 VikRestaurantsBuilder::configurePaymentFramework();
89 // init sms framework
90 VikRestaurantsBuilder::configureSmsFramework();
91 // init mirroring functions for extendable files
92 VikRestaurantsBuilder::setupMirroring();
93 // setup hooks to extend the backup functionalities
94 VikRestaurantsBuilder::setupBackupSystem();
95 // setup hooks to be used for the configuration of the wizard
96 VikRestaurantsBuilder::setupWizard();
97 // fix scripts loading via AJAX
98 VikRestaurantsAssets::fixAjax();
99
100 // setup plugin overrides management
101 add_action('plugins_loaded', array('VikRestaurantsBuilder', 'setupOverridesManager'));
102
103 // setup lite system
104 add_action('plugins_loaded', array('VikRestaurantsLiteManager', 'setup'));
105
106 // add support for Help tabs
107 add_action('current_screen', array('VikRestaurantsScreen', 'help'));
108 // add support for screen options
109 add_action('current_screen', array('VikRestaurantsScreen', 'options'));
110 // always attempt to save screen options
111 add_filter('set-screen-option', array('VikRestaurantsScreen', 'saveOption'), 10, 3);
112 /**
113 * Due to WordPress 5.4.2 changes, we need to attach
114 * VikRestaurants to a dedicated hook in order to
115 * allow the update of the list limit.
116 */
117 add_filter('set_screen_option_vikrestaurants_list_limit', array('VikRestaurantsScreen', 'saveOption'), 10, 3);
118
119 // init Session
120 add_action('init', array('JSessionHandler', 'start'), 1);
121 add_action('wp_logout', array('JSessionHandler', 'destroy'));
122
123 // filter page link to rewrite URI
124 add_action('plugins_loaded', function()
125 {
126 global $pagenow;
127
128 $app = JFactory::getApplication();
129 $input = $app->input;
130
131 // check if the URI contains option=com_vikrestaurants
132 if ($input->get('option') == 'com_vikrestaurants')
133 {
134 // make sure we are not contacting the AJAX and POST end-points
135 if (!wp_doing_ajax() && $pagenow != 'admin-post.php')
136 {
137 /**
138 * Include page in query string only if we are in the back-end,
139 * because WordPress 5.5 seems to break the page loading in case
140 * that argument has been included in query string.
141 *
142 * It is not needed to include this argument in the front-end
143 * as the page should lean on the reached shortcode only.
144 */
145 if ($app->isAdmin())
146 {
147 // inject page=vikrestaurants in GET superglobal
148 $input->get->set('page', 'vikrestaurants');
149 }
150 }
151 else
152 {
153 // inject action=vikrestaurants in GET superglobal for AJAX and POST requests
154 $input->get->set('action', 'vikrestaurants');
155 }
156 }
157 else if ($input->get('page') == 'vikrestaurants' || $input->get('action') == 'vikrestaurants')
158 {
159 // inject option=com_vikrestaurants in GET superglobal for internal component detection
160 $input->get->set('option', 'com_vikrestaurants');
161 }
162 });
163
164 // process the request and obtain the response
165 add_action('init', function()
166 {
167 $app = JFactory::getApplication();
168 $input = $app->input;
169
170 /**
171 * Added support to custom code blocks (snippets).
172 *
173 * @since 1.3
174 */
175 VREFactory::getCodeHub()->import();
176
177 /**
178 * Hook used to fetch the site pre-processing flag.
179 * When this flag is enabled, the plugin will try to dispatch the
180 * site controller within the "init" action. This is made by
181 * fetching the shortcode assigned to the current URI.
182 *
183 * By disabling this flag, the site controller will be dispatched
184 * with the headers already sent.
185 *
186 * @param boolean $preprocess The default preprocess flag.
187 *
188 * @since 1.2
189 */
190 $preprocess = apply_filters('vikrestaurants_site_preprocess', VIKRESTAURANTS_SITE_PREPROCESS);
191
192 // if we are in the front-end, try to parse the URL to inject
193 // option, view and args in the input request
194 if ($app->isSite() && $preprocess)
195 {
196 // get post ID from current URL
197 $id = url_to_postid(JUri::current());
198
199 if ($id)
200 {
201 // get shortcode admin model
202 $model = JModel::getInstance('vikrestaurants', 'shortcode', 'admin');
203 // get shortcode searching by post ID (false to avoid returning a new item)
204 $shortcode = $model->getItem(array('post_id' => $id), false);
205
206 if ($shortcode)
207 {
208 // build args array using the shortcode attributes
209 $args = (array) json_decode($shortcode->json, true);
210 $args['view'] = $shortcode->type;
211 $args['option'] = 'com_vikrestaurants';
212
213 // inject the shortcode args into the input request
214 foreach ($args as $k => $v)
215 {
216 // inject only if not defined
217 $input->def($k, $v);
218 }
219 }
220 }
221 }
222
223 /**
224 * Process VikRestaurants only if it has been requested via GET or POST.
225 *
226 * The pre-process should occur only if we are in the back-end or in case
227 * the related flag is turned on, otherwise the pre-processing technique
228 * would still take effect for those URLs that own "com_vikrestaurants"
229 * set in request (@since 1.2.3).
230 */
231 if (($app->isAdmin() || $preprocess) && ($input->get('option') == 'com_vikrestaurants' || $input->get('page') == 'vikrestaurants'))
232 {
233 VikRestaurantsBody::process();
234 }
235 });
236
237 // handle AJAX requests for both logged and guest users
238 add_action('wp_ajax_vikrestaurants', 'handle_vikrestaurants_ajax');
239 add_action('wp_ajax_nopriv_vikrestaurants', 'handle_vikrestaurants_ajax');
240
241 /**
242 * Callback used to handle AJAX requests coming
243 * from both the front-end and back-end sections.
244 *
245 * @since 1.1
246 */
247 function handle_vikrestaurants_ajax()
248 {
249 // process controller request
250 VikRestaurantsBody::getHtml();
251
252 // die to get a valid response
253 wp_die();
254 }
255
256 // setup admin menu
257 add_action('admin_menu', array('VikRestaurantsBuilder', 'setupAdminMenu'));
258
259 // register widgets
260 add_action('widgets_init', array('VikRestaurantsBuilder', 'setupWidgets'));
261
262 /**
263 * Load plugin language when registering the widgets as well.
264 * Since translations are now loaded at "init", they might not be available yet.
265 *
266 * @since 1.5
267 */
268 add_action('widgets_init', ['VikRestaurantsBuilder', 'loadLanguage'], 1);
269
270 // handle shortcodes (SITE controller dispatcher)
271 add_shortcode('vikrestaurants', function($atts, $content = null)
272 {
273 $app = JFactory::getApplication();
274
275 /**
276 * Force the application client to "site" every time a shortcode is executed.
277 *
278 * @since 1.2.7
279 */
280 $app->setClient('site');
281
282 // wrap attributes in a registry
283 $args = new JObject($atts);
284
285 // get the VIEW (empty if not set)
286 $view = $args->get('view', '');
287
288 if (!$view)
289 {
290 return $content;
291 }
292
293 // load the FORM of the view
294 JLoader::import('adapter.form.form');
295 $path = implode(DIRECTORY_SEPARATOR, array(VREBASE, 'views', $view, 'tmpl', 'default.xml'));
296 // raises an exception if the VIEW is not set
297 $form = JForm::getInstance($view, $path);
298
299 // get all the XML form fields
300 $fields = $form->getFields();
301
302 // filter the fields to get a list of allowed names
303 $fields = array_map(function($f)
304 {
305 return (string) $f->attributes()->name;
306 }, $fields);
307
308 // inject query vars
309 $input = $app->input;
310
311 // since we are going to render the controller manually,
312 // we need to push the option into $_REQUEST pool only
313 // whether it hasn't been added yet
314 $input->def('option', 'com_vikrestaurants');
315
316 // Inject shortcode vars only if they are not set
317 // in the request. This is used to allow the navigation
318 // between the pages.
319 $input->def('view', $view);
320
321 foreach ($fields as $k)
322 {
323 $input->def($k, $args->get($k));
324 }
325
326 /**
327 * When saving a shortcode block through Gutenberg,
328 * WordPress tries to reach the page to check what happens.
329 * The "takeawayconfirm" view of VikRestaurants, in case of
330 * no selected orders, immediately redirects the users to
331 * the "takeaway" page.
332 * This redirect breaks the request made by WordPress for the
333 * validation of the page, which follows the new location.
334 * The code below prevents the execution of the controller
335 * in case the URI matches the REST API end-point.
336 *
337 * @since 1.2.7 The rest_get_url_prefix(), which should be equals
338 * to /wp-json is available only on websites with pretty permalinks
339 * enabled. On sites without pretty permalinks, the route is instead
340 * added to the URL as the rest_route parameter.
341 *
342 * @since 1.3 Included additional condition to make sure we are not
343 * under the management page in the back-end.
344 */
345 $rest_prefix = trailingslashit(rest_get_url_prefix());
346 $is_rest_api = strpos($input->server->getString('REQUEST_URI', ''), $rest_prefix) !== false
347 || JUri::getInstance($input->server->getString('REQUEST_URI', ''))->hasVar('rest_route')
348 || strpos($input->server->getString('REQUEST_URI', ''), '/wp-admin/') !== false;
349
350 if ($is_rest_api && in_array($input->get('view'), ['confirmres', 'takeawayconfirm']))
351 {
352 // return an empty string to prevent any redirects
353 return '';
354 }
355
356 // dispatch the controller
357 return VikRestaurantsBody::getHtml(true);
358 });
359
360 // the callback is fired before the VRE controller is dispatched
361 add_action('vikrestaurants_before_dispatch', function()
362 {
363 $app = JFactory::getApplication();
364 $user = Jfactory::getUser();
365
366 // initialize timezone handler
367 JDate::getDefaultTimezone();
368 date_default_timezone_set($app->get('offset', 'UTC'));
369
370 // check if the user is authorised to access the back-end (only if the client is 'admin')
371 if ($app->isAdmin() && !$user->authorise('core.manage', 'com_vikrestaurants'))
372 {
373 if ($user->guest)
374 {
375 // if the user is not logged, redirect to login page
376 $app->redirect('index.php');
377 exit;
378 }
379 else
380 {
381 // otherwise raise an exception
382 wp_die(
383 '<h1>' . JText::translate('FATAL_ERROR') . '</h1>' .
384 '<p>' . JText::translate('RESOURCE_AUTH_ERROR') . '</p>',
385 403
386 );
387 }
388 }
389
390 if ($app->isAdmin())
391 {
392 // require helper files
393 require_once JPath::clean(VREADMIN . '/helpers/vikrestaurants.php');
394
395 // remove expired credit cards
396 // check every 15 minutes only
397 VikRestaurants::removeExpiredCreditCards();
398 }
399
400 if (!wp_doing_ajax())
401 {
402 // load assets only if we are not doing an AJAX call
403 VikRestaurantsAssets::load();
404 }
405
406 /**
407 * Prevent the confirmation pages from performing an auto-redirect when running
408 * the Bricks plugin preview.
409 *
410 * @since 1.4
411 */
412 if ($app->input->get('bricks') === 'run' && in_array($app->input->get('view'), ['confirmres', 'takeawayconfirm']))
413 {
414 $app->input->set('view', '');
415 }
416 });
417
418 // the callback is fired before displaying MANAGEMAP view
419 add_action('vikrestaurants_after_display_managemap', function()
420 {
421 // if we are not doing AJAX, include CSS to support full screen
422 if (!wp_doing_ajax())
423 {
424 JHtml::fetch(
425 'stylesheet',
426 VIKRESTAURANTS_CORE_MEDIA_URI . 'css/fullscreen.css',
427 array('version' => VIKRESTAURANTS_SOFTWARE_VERSION),
428 array('id' => 'vre-fullscreen-css')
429 );
430 }
431 });
432
433 // the callback is fired before displaying DASHBOARD view
434 add_action('vikrestaurants_before_display_restaurant', function()
435 {
436 $app = JFactory::getApplication();
437 $user = JFactory::getUser();
438
439 // make sure we are not doing AJAX, we are in the back-end and the user is an administrator
440 if (!wp_doing_ajax() && $app->isClient('administrator') && $user->authorise('core.admin', 'com_vikrestaurants'))
441 {
442 JToolbarHelper::shortcodes('com_vikrestaurants');
443 }
444 });
445
446 // instead using the default server timezone, try to use the one
447 // specified within the WordPress configuration
448 add_filter('vik_date_default_timezone', function($timezone)
449 {
450 return JFactory::getApplication()->get('offset', $timezone);
451 });
452
453 // the callback is fired once the VRE controller has been dispatched
454 add_action('vikrestaurants_after_dispatch', function()
455 {
456 // load assets after dispatching the controller to avoid
457 // including JS and CSS when an AJAX function exits or dies
458 // VikRestaurantsAssets::load();
459
460 // load javascript core
461 JHtml::fetch('behavior.core');
462
463 // reload Joomla options after registering the plugin scripts
464 JFactory::getDocument()->addScriptDeclaration('JoomlaCore.loadOptions();');
465
466 // restore standard timezone
467 date_default_timezone_set(JDate::getDefaultTimezone());
468
469 /**
470 * WordPress has some reserved values that shouldn't be used
471 * in query string or within the forms, otherwise they could
472 * be used to rewrite the URLs of the website.
473 *
474 * In example, by using the 'day' argument in query string,
475 * WordPress will start searching for POSTS that were created
476 * on the specified day (of the month), completely ignoring
477 * whether the current URL is used by a shortcode.
478 *
479 * For this reason, within the site section of VikRestaurants,
480 * we should unset all the reserved arguments from the superglobals
481 * once the plugin finished using them.
482 *
483 * @link https://codex.wordpress.org/WordPress_Query_Vars
484 */
485
486 $app = JFactory::getApplication();
487
488 if ($app->isSite())
489 {
490 // define here the list of all the reserved arguments
491 // that are used by VikRestaurants
492 $reserved_args_for_date_query = array(
493 'year',
494 'day',
495 'hour',
496 );
497
498 foreach ($reserved_args_for_date_query as $arg)
499 {
500 // unset argument from REQUEST
501 $app->input->delete($arg);
502 // unset argument from GET
503 $app->input->get->delete($arg);
504 // unset argument from POST
505 $app->input->post->delete($arg);
506 }
507 }
508
509 /**
510 * When the headers have been sent or when the request is AJAX
511 * the assets (CSS and JS) are appended into the document after
512 * the response is dispatched by the controller.
513 * Obviously only in case the controller doesn't manually exit.
514 */
515
516 if ($app->isAdmin())
517 {
518 /**
519 * Includes the manifest.json link within the head of the document for a better compliance
520 * with the Web Application requirements.
521 *
522 * We can attach the manifest after executing the plugin as, in case of redirect or exit,
523 * it doesn't make sense to include a link within the document.
524 *
525 * @since 1.3
526 */
527 (new E4J\VikRestaurants\Document\WebApp(
528 new E4J\VikRestaurants\Document\WebApp\Apps\VikRestaurantsAdminManifest
529 ))->load();
530 }
531 });
532
533 // End-point for front-end post actions.
534 // The end-point URL must be built as .../wp-admin/admin-post.php
535 // and requires $_POST['action'] == 'vikrestaurants' to be submitted through a form or GET.
536 add_action('admin_post_vikrestaurants', 'handle_vikrestaurants_endpoint'); // if the user is logged in
537 add_action('admin_post_nopriv_vikrestaurants', 'handle_vikrestaurants_endpoint'); // if the user in not logged in
538
539 // handle POST end-point
540 function handle_vikrestaurants_endpoint()
541 {
542 // get PLAIN response
543 echo VikRestaurantsBody::getResponse();
544 }
545
546 // Hook used to access the PAGE details when a user is
547 // creating or updating it. This is helpful to make a relation
548 // between the page and the injected shortcode.
549 add_action('save_post', function($post_id)
550 {
551 // get model to access all the existing shortcodes
552 $model = JModel::getInstance('vikrestaurants', 'shortcodes', 'admin');
553 $shortcodes = $model->all(array('id', 'shortcode', 'post_id'));
554
555 // get post data
556 $post = get_post($post_id);
557
558 // include private posts and future schedules
559 $accepted = array(
560 'publish',
561 'private',
562 'future',
563 );
564
565 /**
566 * Check if we are editing a child post as Gutenberg
567 * seems to use always the inherit status, which
568 * refers to a post parent.
569 */
570 if (!in_array($post->post_status, $accepted) && !empty($post->post_parent) && $post->post_parent != $post_id)
571 {
572 // fallback to obtain parent post data
573 $post = get_post($post->post_parent);
574
575 // use new post ID
576 $post_id = $post->ID;
577 }
578
579 if (!in_array($post->post_status, $accepted))
580 {
581 // ignore drafts auto-save
582 return;
583 }
584
585 // get shortcode model
586 $shortcodeModel = JModel::getInstance('vikrestaurants', 'shortcode', 'admin');
587
588 /**
589 * Since we need unique post IDs, all the shortcodes
590 * that are assigned to the specified $post_id should
591 * be detached.
592 */
593 foreach ($shortcodes as $data)
594 {
595 if ($data->post_id == $post_id)
596 {
597 // The post is already assigned to a shortcode.
598 // Unset it to avoid duplicated.
599 $data->post_id = 0;
600 $shortcodeModel->save($data);
601 }
602 }
603
604 // iterate the shortcodes
605 foreach ($shortcodes as $data)
606 {
607 // check if the content of the post contains the shortcode
608 if (strpos($post->post_content, html_entity_decode($data->shortcode)) !== false)
609 {
610 // inject the POST ID
611 $data->post_id = $post_id;
612
613 // update shortcode
614 $shortcodeModel->save($data);
615
616 // stop iterating
617 return;
618 }
619 }
620 });
621
622 // Hook used to unset temporarily the relationship
623 // between the trashed post and the shortcode.
624 add_action('trashed_post', function($post_id)
625 {
626 // get shortcode model
627 $model = JModel::getInstance('vikrestaurants', 'shortcode', 'admin');
628
629 // get the shortcode attached to the trashed post ID
630 $item = $model->getItem(array('post_id' => $post_id), false);
631
632 // if the item exists, temporarily detach the relationship
633 if ($item)
634 {
635 $item->post_id = 0;
636 $item->tmp_post_id = $post_id;
637
638 $model->save($item);
639 }
640 });
641
642 // Hook used to restore permanently the relationship
643 // between the untrashed post and the shortcode.
644 add_action('untrashed_post', function($post_id)
645 {
646 // get shortcode model
647 $model = JModel::getInstance('vikrestaurants', 'shortcode', 'admin');
648
649 // get the shortcode attached to the untrashed post ID
650 $item = $model->getItem(array('tmp_post_id' => $post_id), false);
651
652 // if the item exists, re-attach the relationship
653 if ($item)
654 {
655 $item->post_id = $post_id;
656 $item->tmp_post_id = 0;
657
658 $model->save($item);
659 }
660 });
661
662 // Hook used to temporarily detach the relationship
663 // between the deleted post and the shortcode.
664 add_action('deleted_post', function($post_id)
665 {
666 // get shortcode model
667 $model = JModel::getInstance('vikrestaurants', 'shortcode', 'admin');
668
669 // get the shortcode attached to the trashed post ID
670 $item = $model->getItem(array('tmp_post_id' => $post_id), false);
671
672 // If no item found, the "trash" feature is probably disabled.
673 // Try to take a look for a shortcode with an active relationship.
674 if (!$item)
675 {
676 $item = $model->getItem(array('post_id' => $post_id), false);
677 }
678
679 // if the item exists, permanently detach the relationship
680 if ($item)
681 {
682 $item->post_id = 0;
683 $item->tmp_post_id = 0;
684
685 $model->save($item);
686 }
687 });
688
689 if (JFactory::getApplication()->isAdmin() && !wp_doing_ajax())
690 {
691 VikRestaurantsLoader::import('system.mce');
692
693 // add new buttons
694 add_filter('mce_buttons', ['VikRestaurantsTinyMCE', 'addShortcodesButton']);
695
696 // load the button handlers
697 add_filter('mce_external_plugins', ['VikRestaurantsTinyMCE', 'registerShortcodesScript']);
698 }
699
700 /**
701 * Always load the Gutenberg shortcodes block to support the preview rendering.
702 *
703 * @since 1.3.2
704 */
705 VikRestaurantsLoader::import('system.gutenberg');
706 add_action('init', ['VikRestaurantsGutenberg', 'registerShortcodesScript']);
707
708 /**
709 * Dispatch the uninstallation of VikRestaurants
710 * every time a new blog (multisite) is deleted.
711 *
712 * Fires after the site is deleted from the network (WP 4.8.0 or higher).
713 *
714 * @param integer $blog_id The site ID.
715 * @param boolean $drop True if site's tables should be dropped. Default is false.
716 */
717 add_action('deleted_blog', function($blog_id, $drop)
718 {
719 VikRestaurantsInstaller::uninstall($drop);
720 }, 10, 2);
721
722 /**
723 * Suppress WP Date Query warnings when visiting the views of VikRestaurants as
724 * they might use reserved arguments in query string with wrong values, such
725 * as 'day' with UNIX timestamps.
726 *
727 * @param boolean $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
728 * @param string $function The function that was called.
729 * @param string $message A message explaining what has been done incorrectly.
730 * @param string $version The version of WordPress where the message was added.
731 */
732 add_filter('doing_it_wrong_trigger_error', function($show, $function, $message, $version)
733 {
734 $input = JFactory::getApplication()->input;
735
736 // suppress any WP_Date_Query error messages in VikRestaurants
737 if ($function == 'WP_Date_Query' && $input->get('option') == 'com_vikrestaurants')
738 {
739 // suppress the error
740 return false;
741 }
742
743 // keep the current value otherwise
744 return $show;
745 }, 10, 4);
746
747 /**
748 * Once the plugins have been loaded, evaluates to execute the
749 * scheduled cron jobs.
750 *
751 * Scheduling is processed in case a cron job is hitting wp-cron file
752 * or in case a user is visiting the website.
753 *
754 * @since 1.4
755 */
756 add_action('plugins_loaded', array('VikRestaurantsCron', 'setup'), PHP_INT_MAX);
757
758 /**
759 * Filters the action links displayed for each plugin in the Plugins list table.
760 * Hook used to filter the "deactivation" link and ask a feedback every time that
761 * button is clicked.
762 *
763 * @param array $actions An array of plugin action links. By default this can include 'activate',
764 * 'deactivate', and 'delete'. With Multisite active this can also include
765 * 'network_active' and 'network_only' items.
766 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
767 * @param array $plugin_data An array of plugin data. See `get_plugin_data()`.
768 * @param string $context The plugin context. By default this can include 'all', 'active', 'inactive',
769 * 'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
770 */
771 add_filter('plugin_action_links', array('VikRestaurantsFeedback', 'deactivate'), 10, 4);
772
773 /**
774 * Adjusts the timezone of the website before dispatching
775 * a widget as we are currently outside of the main plugin and
776 * the timezone have probably been restored to the default one.
777 *
778 * @param string $id The widget ID (path name).
779 * @param JObject &$params The widget configuration registry.
780 */
781 add_action('vik_widget_before_dispatch_site', function($id, &$params)
782 {
783 // initialize timezone handler
784 JDate::getDefaultTimezone();
785 date_default_timezone_set(JFactory::getApplication()->get('offset', 'UTC'));
786 }, 10, 2);
787
788 /**
789 * Restores the timezone of the website after dispatching
790 * a widget in order to avoid strange behaviors with other plugins.
791 *
792 * @param string $id The widget ID (path name).
793 * @param string &$html The HTML of the widget to display.
794 */
795 add_action('vik_widget_after_dispatch_site', function($id, &$html)
796 {
797 // restore standard timezone
798 date_default_timezone_set(JDate::getDefaultTimezone());
799 }, 10, 2);
800
801 /**
802 * Action triggered before loading the text domain.
803 * Loads the language handlers when needed from a
804 * different application client.
805 *
806 * @param string $domain The plugin text domain to look for.
807 * @param string $basePath The base path containing the languages.
808 * @param mixed $langtag An optional language tag to use.
809 */
810 add_action('vik_plugin_before_load_language', function($domain, $basePath, $langtag)
811 {
812 if ($domain != 'vikrestaurants')
813 {
814 // do not go ahead
815 return;
816 }
817
818 $app = JFactory::getApplication();
819 $lang = JFactory::getLanguage();
820
821 $handler = VIKRESTAURANTS_LIBRARIES . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
822
823 // check if we are in the site client and the system
824 // needs to load the language used in the back-end
825 if ($app->isSite() && $basePath == JPATH_ADMINISTRATOR)
826 {
827 // load back-end language handler
828 $lang->attachHandler($handler . 'admin.php', $domain);
829 }
830 // check if we are in the admin client and the system
831 // needs to load the language used in the front-end
832 else if ($app->isAdmin() && $basePath == JPATH_SITE)
833 {
834 // load front-end language handler
835 $lang->attachHandler($handler . 'site.php', $domain);
836 }
837 }, 10, 3);
838
839 /**
840 * Added support for Loco Translate.
841 * In case some translations have been edited by using this plugin,
842 * we should look within the Loco Translate folder to check whether
843 * the requested translation is available.
844 *
845 * @param boolean $loaded True if the translation has been already loaded.
846 * @param string $domain The plugin text domain to load.
847 *
848 * @return boolean True if a new translation is loaded.
849 */
850 add_filter('vik_plugin_load_language', function($loaded, $domain)
851 {
852 // proceed only in case the translation hasn't been loaded
853 // and Loco Translate plugin is installed
854 if (!$loaded && is_dir(WP_LANG_DIR . DIRECTORY_SEPARATOR . 'loco'))
855 {
856 // Build LOCO path.
857 // Since load_plugin_textdomain accepts only relative paths,
858 // we should go back to the /wp-contents/ folder first.
859 $loco = implode(DIRECTORY_SEPARATOR, array('..', 'languages', 'loco', 'plugins'));
860
861 // try to load the plugin translation from Loco folder
862 $loaded = load_plugin_textdomain($domain, false, $loco);
863 }
864
865 return $loaded;
866 }, 10, 2);
867
868 /**
869 * Downloads the RSS feeds after loading the dashboard of VikRestaurants.
870 *
871 * @since 1.1
872 */
873 add_action('vikrestaurants_after_display_restaurant', ['VikRestaurantsRssFeeds', 'download']);
874
875 /**
876 * Trigger event to allow the plugins to include custom HTML within the view.
877 * It is possible to return an associative array to group the HTML strings
878 * under different fieldsets. Plain/html string will be always pushed within
879 * the "custom" fieldset instead.
880 *
881 * Displays the RSS configuration.
882 *
883 * @param mixed $forms The HTML to display.
884 * @param mixed $view The current view instance.
885 * @param object $setup An object holding the panel setup.
886 *
887 * @since 1.1
888 */
889 add_filter('vikrestaurants_display_view_config_global', ['VikRestaurantsRssFeeds', 'config'], 10, 3);
890
891 /**
892 * Trigger event to allow the plugins to make something after saving
893 * a record in the database.
894 *
895 * @param mixed $dummy A dummy argument for BC.
896 * @param array $args The saved record.
897 * @param JTable $table The table instance.
898 *
899 * @since 1.1
900 */
901 add_action('vikrestaurants_after_save_config', ['VikRestaurantsRssFeeds', 'save'], 10, 3);
902
903 /**
904 * Hook used to manipulate the RSS channels to which the plugin is subscribed.
905 *
906 * @param array $channels A list of RSS permalinks.
907 * @param bool $status True to return only the published channels.
908 *
909 * @since 1.1
910 */
911 add_filter('vikrestaurants_fetch_rss_channels', ['VikRestaurantsRssFeeds', 'getChannels'], 10, 2);
912
913 /**
914 * Hook used to apply some stuff before returning the RSS reader.
915 *
916 * @param JRssReader &$rss The RSS reader handler.
917 *
918 * @since 1.1
919 */
920 add_action('vikrestaurants_before_use_rss', ['VikRestaurantsRssFeeds', 'ready']);
921
922 /**
923 * Fixed the issue with wptexturize() function, which might convert special characters contained
924 * within <script> tags into an HTML-encoded version (e.g. "&" became "&#038;").
925 *
926 * Short-circuit the usage of wptexturize for the whole front-end.
927 *
928 * @param bool $run Whether to short-circuit wptexturize().
929 *
930 * @since 1.4
931 */
932 add_filter('run_wptexturize', function($run)
933 {
934 return is_admin() ? $run : false;
935 }, PHP_INT_MAX);
936
937 /**
938 * Filters the login page errors.
939 *
940 * Hijack the default redirect to the native WP login page.
941 *
942 * @since 1.5.2
943 *
944 * @param WP_Error $error WP Error object.
945 * @param string $redirectUrl Redirect destination URL.
946 */
947 add_filter('wp_login_errors', function($error, $redirectUrl)
948 {
949 $app = JFactory::getApplication();
950
951 // make sure the login process started from VikRestaurants
952 if (strcasecmp($app->input->getString('referer', ''), 'vikrestaurants') || !$redirectUrl)
953 {
954 // login started by someone else
955 return $error;
956 }
957
958 if (is_wp_error($error))
959 {
960 foreach ($error->get_error_messages() as $errorMessage)
961 {
962 // custom error set, enqueue the message for the user
963 $app->enqueueMessage($errorMessage, 'error');
964 }
965 }
966
967 // attach an argument in query string to easily identify an error
968 $redirectUrl = new JUri($redirectUrl);
969 $redirectUrl->setVar('login_failed', 1);
970
971 // hijack default behavior by redirecting the user to our custom page
972 $app->redirect((string) $redirectUrl);
973 $app->close();
974 }, 10, 2);
975