PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.01
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.01
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 / Models / CalendarSlot.php

CalendarSlot.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.01, at app/Models/CalendarSlot.php

977 lines 30.5 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\Models;
4
5 use FluentBooking\App\Models\Model;
6 use FluentBooking\App\Services\SanitizeService;
7 use FluentBooking\App\Services\AvailabilityService;
8 use FluentBooking\App\Services\BookingFieldService;
9 use FluentBooking\App\Services\DateTimeHelper;
10 use FluentBooking\App\Services\Helper;
11 use FluentBooking\App\Services\BookingService;
12 use FluentBooking\App\Services\EditorShortCodeParser;
13 use FluentBooking\App\Services\LandingPage\LandingPageHandler;
14 use FluentBooking\App\Services\LandingPage\LandingPageHelper;
15 use FluentBooking\App\Services\LocationService;
16 use FluentBooking\Framework\Support\Arr;
17
18 class CalendarSlot extends Model
19 {
20 protected $table = 'fcal_calendar_events';
21
22 protected $guarded = ['id'];
23
24 protected $fillable = [
25 'user_id',
26 'hash',
27 'calendar_id',
28 'duration',
29 'title',
30 'slug',
31 'media_id',
32 'description',
33 'settings',
34 'availability_type',
35 'availability_id',
36 'status',
37 'type',
38 'color_schema',
39 'location_type',
40 'location_heading',
41 'location_settings',
42 'event_type',
43 'is_display_spots',
44 'max_book_per_slot',
45 'created_at',
46 'updated_at',
47 ];
48
49 public static function boot()
50 {
51 parent::boot();
52
53 static::creating(function ($model) {
54 if (empty($model->user_id)) {
55 $model->user_id = get_current_user_id();
56 }
57 $model->hash = md5(wp_generate_uuid4() . time());
58 });
59 }
60
61 public function setSettingsAttribute($settings)
62 {
63 $originalSettings = $this->getOriginal('settings');
64
65 $originalSettings = \maybe_unserialize($originalSettings);
66
67 foreach ($settings as $key => $value) {
68 $originalSettings[$key] = $value;
69 }
70
71 $this->attributes['settings'] = \maybe_serialize($originalSettings);
72 }
73
74 public function getSettingsAttribute($settings)
75 {
76 return \maybe_unserialize($settings);
77 }
78
79 public function setLocationSettingsAttribute($locationSettings)
80 {
81 $this->attributes['location_settings'] = \maybe_serialize($locationSettings);
82 }
83
84 public function getLocationSettingsAttribute($locationSettings)
85 {
86 return \maybe_unserialize($locationSettings);
87 }
88
89 public function calendar()
90 {
91 return $this->belongsTo(Calendar::class, 'calendar_id');
92 }
93
94 public function bookings()
95 {
96 return $this->hasMany(Booking::class, 'event_id');
97 }
98
99 public function user()
100 {
101 return $this->belongsTo(User::class, 'user_id');
102 }
103
104 public function isGroup()
105 {
106 return $this->event_type == 'group';
107 }
108
109 public function isSingleEvent()
110 {
111 return $this->event_type == 'single_event';
112 }
113
114 public function isGroupEvent()
115 {
116 return $this->event_type == 'group_event';
117 }
118
119 public function isRoundRobin()
120 {
121 return $this->event_type == 'round_robin';
122 }
123
124 public function isCollective()
125 {
126 return $this->event_type == 'collective';
127 }
128
129 public function isTeamEvent()
130 {
131 return $this->isRoundRobin() || $this->isCollective();
132 }
133
134 public function isOneOffEvent()
135 {
136 return $this->isSingleEvent() || $this->isGroupEvent();
137 }
138
139 public function isMultiHostEvent()
140 {
141 return $this->isTeamEvent() || $this->isOneOffEvent();
142 }
143
144 public function isMultiHostsEvent()
145 {
146 return $this->isCollective() || $this->isOneOffEvent();
147 }
148
149 public function isMultiGuestEvent()
150 {
151 return $this->isGroup() || $this->isGroupEvent();
152 }
153
154 public function isProEvent()
155 {
156 return $this->isGroup() || $this->isTeamEvent() || $this->isOneOffEvent();
157 }
158
159 public function getAuthorProfile($public = true, $userID = null)
160 {
161 $userID = $userID ?: $this->user_id;
162
163 $user = get_user_by('id', $userID);
164 if (!$user) {
165 return false;
166 }
167
168 $name = trim($user->first_name . ' ' . $user->last_name);
169
170 if (!$name) {
171 $name = $user->display_name;
172 }
173
174 $data = [
175 'ID' => $user->ID,
176 'name' => $name,
177 'avatar' => Helper::fluentBookingUserAvatar($user->ID, $user)
178 ];
179
180 if (!$public) {
181 $data['email'] = $user->user_email;
182 }
183
184 return $data;
185 }
186
187 public function getAuthorProfiles($public = true)
188 {
189 $teamMembers = [];
190 $teamMemberIds = $this->getHostIds();
191
192 foreach ($teamMemberIds as $teamMemberId) {
193 $calendar = Calendar::where('user_id', $teamMemberId)->where('type', 'simple')->first();
194 if ($calendar) {
195 $teamMembers[] = $calendar->getAuthorProfile($public);
196 }
197 }
198
199 return $teamMembers;
200 }
201
202 public function isLocationFieldRequired()
203 {
204 $locationSettings = Arr::get($this, 'location_settings');
205
206 if (count($locationSettings) > 1) {
207 return true;
208 }
209
210 return false;
211 }
212
213 public function isPhoneRequired()
214 {
215 if (count($this->location_settings) == 1) {
216 return Arr::get($this->location_settings, '0.type') == 'phone_guest';
217 }
218
219 return false;
220 }
221
222 public function isAddressRequired()
223 {
224 if (count($this->location_settings) == 1) {
225 return Arr::get($this->location_settings, '0.type') == 'in_person_guest';
226 }
227
228 return false;
229 }
230
231 public function isGuestFieldRequired()
232 {
233 return !$this->isGroup();
234 }
235
236 public function getSlotSettingsSchema($calendarId = null)
237 {
238 $calendarEvent = $calendarId ? CalendarSlot::where('calendar_id', $calendarId)->first() : null;
239
240 return [
241 'schedule_type' => 'weekly_schedules',
242 'weekly_schedules' => Helper::getWeeklyScheduleSchema(),
243 'date_overrides' => [],
244 'range_type' => 'range_days',
245 'range_days' => 60,
246 'range_date_between' => ['', ''],
247 'schedule_conditions' => [
248 'value' => 4,
249 'unit' => 'hours'
250 ],
251 'location_fields' => $this->getLocationFields($calendarEvent)
252 ];
253 }
254
255 public function getNotifications($isEdit = false)
256 {
257 $statuses = $this->getMeta('email_notifications');
258
259 if ($statuses) {
260
261 $defaults = Helper::getDefaultEmailNotificationSettings();
262
263 if ($isEdit) {
264 foreach ($defaults as $key => $default) {
265 if (isset($statuses[$key])) {
266 $statuses[$key]['title'] = $default['title'];
267 }
268 }
269 }
270
271 if (!Arr::get($statuses, 'rescheduled_by_host')) {
272 $statuses['rescheduled_by_host'] = $defaults['rescheduled_by_host'];
273 }
274
275 if (!Arr::get($statuses, 'rescheduled_by_attendee')) {
276 $statuses['rescheduled_by_attendee'] = $defaults['rescheduled_by_attendee'];
277 }
278
279 if (!Arr::get($statuses, 'booking_request_host')) {
280 $statuses['booking_request_host'] = $defaults['booking_request_host'];
281 }
282
283 if (!Arr::get($statuses, 'booking_request_attendee')) {
284 $statuses['booking_request_attendee'] = $defaults['booking_request_attendee'];
285 }
286
287 if (!Arr::get($statuses, 'declined_by_host')) {
288 $statuses['declined_by_host'] = $defaults['declined_by_host'];
289 }
290
291 return $statuses;
292 }
293
294 return Helper::getDefaultEmailNotificationSettings();
295 }
296
297 public function setNotifications($notifications)
298 {
299 $this->updateMeta('email_notifications', $notifications);
300 }
301
302 public function getBookingFields()
303 {
304 return BookingFieldService::getBookingFields($this);
305 }
306
307 public function setBookingFields($bookingFields)
308 {
309 return $this->updateMeta('booking_fields', $bookingFields);
310 }
311
312 public function getScheduleTimezone($hostId = null)
313 {
314 if ($hostId && !$this->isTeamCommonSchedule()) {
315 $schedule = AvailabilityService::getDefaultSchedule($hostId);
316 return Arr::get($schedule, 'value.timezone', 'UTC');
317 }
318
319 if ($this->availability_type == 'existing_schedule') {
320 $schedule = Availability::findOrFail($this->availability_id);
321 return Arr::get($schedule, 'value.timezone', 'UTC');
322 }
323
324 return $this->calendar->author_timezone;
325 }
326
327 public function isMultiDurationEnabled()
328 {
329 return Arr::isTrue($this->settings, 'multi_duration.enabled');
330 }
331
332 public function getDuration($duration = null)
333 {
334 if ($this->isMultiDurationEnabled()) {
335 if (in_array($duration, Arr::get($this->settings, 'multi_duration.available_durations', []))) {
336 return $duration;
337 } else {
338 return Arr::get($this->settings, 'multi_duration.default_duration', '');
339 }
340 }
341
342 return $this->duration;
343 }
344
345 public function getDefaultDuration()
346 {
347 if ($this->isMultiDurationEnabled()) {
348 return Arr::get($this->settings, 'multi_duration.default_duration', '');
349 }
350
351 return $this->duration;
352 }
353
354 public function getAvailableDurations()
355 {
356 if ($this->isMultiDurationEnabled()) {
357 $durationLookup = Helper::getDurationLookup(true);
358 $availableDurations = Arr::get($this->settings, 'multi_duration.available_durations', []);
359
360 return array_map(function ($duration) use ($durationLookup) {
361 return $durationLookup[$duration];
362 }, $availableDurations);
363 }
364
365 $durationLookup = Helper::getDurationLookup();
366
367 $duration = $durationLookup[$this->duration] ?? $this->duration;
368
369 return [$duration];
370 }
371
372 public function getDescription()
373 {
374 if ($this->description) {
375 return $this->description;
376 }
377
378 if ($this->isMultiDurationEnabled()) {
379 return __('Choose your duration and book a meeting with me', 'fluent-booking');
380 }
381
382 // translators: %d is the duration of the meeting in minutes
383 return sprintf(__('Book a meeting with me for %d minutes', 'fluent-booking'), $this->duration);
384 }
385
386 public function getSlotInterval($duration = null)
387 {
388 $duration = $duration ?: $this->duration;
389
390 $interval = Arr::get($this->settings, 'slot_interval', '');
391
392 $slotInterval = empty($interval) ? $duration : intval($interval);
393
394 return $slotInterval;
395 }
396
397 public function isReserveTime()
398 {
399 return Arr::isTrue($this->settings, 'reserve_time', false);
400 }
401
402 public function getAvailableTimes()
403 {
404 return Arr::get($this->settings, 'available_times', []);
405 }
406
407 public function getTotalBufferTime()
408 {
409 $bufferTimeBefore = Arr::get($this->settings, 'buffer_time_before', 0);
410 $bufferTimeAfter = Arr::get($this->settings, 'buffer_time_after', 0);
411
412 return $bufferTimeBefore + $bufferTimeAfter;
413 }
414
415 public function getMaxBookableDateTime($startDate, $timeZone = 'UTC', $format = 'Y-m-d 23:59:59')
416 {
417 $rangeType = Arr::get($this->settings, 'range_type', 'range_days');
418
419 $lastDay = gmdate('Y-m-t 23:59:59', strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
420
421 if ($timeZone != 'UTC') {
422 $lastDay = DateTimeHelper::convertToTimeZone($lastDay, $timeZone, 'UTC', $format);
423 }
424
425 if ($rangeType == 'range_indefinite') {
426 return $lastDay;
427 }
428
429 $maxLookupDate = $this->getMaxLookUpDate();
430
431 $maxDate = DateTimeHelper::convertToTimeZone($maxLookupDate, $this->calendar->author_timezone, 'UTC');
432
433 if (strtotime($maxDate) > strtotime($lastDay)) {
434 return $lastDay;
435 }
436
437 return $maxDate;
438 }
439
440 public function getMinBookableDateTime($startDate = null, $timeZone = null)
441 {
442 $startDate = $startDate ?: gmdate('Y-m-d H:i:s'); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
443
444 $rangeType = Arr::get($this->settings, 'range_type', 'range_days');
445
446 if ($rangeType == 'range_date_between') {
447 $range = Arr::get($this->settings, 'range_date_between', []);
448 if (is_array($range) && count(array_filter($range)) == 2) {
449 if (strtotime($range[0]) >= strtotime($startDate)) {
450 $startDate = gmdate('Y-m-d H:i:s', strtotime($range[0])); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
451 }
452 }
453 }
454
455 $totalCutStamp = DateTimeHelper::getTimestamp() + $this->getCutoutSeconds();
456
457 if (strtotime($startDate) < $totalCutStamp) {
458 $startDate = gmdate('Y-m-d H:i:s', $totalCutStamp); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
459 }
460
461 return $startDate;
462 }
463
464 public function getMaxLookUpDate()
465 {
466 $rangeType = Arr::get($this->settings, 'range_type', 'range_days');
467
468 if ($rangeType == 'range_indefinite') {
469 return false;
470 }
471
472 if ($rangeType == 'range_date_between') {
473 $range = Arr::get($this->settings, 'range_date_between', []);
474 if (is_array($range) && count(array_filter($range)) == 2) {
475 return gmdate('Y-m-d 23:59:59', strtotime($range[1])); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
476 }
477 }
478
479 $rangeDays = Arr::get($this->settings, 'range_days', 60) ?: 60;
480
481 return gmdate('Y-m-d 23:59:59', time() + $rangeDays * DAY_IN_SECONDS); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
482 }
483
484 public function getMinLookUpDate($timeZone = 'UTC')
485 {
486 $rangeType = Arr::get($this->settings, 'range_type', 'range_days');
487
488 $minDate = gmdate('Y-m-d H:i:s'); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
489
490 if ($rangeType == 'range_date_between') {
491 $range = Arr::get($this->settings, 'range_date_between', []);
492 if (is_array($range) && count(array_filter($range)) == 2) {
493 $minDate = gmdate('Y-m-d H:i:s', strtotime($range[0])); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
494 }
495 }
496
497 if ($timeZone != 'UTC') {
498 $minDate = DateTimeHelper::convertToTimeZone($minDate, $timeZone, 'UTC');
499 }
500
501 return $minDate;
502 }
503
504 public function getCutoutSeconds()
505 {
506 $conditions = Arr::get($this->settings, 'schedule_conditions', []);
507
508 if (!$conditions || empty($conditions['unit'])) {
509 return 0;
510 }
511
512 return strtotime('+' . $conditions['value'] . ' ' . $conditions['unit'], 0) - strtotime('+0 seconds', 0);
513 }
514
515 public function getHostIds($hostId = null)
516 {
517 if ($hostId) {
518 return [$hostId];
519 }
520
521 if ($this->isMultiHostEvent()) {
522 return Arr::get($this->settings, 'team_members', []);
523 }
524
525 return [$this->user_id];
526 }
527
528 public function getMaxBookingPerSlot()
529 {
530 return $this->max_book_per_slot;
531 }
532
533 public function getPublicUrl()
534 {
535 $calendar = $this->calendar;
536 if (!$calendar) {
537 return false;
538 }
539
540 $baseUr = $calendar->getLandingPageUrl();
541
542 if (!$baseUr) {
543 return '';
544 }
545
546 if (defined('FLUENT_BOOKING_LANDING_SLUG')) {
547 return $baseUr . '/' . $this->slug;
548 }
549
550 return $baseUr . '&event=' . $this->slug;
551 }
552
553 public function getMeta($key, $default = null)
554 {
555 $meta = Meta::where('object_type', 'calendar_event')
556 ->where('object_id', $this->id)
557 ->where('key', $key)
558 ->first();
559
560 if (!$meta) {
561 return $default;
562 }
563
564 return $meta->value;
565 }
566
567 public function updateMeta($key, $value)
568 {
569 $exist = Meta::where('object_type', 'calendar_event')
570 ->where('object_id', $this->id)
571 ->where('key', $key)
572 ->first();
573
574 if ($exist) {
575 $exist->value = $value;
576 $exist->save();
577 } else {
578 $exist = Meta::create([
579 'object_type' => 'calendar_event',
580 'object_id' => $this->id,
581 'key' => $key,
582 'value' => $value
583 ]);
584 }
585
586 return $exist;
587 }
588
589 public function getLocationFields($calendarEvent = null)
590 {
591 return apply_filters('fluent_booking/get_location_fields', [
592 'conferencing' => [
593 'label' => __('Conferencing', 'fluent-booking'),
594 'options' => [],
595 ],
596 'in_person' => [
597 'label' => __('In Person', 'fluent-booking'),
598 'options' => [
599 'in_person_guest' => [
600 'title' => __('In Person (Attendee Address)', 'fluent-booking'),
601 ],
602 'in_person_organizer' => [
603 'title' => __('In Person (Organizer Address)', 'fluent-booking'),
604 ],
605 ],
606 ],
607 'phone' => [
608 'label' => __('Phone', 'fluent-booking'),
609 'options' => [
610 'phone_guest' => [
611 'title' => __('Attendee Phone Number', 'fluent-booking'),
612 ],
613 'phone_organizer' => [
614 'title' => __('Organizer Phone Number', 'fluent-booking'),
615 ],
616 ],
617 ],
618 'online' => [
619 'label' => __('Online', 'fluent-booking'),
620 'options' => [
621 'online_meeting' => [
622 'title' => __('Online Meeting', 'fluent-booking'),
623 ],
624 ],
625 ],
626 'other' => [
627 'label' => __('Other', 'fluent-booking'),
628 'options' => [
629 'custom' => [
630 'title' => __('Custom', 'fluent-booking'),
631 ],
632 ],
633 ],
634 ], $calendarEvent ?: $this);
635 }
636
637 public function isConfirmationEnabled()
638 {
639 return Arr::isTrue($this->settings, 'requires_confirmation.enabled');
640 }
641
642 public function isConfirmationRequired($bookingStartTime, $bookingCreatedTime = null)
643 {
644 if ($this->isConfirmationEnabled()) {
645 $type = Arr::get($this->settings, 'requires_confirmation.type', 'always');
646 if ($type == 'always') {
647 return true;
648 }
649
650 $bookingStartTime = strtotime($bookingStartTime);
651 $bookingCreatedTime = $bookingCreatedTime ? strtotime($bookingCreatedTime) : time();
652
653 $conditionUnit = Arr::get($this->settings, 'requires_confirmation.condition.unit', 'minutes');
654 $conditionValue = Arr::get($this->settings, 'requires_confirmation.condition.value', 0);
655
656 $conditionTime = $conditionValue * 60;
657 if ($conditionUnit == 'hours') {
658 $conditionTime = $conditionTime * 60;
659 }
660
661 return $bookingStartTime - $bookingCreatedTime < $conditionTime;
662 }
663 return false;
664 }
665
666 public function getCanNotCancelSettings()
667 {
668 if (!isset($this->settings['can_not_cancel'])) {
669 $enabled = Arr::get($this->settings, 'can_cancel') == 'no' ? true : false;
670 return [
671 'enabled' => $enabled,
672 'type' => 'always',
673 ];
674 }
675 return Arr::get($this->settings, 'can_not_cancel', []);
676 }
677
678 public function getCanNotRescheduleSettings()
679 {
680 if (!isset($this->settings['can_not_reschedule'])) {
681 $enabled = Arr::get($this->settings, 'can_reschedule') == 'no' ? true : false;
682 return [
683 'enabled' => $enabled,
684 'type' => 'always',
685 ];
686 }
687 return Arr::get($this->settings, 'can_not_reschedule', []);
688 }
689
690 public function defaultLocationHtml()
691 {
692 if (empty($this->location_settings)) {
693 return '';
694 }
695
696 $default = Arr::get($this, 'location_settings');
697 if (!$default) {
698 return '';
699 }
700
701 return LocationService::getLocationIconHeadingHtml($default, $this);
702 }
703
704 public function defaultPaymentIcon($currency, $amount)
705 {
706 $html = '<div class="fcal_slot_payment_item"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-ea893728=""><path fill="currentColor" d="M256 640v192h640V384H768v-64h150.976c14.272 0 19.456 1.472 24.64 4.288a29.056 29.056 0 0 1 12.16 12.096c2.752 5.184 4.224 10.368 4.224 24.64v493.952c0 14.272-1.472 19.456-4.288 24.64a29.056 29.056 0 0 1-12.096 12.16c-5.184 2.752-10.368 4.224-24.64 4.224H233.024c-14.272 0-19.456-1.472-24.64-4.288a29.056 29.056 0 0 1-12.16-12.096c-2.688-5.184-4.224-10.368-4.224-24.576V640h64z"></path><path fill="currentColor" d="M768 192H128v448h640V192zm64-22.976v493.952c0 14.272-1.472 19.456-4.288 24.64a29.056 29.056 0 0 1-12.096 12.16c-5.184 2.752-10.368 4.224-24.64 4.224H105.024c-14.272 0-19.456-1.472-24.64-4.288a29.056 29.056 0 0 1-12.16-12.096C65.536 682.432 64 677.248 64 663.04V169.024c0-14.272 1.472-19.456 4.288-24.64a29.056 29.056 0 0 1 12.096-12.16C85.568 129.536 90.752 128 104.96 128h685.952c14.272 0 19.456 1.472 24.64 4.288a29.056 29.056 0 0 1 12.16 12.096c2.752 5.184 4.224 10.368 4.224 24.64z"></path><path fill="currentColor" d="M448 576a160 160 0 1 1 0-320 160 160 0 0 1 0 320zm0-64a96 96 0 1 0 0-192 96 96 0 0 0 0 192z"></path></svg>' . $currency . $amount . '</div>';
707 return $html;
708 }
709
710 public function isPaymentEnabled($duration = null)
711 {
712 if ($this->isMultiDurationEnabled()) {
713 $paymentSettings = $this->getPaymentSettings();
714 if (Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes') {
715 $duration = $duration ?? $this->getDefaultDuration();
716 if (!Arr::get($paymentSettings, 'multi_payment_items.'. $duration .'.value')) {
717 return false;
718 }
719 }
720 }
721
722 return $this->type == 'paid' && Helper::isPaymentEnabled();
723 }
724
725 public function isWooEnabled()
726 {
727 return $this->type == 'woo' && defined('WC_PLUGIN_FILE');
728 }
729
730 public function getPaymentItems($duration = null)
731 {
732 $paymentSettings = $this->getPaymentSettings();
733
734 $isMultiEnabled = Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes';
735
736 if ($this->isMultiDurationEnabled() && $isMultiEnabled) {
737 $duration = $duration ?? $this->getDefaultDuration();
738 return [Arr::get($paymentSettings, 'multi_payment_items.'. $duration)];
739 }
740
741 return Arr::get($paymentSettings, 'items', []);
742 }
743
744 public function getPricingTotal()
745 {
746 if (!$this->isPaymentEnabled()) {
747 return 0;
748 }
749
750 $total = 0;
751 $items = $this->getPaymentItems();
752 foreach ($items as $item) {
753 $total += (int)$item['value'];
754 }
755
756 return $total;
757 }
758
759 public function getWooProductPrice()
760 {
761 $paymentSettings = $this->getPaymentSettings();
762
763 $productId = $paymentSettings['woo_product_id'];
764
765 if (Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes') {
766 $duration = $this->getDefaultDuration();
767 $productId = Arr::get($paymentSettings, 'multi_payment_woo_ids.' . $duration);
768 }
769
770 $price = 0;
771 $product = wc_get_product($productId);
772 if ($product) {
773 $price = $product->get_price();
774 }
775
776 return $price;
777 }
778
779 public function getWooProductPriceByDuration($productIds = [])
780 {
781 $productPrices = [];
782
783 foreach ($productIds as $duration => $productId) {
784 $product = wc_get_product($productId);
785 if ($product) {
786 $productPrices[$duration] = [
787 'value' => $product->get_price()
788 ];
789 }
790 }
791
792 return $productPrices;
793 }
794
795 public function isTeamDefaultSchedule()
796 {
797 if ($this->isTeamEvent()) {
798 if (!Arr::isTrue($this->settings, 'common_schedule', false)) {
799 return true;
800 }
801 }
802 return false;
803 }
804
805 public function isTeamCommonSchedule()
806 {
807 if ($this->isTeamEvent()) {
808 if (Arr::isTrue($this->settings, 'common_schedule', false)) {
809 return true;
810 }
811 }
812 return false;
813 }
814
815 public function isRoundRobinDefaultSchedule() {
816 return $this->isRoundRobin() && $this->isTeamDefaultSchedule();
817 }
818
819 public function isRoundRobinCommonSchedule() {
820 return $this->isRoundRobin() && $this->isTeamCommonSchedule();
821 }
822
823 private function getProcessedWeeklySlots($schedule)
824 {
825 $scheduleData = Arr::get($schedule, 'value.weekly_schedules', []);
826 $scheduleTimezone = Arr::get($schedule, 'value.timezone', 'UTC');
827 $schedule = SanitizeService::weeklySchedules($scheduleData, 'UTC', $scheduleTimezone);
828 return AvailabilityService::getUtcWeeklySchedules($schedule, $scheduleTimezone);
829 }
830
831 private function getProcessedDateOverrides($schedule)
832 {
833 $scheduleData = Arr::get($schedule, 'value.date_overrides', []);
834 $scheduleTimezone = Arr::get($schedule, 'value.timezone', 'UTC');
835 $schedule = SanitizeService::slotDateOverrides($scheduleData, 'UTC', $scheduleTimezone);
836 $overrideSlots = AvailabilityService::getUtcDateOverrides($schedule, $scheduleTimezone);
837 $overrideDays = AvailabilityService::getDateOverrideDays($schedule, $scheduleTimezone);
838 return [$overrideSlots, $overrideDays];
839 }
840
841 public function getWeeklySlots($hostId = null)
842 {
843 if ($hostId && !$this->isTeamCommonSchedule()) {
844 $schedule = AvailabilityService::getDefaultSchedule($hostId);
845 return $this->getProcessedWeeklySlots($schedule);
846 }
847
848 if ($this->availability_type === 'existing_schedule') {
849 $schedule = Availability::findOrFail($this->availability_id);
850 return $this->getProcessedWeeklySlots($schedule);
851 }
852
853 $scheduleData = Arr::get($this->settings,'weekly_schedules',[]);
854 $schedule = SanitizeService::weeklySchedules($scheduleData, 'UTC', $this->calendar->author_timezone);
855 return AvailabilityService::getUtcWeeklySchedules($schedule, $this->calendar->author_timezone);
856 }
857
858 public function getDateOverrides($hostId = null)
859 {
860 if ($hostId && !$this->isTeamCommonSchedule()) {
861 $schedule = AvailabilityService::getDefaultSchedule($hostId);
862 return $this->getProcessedDateOverrides($schedule);
863 }
864
865 if ($this->availability_type === 'existing_schedule') {
866 $schedule = Availability::findOrFail($this->availability_id);
867 return $this->getProcessedDateOverrides($schedule);
868 }
869
870 $scheduleData = Arr::get($this->settings,'date_overrides',[]);
871 $schedule = SanitizeService::slotDateOverrides($scheduleData, 'UTC', $this->calendar->author_timezone);
872 $overrideSlots = AvailabilityService::getUtcDateOverrides($schedule, $this->calendar->author_timezone);
873 $overrideDays = AvailabilityService::getDateOverrideDays($schedule, $this->calendar->author_timezone);
874 return [$overrideSlots, $overrideDays];
875 }
876
877 public function getHostIdsSortedByBookings($startDate, $hostId = null)
878 {
879 $hostIds = $this->getHostIds($hostId);
880
881 if (count($hostIds) <= 1) {
882 return $hostIds;
883 }
884
885 $hostBookings = [];
886 foreach ($hostIds as $hostId) {
887 $dayStart = gmdate('Y-m-d 00:00:00',strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
888 $dayEnd = gmdate('Y-m-d 23:59:59',strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
889 $hostBookings[$hostId] = Booking::getHostTotalBooking($this->id, [$hostId], [$dayStart, $dayEnd]);
890 }
891 usort($hostIds, function ($a, $b) use ($hostBookings) {
892 return $hostBookings[$a] - $hostBookings[$b];
893 });
894
895 return $hostIds;
896 }
897
898 public function getPaymentSettings()
899 {
900 $settings = $this->getMeta('payment_settings', []);
901
902 $duration = $this->getDefaultDuration();
903
904 $defaults = [
905 'enabled' => 'no',
906 'multi_payment_enabled' => 'no',
907 'stripe_enabled' => 'no',
908 'paypal_enabled' => 'no',
909 'driver' => 'native',
910 'items' => [
911 [
912 'title' => __('Booking Fee', 'fluent-booking'),
913 'value' => 100
914 ]
915 ],
916 'woo_product_id' => '',
917 'multi_payment_items' => [
918 $duration => [
919 'title' => __('Booking Fee', 'fluent-booking'),
920 'value' => 0
921 ]
922 ],
923 'multi_payment_woo_ids' => [
924 $duration => ''
925 ]
926 ];
927
928 if (!$settings) {
929 $settings = $defaults;
930 }
931
932 return wp_parse_args($settings, $defaults);
933 }
934
935 public function getCalendarEventsMeta()
936 {
937 $eventsMeta = Meta::where('object_id', $this->id)
938 ->where('object_type', 'calendar_event')
939 ->get();
940
941 return $eventsMeta;
942 }
943
944 public function getIntegrationsMeta()
945 {
946 $integrationsMeta = Meta::where('object_id', $this->id)
947 ->where('object_type', 'integration')
948 ->get();
949
950 return $integrationsMeta;
951 }
952
953 /**
954 * Get the attributes that have been changed since last sync.
955 *
956 * @return array
957 */
958 public function getDirty()
959 {
960 $dirty = [];
961 foreach ($this->attributes as $key => $value) {
962 if (!in_array($key, $this->fillable)) {
963 continue;
964 }
965
966 if (!array_key_exists($key, $this->original)) {
967 $dirty[$key] = $value;
968 } elseif ($value !== $this->original[$key] &&
969 !$this->originalIsNumericallyEquivalent($key)) {
970 $dirty[$key] = $value;
971 }
972 }
973
974 return $dirty;
975 }
976 }
977