request, '/'); $urlParts = explode('/', $uri); if ($urlParts[0] != FLUENT_BOOKING_LANDING_SLUG || count($urlParts) < 2) { return; } $authorSlug = sanitize_text_field($urlParts[1]); if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $this->handleEmbeddedStyle(); } $this->routeView($authorSlug, Arr::get($urlParts, 2, null)); } public function handleUrlParamsPage() { $route = isset($_GET['fluent-booking']) ? sanitize_text_field(wp_unslash($_GET['fluent-booking'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $this->handleEmbeddedStyle(); } if ($route == 'booking') { $this->handleAfterBookingPage(); return; } $request = $_REQUEST; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if (empty($request['host'])) { do_action('fluent_booking/landing_page_route_' . $route, $request); return; } $authorSlug = sanitize_text_field($request['host']); $slotSlug = null; if (!empty($request['event'])) { $slotSlug = sanitize_text_field($request['event']); } $this->routeView($authorSlug, $slotSlug); } public function routeView($authorSlug, $slotSlug = null) { $calendar = Calendar::where('slug', $authorSlug)->first(); if (!$calendar) { return; } $sharingSettings = LandingPageHelper::getSettings($calendar); if (Arr::get($sharingSettings, 'enabled') != 'yes') { return ''; } if ($slotSlug) { $slot = CalendarSlot::where('calendar_id', $calendar->id) ->where('slug', $slotSlug) ->first(); if (!$slot) { return; } return $this->renderBookingView($calendar, $slot); } $this->renderHostView($calendar); } private function renderHostView($calendar) { global $wp; $settings = LandingPageHelper::getSettings($calendar, 'public'); $activeEvents = CalendarSlot::where('calendar_id', $calendar->id) ->where('status', 'active'); if ($settings['show_type'] != 'all') { $activeEvents = $activeEvents->whereIn('id', $settings['enabled_slots']); } $activeEvents = $activeEvents->get(); $activeEvents = CalendarEventService::processEvents($calendar, $activeEvents); $metaDescription = Helper::excerpt($calendar->description); $calendar->description = wpautop($calendar->description); $authorProfile = $calendar->getAuthorProfile(true); $globalVars = (new FrontEndHandler())->getGlobalVars(); $currentUrl = home_url($wp->request); $globalVars['is_landing_page'] = true; $globalVars['is_pretty_url'] = defined('FLUENT_BOOKING_LANDING_SLUG'); $globalVars['base_url'] = rtrim($currentUrl, '/'); $jsVars = [ 'fluentCalendarPublicVars' => $globalVars, 'fcal_landing_page' => true ]; $extraJsFiles = []; foreach ($activeEvents as $activeEvent) { $event = clone $activeEvent; $vars = (new FrontEndHandler())->getCalendarEventVars($calendar, $event); $extraJs = $this->getEventLandingExtraJsFiles($vars['form_fields'], $event); if ($extraJs) { $vars['lazy_js_files'] = $extraJs; } $jsVars['fcal_public_vars_' . $calendar->id . '_' . $activeEvent->id] = $vars; $activeEvent->locations = $activeEvent->defaultLocationHtml(); do_action_ref_array('fluent_booking/landing_page_event', [&$activeEvent]); } $assetUrl = App::getInstance('url.assets'); $data = [ 'calendar' => $calendar, 'events' => $activeEvents, 'author' => $authorProfile, 'title' => $calendar->title .' - '.get_bloginfo('name'), 'description' => $metaDescription, 'url' => home_url($wp->request), 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'css_files' => [ App::getInstance('url.assets') . 'public/saas.css' ], 'js_files' => [ 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js', ], 'js_vars' => $jsVars, 'header_js_files' => [ 'fluent_booking_team_app-js' => $assetUrl. 'public/js/team_app.js' ] ]; if ($extraJsFiles) { $extraJsFiles = array_unique($extraJsFiles); $data['js_files'] = array_merge($data['js_files'], $extraJsFiles); } $data = apply_filters('fluent_booking/host_view_page_vars', $data, $calendar, $activeEvents, $authorProfile); $app = App::getInstance(); status_header(200); $app->view->render('landing.author_landing', $data); exit(200); } private function renderBookingView($calendar, $calendarEvent, $existingBooking = null, $isReschedule = false) { if (!$isReschedule) { $settings = LandingPageHelper::getSettings($calendar, 'public'); if ($settings['show_type'] != 'all') { if (!in_array($calendarEvent->id, $settings['enabled_slots'])) { return ''; } } } global $wp; $calendarEvent->max_lookup_date = $calendarEvent->getMaxLookUpDate(); $calendarEvent->min_lookup_date = $calendarEvent->getMinLookUpDate(); if (!empty($_REQUEST['booking_id'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $bookingHash = sanitize_text_field(wp_unslash($_REQUEST['booking_id'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $booking = Booking::where('hash', $bookingHash) ->where('event_id', $calendarEvent->id) ->first(); if ($booking) { $this->showBookingConfimationPage($booking, $calendarEvent); } } $authorProfile = $calendarEvent->getAuthorProfile(true); $calendarEvent->pre_selects = false; if (gmdate('m') != gmdate('m', strtotime($calendarEvent->min_lookup_date))) { // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $calendarEvent->pre_selects = [ 'month' => gmdate('m', strtotime($calendarEvent->min_lookup_date)), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date 'year' => gmdate('Y', strtotime($calendarEvent->min_lookup_date)) // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date ]; } $assetUrl = App::getInstance('url.assets'); $eventVars = (new FrontEndHandler())->getCalendarEventVars($calendar, $calendarEvent); $isRtl = Helper::fluentbooking_is_rtl(); $publicCss = $isRtl ? 'public/saas-rtl.css' : 'public/saas.css'; $title = $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name']; $title = apply_filters('fluent_booking/booking_confirmation_page_title', $title, $calendarEvent, $authorProfile); $data = [ 'calendar' => $calendar, 'calendar_event' => $calendarEvent, 'author' => $authorProfile, 'title' => $title, 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...', 'url' => home_url($wp->request), 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'css_files' => [ $assetUrl . $publicCss ], 'js_files' => [ 'fluent-booking-public-js' => $assetUrl . 'public/js/app.js', ], 'js_vars' => [ 'fluentCalendarPublicVars' => (new FrontEndHandler())->getGlobalVars(), 'fcal_public_vars_' . $calendar->id . '_' . $calendarEvent->id => $eventVars, ] ]; $extraJs = $this->getEventLandingExtraJsFiles($eventVars['form_fields'], $calendarEvent); if ($extraJs) { $data['js_files'] = wp_parse_args($data['js_files'], $extraJs); add_action('fluent_booking/author_landing_head', function () use ($assetUrl) { ?> view->render('landing.booking', $data); exit(200); } private function showBookingConfimationPage($booking, $actionType = 'confirmation') { $validActions = ['confirmation']; if (in_array($booking->status, ['scheduled', 'pending', 'rescheduled'])) { $validActions = array_merge($validActions, ['reschedule', 'cancel']); } if (!in_array($actionType, $validActions)) { $actionType = 'confirmation'; } if ($actionType == 'reschedule') { $this->handleRescheduleView($booking); } if ($actionType == 'confirmation' && !empty($_REQUEST['ics']) && $_REQUEST['ics'] == 'download') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $icsText = BookingService::generateBookingICS($booking); // Output the ICS text header('Content-Type: text/calendar; charset=utf-8'); header('Content-Disposition: attachment; filename=event.ics'); echo $icsText; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped die(); } global $wp; $calendarEvent = $booking->calendar_event; $responseHtml = BookingService::getBookingConfirmationHtml($booking, $actionType); $authorProfile = $calendarEvent->getAuthorProfile(true); $publicCss = 'public/saas_public.css'; if (Helper::fluentbooking_is_rtl()) { $publicCss = 'public/saas_public-rtl.css'; } $data = [ 'title' => __('Confirmation: ', 'fluent-booking') . $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'], 'body' => $responseHtml, 'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...', 'css_files' => [ App::getInstance('url.assets') . $publicCss ], 'js_files' => [], 'js_vars' => [], 'author' => $authorProfile, 'slot' => $calendarEvent, 'url' => home_url($wp->request), 'action_type' => $actionType, 'embedded' => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'theme' => Arr::get(get_option('_fluent_booking_settings'), 'theme','system-default'), 'back_button' => [ 'show' => true, 'text' => __('Back to home', 'fluent-booking'), 'url' => site_url('/') ] ]; if ($actionType == 'cancel') { $data['js_files']['fluent-booking-public-manage-meeting-js'] = App::getInstance('url.assets') . 'public/js/public-manage-meeting.js'; } $data = apply_filters('fluent_booking/booking_confirmation_page_vars', $data, $booking, $calendarEvent); $app = App::getInstance(); status_header(200); $app->view->render('landing.confirmation_page', $data); exit(200); } private function handleAfterBookingPage() { $bookingHash = sanitize_text_field(wp_unslash(Arr::get($_REQUEST, 'meeting_hash'))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if (!$bookingHash) { return; } $booking = Booking::where('hash', $bookingHash)->first(); if (!$booking) { return; } $type = Arr::get($_REQUEST, 'type', 'confirmation'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $this->showBookingConfimationPage($booking, $type); } private function handleRescheduleView(Booking $booking) { add_filter('fluent_booking/public_event_vars', function ($eventVars) use ($booking) { $onlyFields = ['name', 'email', 'rescheduling_reason']; $formFields = $eventVars['form_fields']; $formFields = Collection::make($formFields)->filter(function ($field) use ($onlyFields) { return in_array($field['name'], $onlyFields); })->map(function ($item) { $item['disabled'] = $item['name'] == 'rescheduling_reason' ? false : true; return $item; })->toArray(); $formFields[] = [ 'type' => 'hidden', 'name' => 'rescheduling_hash', 'enabled' => true ]; $eventVars['rescheduling'] = 'yes'; $eventVars['form_fields'] = array_values($formFields); unset($eventVars['payment_items']); unset($eventVars['payment_methods']); return $eventVars; }, 10, 1); add_filter('fluent_calendar/global_booking_vars', function ($vars) use ($booking) { $vars['current_person'] = [ 'name' => trim($booking->first_name . ' ' . $booking->last_name), 'email' => $booking->email, 'rescheduling_hash' => $booking->hash ]; return $vars; }, 10, 1); add_filter('fluent_booking/public_event_vars', function ($vars, $calendarEvent) { $vars['i18']['Schedule_Meeting'] = __('Confirm Reschedule', 'fluent-booking'); $vars['i18']['Continue_to_Payments'] = __('Confirm Reschedule', 'fluent-booking'); $vars['i18']['Confirm_Payment'] = __('Confirm Reschedule', 'fluent-booking'); return $vars; }, 10, 2); add_action('fluent_booking/before_calendar_event_landing_page', function ($calendarEvent) use ($booking) { ?>

getFullBookingDateTimeText($booking->person_time_zone, true)); ?> (person_time_zone); ?>)

renderBookingView($booking->calendar, $booking->calendar_event, $booking, true); } private function handleEmbeddedStyle() { add_action('wp_print_styles', function () { global $wp_styles; if($wp_styles) { foreach ($wp_styles->queue as $style) { $src = $wp_styles->registered[$style]->src; if ( (strpos($src, 'fluentbooking') === false) && (strpos($src, 'fluent_booking') === false) ) { wp_dequeue_style($wp_styles->registered[$style]->handle); } } } }, 100); } public function getEventLandingExtraJsFiles($formFields, $calendarEvent) { $files = []; $assetUrl = App::getInstance('url.assets'); if (BookingFieldService::hasPhoneNumberField($formFields)) { $files['fluent-booking-phone-field-js'] = $assetUrl . 'public/js/phone-field.js'; } if ($calendarEvent->type == 'paid') { $files['fluent-booking-checkout-sdk-stripe-js'] = 'https://js.stripe.com/v3/'; $files['fluent-booking-checkout-handler-stripe-js'] = $assetUrl . 'public/js/stripe-checkout.js'; } return $files; } }