PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 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 All 37 releases
← All changes | admin/helpers/src/multitask/parser.php +337 -0 1.6.0 → 1.8.16 View file →
@@ -1,0 +1,337 @@
1 +<?php
2 +/**
3 + * @package VikBooking
4 + * @subpackage core
5 + * @author Alessio Gaggii - E4J s.r.l.
6 + * @copyright Copyright (C) 2022 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 + * Multitask data extraction for admin widgets.
16 + *
17 + * @since 1.15.0 (J) - 1.5.0 (WP)
18 + */
19 +final class VBOMultitaskParser
20 +{
21 + /**
22 + * The singleton instance of the class.
23 + *
24 + * @var VBOMultitaskFactory
25 + */
26 + private static $instance = null;
27 +
28 + /**
29 + * The view/task where multitask is being used.
30 + *
31 + * @var string
32 + */
33 + private $page_name = '';
34 +
35 + /**
36 + * The page URI where multitask is being used.
37 + *
38 + * @var string
39 + */
40 + private $page_uri = '';
41 +
42 + /**
43 + * The page query values.
44 + *
45 + * @var array
46 + */
47 + private $page_query = [];
48 +
49 + /**
50 + * Returns the global object to immediately support chaining.
51 + * Either a new instance or the existing instance.
52 + *
53 + * @param string $page the name of the view/task.
54 + * @param string $uri the page URI to parse.
55 + *
56 + * @return self
57 + */
58 + public static function getInstance($page = '', $uri = '')
59 + {
60 + if (is_null(static::$instance)) {
61 + static::$instance = new static($page, $uri);
62 + }
63 +
64 + return static::$instance;
65 + }
66 +
67 + /**
68 + * Those pages capable of receiving data for a clicked Push notification through
69 + * query string can use this method to quickly validate and parse the admin widget
70 + * to load and the multitask data + options to set for rendering the information.
71 + *
72 + * @param array $data associative list of multitask data.
73 + * @param mixed $payload JSON-encoded string or decoded object payload.
74 + *
75 + * @return array numeric list of widget ID, data and options.
76 + *
77 + * @since 1.16.5 (J) - 1.6.5 (WP)
78 + */
79 + public static function queryPushData(array $data, $payload)
80 + {
81 + $parsed = [
82 + 'widget_id' => '',
83 + 'multitask_data' => $data,
84 + 'multitask_options' => [],
85 + ];
86 +
87 + if (empty($payload)) {
88 + // do not proceed
89 + return array_values($parsed);
90 + }
91 +
92 + if (is_string($payload)) {
93 + // attempt to JSON-decode the payload encoded string
94 + $decoded_payload = json_decode($payload);
95 +
96 + /**
97 + * Payloads may have been previously encoded in base64, which expects binary data as its input.
98 + * In case of titles or messages in the Push notification payload with multi-byte characters,
99 + * JSON-decoding the string that was base64-decoded, may result into malformed UTF-8 characters.
100 + * In this case, we will try to convert any character to ASCII by ignoring what's not UTF-8.
101 + */
102 + if (json_last_error() && json_last_error() === JSON_ERROR_UTF8) {
103 + // try to convert the encoding from UTF-8 to any ASCII
104 + $payload = json_decode(@iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $payload));
105 + } else {
106 + // assign the properly decoded value
107 + $payload = $decoded_payload;
108 + }
109 + }
110 +
111 + if (is_object($payload) && isset($payload->type) && (isset($payload->title) || isset($payload->message))) {
112 + // determine the type of widget that should handle the notification data
113 + $parsed['widget_id'] = $payload->type == 'Chat' ? 'guest_messages' : 'booking_details';
114 +
115 + // extract and remove raw content from payload
116 + $raw_content = isset($payload->content) ? (array)$payload->content : [];
117 + unset($payload->content);
118 +
119 + // build multitask options
120 + $parsed['multitask_options'] = array_merge(['_push' => 1], (array)$payload, $raw_content);
121 + }
122 +
123 + return array_values($parsed);
124 + }
125 +
126 + /**
127 + * Class constructor.
128 + *
129 + * @param string $page the name of the view/task.
130 + * @param string $uri the page URI to parse.
131 + */
132 + public function __construct($page = '', $uri = '')
133 + {
134 + // set name for view/task to consider
135 + $this->setPageName($page);
136 +
137 + // set URI to parse
138 + $this->setPageURI($uri);
139 + }
140 +
141 + /**
142 + * Builds a multitask data object with the page information
143 + * ready to be passed to the admin widget being rendered.
144 + *
145 + * @return VBOMultitaskData
146 + */
147 + public function getData()
148 + {
149 + /**
150 + * Rendering an admin widget does support injected request values.
151 + *
152 + * @since 1.16.0 (J) - 1.6.0 (WP)
153 + */
154 + $injected_data = JFactory::getApplication()->input->get('multitask_data', [], 'array');
155 +
156 + // extra the options for multitask data, if any
157 + $data_options = [];
158 + if (isset($injected_data['_options'])) {
159 + // access the options received
160 + $data_options = (array)$injected_data['_options'];
161 +
162 + // separate options layer from regular data
163 + unset($injected_data['_options']);
164 + }
165 +
166 + // get a new multitask data object instance
167 + $multitask_data = new VBOMultitaskData($injected_data);
168 +
169 + // inject current page values
170 + $multitask_data->setPage($this->getPageName());
171 + $multitask_data->setURI($this->getPageURI());
172 + $multitask_data->setQuery($this->getPageQueryValues());
173 +
174 + // check if the page has a booking
175 + $page_booking_id = $this->getPageBookingId();
176 + if ($page_booking_id) {
177 + $multitask_data->setBookingId($page_booking_id);
178 + }
179 +
180 + /**
181 + * Register a separate layer of data that will serve as multitask options.
182 + *
183 + * @since 1.16.5 (J) - 1.6.5 (WP)
184 + */
185 + $multitask_data->registerDataOptions($data_options);
186 +
187 + // return the data object for the admin widget
188 + return $multitask_data;
189 + }
190 +
191 + /**
192 + * Binds data to the multitask options object and returns it.
193 + *
194 + * @return VBOMultitaskOptions
195 + *
196 + * @since 1.16.5 (J) - 1.6.5 (WP)
197 + */
198 + public function getOptions()
199 + {
200 + return VBOMultitaskOptions::getInstance(JFactory::getApplication()->input->get('_options', [], 'array'));
201 + }
202 +
203 + /**
204 + * Gets the current name of the view/task.
205 + *
206 + * @return string
207 + */
208 + public function getPageName()
209 + {
210 + return $this->page_name;
211 + }
212 +
213 + /**
214 + * Sets the current name of the view/task.
215 + *
216 + * @param string $page the name of the view/task.
217 + *
218 + * @return self
219 + */
220 + public function setPageName($page = '')
221 + {
222 + $this->page_name = $page;
223 +
224 + return $this;
225 + }
226 +
227 + /**
228 + * Gets the current page URI.
229 + *
230 + * @return string
231 + */
232 + public function getPageURI()
233 + {
234 + return $this->page_uri;
235 + }
236 +
237 + /**
238 + * Sets the current page URI.
239 + *
240 + * @param string $uri the page URI to parse
241 + *
242 + * @return self
243 + */
244 + public function setPageURI($uri = '')
245 + {
246 + $this->page_uri = $uri;
247 +
248 + // parse current URI
249 + $this->parseCurrentURI();
250 +
251 + return $this;
252 + }
253 +
254 + /**
255 + * Gets the current values for the page query.
256 + *
257 + * @return array
258 + */
259 + public function getPageQueryValues()
260 + {
261 + return $this->page_query;
262 + }
263 +
264 + /**
265 + * Parses the current URI to detect values to extract.
266 + *
267 + * @return void
268 + */
269 + private function parseCurrentURI()
270 + {
271 + // reset query values
272 + $this->page_query = [];
273 +
274 + if (empty($this->page_uri)) {
275 + // nothing to parse
276 + return;
277 + }
278 +
279 + // parse URL data
280 + $uri_data = parse_url($this->page_uri);
281 +
282 + if (!isset($uri_data['query'])) {
283 + // no query values to parse
284 + return;
285 + }
286 +
287 + // parse query variables
288 + $uri_data['query'] = str_replace('&amp;', '&', $uri_data['query']);
289 +
290 + // inject parsed string values in page_query
291 + parse_str($uri_data['query'], $this->page_query);
292 +
293 + // adjust values, if needed
294 + if (empty($this->page_name)) {
295 + // try guessing the page from the query values
296 + if (!empty($this->page_query['view'])) {
297 + $this->page_name = $this->page_query['view'];
298 + } elseif (!empty($this->page_query['task'])) {
299 + $this->page_name = $this->page_query['task'];
300 + }
301 + }
302 + }
303 +
304 + /**
305 + * Checks whether the page contains a booking.
306 + *
307 + * @return bool|int false on failure or reservation ID.
308 + */
309 + private function getPageBookingId()
310 + {
311 + if (!is_array($this->page_query) || !count($this->page_query)) {
312 + return false;
313 + }
314 +
315 + // list of pages that can contain a reservation
316 + $pages_with_booking = [
317 + 'editorder',
318 + 'editbusy',
319 + 'bookingcheckin',
320 + ];
321 +
322 + if (!in_array($this->page_name, $pages_with_booking)) {
323 + return false;
324 + }
325 +
326 + if (!isset($this->page_query['cid']) || !is_array($this->page_query['cid'])) {
327 + return false;
328 + }
329 +
330 + if (empty($this->page_query['cid'][0])) {
331 + return false;
332 + }
333 +
334 + // booking ID found
335 + return (int)$this->page_query['cid'][0];
336 + }
337 +}