PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.3.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.3.0
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / app / Services / EditorShortCodeParser.php

EditorShortCodeParser.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.3.0, at app/Services/EditorShortCodeParser.php

538 lines 17.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\App\Services;
4
5 use FluentBooking\App\Models\Booking;
6 use FluentBooking\App\Models\Calendar;
7 use FluentBooking\App\Models\CalendarSlot;
8 use FluentBooking\Framework\Support\Arr;
9
10 class EditorShortCodeParser
11 {
12 protected static $requireHtml = true;
13
14 protected static $store = [
15 'booking' => null,
16 'calendar_booking' => null,
17 'calendar' => null,
18 'host' => null,
19 'user' => null,
20 'custom_booking_data' => null,
21 'payment_order' => null
22 ];
23
24 public static function parse($parsable, $booking, $requireHtml = true)
25 {
26 try {
27 static::$requireHtml = $requireHtml;
28 static::setData($booking);
29 return static::parseShortCodes($parsable);
30 } catch (\Exception $e) {
31 if (defined('WP_DEBUG') && WP_DEBUG) {
32 error_log($e->getTraceAsString()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
33 }
34 return '';
35 }
36 }
37
38 protected static function setData($booking)
39 {
40 static::$store['booking'] = $booking;
41 static::$store['booking_event'] = $booking->calendar_event;
42 static::$store['calendar'] = $booking->calendar;
43 static::$store['host'] = $booking->getHostDetails(false);
44 static::$store['team_members'] = $booking->getHostsDetails(false, $booking->host_user_id);
45 static::$store['custom_booking_data'] = null;
46 static::$store['payment_order'] = null;
47 static::$store['meeting_bookmarks'] = null;
48 }
49
50 protected static function getBookingData($key)
51 {
52 $bookingEvent = static::$store['booking_event'];
53 $calendar = static::$store['calendar'];
54 $booking = static::$store['booking'];
55
56 if (!$bookingEvent || !$calendar || !$booking) {
57 return '';
58 }
59
60 if ($key == 'event_name') {
61 return $bookingEvent->title;
62 }
63
64 if ($key == 'description') {
65 return $bookingEvent->description;
66 }
67
68 if ($key == 'booking_title') {
69 return $booking->getBookingTitle();
70 }
71
72 if ($key == 'additional_guests') {
73 return $booking->getAdditionalGuests(true);
74 }
75
76 if ($key == 'full_start_end_guest_timezone') {
77 return $booking->getShortBookingDateTime($booking->person_time_zone) . ' (' . $booking->person_time_zone . ')';
78 }
79
80 if ($key == 'full_start_end_host_timezone') {
81 return $booking->getShortBookingDateTime($booking->getHostTimezone()) . ' (' . $booking->getHostTimezone() . ')';
82 }
83
84 if ($key == 'full_start_and_end_guest_timezone') {
85 return $booking->getFullBookingDateTimeText($booking->person_time_zone) . ' (' . $booking->person_time_zone . ')';
86 }
87
88 if ($key == 'full_start_and_end_host_timezone') {
89 return $booking->getFullBookingDateTimeText($booking->getHostTimezone()) . ' (' . $booking->getHostTimezone() . ')';
90 }
91
92 if ($key == 'all_bookings_short_times_guest_timezone') {
93 return implode("<br>", $booking->getAllBookingShortTimes($booking->person_time_zone, true));
94 }
95
96 if ($key == 'all_bookings_short_times_host_timezone') {
97 return implode("<br>", $booking->getAllBookingShortTimes($booking->getHostTimezone(), true));
98 }
99
100 if ($key == 'all_bookings_full_times_guest_timezone') {
101 return implode("<br>", $booking->getAllBookingFullTimes($booking->person_time_zone, true));
102 }
103
104 if ($key == 'all_bookings_full_times_host_timezone') {
105 return implode("<br>", $booking->getAllBookingFullTimes($booking->getHostTimezone(), true));
106 }
107
108 if ($key == 'start_date_time') {
109 return $booking->start_time;
110 }
111
112 if (strpos($key, 'start_date_time_for_attendee') === 0) {
113 $format = preg_match('/format\.([a-zA-Z\-: ]+)/', $key, $matches) ? $matches[1] : 'Y-m-d H:i:s';
114 $dateTime = DateTimeHelper::convertFromUtc($booking->start_time, $booking->person_time_zone, 'Y-m-d H:i:s');
115 return date_i18n($format, strtotime($dateTime));
116 }
117
118 if (strpos($key, 'start_date_time_for_host') === 0) {
119 $format = preg_match('/format\.([a-zA-Z\-: ]+)/', $key, $matches) ? $matches[1] : 'Y-m-d H:i:s';
120 $dateTime = DateTimeHelper::convertFromUtc($booking->start_time, $booking->getHostTimezone(), 'Y-m-d H:i:s');
121 return date_i18n($format, strtotime($dateTime));
122 }
123
124 if ($key == 'cancel_reason') {
125 return $booking->getCancelReason(false, true);
126 }
127
128 if ($key == 'reject_reason') {
129 return $booking->getRejectReason(false, true);
130 }
131
132 if ($key == 'reschedule_reason') {
133 return $booking->getRescheduleReason(true);
134 }
135
136 if ($key == 'previous_meeting_time') {
137 return $booking->getPreviousMeetingTime($booking->getHostTimezone()) . ' (' . $booking->getHostTimezone() . ')';
138 }
139
140 if ($key == 'previous_meeting_time_guest_timezone') {
141 return $booking->getPreviousMeetingTime($booking->person_time_zone) . ' (' . $booking->person_time_zone . ')';
142 }
143
144 if ($key == 'previous_meeting_date_time_host_timezone') {
145 return $booking->getPreviousMeetingDateTimeText($booking->getHostTimezone()) . ' (' . $booking->getHostTimezone() . ')';
146 }
147
148 if ($key == 'previous_meeting_date_time_guest_timezone') {
149 return $booking->getPreviousMeetingDateTimeText($booking->person_time_zone) . ' (' . $booking->person_time_zone . ')';
150 }
151
152 if ($key == 'start_time_human_format') {
153 if (time() > strtotime($booking->start_time)) {
154 $suffix = __(' ago', 'fluent-booking');
155 } else {
156 $suffix = __(' from now', 'fluent-booking');
157 }
158
159 return human_time_diff(time(), strtotime($booking->start_time)) . ' ' . $suffix;
160 }
161
162 if ($key == 'cancelation_url') {
163 return $booking->getCancelUrl();
164 }
165
166 if ($key == 'reschedule_url') {
167 return $booking->getRescheduleUrl();
168 }
169
170 if ($key == 'admin_booking_url') {
171 return Helper::getAdminBookingUrl($booking->id) . '&period=upcoming';
172 }
173
174 if ($key == 'booking_confirm_url') {
175 return Helper::getAdminBookingUrl($booking->id) . '&period=pending&confirm_booking=true';
176 }
177
178 if ($key == 'booking_reject_url') {
179 return Helper::getAdminBookingUrl($booking->id) . '&period=pending&reject_booking=true';
180 }
181
182 if ($key == 'location_details_html') {
183 return $booking->getLocationDetailsHtml();
184 }
185
186 if ($key == 'location_details_text') {
187 return $booking->getLocationAsText();
188 }
189
190 if ($key == 'booking_hash') {
191 return $booking->hash;
192 }
193
194 $fillables = (new Booking())->getFillable();
195 $fillables[] = 'id';
196 $fillables[] = 'created_at';
197 $fillables[] = 'updated_at';
198
199 if (in_array($key, $fillables)) {
200 return $booking->{$key};
201 }
202
203 return '';
204 }
205
206 protected static function getBookingCustomData($key)
207 {
208 $booking = static::$store['booking'];
209 if (!$booking) {
210 return '';
211 }
212
213 if (self::$store['custom_booking_data'] === null) {
214 self::$store['custom_booking_data'] = $booking->getMeta('custom_fields_data', []);
215 }
216
217 if (self::$store['custom_booking_data']) {
218 if (preg_match('/format\.([a-zA-Z\-: ]+)/', $key, $matches)) {
219 $fieldKey = preg_split('/\.format\./', $key)[0];
220 $value = Arr::get(self::$store['custom_booking_data'], $fieldKey);
221 $customField = BookingFieldService::getBookingFieldByName($booking->calendar_event, $fieldKey);
222 $formattedDate = DateTimeHelper::getFormattedDate($value, Arr::get($customField, 'date_format'));
223 return $formattedDate ? date_i18n($matches[1], strtotime($formattedDate)) : '';
224 }
225
226 $customField = BookingFieldService::getBookingFieldByName($booking->calendar_event, $key);
227
228 if (Arr::get($customField, 'type') == 'file') {
229 return self::getUploadedFileUrl(Arr::get(self::$store['custom_booking_data'], $key));
230 }
231
232 if (Arr::get($customField, 'type') == 'hidden') {
233 static $resolving = [];
234
235 // Guest-supplied hidden values are parsed again, so a self-reference would recurse until the stack runs out.
236 if (isset($resolving[$key])) {
237 return Arr::get(self::$store['custom_booking_data'], $key);
238 }
239
240 $resolving[$key] = true;
241
242 try {
243 return self::parseShortCodes(Arr::get(self::$store['custom_booking_data'], $key));
244 } finally {
245 unset($resolving[$key]);
246 }
247 }
248
249 return Arr::get(self::$store['custom_booking_data'], $key);
250 }
251
252 return '';
253 }
254
255 protected static function getHostData($key)
256 {
257 $host = static::$store['host'];
258
259 if (is_null($host)) {
260 return '';
261 }
262
263 if ($key == 'timezone') {
264 $booking = static::$store['booking'];
265 return $booking ? $booking->getHostTimezone() : null;
266 }
267
268 return Arr::get($host, $key, '');
269 }
270
271 protected static function getTeamMembersData($key)
272 {
273 $teamMembers = static::$store['team_members'];
274
275 if (empty($teamMembers)) {
276 return '';
277 }
278
279 list($key, $value) = explode('.', $key);
280
281 return Arr::get($teamMembers, $key - 1 . '.' . $value, '');
282 }
283
284 protected static function getGuestData($key)
285 {
286 $guest = static::$store['booking'];
287 if (is_null($guest)) {
288 return '';
289 }
290
291 if ('full_name' == $key) {
292 return $guest['first_name'] . ' ' . $guest['last_name'];
293 }
294 if ('timezone' == $key) {
295 return $guest->person_time_zone;
296 }
297 if ('note' == $key) {
298 return $guest->getMessage();
299 }
300
301 if ($key == 'total_guest') {
302 return $guest->getTotalGuestCount();
303 }
304
305 if ($key == 'form_data_html') {
306 return __('will be available soon', 'fluent-booking');
307 }
308
309 return Arr::get($guest, $key, '');
310 }
311
312 protected static function getBookingEventData($key)
313 {
314 $bookingEvent = static::$store['booking_event'];
315
316 if (is_null($bookingEvent)) {
317 return '';
318 }
319
320 $fillables = (new CalendarSlot())->getFillable();
321
322 if (in_array($key, $fillables) || isset($bookingEvent->{$key})) {
323 return $bookingEvent->{$key};
324 }
325
326 return '';
327 }
328
329 protected static function getCalendarData($key)
330 {
331 $calendar = static::$store['calendar'];
332
333 if (is_null($calendar)) {
334 return '';
335 }
336
337 $fillables = (new Calendar())->getFillable();
338
339 if (in_array($key, $fillables) || isset($calendar->{$key})) {
340 return $calendar->{$key};
341 }
342
343 return '';
344 }
345
346 protected static function getPaymentData($key)
347 {
348 $booking = static::$store['booking'];
349
350 if (is_null($booking)) {
351 return '';
352 }
353
354 if (!$booking->payment_status) {
355 return '';
356 }
357
358 if (is_null(static::$store['payment_order'])) {
359 static::$store['payment_order'] = $booking->payment_order;
360 }
361
362 if (!static::$store['payment_order']) {
363 return '';
364 }
365
366 $order = static::$store['payment_order'];
367
368 if ($key == 'payment_total' && $order) {
369 $isZeroDecimal = CurrenciesHelper::isZeroDecimal($order->currency);
370 if ($isZeroDecimal) {
371 return $order->total_amount;
372 } else {
373 return $order->total_amount / 100;
374 }
375 }
376
377 if ($key == 'receipt_html') {
378 return apply_filters('fluent_booking/payment_receipt_html', '', $booking->hash);
379 }
380
381 if ($key == 'payment_status') {
382 return $order ? $order->status : '';
383 }
384
385 if ($key == 'payment_currency') {
386 return $order ? $order->currency : '';
387 }
388
389 if ($key == 'payment_date') {
390 return $order ? $order->created_at : '';
391 }
392
393 $fillables = (new \FluentBookingPro\App\Models\Order())->getFillable();
394
395 if (in_array($key, $fillables)) {
396 return $order ? $order->{$key} : '';
397 }
398
399 return '';
400 }
401
402 protected static function getUserData($key)
403 {
404 $user = static::$store['user'];
405 if (is_null($user)) {
406 $user = wp_get_current_user();
407 }
408 return $user ? $user->{$key} : '';
409 }
410
411 protected static function getWPData($key)
412 {
413 if ('site_url' == $key) {
414 return site_url();
415 }
416 if ('admin_email' == $key) {
417 return get_option('admin_email');
418 }
419 if ('site_title' == $key) {
420 return get_option('blogname');
421 }
422 return $key;
423 }
424
425 protected static function getOtherData($key)
426 {
427 $meetingBookmarks = self::$store['meeting_bookmarks'];
428 if (!$meetingBookmarks) {
429 $booking = static::$store['booking'];
430 $meetingBookmarks = $booking ? $booking->getMeetingBookmarks() : null;
431 self::$store['meeting_bookmarks'] = $meetingBookmarks;
432 }
433
434 if (0 === strpos($key, 'date.')) {
435 $format = str_replace('date.', '', $key);
436 return gmdate($format, strtotime(current_time('mysql'))); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
437 } elseif ('add_booking_to_calendar' === $key) {
438 return static::parseShortCodes(Helper::getAddToCalendarHtml());
439 } elseif ('add_to_g_calendar_url' === $key) {
440 return Arr::get($meetingBookmarks, 'google.url');
441 } elseif ('add_to_ol_calendar_url' === $key) {
442 return Arr::get($meetingBookmarks, 'outlook.url');
443 } elseif ('add_to_ms_calendar_url' === $key) {
444 return Arr::get($meetingBookmarks, 'msoffice.url');
445 } elseif ('add_to_ics_calendar_url' === $key) {
446 return Arr::get($meetingBookmarks, 'other.url');
447 }
448
449 return $key;
450 }
451
452 protected static function getUploadedFileUrl($fieldValue)
453 {
454 if (empty($fieldValue)) {
455 return '';
456 }
457
458 $files = array_map(function($file) {
459 return '<a href="' . esc_url($file) . '" style="color:#222;font-size:15px;" target="_blank" download="' . esc_attr(basename($file)) . '">' . esc_html(basename($file)) . '</a>';
460 }, $fieldValue);
461
462 return '<ul><li>' . implode('</li><li>', $files) . '</li></ul>';
463 }
464
465 protected static function parseShortCodes($parsable)
466 {
467 if (is_array($parsable)) {
468 return static::parseFromArray($parsable);
469 }
470
471 return static::parseFromString($parsable);
472 }
473
474 protected static function parseFromArray($parsable)
475 {
476 foreach ($parsable as $key => $value) {
477 if (is_array($value)) {
478 $parsable[$key] = static::parseFromArray($value);
479 } else {
480 $parsable[$key] = static::parseFromString($value);
481 }
482 }
483
484 return $parsable;
485 }
486
487 protected static function parseFromString($parsable)
488 {
489 if (!$parsable) {
490 return '';
491 }
492
493 return preg_replace_callback('/({{|##)+(.*?)(}}|##)/', function ($matches) {
494 $value = '';
495
496 if (empty($matches[2])) {
497 return '';
498 }
499
500 $match = $matches[2];
501
502 if (false !== strpos($match, 'guest.')) {
503 $guestProperty = substr($match, strlen('guest.'));
504 $value = static::getGuestData($guestProperty);
505 } elseif (false !== strpos($match, 'booking.custom.')) {
506 $customBookingProp = substr($match, strlen('booking.custom.'));
507 $value = static::getBookingCustomData($customBookingProp);
508 } elseif (false !== strpos($match, 'booking.')) {
509 $bookingProperty = substr($match, strlen('booking.'));
510 $value = static::getBookingData($bookingProperty);
511 } elseif (false !== strpos($match, 'host.')) {
512 $hostProperty = substr($match, strlen('host.'));
513 $value = static::getHostData($hostProperty);
514 } elseif (false !== strpos($match, 'team_member.')) {
515 $teamMemberProperty = substr($match, strlen('team_member.'));
516 $value = static::getTeamMembersData($teamMemberProperty);
517 } elseif (false !== strpos($match, 'event.')) {
518 $eventProperty = substr($match, strlen('event.'));
519 $value = static::getBookingEventData($eventProperty);
520 } elseif (false !== strpos($match, 'calendar.')) {
521 $calendarProperty = substr($match, strlen('calendar.'));
522 $value = static::getCalendarData($calendarProperty);
523 } elseif (false !== strpos($match, 'payment.')) {
524 $paymentProperty = substr($match, strlen('payment.'));
525 $value = static::getPaymentData($paymentProperty);
526 } else {
527 $value = static::getOtherData($match);
528 }
529
530 if (static::$requireHtml && is_array($value)) {
531 $value = Helper::fcalImplodeRecursive(', ', $value);
532 }
533
534 return $value;
535 }, $parsable);
536 }
537 }
538