PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.1.1
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.1.1
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 / Hooks / Handlers / AdminMenuHandler.php

AdminMenuHandler.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.1.1, at app/Hooks/Handlers/AdminMenuHandler.php

851 lines 44.4 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\Hooks\Handlers;
4
5 use FluentBooking\App\App;
6 use FluentBooking\App\Models\Calendar;
7 use FluentBooking\App\Models\CalendarSlot;
8 use FluentBooking\App\Services\DateTimeHelper;
9 use FluentBooking\App\Services\Helper;
10 use FluentBooking\App\Services\PermissionManager;
11 use FluentBooking\App\Services\TransStrings;
12
13 class AdminMenuHandler
14 {
15 public function register()
16 {
17 add_action('admin_menu', [$this, 'add']);
18
19 add_action('admin_enqueue_scripts', function () {
20 if (!isset($_REQUEST['page']) || $_REQUEST['page'] != 'fluent-booking') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
21 return;
22 }
23 $this->enqueueAssets();
24 }, 100);
25 }
26
27 public function add()
28 {
29 $capability = PermissionManager::getMenuPermission();
30 $menuPriority = 26;
31
32 if (defined('FLUENTCRM')) {
33 $menuPriority = 4;
34 }
35
36 add_menu_page(
37 __('Fluent Booking', 'fluent-booking'),
38 __('Fluent Booking', 'fluent-booking'),
39 $capability,
40 'fluent-booking',
41 [$this, 'render'],
42 $this->getMenuIcon(),
43 $menuPriority
44 );
45
46 add_submenu_page(
47 'fluent-booking',
48 __('Dashboard', 'fluent-booking'),
49 __('Dashboard', 'fluent-booking'),
50 $capability,
51 'fluent-booking',
52 [$this, 'render']
53 );
54
55 add_submenu_page(
56 'fluent-booking',
57 __('Calendars', 'fluent-booking'),
58 __('Calendars', 'fluent-booking'),
59 $capability,
60 'fluent-booking#/calendars',
61 [$this, 'render']
62 );
63
64 add_submenu_page(
65 'fluent-booking',
66 __('Bookings', 'fluent-booking'),
67 __('Bookings', 'fluent-booking'),
68 $capability,
69 'fluent-booking#/scheduled-events',
70 [$this, 'render']
71 );
72
73 add_submenu_page(
74 'fluent-booking',
75 __('Availability', 'fluent-booking'),
76 __('Availability', 'fluent-booking'),
77 $capability,
78 'fluent-booking#/availability',
79 [$this, 'render']
80 );
81
82 add_submenu_page(
83 'fluent-booking',
84 __('Settings', 'fluent-booking'),
85 __('Settings', 'fluent-booking'),
86 $capability,
87 'fluent-booking#/settings/general-settings',
88 [$this, 'render']
89 );
90 }
91
92 public function render()
93 {
94 if (!as_has_scheduled_action('fluent_booking_five_minutes_tasks')) {
95 as_schedule_recurring_action(time(), (60 * 5), 'fluent_booking_five_minutes_tasks', [], 'fluent-booking', true);
96 }
97
98 $this->changeFooter();
99
100 $app = App::getInstance();
101
102 $config = $app->config;
103
104 $name = $config->get('app.name');
105
106 $slug = $config->get('app.slug');
107
108 $baseUrl = Helper::getAppBaseUrl();
109
110 if (is_admin()) {
111 $baseUrl = admin_url('admin.php?page=fluent-booking#/');
112 }
113
114 $isNew = $this->isNew();
115
116 $menuItems = [
117 [
118 'key' => 'dashboard',
119 'label' => $isNew ? __('Getting Started', 'fluent-booking') : __('Dashboard', 'fluent-booking'),
120 'permalink' => $baseUrl
121 ],
122 [
123 'key' => 'calendars',
124 'label' => __('Calendars', 'fluent-booking'),
125 'permalink' => $baseUrl . 'calendars'
126 ],
127 [
128 'key' => 'scheduled-events',
129 'label' => __('Bookings', 'fluent-booking'),
130 'permalink' => $baseUrl . 'scheduled-events',
131 ],
132 [
133 'key' => 'availability',
134 'label' => __('Availability', 'fluent-booking'),
135 'permalink' => $baseUrl . 'availability'
136 ]
137 ];
138
139 $settingItems = [];
140 if (PermissionManager::userCan('manage_all_data')) {
141 $settingItems = [
142 'key' => 'settings',
143 'label' => __('Settings', 'fluent-booking'),
144 'permalink' => $baseUrl . 'settings/general-settings'
145 ];
146 }
147
148 $menuItems = apply_filters('fluent_booking/admin_menu_items', $menuItems);
149
150 $assets = $app['url.assets'];
151
152 $portalVars = apply_filters('fluent_booking/admin_portal_vars', [
153 'name' => $name,
154 'slug' => $slug,
155 'menuItems' => $menuItems,
156 'settings' => $settingItems,
157 'baseUrl' => $baseUrl,
158 'logo' => $assets . 'images/logo.svg',
159 'dark_logo' => $assets . 'images/logo_dark.svg',
160 ]);
161
162 do_action('fluent_booking/admin_app_rendering');
163
164 $app->view->render('admin.menu', $portalVars);
165 }
166
167 public function changeFooter()
168 {
169 add_filter('admin_footer_text', function ($content) {
170 $url = 'https://fluentbooking.com/';
171 /* translators: %s: URL of the FluentBooking website */
172 return sprintf(wp_kses(__('Thank you for using <a href="%s">FluentBooking</a>.', 'fluent-booking'), array('a' => array('href' => array()))), esc_url($url)) . '<span title="based on your WP timezone settings" style="margin-left: 10px;" data-timestamp="' . current_time('timestamp') . '" id="fcal_server_timestamp"></span>';
173 });
174
175 add_filter('update_footer', function ($text) {
176 return FLUENT_BOOKING_VERSION;
177 });
178 }
179
180 public function enqueueAssets()
181 {
182 $app = App::getInstance();
183
184 $isRtl = Helper::fluentbooking_is_rtl();
185
186 $assets = $app['url.assets'];
187
188 $slug = $app->config->get('app.slug');
189
190 $adminAppCss = 'admin/admin.css';
191 if ($isRtl) {
192 $adminAppCss = 'admin/admin-rtl.css';
193 wp_enqueue_style('fluentbooking_admin_rtl', $assets . 'admin/fluentbooking_admin_rtl.css', [], FLUENT_BOOKING_ASSETS_VERSION);
194 }
195
196 add_action('wp_print_scripts', function () {
197
198 $isSkip = apply_filters('fluent_booking/skip_no_conflict', false, 'scripts');
199
200 if ($isSkip) {
201 return;
202 }
203
204 global $wp_scripts;
205 if (!$wp_scripts) {
206 return;
207 }
208
209 $approvedSlugs = apply_filters('fluent_booking/asset_listed_slugs', [
210 '\/fluent-crm\/'
211 ]);
212
213 $approvedSlugs[] = '\/fluent-booking\/';
214 $approvedSlugs[] = '\/fluent-booking-pro\/';
215
216 $approvedSlugs = array_unique($approvedSlugs);
217
218 $approvedSlugs = implode('|', $approvedSlugs);
219
220 $pluginUrl = plugins_url();
221
222 $pluginUrl = str_replace(['http:', 'https:'], '', $pluginUrl);
223
224 foreach ($wp_scripts->queue as $script) {
225 if (empty($wp_scripts->registered[$script]) || empty($wp_scripts->registered[$script]->src)) {
226 continue;
227 }
228
229 $src = $wp_scripts->registered[$script]->src;
230 $isMatched = (strpos($src, $pluginUrl) !== false) && !preg_match('/' . $approvedSlugs . '/', $src);
231 if (!$isMatched) {
232 continue;
233 }
234 wp_dequeue_script($wp_scripts->registered[$script]->handle);
235 }
236 });
237
238 add_action('wp_print_styles', function () {
239 $isSkip = apply_filters('fluent_booking/skip_no_conflict', false, 'styles');
240
241 if ($isSkip) {
242 return;
243 }
244
245 global $wp_styles;
246 if (!$wp_styles) {
247 return;
248 }
249
250 $approvedSlugs = apply_filters('fluent_booking/asset_listed_slugs', [
251 '\/fluent-crm\/'
252 ]);
253
254 $approvedSlugs[] = '\/fluent-booking\/';
255 $approvedSlugs[] = '\/fluent-booking-pro\/';
256
257 $approvedSlugs = array_unique($approvedSlugs);
258
259 $approvedSlugs = implode('|', $approvedSlugs);
260
261 $pluginUrl = plugins_url();
262
263 $themeUrl = get_theme_root_uri();
264
265 $pluginUrl = str_replace(['http:', 'https:'], '', $pluginUrl);
266 $themeUrl = str_replace(['http:', 'https:'], '', $themeUrl);
267
268 foreach ($wp_styles->queue as $script) {
269
270 if (empty($wp_styles->registered[$script]) || empty($wp_styles->registered[$script]->src)) {
271 continue;
272 }
273
274 $src = $wp_styles->registered[$script]->src;
275 $pluginMatched = (strpos($src, $pluginUrl) !== false) && !preg_match('/' . $approvedSlugs . '/', $src);
276 $themeMatched = (strpos($src, $themeUrl) !== false) && !preg_match('/' . $approvedSlugs . '/', $src);
277
278 if (!$pluginMatched && !$themeMatched) {
279 continue;
280 }
281
282 wp_dequeue_style($wp_styles->registered[$script]->handle);
283 }
284 }, 999999);
285
286 wp_enqueue_style('fluent_booing_admin_app', $assets . $adminAppCss, [], FLUENT_BOOKING_ASSETS_VERSION, 'all');
287
288 do_action($slug . '_loading_app'); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound
289
290 wp_enqueue_script(
291 $slug . '_admin_app',
292 $assets . 'admin/app.js',
293 array('jquery'),
294 FLUENT_BOOKING_ASSETS_VERSION,
295 true
296 );
297
298 wp_enqueue_script(
299 $slug . '_global_admin',
300 $assets . 'admin/global_admin.js',
301 array(),
302 FLUENT_BOOKING_ASSETS_VERSION,
303 true
304 );
305
306 if (function_exists('wp_enqueue_editor')) {
307 add_filter('user_can_richedit', '__return_true');
308 wp_enqueue_editor();
309 wp_enqueue_media();
310 }
311
312 wp_localize_script($slug . '_admin_app', 'fluentFrameworkAdmin', $this->getDashboardVars($app));
313 }
314
315 public function getDashboardVars($app)
316 {
317 $assets = $app['url.assets'];
318 $currentUser = get_user_by('ID', get_current_user_id());
319
320 $currentUsername = trim($currentUser->first_name . ' ' . $currentUser->last_name);
321 if (!$currentUsername) {
322 $currentUsername = $currentUser->display_name;
323 }
324
325 $isNew = $this->isNew();
326
327 $requireSlug = false;
328
329 if ($isNew) {
330 $result = $this->maybeAutoCreateCalendar($currentUser);
331 if (!$result) {
332 $requireSlug = true;
333 }
334 }
335
336 $calendarId = null;
337
338 $firstCalendar = Calendar::where('user_id', $currentUser->ID)->where('type', 'simple')->first();
339
340 if ($firstCalendar) {
341 $calendarId = $firstCalendar->id;
342 }
343
344 $hasAllAccess = false;
345 if (PermissionManager::hasAllCalendarAccess()) {
346 $hasAllAccess = true;
347 }
348
349 $eventColors = Helper::getEventColors();
350 $meetingDurations = Helper::getMeetingDurations();
351 $multiDurations = Helper::getMeetingMultiDurations();
352 $durationLookup = Helper::getDurationLookup();
353 $multiDurationLookup = Helper::getDurationLookup(true);
354 $scheduleSchema = Helper::getWeeklyScheduleSchema();
355 $bufferTimes = Helper::getBufferTimes();
356 $slotIntervals = Helper::getSlotIntervals();
357 $customFieldTypes = Helper::getCustomFieldTypes();
358 $weekSelectTimes = Helper::getWeekSelectTimes();
359 $overrideSelectTimes = Helper::getOverrideSelectTimes();
360 $statusChangingTimes = Helper::getBookingStatusChangingTimes();
361 $defaultTermsAndConditions = Helper::getDefaultTermsAndConditions();
362 $locationFields = (new CalendarSlot())->getLocationFields();
363
364 return apply_filters('fluent_booking/admin_vars', [
365 'slug' => $slug = $app->config->get('app.slug'),
366 'nonce' => wp_create_nonce($slug),
367 'rest' => $this->getRestInfo($app),
368 'brand_logo' => $this->getMenuIcon(),
369 'asset_url' => $assets,
370 'event_colors' => $eventColors,
371 'meeting_durations' => $meetingDurations,
372 'multi_durations' => $multiDurations,
373 'buffer_times' => $bufferTimes,
374 'slot_intervals' => $slotIntervals,
375 'schedule_schema' => $scheduleSchema,
376 'location_fields' => $locationFields,
377 'custom_field_types' => $customFieldTypes,
378 'week_select_times' => $weekSelectTimes,
379 'duration_lookup' => $durationLookup,
380 'multi_duration_lookup' => $multiDurationLookup,
381 'override_select_times' => $overrideSelectTimes,
382 'status_changing_times' => $statusChangingTimes,
383 'default_terms' => $defaultTermsAndConditions,
384 'me' => [
385 'id' => $currentUser->ID,
386 'calendar_id' => $calendarId,
387 'full_name' => $currentUsername,
388 'email' => $currentUser->user_email,
389 'is_admin' => $hasAllAccess,
390 'permissions' => PermissionManager::getUserPermissions($currentUser, false),
391 ],
392 'all_hosts' => Calendar::getAllHosts(),
393 'is_new' => $isNew,
394 'require_slug' => $requireSlug,
395 'site_url' => site_url('/'),
396 'upgrade_url' => Helper::getUpgradeUrl(),
397 'timezones' => DateTimeHelper::getTimeZones(true),
398 'features' => Helper::getFeatures(),
399 'supported_features' => apply_filters('fluent_booking/supported_featured', [
400 'multi_users' => true
401 ]),
402 'i18' => [
403 'date_time_config' => DateTimeHelper::getI18nDateTimeConfig(),
404 ],
405 'has_pro' => defined('FLUENT_BOOKING_PRO_DIR_FILE'),
406 'require_upgrade' => defined('FLUENT_BOOKING_PRO_DIR_FILE') && !defined('FLUENT_BOOKING_LITE'),
407 'dashboard_notices' => apply_filters('fluent_booking/dashboard_notices', []),
408 'payment_methods' => apply_filters('fluent_booking/payment/get_all_methods', []),
409 'trans' => TransStrings::getStrings(),
410 'date_format' => DateTimeHelper::getDateFormatter(true),
411 'time_format' => DateTimeHelper::getTimeFormatter(true),
412 'date_time_formatter' => DateTimeHelper::getDateFormatter(true) . ', ' . DateTimeHelper::getTimeFormatter(true),
413 'available_date_formats' => DateTimeHelper::getAvailableDateFormats(),
414 'default_booking_filters' => Helper::getDefaultBookingFilters(),
415 'default_paginations' => Helper::getDefaultPaginations(),
416 'pref_settings' => Helper::getPrefSettings(),
417 'settings_menu_items' => static::settingsMenuItems(),
418 'admin_url' => admin_url(),
419 'is_rtl' => Helper::fluentbooking_is_rtl(),
420 'iframe_html' => Helper::getIframeHtml()
421 ]);
422 }
423
424 protected function getRestInfo($app)
425 {
426 $ns = $app->config->get('app.rest_namespace');
427 $ver = $app->config->get('app.rest_version');
428
429 return [
430 'base_url' => esc_url_raw(rest_url()),
431 'url' => rest_url($ns . '/' . $ver),
432 'nonce' => wp_create_nonce('wp_rest'),
433 'namespace' => $ns,
434 'version' => $ver
435 ];
436 }
437
438 protected function getMenuIcon()
439 {
440 return 'data:image/svg+xml;base64,' . base64_encode('<svg width="96" height="101" viewBox="0 0 96 101" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="25.5746" width="6.39365" height="15.9841" rx="3.19683" fill="white"/><rect x="63.9365" width="6.39365" height="15.9841" rx="3.19683" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M54.878 53.0655C54.544 55.6678 53.4646 58.035 51.8535 59.9427C50.1623 61.9572 47.886 63.4614 45.2863 64.1988L45.1741 64.2309L44.9203 64.2976L44.8989 64.303L24.7671 69.7V65.019C24.7671 64.9148 24.7671 64.8106 24.7778 64.7064C24.8953 62.748 26.127 61.0862 27.8476 60.3514C28.0427 60.2659 28.2431 60.1938 28.4515 60.1377L28.6412 60.0869L54.8753 53.0575V53.0655H54.878Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M71.1411 35.8059C70.4571 41.1467 66.6178 45.5017 61.5494 46.9391L61.4372 46.9712L61.1861 47.038H61.1834L61.162 47.0433L24.7671 56.7953V52.1144C24.7671 50.0197 26.0362 48.2216 27.8476 47.4468L28.4515 47.233L28.6385 47.1823L71.1384 35.7952V35.8059H71.1411Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M19.9802 11.1889H75.9246C83.4282 11.1889 89.5111 17.2718 89.5111 24.7754V70H95.9048V24.7754C95.9048 13.7406 86.9593 4.79523 75.9246 4.79523H19.9802C8.94542 4.79523 0 13.7406 0 24.7754V80.7198C0 91.7546 8.94542 100.7 19.9802 100.7L64.9524 100.7V94.3063H19.9802C12.4765 94.3063 6.39365 88.2234 6.39365 80.7198V24.7754C6.39365 17.2718 12.4765 11.1889 19.9802 11.1889Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M95.9524 70.7477V69.7H64.9524V100.7H66.0001L95.9524 70.7477Z" fill="white"/></svg>');
441 }
442
443 protected function isNew()
444 {
445 return apply_filters('fluent_booking/is_new', !Calendar::first());
446 }
447
448 /**
449 * @param $user \WP_User
450 * @return bool | Calendar
451 */
452 protected function maybeAutoCreateCalendar($user)
453 {
454 if (!apply_filters('fluent_booking/auto_create_calendar', false, $user)) {
455 return false;
456 }
457
458 $userName = $user->user_login;
459
460 if (is_email($userName)) {
461 $userName = explode('@', $userName);
462 $userName = $userName[0];
463 }
464
465 if (!Helper::isCalendarSlugAvailable($userName, true)) {
466 return false;
467 }
468
469 $personName = trim($user->first_name . ' ' . $user->last_name);
470
471 if (!$personName) {
472 $personName = $user->display_name;
473 }
474
475 $data = [
476 'user_id' => $user->ID,
477 'title' => $personName,
478 'slug' => $userName
479 ];
480
481 return Calendar::create($data);
482 }
483
484 public static function settingsMenuItems()
485 {
486 $app = App::getInstance();
487 $urlAssets = $app['url.assets'];
488
489 return apply_filters('fluent_booking/settings_menu_items', [
490 'general_settings' => [
491 'title' => __('General', 'fluent-booking'),
492 'disable' => false,
493 'el_icon' => 'Operation',
494 'component_type' => 'StandAloneComponent',
495 'class' => 'general_settings',
496 'route' => [
497 'name' => 'general_settings'
498 ]
499 ],
500 'team_members' => [
501 'title' => __('Team', 'fluent-booking'),
502 'disable' => true,
503 'el_icon' => 'TeamIcon',
504 'component_type' => 'StandAloneComponent',
505 'class' => 'team_members',
506 'route' => [
507 'name' => 'team_members'
508 ]
509 ],
510 'payment_settings' => [
511 'title' => __('Payment', 'fluent-booking'),
512 'disable' => true,
513 'el_icon' => 'Money',
514 'component_type' => 'PaymentSettingsComponent',
515 'class' => 'payment_settings',
516 'route' => [
517 'name' => 'global_payment_settings',
518 ],
519 'children' => [
520 'payment_settings' => [
521 'title' => __('Settings', 'fluent-booking'),
522 'disable' => true,
523 'route' => [
524 'name' => 'global_payment_settings'
525 ]
526 ],
527 'payment_methods' => [
528 'title' => __('Payment Methods', 'fluent-booking'),
529 'disable' => true,
530 'route' => [
531 'name' => 'payment_methods',
532 'params' => [
533 'settings_key' => 'stripe'
534 ]
535 ]
536 ],
537 'payment_coupons' => [
538 'title' => __('Coupons', 'fluent-booking'),
539 'disable' => true,
540 'route' => [
541 'name' => 'payment_coupons'
542 ]
543 ]
544 ],
545 ],
546 'google' => [
547 'title' => __('Google Calendar / Meet', 'fluent-booking'),
548 'disable' => true,
549 'icon_url' => $urlAssets . 'images/gg-calendar.svg',
550 'component_type' => 'StandAloneComponent',
551 'class' => 'configure_google_calendar',
552 'route' => [
553 'name' => 'configure-google'
554 ]
555 ],
556 'outlook' => [
557 'title' => __('Outlook Calendar / MS Teams', 'fluent-booking'),
558 'disable' => true,
559 'icon_url' => $urlAssets . 'images/ol-icon-color.svg',
560 'component_type' => 'GlobalSettingsComponent',
561 'class' => 'configure_outlook_calendar',
562 'route' => [
563 'name' => 'configure-integrations',
564 'params' => [
565 'settings_key' => 'outlook'
566 ]
567 ]
568 ],
569 'apple_calendar' => [
570 'title' => __('Apple Calendar', 'fluent-booking'),
571 'disable' => true,
572 'icon_url' => $urlAssets . 'images/a-cal.svg',
573 'component_type' => 'GlobalSettingsComponent',
574 'class' => 'configure_apple_calendar',
575 'route' => [
576 'name' => 'configure-integrations',
577 'params' => [
578 'settings_key' => 'apple_calendar'
579 ]
580 ]
581 ],
582 'next_cloud_calendar' => [
583 'title' => __('Nextcloud Calendar', 'fluent-booking'),
584 'disable' => true,
585 'svg_icon' => '<svg xmlns="http://www.w3.org/2000/svg" height="800" width="1200" viewBox="-17.0838 -18.65685 148.0596 111.9411"><path d="M57.0328 0C45.2275 0 35.2216 8.0032 32.1204 18.8466c-2.6952-5.7515-8.5359-9.781-15.2633-9.781C7.6053 9.0657 0 16.671 0 25.9228c0 9.2519 7.6052 16.8606 16.857 16.8606 6.7275 0 12.5682-4.0319 15.2635-9.7844 3.1011 10.8442 13.107 18.85 24.9123 18.85 11.718 0 21.6729-7.885 24.8533-18.607 2.745 5.622 8.5135 9.5414 15.1454 9.5414 9.2518 0 16.8605-7.6087 16.8605-16.8606 0-9.2518-7.6087-16.857-16.8605-16.857-6.632 0-12.4003 3.917-15.1454 9.5378C78.7057 7.8825 68.7507 0 57.0328 0zm0 9.8955c8.9116 0 16.0307 7.1156 16.0307 16.0272s-7.119 16.0308-16.0307 16.0308c-8.9116 0-16.0272-7.1192-16.0272-16.0308S48.1212 9.8955 57.0328 9.8955zm-40.1757 9.0657c3.9044 0 6.965 3.0571 6.965 6.9615s-3.0606 6.965-6.965 6.965-6.9616-3.0606-6.9616-6.965 3.0572-6.9615 6.9616-6.9615zm80.1744 0c3.9044 0 6.965 3.0571 6.965 6.9615s-3.0606 6.965-6.965 6.965-6.9616-3.0606-6.9616-6.965 3.0572-6.9615 6.9616-6.9615z" color="currentColor" font-weight="400" font-family="sans-serif" overflow="visible" fill="currentColor"></path><path d="M29.1085 63.7615c2.7752 0 4.3275 1.9756 4.3275 4.939 0 .2822-.2352.5174-.5174.5174h-7.4792c.047 2.6342 1.8816 4.1394 3.9983 4.1394 1.3171 0 2.2579-.5644 2.7283-.9408.2822-.1881.5174-.141.6585.1412l.1411.2352c.1411.2351.094.4703-.1411.6585-.5645.4233-1.7875 1.129-3.4338 1.129-3.0575 0-5.4094-2.2109-5.4094-5.4095.047-3.3868 2.3048-5.4094 5.1272-5.4094zm2.8693 4.4216c-.094-2.1638-1.4112-3.2457-2.9164-3.2457-1.7404 0-3.2456 1.129-3.575 3.2457zm15.584-2.9164v-3.622c0-.3292.1882-.5174.5174-.5174h.3764c.3292 0 .4703.1882.4703.5174v2.446h2.1168c.3292 0 .5174.1882.5174.5174v.1412c0 .3292-.1882.4703-.5174.4703h-2.1168v5.1743c0 2.399 1.4582 2.6812 2.2579 2.7282.4233.047.5644.1411.5644.5174v.2823c0 .3292-.141.4704-.5644.4704-2.2579 0-3.622-1.3642-3.622-3.8102zm10.7718-1.5052c1.7875 0 2.9164.7526 3.4339 1.176.2351.188.2822.4233.047.7055l-.1411.2352c-.1882.2822-.4234.2822-.7056.094-.4704-.3292-1.3641-.9407-2.5871-.9407-2.2579 0-4.0453 1.6934-4.0453 4.1864 0 2.446 1.7874 4.1394 4.0453 4.1394 1.4582 0 2.446-.6585 2.9164-1.0819.2822-.1881.4704-.141.6585.1411l.1411.1882c.1411.2822.0941.4704-.141.7056-.5175.4233-1.7876 1.317-3.6691 1.317-3.0575 0-5.4094-2.2108-5.4094-5.4094.047-3.1986 2.399-5.4564 5.4564-5.4564zm6.2562-3.3398c0-.3292-.1882-.5174.141-.5174h.3764c.3293 0 .8467.1882.8467.5174V71.664c0 1.3171.6115 1.4582 1.0819 1.5053.2352 0 .4233.141.4233.4703v.3293c0 .3293-.1411.5174-.5174.5174-.8467 0-2.352-.2822-2.352-2.54zm9.6429 3.3398c3.0104 0 5.4564 2.3048 5.4564 5.3623 0 3.1046-2.446 5.4565-5.4564 5.4565-3.0105 0-5.4565-2.352-5.4565-5.4565 0-3.0575 2.446-5.3623 5.4565-5.3623zm0 9.5958c2.2108 0 3.9982-1.7875 3.9982-4.2335 0-2.3519-1.7874-4.0923-3.9982-4.0923s-4.0454 1.7875-4.0454 4.0923c.047 2.399 1.8346 4.2335 4.0454 4.2335zm23.4722-9.5958c2.493 0 3.3868 2.0697 3.3868 2.0697h.047s-.047-.3293-.047-.7997v-4.6568c0-.3293-.1412-.5174.1881-.5174h.3763c.3293 0 .8467.1881.8467.5174v13.406c0 .3292-.1411.5174-.4704.5174h-.3292c-.3293 0-.5175-.1411-.5175-.4704v-.7997c0-.3763.0941-.6585.0941-.6585h-.047s-.8938 2.1638-3.575 2.1638c-2.7752 0-4.5157-2.2108-4.5157-5.4095-.094-3.1986 1.8345-5.3623 4.5628-5.3623zm.047 9.5958c1.7404 0 3.3398-1.223 3.3398-4.1864 0-2.1167-1.082-4.1394-3.2927-4.1394-1.8345 0-3.3398 1.5052-3.3398 4.1394.047 2.54 1.3641 4.1864 3.2927 4.1864zm-85.8923.9878h.3763c.3293 0 .5174-.1881.5174-.5174V63.7274c0-1.5993 1.7404-2.7412 3.716-2.7412 1.9757 0 3.7161 1.142 3.7161 2.7412v10.1003c0 .3293.1882.5174.5174.5174h.3763c.3293 0 .4704-.1881.4704-.5174V63.6674c0-2.6812-2.6812-3.9983-5.1272-3.9983-2.3519 0-5.0331 1.317-5.0331 3.9983v10.1603c0 .3293.1411.5174.4704.5174zm78.5073-10.3485h-.3763c-.3293 0-.5175.1882-.5175.5175v5.6916c0 1.5993-1.0348 3.0575-3.0575 3.0575-1.9756 0-3.0575-1.4582-3.0575-3.0575v-5.6916c0-.3293-.1881-.5175-.5174-.5175h-.3763c-.3293 0-.4704.1882-.4704.5175v6.068c0 2.6811 1.9756 3.9982 4.4216 3.9982 2.446 0 4.4217-1.317 4.4217-3.9983v-6.068c.047-.3292-.1412-.5174-.4704-.5174zm-46.5643-.0771c-.1152.0184-.2258.0953-.3317.2214L41.5673 66.41l-1.4249 1.6978-2.1571-2.5715-1.1705-1.3955c-.1058-.1261-.2257-.195-.35-.2058-.1244-.0107-.2533.0366-.3795.1424l-.2884.2416c-.2523.2117-.2392.446-.0276.6982l1.9045 2.2693 1.5793 1.8815-2.3124 2.7553c-.0018.002-.0029.0043-.0046.0064l-1.1668 1.39c-.2117.2523-.188.5178.0643.7295l.2885.2407c.2522.2116.481.1585.6927-.0937l1.9036-2.2693 1.425-1.6977 2.157 2.5715c.0015.0016.0032.0029.0047.0046l1.1668 1.391c.2116.2521.4763.275.7285.0633l.2885-.2416c.2522-.2117.2392-.446.0275-.6983l-1.9045-2.2692-1.5792-1.8815 2.3124-2.7553c.0017-.002.0028-.0044.0046-.0064l1.1668-1.39c.2116-.2523.1879-.5179-.0643-.7295l-.2885-.2416c-.1261-.1058-.2459-.1452-.361-.1268z" fill="currentColor"></path></svg>',
586 'component_type' => 'GlobalSettingsComponent',
587 'class' => 'configure_nextcloud_calendar',
588 'route' => [
589 'name' => 'configure-integrations',
590 'params' => [
591 'settings_key' => 'next_cloud_calendar'
592 ]
593 ]
594 ],
595 'zoom_meeting' => [
596 'title' => __('Zoom', 'fluent-booking'),
597 'disable' => true,
598 'icon_url' => $urlAssets . 'images/zoom.svg',
599 'component_type' => 'StandAloneComponent',
600 'class' => 'zoom_integrations',
601 'route' => [
602 'name' => 'zoom_integrations'
603 ]
604 ],
605 'twilio' => [
606 'title' => __('SMS by Twilio', 'fluent-booking'),
607 'disable' => true,
608 'svg_icon' => '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="twilio"><path d="M0,12c0,6.64,5.359,12,12,12s12-5.36,12-12c0-6.641-5.36-12-12-12C5.381-0.008,0.008,5.352,0,11.971V12z M3.199,12c-0.014-4.846,3.904-8.786,8.75-8.801H12c4.847-0.014,8.786,3.904,8.801,8.75V12c0.015,4.847-3.904,8.786-8.75,8.801H12c-4.846,0.015-8.786-3.904-8.801-8.75V12z"></path><path d="M14.959 17.44c1.361 0 2.481-1.12 2.481-2.48 0-1.359-1.12-2.48-2.481-2.479-1.359 0-2.479 1.12-2.479 2.479C12.486 16.326 13.592 17.432 14.959 17.44zM14.959 11.52c1.361 0 2.481-1.12 2.481-2.479 0-1.361-1.12-2.481-2.481-2.481-1.359 0-2.479 1.12-2.479 2.481C12.487 10.407 13.593 11.513 14.959 11.52zM9.042 17.44c1.359 0 2.479-1.12 2.479-2.48 0-1.359-1.121-2.48-2.479-2.479-1.361 0-2.481 1.12-2.481 2.479C6.567 16.327 7.674 17.433 9.042 17.44zM9.042 11.52c1.359 0 2.479-1.12 2.479-2.479 0-1.361-1.121-2.481-2.479-2.481-1.361 0-2.481 1.12-2.481 2.481C6.567 10.408 7.675 11.513 9.042 11.52z"></path></svg>',
609 'component_type' => 'GlobalSettingsComponent',
610 'class' => 'configure_twilio',
611 'route' => [
612 'name' => 'configure-integrations',
613 'params' => [
614 'settings_key' => 'twilio'
615 ]
616 ]
617 ],
618 'license' => [
619 'title' => __('License', 'fluent-booking'),
620 'disable' => true,
621 'el_icon' => 'Lock',
622 'component_type' => 'StandAloneComponent',
623 'class' => 'configure_license',
624 'route' => [
625 'name' => 'license'
626 ]
627 ]
628 ]);
629 }
630
631 public static function getEventSettingsMenuItems($event)
632 {
633 return apply_filters('fluent_booking/calendar_event_setting_menu_items', [
634 'event_details' => [
635 'type' => 'route',
636 'visible' => true,
637 'disable' => false,
638 'route' => [
639 'name' => 'event_details',
640 'params' => [
641 'calendar_id' => $event->calendar_id,
642 'event_id' => $event->id
643 ]
644 ],
645 'label' => __('Event Details', 'fluent-booking'),
646 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M8 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 13H15" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 17H12" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.68 21 4.95 21 9.65V15.83C21 19.95 20 22.01 15 22.01H9C4 22.01 3 19.95 3 15.83V9.65C3 4.95 4.67 3.69 8 3.5H16Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
647 ],
648 'assignment' => [
649 'type' => 'route',
650 'visible' => false,
651 'disable' => true,
652 'route' => [
653 'name' => 'assignment',
654 'params' => [
655 'calendar_id' => $event->calendar_id,
656 'event_id' => $event->id
657 ]
658 ],
659 'label' => __('Assignment', 'fluent-booking'),
660 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-[16px] w-[16px] stroke-[2px] ltr:mr-2 rtl:ml-2 md:mt-px" data-testid="icon-component"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>'
661 ],
662 'availability_settings' => [
663 'type' => 'route',
664 'visible' => true,
665 'disable' => false,
666 'route' => [
667 'name' => 'availability_settings',
668 'params' => [
669 'calendar_id' => $event->calendar_id,
670 'event_id' => $event->id
671 ]
672 ],
673 'label' => __('Availability', 'fluent-booking'),
674 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M6.66666 1.66699V4.16699" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.3333 1.66699V4.16699" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2.91666 7.5752H17.0833" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M17.5 7.08366V14.167C17.5 16.667 16.25 18.3337 13.3333 18.3337H6.66667C3.75 18.3337 2.5 16.667 2.5 14.167V7.08366C2.5 4.58366 3.75 2.91699 6.66667 2.91699H13.3333C16.25 2.91699 17.5 4.58366 17.5 7.08366Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 11.4167H13.0864" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 13.9167H13.0864" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 11.4167H10.0037" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 13.9167H10.0037" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 11.4167H6.91942" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 13.9167H6.91942" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
675 ],
676 'limit_settings' => [
677 'type' => 'route',
678 'visible' => true,
679 'disable' => false,
680 'route' => [
681 'name' => 'limit_settings',
682 'params' => [
683 'calendar_id' => $event->calendar_id,
684 'event_id' => $event->id
685 ]
686 ],
687 'label' => __('Limits', 'fluent-booking'),
688 'elIcon' => 'Clock'
689 ],
690 'question_settings' => [
691 'type' => 'route',
692 'visible' => true,
693 'disable' => false,
694 'route' => [
695 'name' => 'question_settings',
696 'params' => [
697 'calendar_id' => $event->calendar_id,
698 'event_id' => $event->id
699 ]
700 ],
701 'label' => __('Question Settings', 'fluent-booking'),
702 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 13.8714V13.6441C12 12.908 12.5061 12.5182 13.0121 12.2043C13.5061 11.9012 14 11.5115 14 10.797C14 9.8011 13.1085 9 12 9C10.8915 9 10 9.8011 10 10.797" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.9945 16.4587H12.0053" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.67504 21 4.91005 21 9.48055V15.4903C21 19.4968 20 21.5 15 21.5H9C4 21.5 3 19.4968 3 15.4903V9.48055C3 4.91005 4.67 3.68476 8 3.5H16Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
703 ],
704 'email_notification' => [
705 'type' => 'route',
706 'visible' => true,
707 'disable' => false,
708 'route' => [
709 'name' => 'email_notification',
710 'params' => [
711 'calendar_id' => $event->calendar_id,
712 'event_id' => $event->id
713 ]
714 ],
715 'label' => __('Email Notification', 'fluent-booking'),
716 'elIcon' => 'Message'
717 ],
718 'sms_notification' => [
719 'type' => 'route',
720 'visible' => true,
721 'disable' => true,
722 'route' => [
723 'name' => 'sms_notification',
724 'params' => [
725 'calendar_id' => $event->calendar_id,
726 'event_id' => $event->id
727 ]
728 ],
729 'label' => __('SMS Notification', 'fluent-booking'),
730 'elIcon' => 'Notification'
731 ],
732 'recurring_settings' => [
733 'type' => 'route',
734 'visible' => ($event->isOneToOne() || $event->isGroup()) ? true : false,
735 'disable' => true,
736 'route' => [
737 'name' => 'recurring_settings',
738 'params' => [
739 'calendar_id' => $event->calendar_id,
740 'event_id' => $event->id
741 ]
742 ],
743 'label' => __('Recurring Settings', 'fluent-booking'),
744 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M6 4H21C21.5523 4 22 4.44772 22 5V12H20V6H6V9L1 5L6 1V4ZM18 20H3C2.44772 20 2 19.5523 2 19V12H4V18H18V15L23 19L18 23V20Z"></path></svg>'
745 ],
746 'advanced_settings' => [
747 'type' => 'route',
748 'visible' => true,
749 'disable' => true,
750 'route' => [
751 'name' => 'advanced_settings',
752 'params' => [
753 'calendar_id' => $event->calendar_id,
754 'event_id' => $event->id
755 ]
756 ],
757 'label' => __('Advanced Settings', 'fluent-booking'),
758 'elIcon' => 'Operation'
759 ],
760 'payment_settings' => [
761 'type' => 'route',
762 'visible' => true,
763 'disable' => true,
764 'route' => [
765 'name' => 'payment_settings',
766 'params' => [
767 'calendar_id' => $event->calendar_id,
768 'event_id' => $event->id
769 ]
770 ],
771 'label' => __('Payment Settings', 'fluent-booking'),
772 'elIcon' => 'Money'
773 ],
774 'webhook_settings' => [
775 'type' => 'route',
776 'visible' => true,
777 'disable' => true,
778 'route' => [
779 'name' => 'webhook_settings',
780 'params' => [
781 'calendar_id' => $event->calendar_id,
782 'event_id' => $event->id
783 ]
784 ],
785 'label' => __('Webhooks Feeds', 'fluent-booking'),
786 'elIcon' => 'Link'
787 ],
788 'integrations' => [
789 'type' => 'route',
790 'visible' => true,
791 'disable' => false,
792 'route' => [
793 'name' => 'integrations',
794 'params' => [
795 'calendar_id' => $event->calendar_id,
796 'event_id' => $event->id
797 ]
798 ],
799 'label' => __('Integrations', 'fluent-booking'),
800 'elIcon' => 'Connection'
801 ]
802 ], $event);
803 }
804
805 public static function getCalendarSettingsMenuItems($calendar)
806 {
807 return apply_filters('fluent_booking/calendar_setting_menu_items', [
808 'calendar_settings' => [
809 'type' => 'route',
810 'visible' => true,
811 'disable' => false,
812 'route' => [
813 'name' => 'calendar_settings',
814 'params' => [
815 'calendar_id' => $calendar->id
816 ]
817 ],
818 'label' => __('Calendar Settings', 'fluent-booking'),
819 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 12.8799V11.1199C2 10.0799 2.85 9.21994 3.9 9.21994C5.71 9.21994 6.45 7.93994 5.54 6.36994C5.02 5.46994 5.33 4.29994 6.24 3.77994L7.97 2.78994C8.76 2.31994 9.78 2.59994 10.25 3.38994L10.36 3.57994C11.26 5.14994 12.74 5.14994 13.65 3.57994L13.76 3.38994C14.23 2.59994 15.25 2.31994 16.04 2.78994L17.77 3.77994C18.68 4.29994 18.99 5.46994 18.47 6.36994C17.56 7.93994 18.3 9.21994 20.11 9.21994C21.15 9.21994 22.01 10.0699 22.01 11.1199V12.8799C22.01 13.9199 21.16 14.7799 20.11 14.7799C18.3 14.7799 17.56 16.0599 18.47 17.6299C18.99 18.5399 18.68 19.6999 17.77 20.2199L16.04 21.2099C15.25 21.6799 14.23 21.3999 13.76 20.6099L13.65 20.4199C12.75 18.8499 11.27 18.8499 10.36 20.4199L10.25 20.6099C9.78 21.3999 8.76 21.6799 7.97 21.2099L6.24 20.2199C5.33 19.6999 5.02 18.5299 5.54 17.6299C6.45 16.0599 5.71 14.7799 3.9 14.7799C2.85 14.7799 2 13.9199 2 12.8799Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
820 ],
821 'remote_calendars' => [
822 'type' => 'route',
823 'visible' => true,
824 'disable' => true,
825 'route' => [
826 'name' => 'remote_calendars',
827 'params' => [
828 'calendar_id' => $calendar->id
829 ]
830 ],
831 'label' => __('Remote Calendars', 'fluent-booking'),
832 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-[16px] w-[16px] stroke-[2px] ltr:mr-2 rtl:ml-2 md:mt-0" data-testid="icon-component"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"></rect><line x1="16" x2="16" y1="2" y2="6"></line><line x1="8" x2="8" y1="2" y2="6"></line><line x1="3" x2="21" y1="10" y2="10"></line></svg>'
833 ],
834 'zoom_meeting' => [
835 'type' => 'route',
836 'visible' => true,
837 'disable' => true,
838 'route' => [
839 'name' => 'user_zoom_integration',
840 'params' => [
841 'calendar_id' => $calendar->id
842 ]
843 ],
844 'label' => __('Zoom Integration', 'fluent-booking'),
845 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><circle cx="24" cy="24" r="20" fill="#2196f3"/><path fill="#fff" d="M29,31H14c-1.657,0-3-1.343-3-3V17h15c1.657,0,3,1.343,3,3V31z"/><polygon fill="#fff" points="37,31 31,27 31,21 37,17"/></svg>'
846 ]
847 ], $calendar);
848 }
849 }
850
851