PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.7.0
VikBooking Hotel Booking Engine & PMS v1.7.0
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
vikbooking / admin / helpers / src / notification / elements.php

elements.php in VikBooking Hotel Booking Engine & PMS 1.7.0, at admin/helpers/src/notification/elements.php

385 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author Alessio Gaggii - E4J s.r.l.
6 * @copyright Copyright (C) 2024 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 * Notification elements registry to store a record for the Notification Center.
16 *
17 * @since 1.16.8 (J) - 1.6.8 (WP)
18 */
19 final class VBONotificationElements extends JObject
20 {
21 /**
22 * Valid notification group enumerations.
23 *
24 * @var array
25 */
26 private $groupEnums = [
27 // notifications from Website
28 'website',
29 // notifications from OTAs
30 'otas',
31 // notifications from Channel Manager
32 'cm',
33 // notifications from Guests
34 'guests',
35 // notifications from Operators
36 'operators',
37 // notifications from AI
38 'ai',
39 ];
40
41 /**
42 * Default notification type.
43 *
44 * @var string
45 */
46 private $defaultType = 'info';
47
48 /**
49 * Determines and returns the group to which the notification belongs.
50 *
51 * @return string
52 */
53 public function getGroup()
54 {
55 // check if the group was already determined
56 $group = (string) $this->get('_group', '');
57
58 if (!$group) {
59 // access the notification sender property
60 $group = strtolower((string) $this->get('sender', $this->groupEnums[0]));
61
62 // validate the group property
63 $group = in_array($group, $this->groupEnums) ? $group : $this->groupEnums[0];
64
65 // cache determined group
66 $this->set('_group', $group);
67 }
68
69 return $group;
70 }
71
72 /**
73 * Returns the notification type.
74 *
75 * @return string
76 */
77 public function getType()
78 {
79 // access the notification type
80 $type = strtolower((string) $this->get('type', $this->defaultType));
81
82 // ensure the maximum length of 32 chars is respected
83 return $this->shortenString($type, 32, $this->defaultType);
84 }
85
86 /**
87 * Returns the notification title.
88 *
89 * @return string
90 */
91 public function getTitle()
92 {
93 // access the notification title
94 $title = (string) $this->get('title', '');
95
96 // try to guess the title
97 if (!$title) {
98 // check for virtual credit card balance
99 if (strpos($this->getType(), 'vcc_balance') === 0) {
100 $title = JText::translate('VBO_VCC_BALANCE');
101 if ($title == 'VBO_VCC_BALANCE') {
102 $title = ucwords(str_replace('_', ' ', $this->getType()));
103 }
104 }
105 }
106
107 // ensure the maximum length of 64 chars is respected
108 return $this->shortenString($title, 64);
109 }
110
111 /**
112 * Returns the notification summary.
113 *
114 * @return string
115 */
116 public function getSummary()
117 {
118 // access the notification summary
119 $summary = (string) $this->get('summary', '');
120
121 // normalize the summary, if needed
122 if ($summary && $this->getChannel() && !strcasecmp($this->getType(), 'lvf')) {
123 // listing verification framework (LVF)
124 $summary = JText::sprintf('VBO_VERIFY_LISTING_INFO', $summary);
125 }
126
127 // ensure the maximum length of 256 chars is respected
128 return $this->shortenString($summary, 256);
129 }
130
131 /**
132 * Builds and returns the notification call-to-action data.
133 *
134 * @return null|string
135 */
136 public function getCallToActionData()
137 {
138 $cta_data = [];
139
140 // check if a widget identifier was provided
141 $widget = (string) $this->get('widget', '');
142 if ($widget) {
143 $cta_data['widget'] = $widget;
144 }
145
146 // check if some widget options were provided
147 $widget_options = (array) $this->get('widget_options', []);
148 if ($widget_options) {
149 $cta_data['widget_options'] = $widget_options;
150 }
151
152 // check if a notification URL was provided
153 $cta_url = (string) $this->get('cta_url', $this->get('url'));
154 if ($cta_url) {
155 $cta_data['url'] = $cta_url;
156 }
157
158 // check if a custom label was provided
159 if ($cta_data && is_string($this->get('label'))) {
160 $cta_data['label'] = $this->get('label');
161 }
162
163 if (!$cta_data) {
164 // attempt to determine the CTA payload to set
165 if (strpos($this->getType(), 'vcc_balance') === 0 && ($this->getReservationID() || $this->getOTAReservationID())) {
166 // set call-to-action for Virtual Terminal admin-widget for VCC balance
167 $cta_data = [
168 'label' => JText::translate('VBO_CC_DOCHARGE'),
169 'widget' => 'virtual_terminal',
170 'widget_options' => [
171 'bid' => $this->getReservationID() ?: $this->getOTAReservationID(),
172 ],
173 ];
174 } elseif (!strcasecmp($this->getType(), 'guest_message') && ($this->getReservationID() || $this->getOTAReservationID())) {
175 // set call-to-action for Guest Messages admin-widget to reply to the guest message
176 $cta_data = [
177 'label' => JText::translate('VBO_REPLY'),
178 'widget' => 'guest_messages',
179 'widget_options' => [
180 'bid' => $this->getReservationID() ?: $this->getOTAReservationID(),
181 ],
182 ];
183 } elseif (!strcasecmp($this->getType(), 'ob') && $this->getReservationID()) {
184 // set call-to-action for Bookings Calendar admin-widget in case of overbooking
185 $cta_data = [
186 'widget' => 'bookings_calendar',
187 'widget_options' => [
188 'bid' => $this->getReservationID(),
189 'overbooking' => 1,
190 ],
191 ];
192 }
193 }
194
195 return $cta_data ? json_encode($cta_data) : null;
196 }
197
198 /**
199 * Returns the VikBooking reservation ID.
200 *
201 * @return null|int
202 */
203 public function getReservationID()
204 {
205 $res_id = $this->get('idorder', null);
206
207 return $res_id ? (int) $res_id : null;
208 }
209
210 /**
211 * Returns the OTA reservation ID.
212 *
213 * @return null|string
214 */
215 public function getOTAReservationID()
216 {
217 $ota_res_id = $this->get('idorderota', null);
218
219 return $ota_res_id ? (string) $ota_res_id : null;
220 }
221
222 /**
223 * Returns the channel name.
224 *
225 * @return null|string
226 */
227 public function getChannel()
228 {
229 $channel = $this->get('channel', null);
230
231 return $channel ? (string) $channel : null;
232 }
233
234 /**
235 * Returns the notification date and time.
236 *
237 * @return string
238 */
239 public function getDate()
240 {
241 try {
242 $date = JFactory::getDate($this->get('date') ?: 'now');
243 } catch(Exception $e) {
244 $date = JFactory::getDate();
245 }
246
247 return $date->toSql();
248 }
249
250 /**
251 * Returns the notification signature.
252 *
253 * @return string
254 */
255 public function getSignature()
256 {
257 $signature = (string) $this->get('_signature', '');
258
259 if (!$signature) {
260 $signature = $this->buildSignature();
261 }
262
263 return $signature;
264 }
265
266 /**
267 * Sets the notification signature.
268 *
269 * @return self
270 */
271 public function setSignature(string $signature = '')
272 {
273 $this->set('_signature', $signature);
274
275 return $this;
276 }
277
278 /**
279 * Builds, sets and returns the notification signature.
280 *
281 * @return string
282 */
283 public function buildSignature()
284 {
285 // build notification signature elements
286 $elements = [
287 'id' => $this->get('id', $this->get('notification_id', 0)),
288 'idorder' => $this->get('idorder', 0),
289 'sender' => $this->get('sender', ''),
290 'type' => $this->get('type', ''),
291 'title' => $this->get('title', ''),
292 'summary' => $this->get('summary', ''),
293 ];
294
295 // build notification signature string
296 $signature = md5(serialize($elements));
297
298 // set signature string
299 $this->setSignature($signature);
300
301 return $signature;
302 }
303
304 /**
305 * Returns the notification error code.
306 *
307 * @return int
308 */
309 public function getErrorCode()
310 {
311 return (int) $this->get('_errorCode', 500);
312 }
313
314 /**
315 * Sets the notification error code.
316 *
317 * @return self
318 */
319 public function setErrorCode($code = 500)
320 {
321 $this->set('_errorCode', $code);
322
323 return $this;
324 }
325
326 /**
327 * Ensures a string reflects the given length, or it will be eventually shortened or replaced.
328 *
329 * @param string $value the string to check.
330 * @param int $length the length to reflect.
331 * @param string $fallback optional string to replace as fallback.
332 *
333 * @return string
334 */
335 private function shortenString(string $value, int $length, string $fallback = null)
336 {
337 if (strlen($value) <= $length || $length <= 0) {
338 // length is safe
339 return $value;
340 }
341
342 if ($fallback) {
343 // replace string with provided fallback
344 return $fallback;
345 }
346
347 // shorten the string to the desired length
348 if (!function_exists('mb_strlen')) {
349 // use a regular sub-string without multi-byte support
350 return rtrim(substr($value, 0, $length - 3), '.,?!;:#\'"([{ ') . '...';
351 }
352
353 // calculate string length
354 $size = strlen($value);
355 $mb_size = mb_strlen($value);
356 $ch_diff = $size - $mb_size;
357
358 if ($ch_diff <= 0) {
359 // no multi-byte chars found
360 return rtrim(substr($value, 0, $length - 3), '.,?!;:#\'"([{ ') . '...';
361 }
362
363 // safely construct the string with one multibyte char per time
364 $mb_value = '';
365 $mb_char_start = 0;
366 while (strlen($mb_value) < $length - 3) {
367 // get a one-char multi-byte portion
368 $mb_portion = mb_substr($value, $mb_char_start, 1, 'UTF-8');
369
370 if (strlen($mb_value . $mb_portion) > $length) {
371 // abort to not exceed the length
372 return $mb_value;
373 }
374
375 // add portion to string value
376 $mb_value .= $mb_portion;
377
378 // increase chart start counter
379 $mb_char_start++;
380 }
381
382 return rtrim($mb_value, '.,?!;:#\'"([{ ') . '...';
383 }
384 }
385