PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.2.5
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.2.5
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 / Http / Controllers / SchedulesController.php

SchedulesController.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.2.5, at app/Http/Controllers/SchedulesController.php

781 lines 26.9 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\Http\Controllers;
4
5 use FluentBooking\App\Models\Booking;
6 use FluentBooking\App\Models\Calendar;
7 use FluentBooking\App\Models\CalendarSlot;
8 use FluentBooking\App\Models\BookingActivity;
9 use FluentBooking\Framework\Database\Orm\ModelNotFoundException;
10 use FluentBooking\App\Services\EmailNotificationService;
11 use FluentBooking\App\Services\Helper;
12 use FluentBooking\Framework\Support\Arr;
13 use FluentBooking\App\Services\CurrenciesHelper;
14 use FluentBooking\Framework\Http\Request\Request;
15 use FluentBooking\App\Services\PermissionManager;
16 use FluentBooking\App\Services\CalendarService;
17 use FluentBooking\App\Services\ExportHelper;
18 use FluentBooking\App\Services\Integrations\FluentCRM\CrmContactService;
19 use FluentBooking\App\Services\Integrations\FluentCart\CustomerProfileService;
20 use FluentCrm\App\Services\PermissionManager as CrmPermissionManager;
21
22 class SchedulesController extends Controller
23 {
24 public function index(Request $request)
25 {
26 $author = $this->resolveAuthor($request);
27
28 $query = $this->buildSchedulesQuery($request, $author);
29
30 $query->groupBy('group_id');
31
32 $schedules = $query->paginate();
33
34 foreach ($schedules as $schedule) {
35 $this->formatBooking($schedule);
36 }
37
38 $data = [
39 'schedules' => $schedules,
40 'timezone' => 'UTC'
41 ];
42
43 $data['calendar_event_lists'] = CalendarService::getCalendarOptionsByTitle();
44
45 if ($author == 'me') {
46 $slotOptions = CalendarService::getSlotOptions(null, get_current_user_id());
47 $data['slot_options'] = $slotOptions;
48 }
49
50 if ($request->get('page') == 1) {
51 $this->addCountsForFirstPage($author, $data);
52 }
53
54 return $data;
55 }
56
57 public function export(Request $request)
58 {
59 $limit = (int) apply_filters('fluent_booking/data_export_limit', 2000);
60
61 $author = $this->resolveAuthor($request);
62
63 $query = $this->buildSchedulesQuery($request, $author);
64
65 $relations = [
66 'calendar_event',
67 'user',
68 'booking_activities' => function ($q) {
69 $q->where('type', 'cancel_reason');
70 },
71 'booking_meta',
72 ];
73
74 if (defined('FLUENT_BOOKING_PRO_DIR_FILE')) {
75 $relations[] = 'payment_order.transaction';
76 }
77
78 $query->with($relations);
79
80 $total = (clone $query)->withoutEagerLoads()->count();
81 $limited = $total > $limit;
82
83 $bookings = $query->take($limit)->get();
84
85 $rows = $bookings->map(function ($booking) {
86 $row = ExportHelper::mapBooking($booking);
87 return apply_filters('fluent_booking/booking_export_row', $row, $booking);
88 })->all();
89
90 $rows = apply_filters('fluent_booking/booking_export_columns', $rows, $bookings);
91
92 return [
93 'bookings' => $rows,
94 'limited' => $limited,
95 'total' => $total,
96 ];
97 }
98
99 protected function resolveAuthor(Request $request)
100 {
101 $author = Arr::get($request->get('filters', []), 'author');
102
103 if (is_numeric($author)) {
104 $author = (int) $author;
105 } else {
106 $author = sanitize_text_field($author);
107 }
108
109 $hasPermission = PermissionManager::userCanSeeAllBookings();
110
111 if ($hasPermission) {
112 return $author;
113 }
114
115 if (!$author || $author == 'all') {
116 $authorCalendar = Calendar::where('user_id', get_current_user_id())
117 ->where('type', 'simple')
118 ->first();
119
120 $author = $authorCalendar ? $authorCalendar->id : '';
121 }
122
123 return $author;
124 }
125
126 protected function buildSchedulesQuery(Request $request, $author = null)
127 {
128 $filters = $request->get('filters', []);
129 $search = $request->getSafe('search');
130 $eventVal = Arr::get($filters, 'event');
131 $eventId = is_numeric($eventVal) ? (int) $eventVal : 0;
132 $eventType = sanitize_text_field(Arr::get($filters, 'event_type'));
133 $period = sanitize_text_field(Arr::get($filters, 'period', 'upcoming'));
134 $range = array_map('sanitize_text_field', Arr::get($filters, 'range', []));
135 $email = sanitize_email(Arr::get($filters, 'email', ''));
136
137 $allowedPeriods = ['upcoming', 'completed', 'cancelled', 'pending', 'no_show', 'latest_bookings', 'all'];
138 if (!in_array($period, $allowedPeriods, true)) {
139 $period = 'upcoming';
140 }
141
142 $query = Booking::with(['calendar_event']);
143
144 $hasPermission = PermissionManager::userCanSeeAllBookings();
145
146 if (!$hasPermission || $author == 'me') {
147 $query->where('host_user_id', get_current_user_id());
148 }
149
150 if ($author && $author !== 'all') {
151 if ($author != 'me') {
152 $query->where('calendar_id', $author);
153 }
154 if ($eventId > 0) {
155 $query->where('event_id', $eventId);
156 }
157 if ($eventType && $eventType !== 'all') {
158 $query->where('event_type', $eventType);
159 }
160 }
161
162 if (!empty($email) && is_email($email)) {
163 $query->where('email', $email);
164 }
165
166 do_action_ref_array('fluent_booking/schedules_query', [&$query]);
167
168 $query->applyDateRangeFilter($range);
169 $query->applyComputedStatus($period);
170 $query->applyBookingOrderByStatus($period);
171
172 if (!empty($search)) {
173 $query->searchBy($search);
174 }
175
176 return $query;
177 }
178
179 private function addCountsForFirstPage($author, &$data)
180 {
181 $bookingQuery = Booking::query()
182 ->when(!PermissionManager::userCanSeeAllBookings() || $author == 'me', function($query) {
183 return $query->where('host_user_id', get_current_user_id());
184 })
185 ->when($author && is_numeric($author), function($query) use ($author) {
186 return $query->where('calendar_id', $author);
187 })
188 ->distinct('group_id');
189
190 $data['pending_count'] = (clone $bookingQuery)->whereIn('status', ['pending', 'reserved'])->count('group_id');
191 $data['no_show_count'] = (clone $bookingQuery)->where('status', 'no_show')->count('group_id');
192 $data['cancelled_count'] = (clone $bookingQuery)->where('status', 'cancelled')->count('group_id');
193 }
194
195 public function patchBooking(Request $request, $bookingId)
196 {
197 $booking = Booking::findOrFail($bookingId);
198 $oldBooking = clone $booking;
199
200 $data = $request->all();
201
202 $this->validate($data, [
203 'column' => 'required',
204 ]);
205
206 do_action('fluent_booking/before_patch_booking_schedule', $booking, $data);
207
208 $value = $request->get('value');
209
210 $column = $data['column'];
211
212 if ($booking->{$column} == $value) {
213 return $this->sendError(['message' => __('No changes found', 'fluent-booking')]);
214 }
215
216 $validColumns = [
217 'internal_note',
218 'email',
219 'phone',
220 'first_name',
221 'last_name',
222 'status',
223 'payment_status'
224 ];
225
226 if (!in_array($column, $validColumns)) {
227 return $this->sendError(['message' => __('Invalid column', 'fluent-booking')]);
228 }
229
230 if ($column === 'email') {
231 if (!$value || !is_email($value)) {
232 return $this->sendError(['message' => __('Invalid email address', 'fluent-booking')]);
233 }
234 $value = sanitize_email($value);
235 } else {
236 $value = sanitize_text_field($value);
237 }
238
239 if ($column == 'status') {
240 if (!in_array($value, ['scheduled', 'completed', 'cancelled', 'rejected', 'no_show'])) {
241 return $this->sendError(['message' => __('Invalid status', 'fluent-booking')]);
242 }
243
244 if ($value == 'scheduled' && $booking->payment_method && $booking->payment_order) {
245 $order = $booking->payment_order;
246 $order->total_paid = $order->total_amount;
247 $order->completed_at = gmdate('Y-m-d H:i:s'); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
248 $order->status = 'paid';
249 $order->save();
250
251 $updateData['payment_status'] = 'paid';
252
253 do_action('fluent_booking/log_booking_activity', $this->getPaymentPaidLog($booking->id));
254
255 do_action('fluent_booking/payment/update_payment_status_paid', $booking);
256
257 } else if ($value == 'scheduled') {
258 do_action('fluent_booking/log_booking_activity', $this->getConfirmLog($booking->id));
259 }
260
261 if ($value == 'cancelled') {
262 $cancelReason = sanitize_text_field($data['cancel_reason']);
263 $booking->cancelMeeting($cancelReason, 'host', get_current_user_id());
264 }
265
266 if ($value == 'rejected') {
267 $rejectReason = sanitize_text_field($data['reject_reason']);
268 $booking->rejectMeeting($rejectReason, get_current_user_id());
269 }
270
271 if (in_array($value, ['cancelled', 'rejected'])) {
272 if ($booking->payment_method && Arr::get($data, 'refund_payment') == 'yes') {
273 do_action('fluent_booking/refund_payment_' . $booking->payment_method, $booking, $booking->calendar_event);
274 }
275 return [
276 /* translators: %s: Booking status */
277 'message' => sprintf(__('The booking has been %s', 'fluent-booking'), $value)
278 ];
279 }
280
281 $updateAll = Arr::isTrue($data, 'update_all') && $booking->isMultiGuestBooking();
282
283 if ($updateAll && in_array($value, ['no_show', 'completed'])) {
284 Booking::where('event_id', $booking->event_id)
285 ->where('group_id', $booking->group_id)
286 ->update([
287 'status' => $value
288 ]);
289 return [
290 /* translators: %s: Booking status */
291 'message' => sprintf(__('The booking has been %s', 'fluent-booking'), $value)
292 ];
293 }
294 }
295
296 if ($column == 'payment_status') {
297 if (!in_array($value, ['pending', 'paid'])) {
298 return $this->sendError(['message' => __('Invalid payment status', 'fluent-booking')]);
299 }
300
301 if ($value == 'paid') {
302 do_action('fluent_booking/log_booking_activity', $this->getPaymentPaidLog($booking->id));
303 }
304
305 if ($value == 'pending') {
306 do_action('fluent_booking/log_booking_activity', $this->getPaymentPendingLog($booking->id));
307 }
308
309 if ($booking->payment_order) {
310 do_action('fluent_booking/payment/status_changed', $booking->payment_order, $booking, $value);
311 }
312 }
313
314 $updateData[$column] = $value;
315 $booking->fill($updateData);
316 $booking->save();
317
318 if ($column === 'status') {
319 do_action('fluent_booking/booking_schedule_' . $value, $booking, $booking->calendar_event);
320
321 do_action('fluent_booking/pre_after_booking_' . $value, $booking, $booking->calendar_event);
322
323 $booking = Booking::with(['calendar_event', 'calendar'])->find($booking->id);
324
325 do_action('fluent_booking/after_booking_' . $value, $booking, $booking->calendar_event, $booking);
326 }
327
328 do_action('fluent_booking/after_patch_booking_schedule', $booking, $oldBooking);
329
330 do_action('fluent_booking/after_patch_booking_' . $column, $booking, $booking->calendar_event, $oldBooking->{$column});
331
332 return [
333 /* translators: Updated column name */
334 'message' => sprintf(__('%s has been updated', 'fluent-booking'), ucfirst($column))
335 ];
336 }
337
338 public function getBooking(Request $request, $bookingId)
339 {
340 $booking = Booking::with('calendar_event');
341
342 if (!PermissionManager::userCanSeeAllBookings()) {
343 $booking->whereHostAccess(get_current_user_id());
344 }
345
346 $booking = $booking->findOrFail($bookingId);
347 $booking = $this->formatBooking($booking);
348
349 do_action_ref_array('fluent_booking/booking_schedule', [&$booking]);
350
351 $data = [
352 'schedule' => $booking
353 ];
354
355 if (in_array('all_data', $this->request->get('with', []))) {
356 $data = array_merge($data, $this->getBookingMetaInfo($request, $bookingId));
357 }
358
359 return $data;
360 }
361
362 public function deleteBooking(Request $request, $bookingId)
363 {
364 $booking = Booking::findOrFail($bookingId);
365
366 do_action('fluent_booking/before_delete_booking', $booking);
367
368 $booking->delete();
369
370 do_action('fluent_booking/after_delete_booking', $bookingId);
371
372 if ($booking->isMultiGuestBooking()) {
373 Booking::where('event_id', $booking->event_id)->where('group_id', $booking->group_id)->delete();
374 }
375
376 return [
377 'message' => __('Booking Deleted Successfully!', 'fluent-booking')
378 ];
379 }
380
381 public function sendConfirmationEmail(Request $request, $bookingId)
382 {
383 $booking = Booking::with(['calendar', 'calendar_event'])->findOrFail($bookingId);
384
385 $emailTo = $request->get('email_to', 'guest');
386
387 $notifications = $booking->calendar_event->getNotifications();
388
389 $email = Arr::get($notifications, 'booking_conf_attendee.email', []);
390 if ($emailTo == 'host') {
391 $email = Arr::get($notifications, 'booking_conf_host.email', []);
392 }
393
394 $result = EmailNotificationService::emailOnBooked($booking, $email, $emailTo, 'scheduled', true);
395
396 if (!$result) {
397 return $this->sendError(['message' => __('Notification sending failed', 'fluent-booking')]);
398 }
399
400 return [
401 'message' => __('Notification sent successfully', 'fluent-booking')
402 ];
403 }
404
405 public function getGroupAttendees(Request $request, $groupId)
406 {
407 $booking = Booking::with('slot');
408
409 if (!PermissionManager::userCanSeeAllBookings()) {
410 $booking->whereHostAccess(get_current_user_id());
411 }
412
413 $booking = $booking->where('group_id', $groupId)->first();
414
415 if (!$booking || !$booking->isMultiGuestBooking()) {
416 return $this->sendError(['message' => __('Invalid group id or the event is not a group event', 'fluent-booking')]);
417 }
418
419 $attendees = Booking::where('group_id', $booking->group_id);
420 $search = $request->getSafe('search');
421
422 if (!empty($search)) {
423 $attendees = $attendees->searchBy($search);
424 }
425 $attendees = $attendees->paginate();
426
427 foreach ($attendees as $attendee) {
428 $attendee = $this->formatBooking($attendee);
429 }
430
431 return [
432 'attendees' => $attendees
433 ];
434 }
435
436 public function getBookingActivities(Request $request, $bookingId)
437 {
438 $this->resolveOwnedBookingOrFail($bookingId);
439
440 $activities = BookingActivity::where('booking_id', $bookingId)
441 ->orderBy('id', 'DESC')
442 ->get();
443
444 return [
445 'activities' => $activities
446 ];
447 }
448
449 public function getBookingMetaInfo(Request $request, $bookingId)
450 {
451 $booking = $this->resolveOwnedBookingOrFail($bookingId);
452
453 $activities = BookingActivity::where('booking_id', $booking->id)
454 ->orderBy('id', 'DESC')
455 ->get();
456
457 $activities->each(function ($activity) {
458 $activity->description = wp_unslash($activity->description);
459 });
460
461 $sidebarContents = [];
462 $mainBodyContents = [];
463
464 $canReadCrm = CrmContactService::isActive() && CrmPermissionManager::currentUserCan('fcrm_read_contacts');
465 $crmProfile = $canReadCrm ? CrmContactService::getProfileData($booking->email) : null;
466 if ($crmProfile) {
467 $sidebarContents[] = [
468 'id' => 'fluent_crm_profule',
469 'title' => __('CRM Profile', 'fluent-booking'),
470 'type' => 'crm_profile',
471 'profile' => $crmProfile,
472 ];
473 }
474
475 $cartProfile = CustomerProfileService::canView()
476 ? CustomerProfileService::getProfileData($booking->email)
477 : null;
478 if ($cartProfile) {
479 $sidebarContents[] = [
480 'id' => 'fluent_cart_profile',
481 'title' => __('Cart Profile', 'fluent-booking'),
482 'type' => 'cart_profile',
483 'profile' => $cartProfile,
484 ];
485 }
486
487 $order = null;
488 if ($booking->payment_status && $booking->payment_order) {
489 $order = $booking->payment_order;
490 $relations = ['items', 'transaction'];
491 if (method_exists($order, 'discounts')) {
492 $relations[] = 'discounts';
493 }
494 $order->load($relations);
495 $order->currency_sign = CurrenciesHelper::getCurrencySign($order->currency);
496 }
497
498 $mainBodyContents = apply_filters('fluent_booking/booking_meta_info_main_meta', $mainBodyContents, $booking);
499 $mainBodyContents = apply_filters('fluent_booking/booking_meta_info_main_meta_' . $booking->source, $mainBodyContents, $booking);
500
501 return [
502 'activities' => $activities,
503 'sidebar_contents' => $sidebarContents,
504 'payment_order' => $order,
505 'main_body_contents' => $mainBodyContents
506 ];
507 }
508
509 /**
510 * Return the CRM contact state for a booking plus the full tag/list option
511 * sets, so the admin can manage tags/lists inline from the CRM Profile card.
512 */
513 public function getCrmContact(Request $request, $bookingId)
514 {
515 $booking = $this->resolveOwnedBookingOrFail($bookingId);
516
517 if (!CrmContactService::isActive()) {
518 return $this->sendError([
519 'message' => __('FluentCRM is not active.', 'fluent-booking')
520 ]);
521 }
522
523 if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) {
524 return $this->sendError([
525 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking')
526 ], 403);
527 }
528
529 $state = CrmContactService::getContactState($booking->email);
530
531 if (!$state) {
532 return $this->sendError([
533 'message' => __('No CRM contact found for this booking.', 'fluent-booking')
534 ], 404);
535 }
536
537 return $state;
538 }
539
540 /**
541 * Guest-field prefill for the CRM "Book Appointment" action.
542 * Keyed by contact id, so it carries its own CRM-read gate.
543 */
544 public function getCrmContactPrefill(Request $request)
545 {
546 if (!CrmContactService::isActive()) {
547 return $this->sendError([
548 'message' => __('FluentCRM is not active.', 'fluent-booking')
549 ]);
550 }
551
552 if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) {
553 return $this->sendError([
554 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking')
555 ], 403);
556 }
557
558 $contactId = absint($request->get('contact_id'));
559
560 if (!$contactId) {
561 return $this->sendError([
562 'message' => __('Invalid contact.', 'fluent-booking')
563 ], 422);
564 }
565
566 $prefill = CrmContactService::getBookingPrefillData($contactId);
567
568 if (!$prefill) {
569 return $this->sendError([
570 'message' => __('No CRM contact found.', 'fluent-booking')
571 ], 404);
572 }
573
574 return [
575 'prefill' => $prefill,
576 ];
577 }
578
579 /**
580 * Typeahead search for the admin booking modal's CRM contact picker.
581 * Same intersection gate as getCrmContactPrefill: booking access (policy) AND fcrm_read_contacts.
582 */
583 public function searchCrmContacts(Request $request)
584 {
585 if (!CrmContactService::isActive()) {
586 return $this->sendError([
587 'message' => __('FluentCRM is not active.', 'fluent-booking')
588 ]);
589 }
590
591 if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) {
592 return $this->sendError([
593 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking')
594 ], 403);
595 }
596
597 $search = sanitize_text_field($request->get('search', ''));
598
599 return [
600 'contacts' => CrmContactService::searchContacts($search),
601 ];
602 }
603
604 /**
605 * Bounded, searchable tag/list options for the CRM Profile picker.
606 */
607 public function getCrmOptions(Request $request, $bookingId)
608 {
609 $this->resolveOwnedBookingOrFail($bookingId);
610
611 if (!CrmContactService::isActive()) {
612 return $this->sendError([
613 'message' => __('FluentCRM is not active.', 'fluent-booking')
614 ]);
615 }
616
617 if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) {
618 return $this->sendError([
619 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking')
620 ], 403);
621 }
622
623 $type = $request->get('type') === 'lists' ? 'lists' : 'tags';
624 $search = sanitize_text_field($request->get('search', ''));
625
626 return [
627 'options' => CrmContactService::getOptions($type, $search),
628 ];
629 }
630
631 public function updateCrmTags(Request $request, $bookingId)
632 {
633 return $this->updateCrmTaxonomy($request, $bookingId, 'tags');
634 }
635
636 public function updateCrmLists(Request $request, $bookingId)
637 {
638 return $this->updateCrmTaxonomy($request, $bookingId, 'lists');
639 }
640
641 private function updateCrmTaxonomy(Request $request, $bookingId, $type)
642 {
643 $booking = $this->resolveOwnedBookingOrFail($bookingId);
644
645 if (!CrmContactService::isActive()) {
646 return $this->sendError([
647 'message' => __('FluentCRM is not active.', 'fluent-booking')
648 ]);
649 }
650
651 if (!CrmPermissionManager::currentUserCan('fcrm_manage_contacts')) {
652 return $this->sendError([
653 'message' => __('You do not have permission to manage CRM contacts.', 'fluent-booking')
654 ], 403);
655 }
656
657 $requestKey = $type === 'tags' ? 'tag_ids' : 'list_ids';
658 $desired = (array) $request->get($requestKey, []);
659
660 $result = CrmContactService::syncTaxonomy($booking->email, $type, $desired);
661
662 if ($result === null) {
663 return $this->sendError([
664 'message' => __('No CRM contact found for this booking.', 'fluent-booking')
665 ], 404);
666 }
667
668 return $this->sendSuccess(array_merge([
669 'message' => __('CRM contact updated successfully.', 'fluent-booking'),
670 ], $result));
671 }
672
673 private function resolveOwnedBookingOrFail($bookingId)
674 {
675 $booking = Booking::findOrFail($bookingId);
676
677 if (PermissionManager::userCanSeeAllBookings()) {
678 return $booking;
679 }
680
681 $allowedIds = $booking->getHostIds();
682
683 if (PermissionManager::userCan('manage_own_calendar')) {
684 if ($event = CalendarSlot::find($booking->event_id)) {
685 $allowedIds = array_merge($allowedIds, $event->getHostIds());
686 }
687 }
688
689 if (in_array(get_current_user_id(), $allowedIds)) {
690 return $booking;
691 }
692
693 $exception = new ModelNotFoundException();
694 $exception->setModel(Booking::class, [$bookingId]);
695 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
696 throw $exception;
697 }
698
699 private function formatBooking(&$booking)
700 {
701 $autoCompleteTimeOut = (int) Helper::getGlobalAdminSetting('auto_complete_timing', 60) * 60; // 10 minutes
702
703 if (in_array($booking->status, ['scheduled', 'pending']) && (time() - strtotime($booking->end_time)) > $autoCompleteTimeOut) {
704 $bookingStatus = $booking->status == 'pending' ? 'cancelled' : 'completed';
705 $booking->status = $bookingStatus;
706 $booking->save();
707 $hookName = $bookingStatus === 'cancelled' ? 'auto_cancelled' : $bookingStatus;
708 do_action('fluent_booking/booking_schedule_' . $hookName, $booking, $booking->calendar_event);
709 }
710
711 if ($booking->isMultiHostBooking()) {
712 $booking->host_profiles = $booking->getHostProfiles();
713 }
714
715 if ($booking->isMultiGuestBooking()) {
716 $booking->booked_count = Booking::where('group_id', $booking->group_id)
717 ->whereIn('status', ['scheduled', 'completed'])->count();
718 } else {
719 $booking->additional_guests = $booking->getAdditionalGuests();
720 }
721
722 $booking->title = $booking->getBookingTitle(true);
723 $booking->author = $booking->getHostDetails(false);
724 $booking->details = $booking->getConfirmationData(true);
725 $booking->location = $booking->getLocationDetailsHtml();
726 $booking->reschedule_url = $booking->getRescheduleUrl();
727 $booking->happening_status = $booking->getOngoingStatus();
728 $booking->booking_status_text = $booking->getBookingStatus();
729 $booking->payment_status_text = $booking->getPaymentStatus();
730 $booking->custom_form_data = $booking->getCustomFormData();
731
732 do_action_ref_array('fluent_booking/format_booking_schedule', [&$booking]);
733
734 return $booking;
735 }
736
737 private function getConfirmedBy()
738 {
739 $confirmedBy = 'host';
740 $userId = get_current_user_id();
741 if ($userId && $user = get_user_by('ID', $userId)) {
742 $confirmedBy = $user->display_name;
743 }
744
745 return $confirmedBy;
746 }
747
748 private function getPaymentPaidLog($bookingId)
749 {
750 return [
751 'booking_id' => $bookingId,
752 'status' => 'closed',
753 'type' => 'success',
754 'title' => __('Payment Successfully Completed', 'fluent-booking'),
755 'description' => __('Payment marked as paid by ', 'fluent-booking') . $this->getConfirmedBy()
756 ];
757 }
758
759 private function getPaymentPendingLog($bookingId)
760 {
761 return [
762 'booking_id' => $bookingId,
763 'status' => 'closed',
764 'type' => 'success',
765 'title' => __('Payment Successfully Marked as Pending', 'fluent-booking'),
766 'description' => __('Payment marked as pending by ', 'fluent-booking') . $this->getConfirmedBy()
767 ];
768 }
769
770 private function getConfirmLog($bookingId)
771 {
772 return [
773 'booking_id' => $bookingId,
774 'status' => 'closed',
775 'type' => 'success',
776 'title' => __('Booking Confirmed', 'fluent-booking'),
777 'description' => __('Booking has been confirmed by ', 'fluent-booking') . $this->getConfirmedBy()
778 ];
779 }
780 }
781