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/CalendarService.php +432 -22 1.5.1 → 2.5.0 View file →
@@ -1,18 +1,369 @@
1 1 <?php
2 2
3 3 namespace FluentBooking\App\Services;
4 4
5 -use FluentBooking\Framework\Support\Arr;
6 5 use FluentBooking\App\Models\Calendar;
7 6 use FluentBooking\App\Models\CalendarSlot;
7 +use FluentBooking\App\Models\Availability;
8 +use FluentBooking\App\Services\Helper;
9 +use FluentBooking\Framework\Support\Arr;
8 10
9 11 class CalendarService
10 12 {
11 - public static function getSlotOptions($calendarId)
13 + public static function createCalendar($data, $useCurrentUser = false, $isFileInput = false)
12 14 {
15 + $calendarData = self::prepareCalendarData($data, $useCurrentUser, $isFileInput);
16 +
17 + if (is_wp_error($calendarData)) {
18 + return new \WP_Error($calendarData->get_error_code(), $calendarData->get_error_message());
19 + }
20 +
21 + $calendarData['slug'] = sanitize_title($calendarData['title']);
22 +
23 + if (!Helper::isCalendarSlugAvailable($calendarData['slug'], true)) {
24 + $calendarData['slug'] .= '-' . time();
25 + }
26 +
27 + $calendar = Calendar::create($calendarData);
28 +
29 + $calendarMetas = self::prepareCalendarMetas(Arr::get($data, 'metas', []));
30 +
31 + $calendar->metas()->createMany($calendarMetas);
32 +
33 + $availabilitiesData = Arr::get($data, 'availabilities', []);
34 +
35 + $createdAvailabilities = self::createAvailabilities($calendar, $availabilitiesData);
36 +
37 + $eventsData = Arr::get($data, 'events', []);
38 +
39 + self::createCalendarEvents($calendar, $eventsData, $createdAvailabilities);
40 +
41 + do_action('fluent_booking/after_create_calendar', $calendar);
42 +
43 + return [
44 + 'calendar' => $calendar
45 + ];
46 + }
47 +
48 + public static function createAvailabilities($calendar, $availabilitiesData)
49 + {
50 + $createdAvailabilities = [];
51 +
52 + foreach ($availabilitiesData as $existingId => $availabilityData) {
53 + $availability = Arr::only($availabilityData, ['key', 'value']);
54 + $availability['value']['timezone'] = $calendar->author_timezone;
55 + $availability['object_id'] = $calendar->user_id;
56 + $availabilityModel = Availability::create($availability);
57 + $createdAvailabilities[$existingId] = $availabilityModel->id;
58 + }
59 +
60 + return $createdAvailabilities;
61 + }
62 +
63 + public static function createCalendarEvents($calendar, $eventsData, $availabilities = [])
64 + {
65 + $defaultEventData = (new CalendarSlot())->getEventDefaultData($calendar);
66 +
67 + if (empty($eventsData)) {
68 + $eventsData = [$defaultEventData];
69 + }
70 +
71 + $createEventsData = [];
72 +
73 + $createEventMetasData = [];
74 +
75 + foreach ($eventsData as $eventData) {
76 + $eventMetas = Arr::get($eventData, 'event_metas', []);
77 +
78 + $eventData = self::prepareEventData($eventData, $calendar, $availabilities);
79 +
80 + $createEventData = wp_parse_args($eventData, $defaultEventData);
81 +
82 + $createEventData['slug'] = Helper::generateSlotSlug((int)$createEventData['duration'] . 'min', $calendar);
83 +
84 + $createEventData['settings'] = wp_parse_args($createEventData['settings'], $defaultEventData['settings']);
85 +
86 + $createEventsData[] = Arr::only($createEventData, (new CalendarSlot())->getFillable());
87 +
88 + $createEventMetasData[] = $eventMetas;
89 + }
90 +
91 + $createdEvents = $calendar->events()->createMany($createEventsData);
92 +
93 + foreach ($createdEvents as $index => $event) {
94 + $eventMetasData = Arr::get($createEventMetasData, $index, []);
95 +
96 + $eventMetasData = self::prepareEventMetas($eventMetasData, $event);
97 +
98 + $event->event_metas()->createMany($eventMetasData);
99 + }
100 +
101 + return $createdEvents;
102 + }
103 +
104 + protected static function prepareCalendarData($calendarData, $useCurrentUser = false, $isFileInput = false)
105 + {
106 + if (!$calendarData) {
107 + return new \WP_Error('invalid_data', esc_html__('Invalid JSON Data', 'fluent-booking'));
108 + }
109 +
110 + $preparedData = [
111 + 'title' => sanitize_text_field(Arr::get($calendarData, 'title')),
112 + 'description' => sanitize_textarea_field(Arr::get($calendarData, 'description')),
113 + 'user_id' => intval(Arr::get($calendarData, 'user_id')),
114 + 'status' => sanitize_text_field(Arr::get($calendarData, 'status', 'active')),
115 + 'type' => sanitize_text_field(Arr::get($calendarData, 'type', 'simple')),
116 + 'event_type' => sanitize_text_field(Arr::get($calendarData, 'event_type')),
117 + 'account_type' => sanitize_text_field(Arr::get($calendarData, 'account_type')),
118 + 'visibility' => sanitize_text_field(Arr::get($calendarData, 'visibility')),
119 + 'author_timezone' => sanitize_text_field(Arr::get($calendarData, 'author_timezone')),
120 + ];
121 +
122 + if ($useCurrentUser || !Arr::get($preparedData, 'user_id')) {
123 + $preparedData['user_id'] = get_current_user_id();
124 + }
125 +
126 + if (!Arr::get($preparedData, 'author_timezone')) {
127 + $preparedData['author_timezone'] = wp_timezone_string();
128 + }
129 +
130 + if (!in_array(Arr::get($preparedData, 'type'), ['simple', 'team', 'event'])) {
131 + $preparedData['type'] = 'simple';
132 + }
133 +
134 + $user = get_user_by('ID', $preparedData['user_id']);
135 +
136 + if (!$user) {
137 + return new \WP_Error('invalid_user', esc_html__('Invalid User ID', 'fluent-booking'));
138 + }
139 +
140 + $isHostCalendar = $preparedData['type'] == 'simple' ? true : false;
141 +
142 + if ($isHostCalendar || !$preparedData['title']) {
143 + $preparedData['title'] = is_email($user->user_login) ? explode('@', $user->user_login)[0] : $user->user_login;
144 + }
145 +
146 + $firstCalendar = Calendar::where('user_id', $preparedData['user_id'])->where('type', 'simple')->first();
147 +
148 + if ($isHostCalendar && $firstCalendar) {
149 + if ($isFileInput) {
150 + return new \WP_Error('calendar_exists', esc_html__('The user already has a calendar. Please delete it first to create a new one', 'fluent-booking'));
151 + }
152 + return $firstCalendar;
153 + }
154 +
155 + return $preparedData;
156 + }
157 +
158 + protected static function prepareCalendarMetas($calendarMetas)
159 + {
160 + $preparedCalendarMetas = [];
161 +
162 + foreach ($calendarMetas as $calendarMeta) {
163 + if (empty($calendarMeta['key']) || empty($calendarMeta['value'])) {
164 + continue;
165 + }
166 +
167 + $value = $calendarMeta['value'];
168 +
169 + $preparedCalendarMetas[] = [
170 + 'key' => sanitize_text_field($calendarMeta['key']),
171 + 'value' => is_array($value) ? self::sanitize_mapped_data($value) : sanitize_text_field($value),
172 + // Bound to the imported calendar; never let the payload pick the type
173 + // (e.g. a user_meta / _access_permissions row).
174 + 'object_type' => 'Calendar'
175 + ];
176 + }
177 +
178 + return $preparedCalendarMetas;
179 + }
180 +
181 + protected static function prepareEventData($eventData, $calendar, $availabilities = [])
182 + {
183 + $preparedEventData = [
184 + 'title' => sanitize_text_field(Arr::get($eventData, 'title')),
185 + 'duration' => (int)Arr::get($eventData, 'duration', 30),
186 + 'description' => wp_kses_post(Arr::get($eventData, 'description')),
187 + 'type' => sanitize_text_field(Arr::get($eventData, 'type')),
188 + 'status' => sanitize_text_field(Arr::get($eventData, 'status', 'active')),
189 + 'color_schema' => sanitize_text_field(Arr::get($eventData, 'color_schema', '#0099ff')),
190 + 'event_type' => sanitize_text_field(Arr::get($eventData, 'event_type')),
191 + 'availability_id' => (int)self::prepareAvailabilityId(Arr::get($eventData, 'availability_id', 0), $availabilities),
192 + 'availability_type' => sanitize_text_field(Arr::get($eventData, 'availability_type')),
193 + 'location_type' => sanitize_text_field(Arr::get($eventData, 'location_type')),
194 + 'location_settings' => SanitizeService::locationSettings(Arr::get($eventData, 'location_settings', [])),
195 + 'max_book_per_slot' => (int)Arr::get($eventData, 'max_book_per_slot', 1),
196 + 'is_display_spots' => (bool)Arr::get($eventData, 'is_display_spots', false),
197 + ];
198 +
199 + if (!empty($eventData['hash'])) {
200 + $hash = sanitize_text_field($eventData['hash']);
201 + if (!CalendarSlot::where('hash', $hash)->exists()) {
202 + $preparedEventData['hash'] = $hash;
203 + }
204 + }
205 +
206 + $eventSettings = Arr::get($eventData, 'settings', []);
207 +
208 + if (!$eventSettings) {
209 + return $preparedEventData;
210 + }
211 +
212 + $preparedEventData['settings'] = [
213 + 'schedule_type' => sanitize_text_field(Arr::get($eventSettings, 'schedule_type')),
214 + 'weekly_schedules' => SanitizeService::weeklySchedules(Arr::get($eventSettings, 'weekly_schedules', []), $calendar->author_timezone, 'UTC', true),
215 + 'date_overrides' => SanitizeService::slotDateOverrides(Arr::get($eventSettings, 'date_overrides', []), $calendar->author_timezone, 'UTC', null, true),
216 + 'range_type' => sanitize_text_field(Arr::get($eventSettings, 'range_type')),
217 + 'range_days' => (int)(Arr::get($eventSettings, 'range_days', 60)) ?: 60,
218 + 'range_date_between' => SanitizeService::rangeDateBetween(Arr::get($eventSettings, 'range_date_between', ['', ''])),
219 + 'schedule_conditions' => SanitizeService::scheduleConditions(Arr::get($eventSettings, 'schedule_conditions', [])),
220 + 'common_schedule' => Arr::isTrue($eventSettings, 'common_schedule', false),
221 + 'buffer_time_before' => sanitize_text_field(Arr::get($eventSettings, 'buffer_time_before', '0')),
222 + 'buffer_time_after' => sanitize_text_field(Arr::get($eventSettings, 'buffer_time_after', '0')),
223 + 'slot_interval' => sanitize_text_field(Arr::get($eventSettings, 'slot_interval', '')),
224 + 'team_members' => array_map('intval', Arr::get($eventSettings, 'team_members', [])),
225 + 'multi_duration' => [
226 + 'enabled' => Arr::isTrue($eventSettings, 'multi_duration.enabled'),
227 + 'default_duration' => Arr::get($eventSettings, 'multi_duration.default_duration', ''),
228 + 'available_durations' => array_map('sanitize_text_field', Arr::get($eventSettings, 'multi_duration.available_durations', []))
229 + ],
230 + 'booking_frequency' => [
231 + 'enabled' => Arr::isTrue($eventSettings, 'booking_frequency.enabled'),
232 + 'limits' => self::sanitize_mapped_data(Arr::get($eventSettings, 'booking_frequency.limits', []))
233 + ],
234 + 'booking_duration' => [
235 + 'enabled' => Arr::isTrue($eventSettings, 'booking_duration.enabled'),
236 + 'limits' => self::sanitize_mapped_data(Arr::get($eventSettings, 'booking_duration.limits', []))
237 + ],
238 + 'lock_timezone' => [
239 + 'enabled' => Arr::isTrue($eventSettings, 'lock_timezone.enabled'),
240 + 'timezone' => sanitize_text_field(Arr::get($eventSettings, 'lock_timezone.timezone'))
241 + ],
242 + 'booking_title' => sanitize_text_field(Arr::get($eventSettings, 'booking_title')),
243 + 'submit_button_text' => sanitize_text_field(Arr::get($eventSettings, 'submit_button_text')),
244 + 'custom_redirect' => [
245 + 'enabled' => Arr::isTrue($eventSettings, 'custom_redirect.enabled'),
246 + 'redirect_url' => sanitize_url(Arr::get($eventSettings, 'custom_redirect.redirect_url')),
247 + 'is_query_string' => Arr::get($eventSettings, 'custom_redirect.is_query_string') == 'yes' ? 'yes' : 'no',
248 + 'query_string' => sanitize_text_field(Arr::get($eventSettings, 'custom_redirect.query_string')),
249 + ],
250 + 'requires_confirmation' => [
251 + 'enabled' => Arr::isTrue($eventSettings, 'requires_confirmation.enabled'),
252 + 'type' => sanitize_text_field(Arr::get($eventSettings, 'requires_confirmation.type')),
253 + 'condition' => [
254 + 'unit' => sanitize_text_field(Arr::get($eventSettings, 'requires_confirmation.condition.unit')),
255 + 'value' => intval(Arr::get($eventSettings, 'requires_confirmation.condition.value'))
256 + ]
257 + ],
258 + 'multiple_booking' => [
259 + 'enabled' => Arr::isTrue($eventSettings, 'multiple_booking.enabled'),
260 + 'limit' => intval(Arr::get($eventSettings, 'multiple_booking.limit'))
261 + ],
262 + 'can_not_cancel' => [
263 + 'enabled' => Arr::isTrue($eventSettings, 'can_not_cancel.enabled'),
264 + 'type' => sanitize_text_field(Arr::get($eventSettings, 'can_not_cancel.type')),
265 + 'message' => sanitize_text_field(Arr::get($eventSettings, 'can_not_cancel.message')),
266 + 'condition' => [
267 + 'unit' => sanitize_text_field(Arr::get($eventSettings, 'can_not_cancel.condition.unit')),
268 + 'value' => intval(Arr::get($eventSettings, 'can_not_cancel.condition.value'))
269 + ]
270 + ],
271 + 'can_not_reschedule' => [
272 + 'enabled' => Arr::isTrue($eventSettings, 'can_not_reschedule.enabled'),
273 + 'type' => sanitize_text_field(Arr::get($eventSettings, 'can_not_reschedule.type')),
274 + 'message' => sanitize_text_field(Arr::get($eventSettings, 'can_not_reschedule.message')),
275 + 'condition' => [
276 + 'unit' => sanitize_text_field(Arr::get($eventSettings, 'can_not_reschedule.condition.unit')),
277 + 'value' => intval(Arr::get($eventSettings, 'can_not_reschedule.condition.value'))
278 + ]
279 + ]
280 + ];
281 +
282 + return $preparedEventData;
283 + }
284 +
285 + protected static function prepareEventMetas($eventMetasData, $event = null)
286 + {
287 + $preparedEventMetas = [];
288 +
289 + foreach ($eventMetasData as $eventMeta) {
290 + if (empty($eventMeta['key']) || empty($eventMeta['value'])) {
291 + continue;
292 + }
293 +
294 + $value = $eventMeta['value'];
295 +
296 + // Only the two types an event actually stores; anything else in the
297 + // payload (e.g. user_meta / _access_permissions) is dropped.
298 + $objectType = sanitize_text_field(Arr::get($eventMeta, 'object_type'));
299 + if (!in_array($objectType, ['calendar_event', 'integration'], true)) {
300 + continue;
301 + }
302 +
303 + if ($eventMeta['key'] == 'email_notification') {
304 + $value = self::updateNotificationImageUrl($value);
305 + }
306 +
307 + // Rendered on the public form via {@html}; sanitize as the admin path does.
308 + if ($eventMeta['key'] == 'booking_fields' && is_array($value)) {
309 + $value = BookingFieldService::sanitizeBookingFields($value, $event);
310 + }
311 +
312 + $preparedEventMetas[] = [
313 + 'key' => sanitize_text_field($eventMeta['key']),
314 + 'value' => is_array($value) ? self::sanitize_mapped_data($value) : sanitize_text_field($value),
315 + 'object_type' => $objectType
316 + ];
317 + }
318 +
319 + return $preparedEventMetas;
320 + }
321 +
322 + protected static function prepareAvailabilityId($availabilityId, $availabilities)
323 + {
324 + if ($availabilityId && isset($availabilities[$availabilityId])) {
325 + return $availabilities[$availabilityId];
326 + }
327 +
328 + if ($availabilities) {
329 + $firstKey = array_key_first($availabilities);
330 + return $availabilities[$firstKey];
331 + }
332 +
333 + return $availabilityId;
334 + }
335 +
336 + protected static function updateNotificationImageUrl($notifications)
337 + {
338 + $formattedNotifications = [];
339 +
340 + foreach ($notifications as $key => $notification) {
341 + $emailBody = Arr::get($notification, 'email.body');
342 + if (!$emailBody) {
343 + continue;
344 + }
345 +
346 + $newImageUrl = FLUENT_BOOKING_URL . 'assets/images';
347 + $pattern = '/(https:\/\/[^"]*?' . preg_quote('assets/images', '/') . ')/';
348 + $emailBody = preg_replace($pattern, $newImageUrl, $emailBody);
349 + $notification['email']['body'] = $emailBody;
350 +
351 + $formattedNotifications[$key] = $notification;
352 + }
353 +
354 + return $formattedNotifications;
355 + }
356 +
357 + public static function getSlotOptions($calendarId = null, $userId = null)
358 + {
13 359 $calendarSlots = CalendarSlot::select(['id', 'title'])
14 - ->where('calendar_id', $calendarId)
360 + ->when($calendarId, function ($query) use ($calendarId) {
361 + return $query->where('calendar_id', $calendarId);
362 + })
363 + ->when($userId, function ($query) use ($userId) {
364 + return $query->where('user_id', $userId);
365 + })
15 366 ->where('status', '!=', 'expired')
16 367 ->latest()
17 368 ->get();
18 369
@@ -31,9 +382,9 @@
31 382 $calendars = Calendar::select(['id', 'title'])
32 383 ->when(!PermissionManager::hasAllCalendarAccess(true), function ($query) {
33 384 return $query->where('user_id', get_current_user_id());
34 385 })
35 - ->with(['slots' => function($query) {
386 + ->with(['slots' => function ($query) {
36 387 $query->where('status', '!=', 'expired');
37 388 }])
38 389 ->latest()
39 390 ->get();
@@ -38,9 +389,9 @@
38 389 ->latest()
39 390 ->get();
40 391
41 392 $formattedCalendars = [];
42 - foreach ($calendars as $index => $calendar) {
393 + foreach ($calendars as $calendar) {
43 394 $slots = Arr::get($calendar, 'slots');
44 395 if (!empty($slots)) {
45 396 $options = [];
46 397 foreach ($slots as $slot) {
@@ -49,9 +400,9 @@
49 400 'value' => Arr::get($slot, 'id')
50 401 ];
51 402 }
52 403 if (!empty($options)) {
53 - $formattedCalendars[$index] = [
404 + $formattedCalendars[] = [
54 405 'label' => Arr::get($calendar, 'title'),
55 406 'options' => $options
56 407 ];
57 408 }
@@ -61,32 +412,35 @@
61 412 }
62 413
63 414 public static function getCalendarOptionsByTitle($condition = '')
64 415 {
65 - $calendarQuery = Calendar::select(['id', 'title'])
416 + $calendarsQuery = Calendar::select(['id', 'title', 'user_id'])
66 417 ->where('status', '!=', 'expired')
67 - ->when(!PermissionManager::hasAllCalendarAccess(true), function ($query) {
68 - return $query->where('user_id', get_current_user_id());
69 - });
418 + ->with(['slots' => function ($query) {
419 + $query->where('status', '!=', 'expired');
420 + }]);
70 421
71 422 switch ($condition) {
72 423 case 'only_hosts':
73 - $calendarQuery->where('type', 'simple');
424 + $calendarsQuery->where('type', 'simple');
74 425 break;
75 426 case 'only_teams':
76 - $calendarQuery->where('type', 'team');
427 + $calendarsQuery->where('type', 'team');
77 428 break;
78 429 case 'only_events':
79 - $calendarQuery->where('type', 'event');
430 + $calendarsQuery->where('type', 'event');
80 431 break;
81 432 }
82 433
83 - $calendars = $calendarQuery->with(['slots' => function($query) {
84 - $query->where('status', '!=', 'expired');
85 - }])->latest()->get();
434 + if (!PermissionManager::hasAllCalendarAccess(true)) {
435 + $attachedCalendarIds = self::getAttachedCalendarIds($calendarsQuery);
436 + $calendarsQuery->whereIn('id', $attachedCalendarIds);
437 + }
86 438
439 + $calendars = $calendarsQuery->latest()->get();
440 +
87 441 $formattedCalendars = [];
88 - foreach ($calendars as $index => $calendar) {
442 + foreach ($calendars as $calendar) {
89 443 $slots = Arr::get($calendar, 'slots');
90 444 if (!empty($slots)) {
91 445 $options = [];
92 446 foreach ($slots as $slot) {
@@ -95,9 +449,9 @@
95 449 'title' => Arr::get($slot, 'title')
96 450 ];
97 451 }
98 452 if (!empty($options)) {
99 - $formattedCalendars[$index] = [
453 + $formattedCalendars[] = [
100 454 'id' => Arr::get($calendar, 'id'),
101 455 'title' => Arr::get($calendar, 'title'),
102 456 'options' => $options
103 457 ];
@@ -106,22 +460,65 @@
106 460 }
107 461 return apply_filters('fluent_booking/calendar_options_by_title', $formattedCalendars);
108 462 }
109 463
464 + public static function getAttachedCalendarIds($calendarsQuery)
465 + {
466 + $userId = get_current_user_id();
467 +
468 + $calendars = $calendarsQuery->get();
469 +
470 + $calendarIds = [];
471 + foreach ($calendars as $calendar) {
472 + if ($calendar->user_id == $userId) {
473 + $calendarIds[] = $calendar->id;
474 + continue;
475 + }
476 +
477 + $events = Arr::get($calendar, 'slots', []);
478 + foreach ($events as $event) {
479 + $teamMembers = Arr::get($event, 'settings.team_members', []);
480 + if (in_array($userId, $teamMembers)) {
481 + $calendarIds[] = $calendar->id;
482 + }
483 + }
484 + }
485 +
486 + return $calendarIds;
487 + }
488 +
489 + public static function isSharedCalendar($calendar)
490 + {
491 + $calendarEvents = $calendar->events;
492 +
493 + $userId = get_current_user_id();
494 +
495 + foreach ($calendarEvents as $event) {
496 + if ($event->user_id == $userId) {
497 + return true;
498 + }
499 + $teamMembers = Arr::get($event, 'settings.team_members', []);
500 + if (in_array($userId, $teamMembers)) {
501 + return true;
502 + }
503 + }
504 +
505 + return false;
506 + }
507 +
110 508 public static function updateCalendarEventsSchedule($calendarId, $oldTimezone, $updatedTimezone)
111 509 {
112 510 $calendarEvents = CalendarSlot::query()->where('calendar_id', $calendarId)->get();
113 511
114 - foreach ($calendarEvents as $event)
115 - {
512 + foreach ($calendarEvents as $event) {
116 513 if ($weeklySchedule = Arr::get($event->settings, 'weekly_schedules', [])) {
117 514 $originalSchedule = SanitizeService::weeklySchedules($weeklySchedule, 'UTC', $oldTimezone);
118 - $weeklySchedule = SanitizeService::weeklySchedules($originalSchedule, $updatedTimezone, 'UTC');
515 + $weeklySchedule = SanitizeService::weeklySchedules($originalSchedule, $updatedTimezone, 'UTC', true);
119 516 }
120 517
121 518 if ($dateOverride = Arr::get($event->settings, 'date_overrides', [])) {
122 519 $originalOverride = SanitizeService::slotDateOverrides($dateOverride, 'UTC', $oldTimezone);
123 - $dateOverride = SanitizeService::slotDateOverrides($originalOverride, $updatedTimezone, 'UTC');
520 + $dateOverride = SanitizeService::slotDateOverrides($originalOverride, $updatedTimezone, 'UTC', null, true);
124 521 }
125 522
126 523 $event->settings = [
127 524 'weekly_schedules' => $weeklySchedule,
@@ -129,6 +526,19 @@
129 526 ];
130 527
131 528 $event->save();
132 529 }
530 + }
531 +
532 + private static function sanitize_mapped_data($settings)
533 + {
534 + $sanitizerMap = [
535 + 'value' => 'intval',
536 + 'unit' => 'sanitize_text_field',
537 + 'subject' => 'sanitize_text_field',
538 + 'body' => 'fcal_sanitize_html',
539 + 'additional_recipients' => 'sanitize_text_field'
540 + ];
541 +
542 + return Helper::fcal_backend_sanitizer($settings, $sanitizerMap);
133 543 }
134 544 }