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 / adapter / application / application.php

application.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/adapter/application/application.php

811 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikWP - Libraries
4 * @subpackage adapter.application
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2023 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 * This adapter is required to wrap common wordpress functions
16 * within the CMSApplication Joomla interface.
17 * This is helpful to improve the portability between Joomla and Wordpress.
18 *
19 * @since 10.0
20 */
21 class JApplication
22 {
23 /**
24 * Input handler for REQUEST manipulation.
25 *
26 * @var JInput
27 */
28 private $input = null;
29
30 /**
31 * The application client name.
32 *
33 * @var string
34 */
35 private $name = null;
36
37 /**
38 * Flag to check if the redirect is going to be made via javascript.
39 *
40 * @var boolean
41 */
42 private $jsRedirect = false;
43
44 /**
45 * The HTTP header status code.
46 *
47 * @var integer
48 * @since 10.1.40
49 */
50 private $status = null;
51
52 /**
53 * Class constructor.
54 *
55 * @param JInput $input The input handler.
56 */
57 public function __construct($input = null)
58 {
59 // setup application input
60 if (is_null($input))
61 {
62 $this->input = new JInput;
63 }
64 else
65 {
66 $this->input = $input;
67 }
68
69 // get current page
70 global $pagenow;
71
72 if (!$pagenow)
73 {
74 /**
75 * Current page not yet registered, we are probably under a multi-site,
76 * because the plugins_loaded hook may run before loading vars.php file.
77 *
78 * For this reason, we should auto-fill this global variable in advance
79 * by ourselves, simply by checking whether the request URL ends with
80 * admin-ajax.php
81 *
82 * @since 10.1.33
83 */
84 $self = $this->input->server->getString('PHP_SELF');
85
86 if (preg_match("/\/admin-ajax\.php$/i", $self))
87 {
88 // we reached the admin-ajax.php file, flag it
89 $pagenow = 'admin-ajax.php';
90 }
91 }
92
93 /**
94 * Set application client according to the side we
95 * are located. In case of AJAX end-point, we should
96 * fetch the client according to a reserved key
97 * that should be set in request.
98 *
99 * @since 10.1.31
100 */
101 if ($pagenow !== 'admin-ajax.php')
102 {
103 // rely on the location of the file
104 $this->name = is_admin() && $pagenow != 'admin-post.php' ? 'administrator' : 'site';
105 }
106 else
107 {
108 // rely on the AJAX reserved key
109 $this->name = $this->input->get('vik_ajax_client', 'administrator');
110 }
111 }
112
113 /**
114 * Magic method to access private properties.
115 *
116 * @param string $name The property to access.
117 *
118 * @return mixed The property.
119 */
120 public function __get($name)
121 {
122 if ($name == 'input')
123 {
124 return $this->input;
125 }
126
127 return null;
128 }
129
130 /**
131 * Returns a property of the object or the default value if the property is not set.
132 *
133 * @param string $key The name of the property.
134 * @param mixed $def The default value (optional) if none is set.
135 *
136 * @return mixed The value of the configuration.
137 */
138 public function get($key, $def = null)
139 {
140 /**
141 * The configuration is now parsed within a separated object.
142 *
143 * @see JConfig
144 * @since 10.1.4
145 */
146 return JFactory::getConfig()->get($key, $def);
147 }
148
149 /**
150 * Returns a property of the object or the default value if the property is not set.
151 *
152 * @uses get()
153 */
154 public function getCfg($key, $def = null)
155 {
156 return $this->get($key, $def);
157 }
158
159 /**
160 * Modifies a property of the object, creating it if it does not already exist.
161 *
162 * @param string $key The name of the property.
163 * @param mixed $val The value of the property to set (optional).
164 * @param mixed $network An optional flag to check whether the option
165 * should be updated for the current blog or for
166 * a different one (@since 10.1.31).
167 * - false only the current blog will be updated;
168 * - true all the network blogs will be updated;
169 * - int only the specified blog will be updated.
170 *
171 * @return mixed Previous value of the property.
172 *
173 * @uses get()
174 */
175 public function set($key, $val = null, $network = false)
176 {
177 $prev = $this->get($key);
178
179 if ($network === false || !is_multisite())
180 {
181 // use default function
182 update_option($key, $val);
183 }
184 else
185 {
186 if ($network === true)
187 {
188 // get all network sites
189 $sites = array_map(function($site)
190 {
191 // take only the blog ID
192 return $site->blog_id;
193 }, get_sites());
194 }
195 else
196 {
197 // create a list with the specified blog ID
198 $sites = array((int) $network);
199 }
200
201 // update all existing networks
202 foreach ($sites as $blog_id)
203 {
204 // switch to blog
205 switch_to_blog($blog_id);
206
207 // update network option
208 update_option($key, $val);
209
210 // restore previous blog
211 restore_current_blog();
212 }
213 }
214
215 return $prev;
216 }
217
218 /**
219 * Is admin interface?
220 *
221 * @return boolean True if this application is administrator.
222 *
223 * @uses isClient()
224 */
225 public function isAdmin()
226 {
227 return $this->isClient('administrator');
228 }
229
230 /**
231 * Is site interface?
232 *
233 * @return boolean True if this application is site.
234 *
235 * @uses isClient()
236 */
237 public function isSite()
238 {
239 return $this->isClient('site');
240 }
241
242 /**
243 * Check the client interface by name.
244 *
245 * @param string $identifier String identifier for the application interface.
246 *
247 * @return boolean True if this application is of the given type client interface.
248 */
249 public function isClient($identifier)
250 {
251 return $this->name === $identifier;
252 }
253
254 /**
255 * Forces the application to run under the specified client.
256 *
257 * @param string $identifier String identifier for the application interface.
258 *
259 * @return void
260 *
261 * @since 10.1.39
262 */
263 public function setClient($identifier)
264 {
265 $this->name = $identifier;
266 }
267
268 /**
269 * Gets a user state.
270 *
271 * @param string $key The key of the user state.
272 * @param mixed $default The default value for the state if not found.
273 *
274 * @return mixed The user state.
275 *
276 * @since 10.1.15
277 */
278 public function getUserState($key, $default = null)
279 {
280 $session = JFactory::getSession();
281
282 // extract user state from session
283 return $session->get($key, $default, 'jsession.userstate');
284 }
285
286 /**
287 * Sets the value of a user state variable.
288 *
289 * @param string $key The key of the user state.
290 * @param mixed $value The value of the variable.
291 *
292 * @return mixed The previous state, if one existed.
293 *
294 * @since 10.1.15
295 */
296 public function setUserState($key, $value)
297 {
298 // get previous state, if any
299 $old = $this->getUserState($key);
300
301 $session = JFactory::getSession();
302
303 // update session with specified state
304 $session->set($key, $value, 'jsession.userstate');
305
306 // return previous state
307 return $old;
308 }
309
310 /**
311 * Gets the value of a user state variable.
312 *
313 * @param string $key The key of the user state variable.
314 * @param string $request The name of the variable passed in a request.
315 * @param mixed $default The default value for the variable if not found.
316 * @param string $type Filter for the variable.
317 *
318 * @return mixed The request user state.
319 *
320 * @uses getUserState()
321 * @uses setUserState()
322 */
323 public function getUserStateFromRequest($key, $request, $default = null, $type = 'none')
324 {
325 // try to get value from the request
326 $val = $this->input->get($request, null, $type);
327
328 if (!is_null($val))
329 {
330 // the value exists, register the user state for later use and return it
331 $this->setUserState($key, $val);
332
333 return $val;
334 }
335
336 // Otherwise try to access the current user state.
337 // Returns default value if user state was not previously set.
338 return $this->getUserState($key, $default);
339 }
340
341 /**
342 * Enqueue a system message.
343 *
344 * @param string $msg The message to enqueue.
345 * @param string $type The message type (success, notice, warning or error).
346 *
347 * @return void
348 */
349 public function enqueueMessage($msg, $type = 'success')
350 {
351 $session = JFactory::getSession();
352
353 // use a different namespace for each application client
354 $namespace = 'jsession.' . $this->name . '.system';
355
356 // create system message object
357 $obj = new stdClass;
358 $obj->message = $msg;
359 $obj->type = $type;
360
361 // get queue from the session (an empty array if not set)
362 $queue = $session->get('messagesqueue', array(), $namespace);
363
364 // push the object only if it is not already in the queue
365 if (!in_array($obj, $queue))
366 {
367 $queue[] = $obj;
368 $session->set('messagesqueue', $queue, $namespace);
369 }
370 }
371
372 /**
373 * Returns the queue containing the system messages.
374 *
375 * @return array The messages list.
376 */
377 public function getMessagesQueue()
378 {
379 $session = JFactory::getSession();
380
381 // use a different namespace for each application client
382 $namespace = 'jsession.' . $this->name . '.system';
383
384 // get queue from the session (an empty array if not set)
385 $queue = $session->get('messagesqueue', array(), $namespace);
386
387 // flush the system queue to avoid displaying duplicated messages
388 $session->clear('messagesqueue', $namespace);
389
390 return $queue;
391 }
392
393 /**
394 * Returns the application JMenu object.
395 *
396 * @param string $name The name of the application/client.
397 * @param array $options An optional associative array of configuration settings.
398 *
399 * @return JMenu|null
400 *
401 * @since 10.1.19
402 */
403 public function getMenu($name = null, array $options = array())
404 {
405 if (!isset($name))
406 {
407 $name = $this->name;
408 }
409
410 // inject this application object into the JMenu tree if one isn't already specified
411 if (!isset($options['app']))
412 {
413 $options['app'] = $this;
414 }
415
416 try
417 {
418 // load JMenu file
419 JLoader::import('adapter.menu.menu');
420
421 // try to obtain a valid menu instance
422 $menu = JMenu::getInstance($name, $options);
423 }
424 catch (Exception $e)
425 {
426 return null;
427 }
428
429 return $menu;
430 }
431
432 /**
433 * Returns the application JPathway object.
434 *
435 * @param string $name The name of the application.
436 * @param array $options An optional associative array of configuration settings.
437 *
438 * @return JPathway|null
439 *
440 * @since 10.1.19
441 */
442 public function getPathway($name = null, $options = array())
443 {
444 if (!isset($name))
445 {
446 $name = $this->name;
447 }
448
449 try
450 {
451 // load JPathway file
452 JLoader::import('adapter.pathway.pathway');
453
454 // try to obtain a valid pathway
455 $pathway = JPathway::getInstance($name, $options);
456 }
457 catch (Exception $e)
458 {
459 return null;
460 }
461
462 return $pathway;
463 }
464
465 /**
466 * Returns the application JRouter object.
467 *
468 * @param string $name The name of the application.
469 * @param array $options An optional associative array of configuration settings.
470 *
471 * @return JRouter A JRouter object.
472 *
473 * @throws Exception
474 *
475 * @since 10.1.19
476 */
477 public function getRouter($name = null, array $options = array())
478 {
479 try
480 {
481 // load JRouter file
482 JLoader::import('adapter.router.router');
483
484 // try to obtain a valid router, if any
485 $router = JRouter::getInstance($name ?: 'site', $options);
486 }
487 catch (Exception $e)
488 {
489 return null;
490 }
491
492 return $router;
493 }
494
495 /**
496 * Registers a handler to a particular event group.
497 *
498 * @param string $event The event name.
499 * @param callable $handler The handler, a function or an instance of an event object.
500 *
501 * @return self This object to support chaining.
502 *
503 * @since 10.1.30
504 */
505 public function registerEvent($event, $handler)
506 {
507 // proxy for JEventDispatcher
508 return JEventDispatcher::getInstance()->register($event, $handler);
509 }
510
511 /**
512 * Calls all handlers associated with an event group.
513 *
514 * @param string $event The event name.
515 * @param array $args An array of arguments (optional).
516 *
517 * @return array An array of results from each function call, or null if no dispatcher is defined.
518 *
519 * @since 10.1.30
520 */
521 public function triggerEvent($event, ?array $args = null)
522 {
523 // proxy for JEventDispatcher
524 return JEventDispatcher::getInstance()->trigger($event, $args);
525 }
526
527 /**
528 * Redirect to another URL.
529 *
530 * If the headers have not been sent the redirect will be accomplished using a "301 Moved Permanently"
531 * or "303 See Other" code in the header pointing to the new location. If the headers have already been
532 * sent this will be accomplished using a JavaScript statement.
533 *
534 * @param string $url The URL to redirect to. Can only be http/https URL.
535 * @param integer $status The HTTP 1.1 status code to be provided. 303 is assumed by default.
536 *
537 * @return void
538 *
539 * @uses shouldRedirect()
540 *
541 * @link https://developer.wordpress.org/reference/functions/wp_redirect/
542 */
543 public function redirect($url, $status = 303)
544 {
545 if ($this->isAdmin())
546 {
547 // if the URL starts with index.php, replace it into admin.php
548 if (strpos($url, 'index.php?') === 0)
549 {
550 $url = str_replace('index.php?', 'admin.php?', $url);
551 }
552 // else if the URL starts with ?, prepend admin.php
553 else if (strpos($url, '?') === 0)
554 {
555 $url = 'admin.php' . $url;
556 }
557
558 // change end-point in case we are doing AJAX
559 if (wp_doing_ajax())
560 {
561 /**
562 * @note this is not really used for AJAX calls,
563 * but for redirects between "iframe" pages
564 * (contents rendered via AJAX in modal boxes).
565 */
566 $url = str_replace('admin.php', 'admin-ajax.php', $url);
567 }
568 }
569 else
570 {
571 // if the URL is "index.php", we probably need to visit the home page
572 if ($url == 'index.php')
573 {
574 $url = JUri::root();
575 }
576
577 // we don't need to route URLs that start with "index.php" because
578 // we are (probably) already under a rewritten page and this means
579 // that the plugin is going to be processed correctly.
580 }
581
582 // redirect is allowed only if the headers haven't been sent yet
583 if (!headers_sent())
584 {
585 wp_redirect($url, $status);
586 exit;
587 }
588
589 // JS redirect only once
590 if (!$this->shouldRedirect())
591 {
592 // register JS redirect
593 $this->jsRedirect = true;
594
595 // otherwise redirect using javascript
596 echo "<script>document.location.href='" . str_replace("'", '&apos;', $url) . "';</script>\n";
597 }
598 }
599
600 /**
601 * Checks if the application is going to do a JS redirect.
602 * The javascript redirect is applied when the headers have been already sent.
603 *
604 * @return boolean True if JS redirect, otherwise false.
605 */
606 public function shouldRedirect()
607 {
608 return $this->jsRedirect;
609 }
610
611 /**
612 * Login authentication function.
613 *
614 * @param array $credentials Array('username' => string, 'password' => string)
615 * @param array $options Array('remember' => boolean)
616 *
617 * @return boolean True on success, false if failed.
618 */
619 public function login($credentials, $options = array())
620 {
621 $login = array();
622 $login['user_login'] = $credentials['username'];
623 $login['user_password'] = $credentials['password'];
624 $login['remember'] = isset($options['remember']) ? $options['remember'] : false;
625
626 $options['redirect'] = isset($options['redirect']) ? $options['redirect'] : '';
627
628 // direct login only if the headers haven't been sent
629 if (!headers_sent())
630 {
631 $res = wp_signon($login);
632
633 return $res instanceof WP_User;
634 }
635 // otherwise use <form> workaround to dispatch wp-login.php
636 else
637 {
638 $url = wp_login_url($options['redirect']);
639 $url .= (strpos($url, '?') !== false ? '&' : '?') . 'action=login';
640
641 ?>
642
643 <form action="<?php echo $url; ?>" method="post" name="loginform" id="loginform">
644 <input type="hidden" name="log" value="<?php echo $login['user_login']; ?>" />
645 <input type="hidden" name="pwd" value="<?php echo $login['user_password']; ?>" />
646 <input type="hidden" name="rememberme" value="<?php echo $login['remember'] ? '1' : ''; ?>" />
647 </form>
648
649 <script>
650 document.loginform.submit();
651 </script>
652
653 <?php
654 }
655 }
656
657 /**
658 * Log the current user out, by destroying the current user session.
659 * It takes a non-used parameter for compatibility with other CMS.
660 *
661 * @param int $uid the id of the current user logged in
662 *
663 * @return void
664 *
665 * @since 10.1.5
666 */
667 public function logout($uid)
668 {
669 wp_logout();
670 }
671
672 /**
673 * Method to close the application.
674 *
675 * @param integer $code The exit code (optional; default is 0).
676 *
677 * @return void
678 *
679 * @since 10.1.33
680 */
681 public function close($code = 0)
682 {
683 exit($code);
684 }
685
686 /**
687 * Method to set a response header. If the replace flag is set then all headers
688 * with the given name will be replaced by the new one. The headers are stored
689 * in an internal array to be sent when the site is dispatched to the browser.
690 *
691 * @param string $name The name of the header to set.
692 * @param string $value The value of the header to set.
693 * @param boolean $replace True to replace any headers with the same name.
694 *
695 * @return self This object to support chaining.
696 *
697 * @since 10.1.33
698 */
699 public function setHeader($name, $value, $replace = false)
700 {
701 /**
702 * We have to treat the status in a slightly different way because WordPress is unable
703 * to properly send this header. All the headers registered through the "wp_headers"
704 * hook are always sent with the "{KEY}: {VALUE}" format, while the status should be
705 * sent as {PROTOCOL} {CODE} {DESCRIPTION}.
706 *
707 * @since 10.1.40
708 */
709 if (strtolower($name) === 'status')
710 {
711 if (is_null($this->status) || $replace)
712 {
713 // update HTTP status
714 $this->status = (int) $value;
715 }
716 }
717 else
718 {
719 // register filter to attach the given header into the WP pool
720 add_filter('wp_headers', function($headers) use ($name, $value, $replace)
721 {
722 if (!isset($headers[$name]) || $replace)
723 {
724 // set/replace header with the given value
725 $headers[$name] = $value;
726 }
727
728 return $headers;
729 });
730 }
731
732 return $this;
733 }
734
735 /**
736 * Method to get the array of response headers to be sent when
737 * the response is dispatched to the client.
738 *
739 * @return array
740 *
741 * @since 10.1.33
742 */
743 public function getHeaders()
744 {
745 global $wp;
746
747 $headers = [];
748
749 if (!is_null($this->status))
750 {
751 // manually register the status header within the pool
752 $headers['status'] = $this->status;
753 }
754
755 /**
756 * Filters the HTTP headers before they're sent to the browser.
757 *
758 * @since 2.8.0
759 *
760 * @param string[] $headers Associative array of headers to be sent.
761 * @param WP $this Current WordPress environment instance.
762 */
763 return apply_filters('wp_headers', $headers, $wp);
764 }
765
766 /**
767 * Method to clear any set response headers.
768 *
769 * @return self This object to support chaining.
770 *
771 * @since 10.1.33
772 */
773 public function clearHeaders()
774 {
775 // remove all the callbacks assigned to this hook
776 remove_filter('wp_headers');
777
778 // clear the previously registered HTTP status code too
779 $this->status = null;
780
781 return $this;
782 }
783
784 /**
785 * Sends the response headers.
786 *
787 * @return self This object to support chaining.
788 *
789 * @since 10.1.33
790 */
791 public function sendHeaders()
792 {
793 global $wp;
794
795 // send headers through WP
796 $wp->send_headers();
797
798 /**
799 * In case we have a registered HTTP status code, send this header.
800 *
801 * @since 10.1.40
802 */
803 if (!is_null($this->status))
804 {
805 status_header($this->status);
806 }
807
808 return $this;
809 }
810 }
811