PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.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 All 34 releases
← All changes | app/Services/LandingPage/LandingPageHandler.php +75 -40 1.5.1 → 2.5.0 View file →
@@ -6,13 +6,15 @@
6 6 use FluentBooking\App\Hooks\Handlers\FrontEndHandler;
7 7 use FluentBooking\App\Models\Booking;
8 8 use FluentBooking\App\Models\Calendar;
9 9 use FluentBooking\App\Models\CalendarSlot;
10 +use FluentBooking\App\Services\CalendarEventService;
10 11 use FluentBooking\App\Services\BookingFieldService;
11 12 use FluentBooking\App\Services\BookingService;
12 13 use FluentBooking\App\Services\Helper;
13 14 use FluentBooking\Framework\Support\Arr;
14 15 use FluentBooking\Framework\Support\Collection;
16 +use FluentBooking\App\Vite;
15 17
16 18 class LandingPageHandler
17 19 {
18 20 public function boot()
@@ -38,15 +40,23 @@
38 40 }
39 41
40 42 $authorSlug = sanitize_text_field($urlParts[1]);
41 43
44 + if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
45 + $this->handleEmbeddedStyle();
46 + }
47 +
42 48 $this->routeView($authorSlug, Arr::get($urlParts, 2, null));
43 49 }
44 50
45 51 public function handleUrlParamsPage()
46 52 {
47 - $route = sanitize_text_field($_GET['fluent-booking']); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
53 + $route = isset($_GET['fluent-booking']) ? sanitize_text_field(wp_unslash($_GET['fluent-booking'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
48 54
55 + if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
56 + $this->handleEmbeddedStyle();
57 + }
58 +
49 59 if ($route == 'booking') {
50 60 $this->handleAfterBookingPage();
51 61 return;
52 62 }
@@ -89,9 +99,9 @@
89 99 ->first();
90 100 if (!$slot) {
91 101 return;
92 102 }
93 - $this->renderBookingView($calendar, $slot);
103 + return $this->renderBookingView($calendar, $slot);
94 104 }
95 105
96 106 $this->renderHostView($calendar);
97 107 }
@@ -109,14 +119,9 @@
109 119 }
110 120
111 121 $activeEvents = $activeEvents->get();
112 122
113 - foreach ($activeEvents as $activeEvent) {
114 - $activeEvent->public_url = $activeEvent->getPublicUrl();
115 - $activeEvent->durations = $activeEvent->getAvailableDurations();
116 - $activeEvent->description = $activeEvent->getDescription();
117 - $activeEvent->short_description = Helper::excerpt($activeEvent->description);
118 - }
123 + $activeEvents = CalendarEventService::processEvents($calendar, $activeEvents);
119 124
120 125 $metaDescription = Helper::excerpt($calendar->description);
121 126
122 127 $calendar->description = wpautop($calendar->description);
@@ -146,11 +151,11 @@
146 151 $vars['lazy_js_files'] = $extraJs;
147 152 }
148 153 $jsVars['fcal_public_vars_' . $calendar->id . '_' . $activeEvent->id] = $vars;
149 154 $activeEvent->locations = $activeEvent->defaultLocationHtml();
155 + do_action_ref_array('fluent_booking/landing_page_event', [&$activeEvent]);
150 156 }
151 157
152 - $assetUrl = App::getInstance('url.assets');
153 158 $data = [
154 159 'calendar' => $calendar,
155 160 'events' => $activeEvents,
156 161 'author' => $authorProfile,
@@ -156,17 +161,18 @@
156 161 'author' => $authorProfile,
157 162 'title' => $calendar->title .' - '.get_bloginfo('name'),
158 163 'description' => $metaDescription,
159 164 'url' => home_url($wp->request),
165 + 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
160 166 'css_files' => [
161 - App::getInstance('url.assets') . 'public/saas.css'
167 + Vite::styleUrl('saas_css')
162 168 ],
163 169 'js_files' => [
164 - 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
170 + 'fluent-booking-public-js' => Vite::scriptUrl('public_app'),
165 171 ],
166 172 'js_vars' => $jsVars,
167 173 'header_js_files' => [
168 - 'fluent_booking_team_app-js' => $assetUrl. 'public/js/team_app.js'
174 + 'fluent_booking_team_app-js' => Vite::scriptUrl('team_app')
169 175 ]
170 176 ];
171 177
172 178 if ($extraJsFiles) {
@@ -173,8 +179,10 @@
173 179 $extraJsFiles = array_unique($extraJsFiles);
174 180 $data['js_files'] = array_merge($data['js_files'], $extraJsFiles);
175 181 }
176 182
183 + $data = apply_filters('fluent_booking/host_view_page_vars', $data, $calendar, $activeEvents, $authorProfile);
184 +
177 185 $app = App::getInstance();
178 186 status_header(200);
179 187 $app->view->render('landing.author_landing', $data);
180 188 exit(200);
@@ -179,14 +187,16 @@
179 187 $app->view->render('landing.author_landing', $data);
180 188 exit(200);
181 189 }
182 190
183 - private function renderBookingView($calendar, $calendarEvent, $existingBooking = null)
191 + private function renderBookingView($calendar, $calendarEvent, $existingBooking = null, $isReschedule = false)
184 192 {
185 - $settings = LandingPageHelper::getSettings($calendar, 'public');
186 - if ($settings['show_type'] != 'all') {
187 - if (!in_array($calendarEvent->id, $settings['enabled_slots'])) {
188 - return '';
193 + if (!$isReschedule) {
194 + $settings = LandingPageHelper::getSettings($calendar, 'public');
195 + if ($settings['show_type'] != 'all') {
196 + if (!in_array($calendarEvent->id, $settings['enabled_slots'])) {
197 + return '';
198 + }
189 199 }
190 200 }
191 201
192 202 global $wp;
@@ -194,9 +204,9 @@
194 204 $calendarEvent->max_lookup_date = $calendarEvent->getMaxLookUpDate();
195 205 $calendarEvent->min_lookup_date = $calendarEvent->getMinLookUpDate();
196 206
197 207 if (!empty($_REQUEST['booking_id'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
198 - $bookingHash = sanitize_text_field($_REQUEST['booking_id']); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
208 + $bookingHash = sanitize_text_field(wp_unslash($_REQUEST['booking_id'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
199 209 $booking = Booking::where('hash', $bookingHash)
200 210 ->where('event_id', $calendarEvent->id)
201 211 ->first();
202 212 if ($booking) {
@@ -218,26 +228,27 @@
218 228 $assetUrl = App::getInstance('url.assets');
219 229
220 230 $eventVars = (new FrontEndHandler())->getCalendarEventVars($calendar, $calendarEvent);
221 231
222 - $isRtl = Helper::fluentbooking_is_rtl();
232 + $publicCss = 'saas_css';
223 233
224 - $publicCss = 'public/saas.css';
225 - if ($isRtl) {
226 - $publicCss = 'public/saas-rtl.css';
227 - }
234 + $title = $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'];
235 +
236 + $title = apply_filters('fluent_booking/booking_confirmation_page_title', $title, $calendarEvent, $authorProfile);
237 +
228 238 $data = [
229 239 'calendar' => $calendar,
230 240 'calendar_event' => $calendarEvent,
231 241 'author' => $authorProfile,
232 - 'title' => $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'],
242 + 'title' => $title,
233 243 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
234 244 'url' => home_url($wp->request),
245 + 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
235 246 'css_files' => [
236 - $assetUrl . $publicCss
247 + Vite::styleUrl($publicCss)
237 248 ],
238 249 'js_files' => [
239 - 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
250 + 'fluent-booking-public-js' => Vite::scriptUrl('public_app'),
240 251 ],
241 252 'js_vars' => [
242 253 'fluentCalendarPublicVars' => (new FrontEndHandler())->getGlobalVars(),
243 254 'fcal_public_vars_' . $calendar->id . '_' . $calendarEvent->id => $eventVars,
@@ -271,9 +282,8 @@
271 282
272 283 private function showBookingConfimationPage($booking, $actionType = 'confirmation')
273 284 {
274 285 $validActions = ['confirmation'];
275 - $isRtl = Helper::fluentbooking_is_rtl();
276 286
277 287 if (in_array($booking->status, ['scheduled', 'pending', 'rescheduled'])) {
278 288 $validActions = array_merge($validActions, ['reschedule', 'cancel']);
279 289 }
@@ -294,24 +304,24 @@
294 304 echo $icsText; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
295 305 die();
296 306 }
297 307
308 + global $wp;
309 +
298 310 $calendarEvent = $booking->calendar_event;
299 - global $wp;
311 +
300 312 $responseHtml = BookingService::getBookingConfirmationHtml($booking, $actionType);
301 313
302 314 $authorProfile = $calendarEvent->getAuthorProfile(true);
303 315
304 - $publicCss = 'public/saas_public.css';
305 - if ($isRtl) {
306 - $publicCss = 'public/saas_public-rtl.css';
307 - }
316 + $publicCss = 'saas_public_css';
317 +
308 318 $data = [
309 319 'title' => __('Confirmation: ', 'fluent-booking') . $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'],
310 320 'body' => $responseHtml,
311 321 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
312 322 'css_files' => [
313 - App::getInstance('url.assets') . $publicCss
323 + Vite::styleUrl($publicCss)
314 324 ],
315 325 'js_files' => [],
316 326 'js_vars' => [],
317 327 'author' => $authorProfile,
@@ -317,15 +327,23 @@
317 327 'author' => $authorProfile,
318 328 'slot' => $calendarEvent,
319 329 'url' => home_url($wp->request),
320 330 'action_type' => $actionType,
321 - 'theme' => Arr::get(get_option('_fluent_booking_settings'), 'theme','system-default')
331 + 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
332 + 'theme' => Arr::get(get_option('_fluent_booking_settings'), 'theme','system-default'),
333 + 'back_button' => [
334 + 'show' => true,
335 + 'text' => __('Back to home', 'fluent-booking'),
336 + 'url' => site_url('/')
337 + ]
322 338 ];
323 339
324 340 if ($actionType == 'cancel') {
325 - $data['js_files']['fluent-booking-public-manage-meeting-js'] = App::getInstance('url.assets') . 'public/js/public-manage-meeting.js';
341 + $data['js_files']['fluent-booking-public-manage-meeting-js'] = Vite::scriptUrl('manage_meeting');
326 342 }
327 343
344 + $data = apply_filters('fluent_booking/booking_confirmation_page_vars', $data, $booking, $calendarEvent);
345 +
328 346 $app = App::getInstance();
329 347 status_header(200);
330 348 $app->view->render('landing.confirmation_page', $data);
331 349 exit(200);
@@ -332,21 +350,20 @@
332 350 }
333 351
334 352 private function handleAfterBookingPage()
335 353 {
336 - $bookingHash = sanitize_text_field(Arr::get($_REQUEST, 'meeting_hash')); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
337 -
354 + $bookingHash = sanitize_text_field(wp_unslash(Arr::get($_REQUEST, 'meeting_hash'))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
338 355 if (!$bookingHash) {
339 356 return;
340 357 }
341 358
342 359 $booking = Booking::where('hash', $bookingHash)->first();
343 -
344 360 if (!$booking) {
345 361 return;
346 362 }
347 363
348 364 $type = Arr::get($_REQUEST, 'type', 'confirmation'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
365 +
349 366 $this->showBookingConfimationPage($booking, $type);
350 367 }
351 368
352 369 private function handleRescheduleView(Booking $booking)
@@ -414,11 +431,29 @@
414 431 </style>
415 432 <?php
416 433 });
417 434
418 - $this->renderBookingView($booking->calendar, $booking->calendar_event, $booking);
435 + $this->renderBookingView($booking->calendar, $booking->calendar_event, $booking, true);
419 436 }
420 437
438 + private function handleEmbeddedStyle()
439 + {
440 + add_action('wp_print_styles', function () {
441 + global $wp_styles;
442 + if($wp_styles) {
443 + foreach ($wp_styles->queue as $style) {
444 + $src = $wp_styles->registered[$style]->src;
445 + if (
446 + (strpos($src, 'fluentbooking') === false) &&
447 + (strpos($src, 'fluent_booking') === false)
448 + ) {
449 + wp_dequeue_style($wp_styles->registered[$style]->handle);
450 + }
451 + }
452 + }
453 + }, 100);
454 + }
455 +
421 456 public function getEventLandingExtraJsFiles($formFields, $calendarEvent)
422 457 {
423 458 $files = [];
424 459 $assetUrl = App::getInstance('url.assets');
@@ -423,9 +458,9 @@
423 458 $files = [];
424 459 $assetUrl = App::getInstance('url.assets');
425 460
426 461 if (BookingFieldService::hasPhoneNumberField($formFields)) {
427 - $files['fluent-booking-phone-field-js'] = $assetUrl . 'public/js/phone-field.js';
462 + $files['fluent-booking-phone-field-js'] = Vite::scriptUrl('phone_field');
428 463 }
429 464
430 465 if ($calendarEvent->type == 'paid') {
431 466 $files['fluent-booking-checkout-sdk-stripe-js'] = 'https://js.stripe.com/v3/';