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 +76 -51 1.5.02 → 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);
@@ -145,11 +150,12 @@
145 150 if ($extraJs) {
146 151 $vars['lazy_js_files'] = $extraJs;
147 152 }
148 153 $jsVars['fcal_public_vars_' . $calendar->id . '_' . $activeEvent->id] = $vars;
154 + $activeEvent->locations = $activeEvent->defaultLocationHtml();
155 + do_action_ref_array('fluent_booking/landing_page_event', [&$activeEvent]);
149 156 }
150 157
151 - $assetUrl = App::getInstance('url.assets');
152 158 $data = [
153 159 'calendar' => $calendar,
154 160 'events' => $activeEvents,
155 161 'author' => $authorProfile,
@@ -155,17 +161,18 @@
155 161 'author' => $authorProfile,
156 162 'title' => $calendar->title .' - '.get_bloginfo('name'),
157 163 'description' => $metaDescription,
158 164 'url' => home_url($wp->request),
165 + 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
159 166 'css_files' => [
160 - App::getInstance('url.assets') . 'public/saas.css'
167 + Vite::styleUrl('saas_css')
161 168 ],
162 169 'js_files' => [
163 - 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
170 + 'fluent-booking-public-js' => Vite::scriptUrl('public_app'),
164 171 ],
165 172 'js_vars' => $jsVars,
166 173 'header_js_files' => [
167 - 'fluent_booking_team_app-js' => $assetUrl. 'public/js/team_app.js'
174 + 'fluent_booking_team_app-js' => Vite::scriptUrl('team_app')
168 175 ]
169 176 ];
170 177
171 178 if ($extraJsFiles) {
@@ -170,20 +177,11 @@
170 177
171 178 if ($extraJsFiles) {
172 179 $extraJsFiles = array_unique($extraJsFiles);
173 180 $data['js_files'] = array_merge($data['js_files'], $extraJsFiles);
174 - add_action('fluent_booking/main_landing', function () use ($assetUrl) {
175 - ?>
176 - <style>
177 - .fcal_phone_wrapper .flag {
178 - background: url(<?php echo esc_url($assetUrl.'images/flags_responsive.png'); ?>) no-repeat;
179 - background-size: 100%;
180 - }
181 - </style>
182 - <?php
183 - });
181 + }
184 182
185 - }
183 + $data = apply_filters('fluent_booking/host_view_page_vars', $data, $calendar, $activeEvents, $authorProfile);
186 184
187 185 $app = App::getInstance();
188 186 status_header(200);
189 187 $app->view->render('landing.author_landing', $data);
@@ -189,14 +187,16 @@
189 187 $app->view->render('landing.author_landing', $data);
190 188 exit(200);
191 189 }
192 190
193 - private function renderBookingView($calendar, $calendarEvent, $existingBooking = null)
191 + private function renderBookingView($calendar, $calendarEvent, $existingBooking = null, $isReschedule = false)
194 192 {
195 - $settings = LandingPageHelper::getSettings($calendar, 'public');
196 - if ($settings['show_type'] != 'all') {
197 - if (!in_array($calendarEvent->id, $settings['enabled_slots'])) {
198 - 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 + }
199 199 }
200 200 }
201 201
202 202 global $wp;
@@ -204,9 +204,9 @@
204 204 $calendarEvent->max_lookup_date = $calendarEvent->getMaxLookUpDate();
205 205 $calendarEvent->min_lookup_date = $calendarEvent->getMinLookUpDate();
206 206
207 207 if (!empty($_REQUEST['booking_id'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
208 - $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
209 209 $booking = Booking::where('hash', $bookingHash)
210 210 ->where('event_id', $calendarEvent->id)
211 211 ->first();
212 212 if ($booking) {
@@ -228,26 +228,27 @@
228 228 $assetUrl = App::getInstance('url.assets');
229 229
230 230 $eventVars = (new FrontEndHandler())->getCalendarEventVars($calendar, $calendarEvent);
231 231
232 - $isRtl = Helper::fluentbooking_is_rtl();
232 + $publicCss = 'saas_css';
233 233
234 - $publicCss = 'public/saas.css';
235 - if ($isRtl) {
236 - $publicCss = 'public/saas-rtl.css';
237 - }
234 + $title = $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'];
235 +
236 + $title = apply_filters('fluent_booking/booking_confirmation_page_title', $title, $calendarEvent, $authorProfile);
237 +
238 238 $data = [
239 239 'calendar' => $calendar,
240 240 'calendar_event' => $calendarEvent,
241 241 'author' => $authorProfile,
242 - 'title' => $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'],
242 + 'title' => $title,
243 243 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
244 244 'url' => home_url($wp->request),
245 + 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
245 246 'css_files' => [
246 - $assetUrl . $publicCss
247 + Vite::styleUrl($publicCss)
247 248 ],
248 249 'js_files' => [
249 - 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
250 + 'fluent-booking-public-js' => Vite::scriptUrl('public_app'),
250 251 ],
251 252 'js_vars' => [
252 253 'fluentCalendarPublicVars' => (new FrontEndHandler())->getGlobalVars(),
253 254 'fcal_public_vars_' . $calendar->id . '_' . $calendarEvent->id => $eventVars,
@@ -281,9 +282,8 @@
281 282
282 283 private function showBookingConfimationPage($booking, $actionType = 'confirmation')
283 284 {
284 285 $validActions = ['confirmation'];
285 - $isRtl = Helper::fluentbooking_is_rtl();
286 286
287 287 if (in_array($booking->status, ['scheduled', 'pending', 'rescheduled'])) {
288 288 $validActions = array_merge($validActions, ['reschedule', 'cancel']);
289 289 }
@@ -304,24 +304,24 @@
304 304 echo $icsText; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
305 305 die();
306 306 }
307 307
308 + global $wp;
309 +
308 310 $calendarEvent = $booking->calendar_event;
309 - global $wp;
311 +
310 312 $responseHtml = BookingService::getBookingConfirmationHtml($booking, $actionType);
311 313
312 314 $authorProfile = $calendarEvent->getAuthorProfile(true);
313 315
314 - $publicCss = 'public/saas_public.css';
315 - if ($isRtl) {
316 - $publicCss = 'public/saas_public-rtl.css';
317 - }
316 + $publicCss = 'saas_public_css';
317 +
318 318 $data = [
319 319 'title' => __('Confirmation: ', 'fluent-booking') . $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'],
320 320 'body' => $responseHtml,
321 321 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
322 322 'css_files' => [
323 - App::getInstance('url.assets') . $publicCss
323 + Vite::styleUrl($publicCss)
324 324 ],
325 325 'js_files' => [],
326 326 'js_vars' => [],
327 327 'author' => $authorProfile,
@@ -327,15 +327,23 @@
327 327 'author' => $authorProfile,
328 328 'slot' => $calendarEvent,
329 329 'url' => home_url($wp->request),
330 330 'action_type' => $actionType,
331 - '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 + ]
332 338 ];
333 339
334 340 if ($actionType == 'cancel') {
335 - $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');
336 342 }
337 343
344 + $data = apply_filters('fluent_booking/booking_confirmation_page_vars', $data, $booking, $calendarEvent);
345 +
338 346 $app = App::getInstance();
339 347 status_header(200);
340 348 $app->view->render('landing.confirmation_page', $data);
341 349 exit(200);
@@ -342,21 +350,20 @@
342 350 }
343 351
344 352 private function handleAfterBookingPage()
345 353 {
346 - $bookingHash = sanitize_text_field(Arr::get($_REQUEST, 'meeting_hash')); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
347 -
354 + $bookingHash = sanitize_text_field(wp_unslash(Arr::get($_REQUEST, 'meeting_hash'))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
348 355 if (!$bookingHash) {
349 356 return;
350 357 }
351 358
352 359 $booking = Booking::where('hash', $bookingHash)->first();
353 -
354 360 if (!$booking) {
355 361 return;
356 362 }
357 363
358 364 $type = Arr::get($_REQUEST, 'type', 'confirmation'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
365 +
359 366 $this->showBookingConfimationPage($booking, $type);
360 367 }
361 368
362 369 private function handleRescheduleView(Booking $booking)
@@ -424,11 +431,29 @@
424 431 </style>
425 432 <?php
426 433 });
427 434
428 - $this->renderBookingView($booking->calendar, $booking->calendar_event, $booking);
435 + $this->renderBookingView($booking->calendar, $booking->calendar_event, $booking, true);
429 436 }
430 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 +
431 456 public function getEventLandingExtraJsFiles($formFields, $calendarEvent)
432 457 {
433 458 $files = [];
434 459 $assetUrl = App::getInstance('url.assets');
@@ -433,9 +458,9 @@
433 458 $files = [];
434 459 $assetUrl = App::getInstance('url.assets');
435 460
436 461 if (BookingFieldService::hasPhoneNumberField($formFields)) {
437 - $files['fluent-booking-phone-field-js'] = $assetUrl . 'public/js/phone-field.js';
462 + $files['fluent-booking-phone-field-js'] = Vite::scriptUrl('phone_field');
438 463 }
439 464
440 465 if ($calendarEvent->type == 'paid') {
441 466 $files['fluent-booking-checkout-sdk-stripe-js'] = 'https://js.stripe.com/v3/';