where('id', '!=', $exceptId)->first(); } else { $exist = Calendar::where('slug', $slug)->first(); } if ($exist) { return false; } } if (is_numeric($slug)) { return false; } // check if $slug has any special characters or any space. We will only allow alpha-numeric values return preg_match('/^[a-zA-Z0-9_-]+$/', $slug); } public static function isEventSlugAvailable($slug, $checkDb = true, $calendarId = null, $exceptId = null) { if (in_array($slug, self::$reserved)) { return false; } if (strlen($slug) < 4) { return false; } if ($checkDb) { $eventQuery = CalendarSlot::where('slug', $slug); if ($exceptId) { $eventQuery->where('id', '!=', $exceptId); } if ($calendarId) { $eventQuery->where('calendar_id', $calendarId); } $exist = $eventQuery->first(); if ($exist) { return false; } } if (is_numeric($slug)) { return false; } // check if $slug has any special characters or any space. We will only allow alpha-numeric values return preg_match('/^[a-zA-Z0-9_-]+$/', $slug); } public static function getAppBaseUrl($extension = '') { return apply_filters('fluent_booking/admin_base_url', admin_url('admin.php?page=fluent-booking#/' . $extension), $extension); } public static function getAdminBookingUrl($bookingId) { return self::getAppBaseUrl('scheduled-events?booking_id=' . $bookingId); } public static function getUpgradeUrl() { return 'https://fluentbooking.com/pricing/?utm_source=plugin&utm_medium=wp_install&utm_campaign=fcal_upgrade&theme=' . self::getActiveThemeName(); } public static function getNextBookingGroup() { $lastBooking = Booking::orderBy('group_id', 'desc')->first(['group_id']); if ($lastBooking) { return $lastBooking->group_id + 1; } return 1; } public static function getNextIndex() { static $index = 0; $index += 1; return $index; } public static function getGlobalPaymentSettings() { static $settings; if ($settings) { return $settings; } $settings = get_option('fluent_booking_global_payment_settings', []); return $settings; } public static function isPaymentEnabled($calendarEvent = null) { $settings = CurrenciesHelper::getGlobalCurrencySettings(); if (Arr::get($settings, 'is_active') == 'yes') { return true; } if ($calendarEvent) { if ($calendarEvent->type != 'paid') { return false; } $exist = Meta::where('object_type', 'calendar_slot') ->where('object_id', $calendarEvent->id) ->where('key', 'payment_settings') ->first(); return $exist && $exist->value && Arr::get($exist->value, 'enabled') == 'yes'; } return false; } public static function isPaymentConfigured($method = 'stripe') { $settings = get_option('fluent_booking_payment_settings_' . $method, []); return Arr::get($settings, 'is_active', 'no') == 'yes'; } /** * Sanitize form inputs recursively. * * @param $input * * @return mixed $input */ public static function fluentbookingSanitizer($input, $attribute = null, $fields = []) { if (is_string($input)) { $element = Arr::get($fields, $attribute . '.element'); if (in_array($element, ['post_content', 'rich_text_input'])) { return wp_kses_post($input); } elseif ('textarea' === $element) { $input = sanitize_textarea_field($input); } elseif ('input_email' === $element) { $input = strtolower(sanitize_text_field($input)); } elseif ('input_url' === $element) { $input = sanitize_url($input); } else { $input = sanitize_text_field($input); } } elseif (is_array($input)) { foreach ($input as $key => &$value) { $attribute = $attribute ? $attribute . '[' . $key . ']' : $key; $value = self::fluentbookingSanitizer($value, $attribute, $fields); $attribute = null; } } return $input; } public static function getMeta($group, $objectId, $key, $withModel = false) { $meta = Meta::where('object_type', $group) ->where('object_id', $objectId) ->where('key', $key) ->first(); if ($meta) { if ($withModel) { return $meta; } return $meta->value; } return null; } public static function updateMeta($group, $objectId, $key, $value) { $meta = self::getMeta($group, $objectId, $key, true); if ($meta) { $meta->value = $value; $meta->save(); return $meta; } return Meta::create([ 'object_type' => $group, 'key' => $key, 'object_id' => $objectId, 'value' => $value ]); } public static function deleteMeta($group, $objectId, $key) { return Meta::where('object_type', $group) ->where('object_id', $objectId) ->where('key', $key) ->delete(); } public static function getBookingMeta($eventId, $metaKey, $withModel = false) { $bookingMeta = BookingMeta::where('booking_id', $eventId) ->where('meta_key', $metaKey) ->first(); if ($bookingMeta) { return $withModel ? $bookingMeta : $bookingMeta->value; } return null; } public static function updateBookingMeta($eventId, $metaKey, $value) { $bookingMeta = self::getBookingMeta($eventId, $metaKey, true); if ($bookingMeta) { $bookingMeta->value = $value; $bookingMeta->save(); return $bookingMeta; } return BookingMeta::create([ 'booking_id' => $eventId, 'meta_key' => $metaKey, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'value' => $value ]); } public static function getUserDisplayName($userId = null) { if (!$userId) { $userId = get_current_user_id(); } if (!$userId) { return ''; } $user = get_user_by('ID', $userId); return self::getDisplayNameFromUser($user); } public static function getDisplayNameFromUser($user) { if (!$user) { return ''; } $firstName = is_object($user) ? ($user->first_name ?? '') : ''; $lastName = is_object($user) ? ($user->last_name ?? '') : ''; $name = trim($firstName . ' ' . $lastName); if ($name !== '') { return $name; } $displayName = is_object($user) ? ($user->display_name ?? '') : ''; return (string) $displayName; } public static function getUserEmail($userId = null) { $userId = $userId ?: get_current_user_id(); if (!$userId) { return ''; } $user = get_user_by('ID', $userId); return $user->user_email; } public static function excerpt($text, $max_length = 160) { // Strip HTML tags and convert entities to their corresponding characters $text = html_entity_decode(wp_strip_all_tags($text)); // Remove any line breaks, tabs, or extra whitespace $text = preg_replace('/\s+/', ' ', trim($text)); if (mb_strlen($text) > $max_length) { $text = mb_substr($text, 0, $max_length); $text = preg_replace('/\s+\S+$/', '', $text) . '...'; } return $text; } public static function generateSlotSlug($default, $calendar) { $original = sanitize_title($default, $default, 'display'); $default = $original; $counter = 1; while (CalendarSlot::where('calendar_id', $calendar->id)->where('slug', $default)->first()) { $default = $original . '-' . $counter; $counter += 1; } return apply_filters('fluent_booking/slot_slug', $default, $original); } public static function getIp($defalt = '127.0.0.1') { static $ipAddress; if ($ipAddress) { return $ipAddress; } if (empty($_SERVER['REMOTE_ADDR'])) { // It's a local cli request return $defalt; } $ipAddress = ''; $serverData = $_SERVER; $HTTP_CF_CONNECTING_IP = Arr::get($serverData, 'HTTP_CF_CONNECTING_IP'); $RemoteAddr = Arr::get($serverData, 'REMOTE_ADDR'); $clientIp = Arr::get($serverData, 'HTTP_CLIENT_IP'); $HTTP_X_FORWARDED_FOR = Arr::get($serverData, 'HTTP_X_FORWARDED_FOR'); if ($HTTP_CF_CONNECTING_IP) { //If it's a valid Cloudflare request if (self::isCfIp($RemoteAddr)) { //Use the CF-Connecting-IP header. $ipAddress = $HTTP_CF_CONNECTING_IP; } else { //If it isn't valid, then use REMOTE_ADDR. $ipAddress = $RemoteAddr; } } else if ($RemoteAddr == '127.0.0.1') { // most probably it's local reverse proxy if ($clientIp) { $ipAddress = $clientIp; } else if ($HTTP_X_FORWARDED_FOR) { $ipAddress = (string)rest_is_ip_address(trim(current(preg_split('/,/', sanitize_text_field($HTTP_X_FORWARDED_FOR))))); } } if (!$ipAddress) { $ipAddress = $RemoteAddr; } $ipAddress = preg_replace('/^(\d+\.\d+\.\d+\.\d+):\d+$/', '\1', $ipAddress); $ipAddress = apply_filters('fluent_booking/user_ip', $ipAddress, []); $ipAddress = sanitize_text_field(wp_unslash($ipAddress)); return $ipAddress; } private static function isCfIp($ip = '') { if (!$ip) { $serverData = $_SERVER; $REMOTE_ADDR = Arr::get($serverData, 'REMOTE_ADDR'); $ip = $REMOTE_ADDR; } $cloudflareIPRanges = array( '173.245.48.0/20', '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22', '141.101.64.0/18', '108.162.192.0/18', '190.93.240.0/20', '188.114.96.0/20', '197.234.240.0/22', '198.41.128.0/17', '162.158.0.0/15', '104.16.0.0/13', '104.24.0.0/14', '172.64.0.0/13', '131.0.72.0/22', ); //Make sure that the request came via Cloudflare. foreach ($cloudflareIPRanges as $range) { //Use the ip_in_range function from Joomla. if (self::ipInRange($ip, $range)) { //IP is valid. Belongs to Cloudflare. return true; } } return false; } private static function ipInRange($ip, $range) { if (strpos($range, '/') !== false) { // $range is in IP/NETMASK format list($range, $netmask) = explode('/', $range, 2); if (strpos($netmask, '.') !== false) { // $netmask is a 255.255.0.0 format $netmask = str_replace('*', '0', $netmask); $netmask_dec = ip2long($netmask); return ((ip2long($ip) & $netmask_dec) == (ip2long($range) & $netmask_dec)); } else { // $netmask is a CIDR size block // fix the range argument $x = explode('.', $range); while (count($x) < 4) $x[] = '0'; list($a, $b, $c, $d) = $x; $range = sprintf("%u.%u.%u.%u", empty($a) ? '0' : $a, empty($b) ? '0' : $b, empty($c) ? '0' : $c, empty($d) ? '0' : $d); $range_dec = ip2long($range); $ip_dec = ip2long($ip); # Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s #$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0')); # Strategy 2 - Use math to create it $wildcard_dec = pow(2, (32 - $netmask)) - 1; $netmask_dec = ~$wildcard_dec; return (($ip_dec & $netmask_dec) == ($range_dec & $netmask_dec)); } } else { // range might be 255.255.*.* or 1.2.3.0-1.2.3.255 if (strpos($range, '*') !== false) { // a.b.*.* format // Just convert to A-B format by setting * to 0 for A and 255 for B $lower = str_replace('*', '0', $range); $upper = str_replace('*', '255', $range); $range = "$lower-$upper"; } if (strpos($range, '-') !== false) { // A-B format list($lower, $upper) = explode('-', $range, 2); $lower_dec = (float)sprintf("%u", ip2long($lower)); $upper_dec = (float)sprintf("%u", ip2long($upper)); $ip_dec = (float)sprintf("%u", ip2long($ip)); return (($ip_dec >= $lower_dec) && ($ip_dec <= $upper_dec)); } return false; } } public static function fcal_sanitize_html($html) { if (!$html) { return $html; } // Return $html if it's just a plain text if (!preg_match('/<[^>]*>/', $html)) { return $html; } $tags = wp_kses_allowed_html('post'); $tags['style'] = [ 'types' => [], ]; // iframe $tags['iframe'] = [ 'width' => [], 'height' => [], 'src' => [], 'title' => [], 'frameborder' => [], 'allow' => [], 'class' => [], 'id' => [], 'allowfullscreen' => [], 'style' => [], ]; //button $tags['button'] = [ 'onclick' => [] ]; //svg if (empty($tags['svg'])) { $svg_args = [ 'svg' => [ 'class' => true, 'aria-hidden' => true, 'aria-labelledby' => true, 'role' => true, 'xmlns' => true, 'width' => true, 'height' => true, 'viewbox' => true, ], 'g' => ['fill' => true], 'title' => ['title' => true], 'path' => [ 'd' => true, 'fill' => true, 'transform' => true, ], ]; $tags = array_merge($tags, $svg_args); } $tags = apply_filters('fluent_booking/allowed_html_tags', $tags); return wp_kses($html, $tags); } /** * Sanitize inputs recursively. * * @param array $input * @param array $sanitizeMap * * @return array $input */ public static function fcal_backend_sanitizer($inputs, $sanitizeMap = []) { $originalValues = $inputs; foreach ($inputs as $key => &$value) { if (is_array($value)) { $value = self::fcal_backend_sanitizer($value, $sanitizeMap); } else { $method = Arr::get($sanitizeMap, $key); if (!$method) { continue; } if (is_callable($method)) { $value = call_user_func($method, $value); } elseif (method_exists(self::class, $method)) { $value = call_user_func([self::class, $method], $value); } } } return apply_filters('fluent_booking/backend_sanitized_values', $inputs, $originalValues); } /** * Recursively implode a multi-dimentional array * * @param string $glue * @param array $array * * @return string */ public static function fcalImplodeRecursive($glue, array $array) { $fn = function ($glue, array $array) use (&$fn) { $result = ''; foreach ($array as $item) { if (is_array($item)) { $result .= $fn($glue, $item); } else { $result .= $glue . $item; } } return $result; }; return ltrim($fn($glue, $array), $glue); } public static function getEventColors() { return apply_filters('fluent_booking/event_colors', [ [ 'label' => __('Red-Orange', 'fluent-booking'), 'value' => '#ff4f00' ], [ 'label' => __('Deep Lilac', 'fluent-booking'), 'value' => '#e55cff' ], [ 'label' => __('Purple', 'fluent-booking'), 'value' => '#8247f5' ], [ 'label' => __('Vivid Blue', 'fluent-booking'), 'value' => '#0099ff' ], [ 'label' => __('Cyan', 'fluent-booking'), 'value' => '#0ae8f0' ], [ 'label' => __('Emerald Green', 'fluent-booking'), 'value' => '#17e885' ], [ 'label' => __('Lime Green', 'fluent-booking'), 'value' => '#ccf000' ], [ 'label' => __('Amber', 'fluent-booking'), 'value' => '#ffa600' ] ]); } public static function getMeetingDurations() { return apply_filters('fluent_booking/meeting_durations_schema', [ [ 'value' => '15', 'label' => __('15 Minutes', 'fluent-booking') ], [ 'value' => '30', 'label' => __('30 Minutes', 'fluent-booking') ], [ 'value' => '45', 'label' => __('45 Minutes', 'fluent-booking') ], [ 'value' => '60', 'label' => __('60 Minutes', 'fluent-booking') ], [ 'value' => 'custom', 'label' => __('Custom', 'fluent-booking') ] ]); } public static function getMeetingMultiDurations() { return apply_filters('fluent_booking/meeting_multi_durations_schema', [ [ 'value' => '5', 'label' => __('5 Minutes', 'fluent-booking') ], [ 'value' => '10', 'label' => __('10 Minutes', 'fluent-booking') ], [ 'value' => '15', 'label' => __('15 Minutes', 'fluent-booking') ], [ 'value' => '30', 'label' => __('30 Minutes', 'fluent-booking') ], [ 'value' => '45', 'label' => __('45 Minutes', 'fluent-booking') ], [ 'value' => '50', 'label' => __('50 Minutes', 'fluent-booking') ], [ 'value' => '60', 'label' => __('60 Minutes', 'fluent-booking') ], [ 'value' => '90', 'label' => __('90 Minutes', 'fluent-booking') ], [ 'value' => '120', 'label' => __('120 Minutes', 'fluent-booking') ], [ 'value' => '150', 'label' => __('150 Minutes', 'fluent-booking') ], [ 'value' => '180', 'label' => __('180 Minutes', 'fluent-booking') ], [ 'value' => '240', 'label' => __('240 Minutes', 'fluent-booking') ], [ 'value' => '480', 'label' => __('480 Minutes', 'fluent-booking') ] ]); } public static function getDurationLookup($multiDuration = false) { $durations = $multiDuration ? self::getMeetingMultiDurations() : self::getMeetingDurations(); $durationLookup = []; foreach ($durations as $duration) { $durationLookup[$duration['value']] = $duration['label']; } return $durationLookup; } public static function formatDuration($totalMinutes) { $days = floor($totalMinutes / 1440); // 1440 minutes in a day $hours = floor(($totalMinutes % 1440) / 60); $minutes = $totalMinutes % 60; $formattedDuration = []; if ($days > 0) { $unit = $days > 1 ? __('Days', 'fluent-booking') : __('Day', 'fluent-booking'); $formattedDuration[] = $days . ' ' . $unit; } if ($hours > 0) { $unit = $hours > 1 ? __('Hours', 'fluent-booking') : __('Hour', 'fluent-booking'); $formattedDuration[] = $hours . ' ' . $unit; } if ($minutes > 0 || empty($formattedDuration)) { $unit = $minutes > 1 ? __('Minutes', 'fluent-booking') : __('Minute', 'fluent-booking'); $formattedDuration[] = $minutes . ' ' . $unit; } return implode(' ', $formattedDuration); } public static function getBufferTimes() { return apply_filters('fluent_booking/buffer_times_schema', [ [ 'value' => '0', 'label' => __('No buffer time', 'fluent-booking') ], [ 'value' => '5', 'label' => __('5 Minutes', 'fluent-booking') ], [ 'value' => '10', 'label' => __('10 Minutes', 'fluent-booking') ], [ 'value' => '15', 'label' => __('15 Minutes', 'fluent-booking') ], [ 'value' => '20', 'label' => __('20 Minutes', 'fluent-booking') ], [ 'value' => '30', 'label' => __('30 Minutes', 'fluent-booking') ], [ 'value' => '45', 'label' => __('45 Minutes', 'fluent-booking') ], [ 'value' => '60', 'label' => __('60 Minutes', 'fluent-booking') ], [ 'value' => '90', 'label' => __('90 Minutes', 'fluent-booking') ], [ 'value' => '120', 'label' => __('120 Minutes', 'fluent-booking') ] ]); } public static function getSlotIntervals() { return apply_filters('fluent_booking/slot_intervals_schema', [ [ 'value' => '', 'label' => __('Use event length (default)', 'fluent-booking') ], [ 'value' => '5', 'label' => __('5 Minutes', 'fluent-booking') ], [ 'value' => '10', 'label' => __('10 Minutes', 'fluent-booking') ], [ 'value' => '15', 'label' => __('15 Minutes', 'fluent-booking') ], [ 'value' => '20', 'label' => __('20 Minutes', 'fluent-booking') ], [ 'value' => '30', 'label' => __('30 Minutes', 'fluent-booking') ], [ 'value' => '45', 'label' => __('45 Minutes', 'fluent-booking') ], [ 'value' => '60', 'label' => __('60 Minutes', 'fluent-booking') ], [ 'value' => '75', 'label' => __('75 Minutes', 'fluent-booking') ], [ 'value' => '90', 'label' => __('90 Minutes', 'fluent-booking') ], [ 'value' => '105', 'label' => __('105 Minutes', 'fluent-booking') ], [ 'value' => '120', 'label' => __('120 Minutes', 'fluent-booking') ] ]); } public static function getBookingStatusChangingTimes() { return apply_filters('fluent_booking/booking_status_changing_times_schema', [ [ 'value' => '5', 'label' => __('5 Minutes', 'fluent-booking') ], [ 'value' => '10', 'label' => __('10 Minutes', 'fluent-booking') ], [ 'value' => '20', 'label' => __('20 Minutes', 'fluent-booking') ], [ 'value' => '30', 'label' => __('30 Minutes', 'fluent-booking') ], [ 'value' => '40', 'label' => __('40 Minutes', 'fluent-booking') ], [ 'value' => '50', 'label' => __('50 Minutes', 'fluent-booking') ], [ 'value' => '60', 'label' => __('1 Hour', 'fluent-booking') ], [ 'value' => '120', 'label' => __('2 Hours', 'fluent-booking') ], [ 'value' => '180', 'label' => __('3 Hours', 'fluent-booking') ], [ 'value' => '360', 'label' => __('6 Hours', 'fluent-booking') ], [ 'value' => '720', 'label' => __('12 Hours', 'fluent-booking') ], [ 'value' => '1440', 'label' => __('1 Day', 'fluent-booking') ], [ 'value' => '2880', 'label' => __('2 Days', 'fluent-booking') ] ]); } public static function getBookingPeriodOptions() { return apply_filters('fluent_booking/booking_period_options', [ 'upcoming' => __('Upcoming', 'fluent-booking'), 'completed' => __('Completed', 'fluent-booking'), 'pending' => __('Pending', 'fluent-booking'), 'cancelled' => __('Cancelled', 'fluent-booking'), 'all' => __('All', 'fluent-booking'), ]); } public static function getWeekSelectTimes() { return apply_filters('fluent_booking/week_select_times_schema', [ 'start' => '00:00', 'step' => '00:15', 'end' => '23:45' ]); } public static function getOverrideSelectTimes() { return apply_filters('fluent_booking/override_select_times_schema', [ 'start' => '00:00', 'step' => '00:15', 'end' => '23:45' ]); } public static function getWeeklyScheduleSchema() { return apply_filters('fluent_booking/weekly_schedule_schema', [ 'sun' => [ 'enabled' => false, 'slots' => [] ], 'mon' => [ 'enabled' => true, 'slots' => [ ['start' => '09:00', 'end' => '17:00'] ], ], 'tue' => [ 'enabled' => true, 'slots' => [ ['start' => '09:00', 'end' => '17:00'] ], ], 'wed' => [ 'enabled' => true, 'slots' => [ ['start' => '09:00', 'end' => '17:00'] ], ], 'thu' => [ 'enabled' => true, 'slots' => [ ['start' => '09:00', 'end' => '17:00'] ], ], 'fri' => [ 'enabled' => true, 'slots' => [ ['start' => '09:00', 'end' => '17:00'] ], ], 'sat' => [ 'enabled' => false, 'slots' => [] ], ]); } public static function getCustomFieldTypes() { return apply_filters('fluent_booking/custom_fields_types', [ [ 'value' => 'email', 'label' => __('Email', 'fluent-booking') ], [ 'value' => 'text', 'label' => __('Text', 'fluent-booking') ], [ 'value' => 'textarea', 'label' => __('Textarea', 'fluent-booking') ], [ 'value' => 'number', 'label' => __('Number', 'fluent-booking') ], [ 'value' => 'phone', 'label' => __('Phone', 'fluent-booking') ], [ 'value' => 'radio', 'label' => __('Radio', 'fluent-booking') ], [ 'value' => 'dropdown', 'label' => __('Select', 'fluent-booking') ], [ 'value' => 'multi-select', 'label' => __('Multi Select', 'fluent-booking') ], [ 'value' => 'checkbox', 'label' => __('Checkbox', 'fluent-booking') ], [ 'value' => 'checkbox-group', 'label' => __('Checkbox Group', 'fluent-booking') ], [ 'value' => 'date', 'label' => __('Date', 'fluent-booking') ], [ 'value' => 'file', 'label' => __('File', 'fluent-booking') ], [ 'value' => 'hidden', 'label' => __('Hidden', 'fluent-booking') ], [ 'value' => 'terms-and-conditions', 'label' => __('Terms & Conditions', 'fluent-booking') ] ]); } public static function getDefaultTermsAndConditions() { $termsAndConditions = __('I have read and agree to the Terms and Conditions and Privacy Policy.', 'fluent-booking'); return apply_filters('fluent_booking/default_terms_and_conditions', $termsAndConditions); } public static function getDefaultEmailNotificationSettings() { $assetUrl = App::getInstance()['url.assets']; $checkImage = $assetUrl . 'images/check-mark.png'; $cancelImage = $assetUrl . 'images/cancel-mark.png'; $scheduleImage = $assetUrl . 'images/schedule-mark.png'; return apply_filters('fluent_booking/default_email_notification_settings', [ 'booking_conf_attendee' => [ 'enabled' => true, 'title' => __('Booking Confirmation Email to Attendee', 'fluent-booking'), 'email' => [ 'subject' => 'Booking Confirmation between {{host.name}} & {{guest.full_name}}', 'body' => '
Event Name
{{booking.event_name}} with {{host.name}}
When
{{booking.full_start_end_guest_timezone}}
Who
Where
{{booking.location_details_html}}
Additional notes
{{guest.note}}
' . __('Need to make a change?', 'fluent-booking') . ' ' . __('Reschedule', 'fluent-booking') . ' or ' . __('Cancel', 'fluent-booking') . '
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}}
Who
Where
{{booking.location_details_html}}
Note
{{guest.note}}
Additional Data
{{guest.form_data_html}}
Event Name
{{booking.event_name}} with {{host.name}}
{{booking.full_start_end_guest_timezone}}
Where
{{booking.location_details_html}}
Additional notes
{{guest.note}}
' . __('Need to make a change?', 'fluent-booking') . ' ' . __('Reschedule', 'fluent-booking') . ' or ' . __('Cancel', 'fluent-booking') . '
', 'times' => [ [ 'unit' => 'minutes', 'value' => 15, ] ] ], ], 'reminder_to_host' => [ 'enabled' => false, 'is_host' => true, 'title' => __('Configure Meeting Reminder to Organizer (You)', 'fluent-booking'), 'email' => [ 'additional_recipients' => '', 'subject' => 'Meeting Reminder with {{host.name}} @ {{booking.start_date_time_for_host}}', 'body' => 'Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}}
Who
Where
{{booking.location_details_html}}
Note
{{guest.note}}
Additional Data
{{guest.form_data_html}}
A scheduled meeting has been canceled. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}} (cancelled)
Cancellation Reason
{{booking.cancel_reason}}
Who
Where
{{booking.location_details_html}}
Note
{{guest.note}}
Additional Data
{{guest.form_data_html}}
Your scheduled meeting has been canceled. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}} (cancelled)
Cancellation Reason
{{booking.cancel_reason}}
' ], ], 'rescheduled_by_attendee' => [ 'enabled' => true, 'is_host' => true, 'title' => __('Booking Rescheduled by Attendee (email to Organizer)', 'fluent-booking'), 'email' => [ 'additional_recipients' => '', 'subject' => 'A booking was rescheduled with {{guest.full_name}}', 'body' => 'A scheduled meeting has been rescheduled. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
New Time: {{booking.full_start_end_host_timezone}} (new)
Previous Time: {{booking.previous_meeting_time}}
Rescheduling Reason
{{booking.reschedule_reason}}
Who
Where
{{booking.location_details_html}}
Note
{{guest.note}}
Additional Data
{{guest.form_data_html}}
Your scheduled meeting has been rescheduled. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
New Time: {{booking.full_start_end_host_timezone}} (new)
Previous Time: {{booking.previous_meeting_time_guest_timezone}}
Rescheduling Reason
{{booking.reschedule_reason}}
' . __('Need to make a change?', 'fluent-booking') . ' ' . __('Reschedule', 'fluent-booking') . ' or ' . __('Cancel', 'fluent-booking') . '
Someone has requested to schedule an event on your calendar. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}}
Who
Where
{{booking.location_details_html}}
Note
{{guest.note}}
Additional Data
{{guest.form_data_html}}
Please wait for the host to confirm your booking.
Event Name
{{booking.event_name}} with {{host.name}}
When
{{booking.full_start_end_guest_timezone}}
Who
Where
{{booking.location_details_html}}
Additional notes
{{guest.note}}
' . __('Need to make a change?', 'fluent-booking') . ' ' . __('Reschedule', 'fluent-booking') . ' or ' . __('Cancel', 'fluent-booking') . '
' ], ], 'declined_by_host' => [ 'enabled' => true, 'title' => __('Booking Declined by Organizer (email to Attendee)', 'fluent-booking'), 'email' => [ 'subject' => 'Booking Declined: Your booking was declined with {{host.name}}', 'body' => 'Your booking request has been declined. Here are the details:
Event Name
{{booking.event_name}} with {{guest.full_name}}
When
{{booking.full_start_end_host_timezone}} (declined)
Reason
{{booking.reject_reason}}
' ], ], ]); } public static function getAddToCalendarHtml($assetUrl = '') { $assetUrl = $assetUrl ?: App::getInstance()['url.assets']; $html = '| ' . __('Add to calendar', 'fluent-booking') . ' |
|