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/Models/CalendarSlot.php +320 -65 1.5.1 → 2.5.0 View file →
@@ -2,19 +2,17 @@
2 2
3 3 namespace FluentBooking\App\Models;
4 4
5 5 use FluentBooking\App\Models\Model;
6 +use FluentBooking\Framework\Support\Arr;
6 7 use FluentBooking\App\Services\SanitizeService;
7 8 use FluentBooking\App\Services\AvailabilityService;
8 9 use FluentBooking\App\Services\BookingFieldService;
9 10 use FluentBooking\App\Services\DateTimeHelper;
10 11 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;
12 +use FluentBooking\App\Services\CurrenciesHelper;
15 13 use FluentBooking\App\Services\LocationService;
16 -use FluentBooking\Framework\Support\Arr;
14 +use FluentBooking\App\Services\Integrations\FluentCart\CartHelper;
17 15
18 16 class CalendarSlot extends Model
19 17 {
20 18 protected $table = 'fcal_calendar_events';
@@ -53,9 +51,12 @@
53 51 static::creating(function ($model) {
54 52 if (empty($model->user_id)) {
55 53 $model->user_id = get_current_user_id();
56 54 }
57 - $model->hash = md5(wp_generate_uuid4() . time());
55 +
56 + if (empty($model->hash)) {
57 + $model->hash = md5(wp_generate_uuid4() . time());
58 + }
58 59 });
59 60 }
60 61
61 62 public function setSettingsAttribute($settings)
@@ -85,8 +86,19 @@
85 86 {
86 87 return \maybe_unserialize($locationSettings);
87 88 }
88 89
90 + public function getShortDescriptionAttribute()
91 + {
92 + $description = preg_replace('/<[^>]*>/', ' ', $this->getDescription());
93 +
94 + $maxLength = apply_filters('fluent_booking/event_short_description_length', 160, $this);
95 +
96 + $description = Helper::excerpt($description, $maxLength);
97 +
98 + return apply_filters('fluent_booking/event_short_description', $description, $this);
99 + }
100 +
89 101 public function calendar()
90 102 {
91 103 return $this->belongsTo(Calendar::class, 'calendar_id');
92 104 }
@@ -100,8 +112,19 @@
100 112 {
101 113 return $this->belongsTo(User::class, 'user_id');
102 114 }
103 115
116 + public function event_metas()
117 + {
118 + return $this->hasMany(Meta::class, 'object_id', 'id')
119 + ->whereIn('object_type', ['calendar_event', 'integration']);
120 + }
121 +
122 + public function isOneToOne()
123 + {
124 + return $this->event_type == 'single';
125 + }
126 +
104 127 public function isGroup()
105 128 {
106 129 return $this->event_type == 'group';
107 130 }
@@ -115,8 +138,18 @@
115 138 {
116 139 return $this->event_type == 'group_event';
117 140 }
118 141
142 + /**
143 + * Every value event_type can hold, on both fcal_calendar_slots and fcal_bookings.
144 + *
145 + * @return array
146 + */
147 + public static function getEventTypes()
148 + {
149 + return ['single', 'group', 'round_robin', 'collective', 'single_event', 'group_event'];
150 + }
151 +
119 152 public function isRoundRobin()
120 153 {
121 154 return $this->event_type == 'round_robin';
122 155 }
@@ -150,13 +183,33 @@
150 183 {
151 184 return $this->isGroup() || $this->isGroupEvent();
152 185 }
153 186
187 + public function isRecurringEvent()
188 + {
189 + return Arr::isTrue($this->getRecurringConfig(), 'enabled');
190 + }
191 +
154 192 public function isProEvent()
155 193 {
156 - return $this->isGroup() || $this->isTeamEvent() || $this->isOneOffEvent();
194 + return $this->isGroup() || $this->isTeamEvent() || $this->isOneOffEvent() || $this->allowMultiBooking();
157 195 }
158 196
197 + public function isMultiBooking()
198 + {
199 + return Arr::isTrue($this->settings, 'multiple_booking.enabled');
200 + }
201 +
202 + public function allowMultiBooking()
203 + {
204 + return $this->isMultiBooking() || $this->isRecurringEvent();
205 + }
206 +
207 + public function multiBookingLimit()
208 + {
209 + return Arr::get($this->settings, 'multiple_booking.limit', 5);
210 + }
211 +
159 212 public function getAuthorProfile($public = true, $userID = null)
160 213 {
161 214 $userID = $userID ?: $this->user_id;
162 215
@@ -185,14 +238,22 @@
185 238 }
186 239
187 240 public function getAuthorProfiles($public = true)
188 241 {
189 - $teamMembers = [];
242 + $teamMembers = [];
190 243 $teamMemberIds = $this->getHostIds();
191 244
245 + cache_users($teamMemberIds);
246 +
247 + $calendars = Calendar::whereIn('user_id', $teamMemberIds)
248 + ->where('type', 'simple')
249 + ->orderBy('id', 'desc')
250 + ->with(['metas', 'user', 'user.metas'])
251 + ->get()
252 + ->keyBy('user_id');
253 +
192 254 foreach ($teamMemberIds as $teamMemberId) {
193 - $calendar = Calendar::where('user_id', $teamMemberId)->where('type', 'simple')->first();
194 - if ($calendar) {
255 + if ($calendar = $calendars->get($teamMemberId)) {
195 256 $teamMembers[] = $calendar->getAuthorProfile($public);
196 257 }
197 258 }
198 259
@@ -198,8 +259,13 @@
198 259
199 260 return $teamMembers;
200 261 }
201 262
263 + public function getRecurringConfig()
264 + {
265 + return Arr::get($this->settings, 'recurring_config', []);
266 + }
267 +
202 268 public function isLocationFieldRequired()
203 269 {
204 270 $locationSettings = Arr::get($this, 'location_settings');
205 271
@@ -229,11 +295,83 @@
229 295 }
230 296
231 297 public function isGuestFieldRequired()
232 298 {
233 - return !$this->isMultiGuestEvent();
299 + return true;
234 300 }
235 301
302 + public function getEventDefaultData($calendar)
303 + {
304 + $weeklySchedule = Helper::getWeeklyScheduleSchema();
305 +
306 + $availability = AvailabilityService::maybeCreateAvailability($calendar, $weeklySchedule);
307 +
308 + $defaultData = [
309 + 'title' => '',
310 + 'calendar_id' => $calendar->id,
311 + 'user_id' => $calendar->user_id,
312 + 'status' => 'active',
313 + 'event_type' => 'single',
314 + 'description' => '',
315 + 'duration' => '30',
316 + 'color_schema' => '#0099ff',
317 + 'availability_type' => 'existing_schedule',
318 + 'availability_id' => (int)$availability->id,
319 + 'max_book_per_slot' => 1,
320 + 'is_display_spots' => false,
321 + 'location_settings' => [
322 + [
323 + 'type' => '',
324 + 'title' => '',
325 + 'description' => '',
326 + 'host_phone_number' => ''
327 + ]
328 + ],
329 + 'settings' => [
330 + 'schedule_type' => 'weekly_schedules',
331 + 'weekly_schedules' => $weeklySchedule,
332 + 'date_overrides' => [],
333 + 'range_type' => 'range_days',
334 + 'range_days' => 60,
335 + 'range_date_between' => ['', ''],
336 + 'schedule_conditions' => [
337 + 'value' => 4,
338 + 'unit' => 'hours'
339 + ]
340 + ]
341 + ];
342 +
343 + return $defaultData;
344 + }
345 +
346 + public function getEventSchema($calendar)
347 + {
348 + $userCalendarId = $calendar->type == 'simple' ? $calendar->id : null;
349 +
350 + $settingsSchema = $this->getSlotSettingsSchema($userCalendarId);
351 +
352 + $schema = [
353 + 'title' => '',
354 + 'status' => 'active',
355 + 'description' => '',
356 + 'duration' => '30',
357 + 'color_schema' => '#0099ff',
358 + 'calendar' => $calendar,
359 + 'settings' => $settingsSchema,
360 + 'max_book_per_slot' => 1,
361 + 'location_settings' => [
362 + [
363 + 'type' => '',
364 + 'title' => '',
365 + 'description' => '',
366 + 'host_phone_number' => ''
367 + ]
368 + ]
369 + ];
370 +
371 + return $schema;
372 + }
373 +
236 374 public function getSlotSettingsSchema($calendarId = null)
237 375 {
238 376 $calendarEvent = $calendarId ? CalendarSlot::where('calendar_id', $calendarId)->first() : null;
239 377
@@ -259,13 +397,15 @@
259 397 if ($statuses) {
260 398
261 399 $defaults = Helper::getDefaultEmailNotificationSettings();
262 400
263 - if ($isEdit) {
264 - foreach ($defaults as $key => $default) {
265 - if (isset($statuses[$key])) {
401 + foreach ($defaults as $key => $default) {
402 + if (isset($statuses[$key])) {
403 + if ($isEdit) {
266 404 $statuses[$key]['title'] = $default['title'];
267 405 }
406 + $emailBody = str_replace('fluent-booking-pro/core', 'fluent-booking', $statuses[$key]['email']['body']);
407 + $statuses[$key]['email']['body'] = $emailBody;
268 408 }
269 409 }
270 410
271 411 if (!Arr::get($statuses, 'rescheduled_by_host')) {
@@ -274,9 +414,9 @@
274 414
275 415 if (!Arr::get($statuses, 'rescheduled_by_attendee')) {
276 416 $statuses['rescheduled_by_attendee'] = $defaults['rescheduled_by_attendee'];
277 417 }
278 -
418 +
279 419 if (!Arr::get($statuses, 'booking_request_host')) {
280 420 $statuses['booking_request_host'] = $defaults['booking_request_host'];
281 421 }
282 422
@@ -311,15 +451,17 @@
311 451
312 452 public function getScheduleTimezone($hostId = null)
313 453 {
314 454 if ($hostId && !$this->isTeamCommonSchedule()) {
315 - $schedule = AvailabilityService::getDefaultSchedule($hostId);
455 + $schedule = $this->getHostSchedule($hostId);
316 456 return Arr::get($schedule, 'value.timezone', 'UTC');
317 457 }
318 458
319 459 if ($this->availability_type == 'existing_schedule') {
320 - $schedule = Availability::findOrFail($this->availability_id);
321 - return Arr::get($schedule, 'value.timezone', 'UTC');
460 + $schedule = Availability::find($this->availability_id);
461 + if ($schedule) {
462 + return Arr::get($schedule, 'value.timezone', 'UTC');
463 + }
322 464 }
323 465
324 466 return $this->calendar->author_timezone;
325 467 }
@@ -346,9 +488,9 @@
346 488 {
347 489 if ($this->isMultiDurationEnabled()) {
348 490 return Arr::get($this->settings, 'multi_duration.default_duration', '');
349 491 }
350 -
492 +
351 493 return $this->duration;
352 494 }
353 495
354 496 public function getAvailableDurations()
@@ -363,9 +505,9 @@
363 505 }
364 506
365 507 $durationLookup = Helper::getDurationLookup();
366 508
367 - $duration = $durationLookup[$this->duration] ?? $this->duration;
509 + $duration = $durationLookup[$this->duration] ?? Helper::formatDuration($this->duration);
368 510
369 511 return [$duration];
370 512 }
371 513
@@ -440,8 +582,12 @@
440 582 public function getMinBookableDateTime($startDate = null, $timeZone = null)
441 583 {
442 584 $startDate = $startDate ?: gmdate('Y-m-d H:i:s'); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
443 585
586 + if ($timeZone) {
587 + $startDate = DateTimeHelper::convertToTimeZone($startDate, $timeZone, 'UTC');
588 + }
589 +
444 590 $rangeType = Arr::get($this->settings, 'range_type', 'range_days');
445 591
446 592 if ($rangeType == 'range_date_between') {
447 593 $range = Arr::get($this->settings, 'range_date_between', []);
@@ -447,8 +593,9 @@
447 593 $range = Arr::get($this->settings, 'range_date_between', []);
448 594 if (is_array($range) && count(array_filter($range)) == 2) {
449 595 if (strtotime($range[0]) >= strtotime($startDate)) {
450 596 $startDate = gmdate('Y-m-d H:i:s', strtotime($range[0])); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
597 + $startDate = DateTimeHelper::convertToTimeZone($startDate, $this->calendar->author_timezone, 'UTC');
451 598 }
452 599 }
453 600 }
454 601
@@ -489,9 +636,9 @@
489 636
490 637 if ($rangeType == 'range_date_between') {
491 638 $range = Arr::get($this->settings, 'range_date_between', []);
492 639 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
640 + $minDate = gmdate('Y-m-d H:i:s', strtotime($range[0])); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
494 641 }
495 642 }
496 643
497 644 if ($timeZone != 'UTC') {
@@ -508,9 +655,11 @@
508 655 if (!$conditions || empty($conditions['unit'])) {
509 656 return 0;
510 657 }
511 658
512 - return strtotime('+' . $conditions['value'] . ' ' . $conditions['unit'], 0) - strtotime('+0 seconds', 0);
659 + $value = max(0, (int) Arr::get($conditions, 'value', 0));
660 +
661 + return strtotime('+' . $value . ' ' . $conditions['unit'], 0) - strtotime('+0 seconds', 0);
513 662 }
514 663
515 664 public function getHostIds($hostId = null)
516 665 {
@@ -649,8 +798,20 @@
649 798 ],
650 799 ], $calendarEvent ?: $this);
651 800 }
652 801
802 + public function isDisplaySpots()
803 + {
804 + return $this->is_display_spots == true;
805 + }
806 +
807 + public function isAdditionalGuestEnabled()
808 + {
809 + $guestField = BookingFieldService::getBookingFieldByName($this, 'guests');
810 +
811 + return Arr::isTrue($guestField, 'enabled', false);
812 + }
813 +
653 814 public function isConfirmationEnabled()
654 815 {
655 816 return Arr::isTrue($this->settings, 'requires_confirmation.enabled');
656 817 }
@@ -656,28 +817,31 @@
656 817 }
657 818
658 819 public function isConfirmationRequired($bookingStartTime, $bookingCreatedTime = null)
659 820 {
660 - if ($this->isConfirmationEnabled()) {
661 - $type = Arr::get($this->settings, 'requires_confirmation.type', 'always');
662 - if ($type == 'always') {
663 - return true;
664 - }
665 -
666 - $bookingStartTime = strtotime($bookingStartTime);
667 - $bookingCreatedTime = $bookingCreatedTime ? strtotime($bookingCreatedTime) : time();
821 + if (!$this->isConfirmationEnabled() || !is_string($bookingStartTime)) {
822 + return false;
823 + }
668 824
669 - $conditionUnit = Arr::get($this->settings, 'requires_confirmation.condition.unit', 'minutes');
670 - $conditionValue = Arr::get($this->settings, 'requires_confirmation.condition.value', 0);
825 + $type = Arr::get($this->settings, 'requires_confirmation.type', 'always');
826 + if ($type == 'always') {
827 + return true;
828 + }
671 829
672 - $conditionTime = $conditionValue * 60;
673 - if ($conditionUnit == 'hours') {
674 - $conditionTime = $conditionTime * 60;
675 - }
830 + $bookingStartTime = strtotime($bookingStartTime);
831 + $bookingCreatedTime = $bookingCreatedTime ? strtotime($bookingCreatedTime) : time();
676 832
677 - return $bookingStartTime - $bookingCreatedTime < $conditionTime;
833 + $conditionUnit = Arr::get($this->settings, 'requires_confirmation.condition.unit', 'minutes');
834 + $conditionValue = Arr::get($this->settings, 'requires_confirmation.condition.value', 0);
835 +
836 + $conditionTime = $conditionValue * 60;
837 + if ($conditionUnit == 'hours') {
838 + $conditionTime = $conditionTime * 60;
839 + } elseif ($conditionUnit == 'days') {
840 + $conditionTime = $conditionTime * 60 * 24;
678 841 }
679 - return false;
842 +
843 + return $bookingStartTime - $bookingCreatedTime < $conditionTime;
680 844 }
681 845
682 846 public function getCanNotCancelSettings()
683 847 {
@@ -716,11 +880,13 @@
716 880
717 881 return LocationService::getLocationIconHeadingHtml($default, $this);
718 882 }
719 883
720 - public function defaultPaymentIcon($currency, $amount)
884 + public function defaultPaymentIcon($amount, $currencySettings = [])
721 885 {
722 - $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>';
886 + $formattedAmount = $currencySettings ? fluentbookingFormattedAmount((float)$amount * 100, $currencySettings) : $amount;
887 + $svg = '<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>';
888 + $html = '<span class="fcal_slot_payment_icon">' . $svg . $formattedAmount . '</span>';
723 889 return $html;
724 890 }
725 891
726 892 public function isPaymentEnabled($duration = null)
@@ -728,9 +894,9 @@
728 894 if ($this->isMultiDurationEnabled()) {
729 895 $paymentSettings = $this->getPaymentSettings();
730 896 if (Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes') {
731 897 $duration = $duration ?? $this->getDefaultDuration();
732 - if (!Arr::get($paymentSettings, 'multi_payment_items.'. $duration .'.value')) {
898 + if (!Arr::get($paymentSettings, 'multi_payment_items.' . $duration . '.value')) {
733 899 return false;
734 900 }
735 901 }
736 902 }
@@ -737,13 +903,25 @@
737 903
738 904 return $this->type == 'paid' && Helper::isPaymentEnabled();
739 905 }
740 906
907 + public function isPaidEvent()
908 + {
909 + $paymentSettings = $this->getPaymentSettings();
910 +
911 + return $this->type != 'free' && Arr::get($paymentSettings, 'enabled') == 'yes';
912 + }
913 +
741 914 public function isWooEnabled()
742 915 {
743 916 return $this->type == 'woo' && defined('WC_PLUGIN_FILE');
744 917 }
745 918
919 + public function isCartEnabled()
920 + {
921 + return $this->type == 'cart' && defined('FLUENTCART_VERSION');
922 + }
923 +
746 924 public function getPaymentItems($duration = null)
747 925 {
748 926 $paymentSettings = $this->getPaymentSettings();
749 927
@@ -749,31 +927,50 @@
749 927
750 928 $isMultiEnabled = Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes';
751 929
752 930 if ($this->isMultiDurationEnabled() && $isMultiEnabled) {
753 - $duration = $duration ?? $this->getDefaultDuration();
754 - return [Arr::get($paymentSettings, 'multi_payment_items.'. $duration)];
931 + $duration = $duration ?: $this->getDefaultDuration();
932 + return [Arr::get($paymentSettings, 'multi_payment_items.' . $duration)];
755 933 }
756 934
757 935 return Arr::get($paymentSettings, 'items', []);
758 936 }
759 937
760 - public function getPricingTotal()
938 + public function getEventPrice($duration = null)
761 939 {
940 + if (!$this->isPaidEvent()) {
941 + return 0;
942 + }
943 +
944 + $paymentSettings = $this->getPaymentSettings();
945 +
946 + if ($this->isCartEnabled()) {
947 + return CartHelper::getCartProductPrice($paymentSettings, $duration, false);
948 + }
949 +
950 + if ($this->isWooEnabled()) {
951 + return $this->getWooProductPrice($duration);
952 + }
953 +
954 + return $this->getPricingTotal($duration);
955 + }
956 +
957 + public function getPricingTotal($duration = null)
958 + {
762 959 if (!$this->isPaymentEnabled()) {
763 960 return 0;
764 961 }
765 962
766 963 $total = 0;
767 - $items = $this->getPaymentItems();
964 + $items = $this->getPaymentItems($duration);
768 965 foreach ($items as $item) {
769 - $total += (int)$item['value'];
966 + $total += $item['value'];
770 967 }
771 968
772 969 return $total;
773 970 }
774 971
775 - public function getWooProductPrice()
972 + public function getWooProductPrice($duration = null)
776 973 {
777 974 $paymentSettings = $this->getPaymentSettings();
778 975
779 976 $productId = $paymentSettings['woo_product_id'];
@@ -778,9 +975,9 @@
778 975
779 976 $productId = $paymentSettings['woo_product_id'];
780 977
781 978 if (Arr::get($paymentSettings, 'multi_payment_enabled') == 'yes') {
782 - $duration = $this->getDefaultDuration();
979 + $duration = $duration ?? $this->getDefaultDuration();
783 980 $productId = Arr::get($paymentSettings, 'multi_payment_woo_ids.' . $duration);
784 981 }
785 982
786 983 $price = 0;
@@ -787,9 +984,9 @@
787 984 $product = wc_get_product($productId);
788 985 if ($product) {
789 986 $price = $product->get_price();
790 987 }
791 -
988 +
792 989 return $price;
793 990 }
794 991
795 992 public function getWooProductPriceByDuration($productIds = [])
@@ -799,9 +996,9 @@
799 996 foreach ($productIds as $duration => $productId) {
800 997 $product = wc_get_product($productId);
801 998 if ($product) {
802 999 $productPrices[$duration] = [
803 - 'value' => $product->get_price()
1000 + 'value' => wc_price($product->get_price())
804 1001 ];
805 1002 }
806 1003 }
807 1004
@@ -807,8 +1004,28 @@
807 1004
808 1005 return $productPrices;
809 1006 }
810 1007
1008 + public function getPaymentHtml()
1009 + {
1010 + $paymentHtml = '';
1011 +
1012 + $driver = Arr::get($this->getPaymentSettings(), 'driver');
1013 +
1014 + if ($driver == 'native' && $this->isPaymentEnabled()) {
1015 + $currencySettings = CurrenciesHelper::getGlobalCurrencySettings();
1016 + $totalPayment = $this->getPricingTotal();
1017 + $paymentHtml = $this->defaultPaymentIcon($totalPayment, $currencySettings);
1018 + }
1019 +
1020 + if ($driver == 'woo' && $this->isWooEnabled()) {
1021 + $totalPayment = wc_price($this->getWooProductPrice());
1022 + $paymentHtml = $this->defaultPaymentIcon($totalPayment);
1023 + }
1024 +
1025 + return $paymentHtml;
1026 + }
1027 +
811 1028 public function isTeamDefaultSchedule()
812 1029 {
813 1030 if ($this->isTeamEvent()) {
814 1031 if (!Arr::isTrue($this->settings, 'common_schedule', false)) {
@@ -827,16 +1044,23 @@
827 1044 }
828 1045 return false;
829 1046 }
830 1047
831 - public function isRoundRobinDefaultSchedule() {
1048 + public function isRoundRobinDefaultSchedule()
1049 + {
832 1050 return $this->isRoundRobin() && $this->isTeamDefaultSchedule();
833 1051 }
834 1052
835 - public function isRoundRobinCommonSchedule() {
1053 + public function isRoundRobinCommonSchedule()
1054 + {
836 1055 return $this->isRoundRobin() && $this->isTeamCommonSchedule();
837 1056 }
838 1057
1058 + public function isCollectiveDefaultSchedule()
1059 + {
1060 + return $this->isCollective() && $this->isTeamDefaultSchedule();
1061 + }
1062 +
839 1063 private function getProcessedWeeklySlots($schedule)
840 1064 {
841 1065 $scheduleData = Arr::get($schedule, 'value.weekly_schedules', []);
842 1066 $scheduleTimezone = Arr::get($schedule, 'value.timezone', 'UTC');
@@ -856,18 +1080,20 @@
856 1080
857 1081 public function getWeeklySlots($hostId = null)
858 1082 {
859 1083 if ($hostId && !$this->isTeamCommonSchedule()) {
860 - $schedule = AvailabilityService::getDefaultSchedule($hostId);
1084 + $schedule = $this->getHostSchedule($hostId);
861 1085 return $this->getProcessedWeeklySlots($schedule);
862 1086 }
863 1087
864 1088 if ($this->availability_type === 'existing_schedule') {
865 - $schedule = Availability::findOrFail($this->availability_id);
866 - return $this->getProcessedWeeklySlots($schedule);
1089 + $schedule = Availability::find($this->availability_id);
1090 + if ($schedule) {
1091 + return $this->getProcessedWeeklySlots($schedule);
1092 + }
867 1093 }
868 1094
869 - $scheduleData = Arr::get($this->settings,'weekly_schedules',[]);
1095 + $scheduleData = Arr::get($this->settings, 'weekly_schedules', []);
870 1096 $schedule = SanitizeService::weeklySchedules($scheduleData, 'UTC', $this->calendar->author_timezone);
871 1097 return AvailabilityService::getUtcWeeklySchedules($schedule, $this->calendar->author_timezone);
872 1098 }
873 1099
@@ -873,18 +1099,20 @@
873 1099
874 1100 public function getDateOverrides($hostId = null)
875 1101 {
876 1102 if ($hostId && !$this->isTeamCommonSchedule()) {
877 - $schedule = AvailabilityService::getDefaultSchedule($hostId);
1103 + $schedule = $this->getHostSchedule($hostId);
878 1104 return $this->getProcessedDateOverrides($schedule);
879 1105 }
880 1106
881 1107 if ($this->availability_type === 'existing_schedule') {
882 - $schedule = Availability::findOrFail($this->availability_id);
883 - return $this->getProcessedDateOverrides($schedule);
1108 + $schedule = Availability::find($this->availability_id);
1109 + if ($schedule) {
1110 + return $this->getProcessedDateOverrides($schedule);
1111 + }
884 1112 }
885 1113
886 - $scheduleData = Arr::get($this->settings,'date_overrides',[]);
1114 + $scheduleData = Arr::get($this->settings, 'date_overrides', []);
887 1115 $schedule = SanitizeService::slotDateOverrides($scheduleData, 'UTC', $this->calendar->author_timezone);
888 1116 $overrideSlots = AvailabilityService::getUtcDateOverrides($schedule, $this->calendar->author_timezone);
889 1117 $overrideDays = AvailabilityService::getDateOverrideDays($schedule, $this->calendar->author_timezone);
890 1118 return [$overrideSlots, $overrideDays];
@@ -899,10 +1127,10 @@
899 1127 }
900 1128
901 1129 $hostBookings = [];
902 1130 foreach ($hostIds as $hostId) {
903 - $dayStart = gmdate('Y-m-d 00:00:00',strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
904 - $dayEnd = gmdate('Y-m-d 23:59:59',strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1131 + $dayStart = gmdate('Y-m-d 00:00:00', strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1132 + $dayEnd = gmdate('Y-m-d 23:59:59', strtotime($startDate)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
905 1133 $hostBookings[$hostId] = Booking::getHostTotalBooking($this->id, [$hostId], [$dayStart, $dayEnd]);
906 1134 }
907 1135 usort($hostIds, function ($a, $b) use ($hostBookings) {
908 1136 return $hostBookings[$a] - $hostBookings[$b];
@@ -921,8 +1149,9 @@
921 1149 'enabled' => 'no',
922 1150 'multi_payment_enabled' => 'no',
923 1151 'stripe_enabled' => 'no',
924 1152 'paypal_enabled' => 'no',
1153 + 'offline_enabled' => 'no',
925 1154 'driver' => 'native',
926 1155 'items' => [
927 1156 [
928 1157 'title' => __('Booking Fee', 'fluent-booking'),
@@ -929,8 +1158,9 @@
929 1158 'value' => 100
930 1159 ]
931 1160 ],
932 1161 'woo_product_id' => '',
1162 + 'cart_product_id' => '',
933 1163 'multi_payment_items' => [
934 1164 $duration => [
935 1165 'title' => __('Booking Fee', 'fluent-booking'),
936 1166 'value' => 0
@@ -937,24 +1167,49 @@
937 1167 ]
938 1168 ],
939 1169 'multi_payment_woo_ids' => [
940 1170 $duration => ''
1171 + ],
1172 + 'multi_payment_cart_ids' => [
1173 + $duration => ''
941 1174 ]
942 1175 ];
943 1176
1177 + $defaults = apply_filters('fluent_booking/event_payment_settings_defaults', $defaults, $this);
1178 +
944 1179 if (!$settings) {
945 1180 $settings = $defaults;
946 1181 }
947 1182
948 - return wp_parse_args($settings, $defaults);
1183 + $settings = wp_parse_args($settings, $defaults);
1184 +
1185 + return apply_filters('fluent_booking/get_event_payment_settings', $settings, $this);
949 1186 }
950 1187
1188 + public function getHostSchedule($hostId)
1189 + {
1190 + $hostSchedules = Arr::get($this->settings, 'hosts_schedules', []);
1191 + if (isset($hostSchedules[$hostId])) {
1192 + return Availability::find($hostSchedules[$hostId]);
1193 + }
1194 + return AvailabilityService::getDefaultSchedule($hostId);
1195 + }
1196 +
1197 + public function getHostsSchedules() {
1198 + $hostIds = $this->getHostIds();
1199 + $hostSchedules = Arr::get($this->settings, 'hosts_schedules', []);
1200 + foreach ($hostIds as $hostId) {
1201 + $hostSchedules[$hostId] = $hostSchedules[$hostId] ?? AvailabilityService::getDefaultSchedule($hostId)['id'];
1202 + }
1203 + return $hostSchedules;
1204 + }
1205 +
951 1206 public function getCalendarEventsMeta()
952 1207 {
953 1208 $eventsMeta = Meta::where('object_id', $this->id)
954 1209 ->where('object_type', 'calendar_event')
955 1210 ->get();
956 -
1211 +
957 1212 return $eventsMeta;
958 1213 }
959 1214
960 1215 public function getIntegrationsMeta()
@@ -961,9 +1216,9 @@
961 1216 {
962 1217 $integrationsMeta = Meta::where('object_id', $this->id)
963 1218 ->where('object_type', 'integration')
964 1219 ->get();
965 -
1220 +
966 1221 return $integrationsMeta;
967 1222 }
968 1223
969 1224 /**