PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.3.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.3.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 1.7.2 All 33 releases
fluent-booking / app / Services / Integrations / FluentCRM / FluentCrmInit.php

FluentCrmInit.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.3.0, at app/Services/Integrations/FluentCRM/FluentCrmInit.php

196 lines 6.6 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\Services\Integrations\FluentCRM;
4
5 use FluentBooking\App\Models\Booking;
6 use FluentBooking\Framework\Support\Arr;
7 use FluentBooking\App\Services\DateTimeHelper;
8 use FluentCrm\App\Models\Subscriber;
9 use FluentCrm\App\Services\Html\TableBuilder;
10 use FluentCrm\App\Services\PermissionManager as CrmPermissionManager;
11
12 class FluentCrmInit
13 {
14 public function __construct()
15 {
16 $this->registerHooks();
17 $this->registerIntegrations();
18
19 // Contextual SmartCodes
20 (new CrmSmartCode())->register();
21
22 add_filter('fluent_crm_asset_listed_slugs', function ($lists) {
23 $lists[] = 'fluent-booking';
24 return $lists;
25 });
26 }
27
28 public function registerIntegrations()
29 {
30 $this->addAutomations();
31 }
32
33 public function registerHooks()
34 {
35 add_filter('fluentcrm_profile_sections', [$this, 'addProfileSection'], 10, 1);
36 add_filter('fluencrm_profile_section_fluent_booking', [$this, 'getProfileSection'], 10, 2);
37 }
38
39 public function addAutomations()
40 {
41 new NewBookingTrigger();
42 new CancelBookingTrigger();
43 new BookingCompletedTrigger();
44 new BookingRescheduledTrigger();
45 }
46
47 public function addProfileSection($sections)
48 {
49 $sections['booking'] = [
50 'name' => 'fluentcrm_profile_extended',
51 'title' => __('Bookings', 'fluent-booking'),
52 'handler' => 'route',
53 'query' => [
54 'handler' => 'fluent_booking'
55 ],
56 ];
57
58 return $sections;
59 }
60
61 public function getProfileSection($sections, Subscriber $contact)
62 {
63 if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) {
64 return $sections;
65 }
66
67 $sections['heading'] = __('Bookings (Fluent Booking)', 'fluent-booking');
68
69 $limit = (int) apply_filters('fluent_booking/crm_meetings_limit', 20);
70 $limit = max(1, $limit);
71
72 $email = strtolower(trim((string) $contact->email));
73
74 $base = Booking::where('email', $email);
75
76 $total = (clone $base)->count();
77
78 $meetings = (clone $base)
79 ->with(['slot', 'calendar', 'calendar.metas'])
80 ->orderBy('start_time', 'DESC')
81 ->limit($limit)
82 ->get();
83
84 $rows = [];
85 $hostCache = [];
86 foreach ($meetings as $meeting) {
87 if (!$meeting->calendar || !$meeting->slot) {
88 continue;
89 }
90 $cid = $meeting->calendar->id;
91 if (!isset($hostCache[$cid])) {
92 $hostCache[$cid] = $meeting->calendar->getAuthorProfile();
93 }
94
95 $rows[] = apply_filters('fluent_booking/crm_meeting_data', $this->mapMeetingRow($meeting, $hostCache[$cid]), $meeting);
96 }
97
98 $response = apply_filters('fluent_booking/crm_meetings_response', [
99 'total' => $total,
100 'data' => $rows,
101 'columns_config' => [
102 'id' => ['label' => __('ID', 'fluent-booking'), 'width' => '100px'],
103 'title' => ['label' => __('Event', 'fluent-booking')],
104 'status' => ['label' => __('Status', 'fluent-booking'), 'width' => '150px'],
105 'meeting_at' => ['label' => __('Meeting At', 'fluent-booking'), 'width' => '200px'],
106 'action' => ['label' => __('Action', 'fluent-booking'), 'width' => '100px'],
107 ],
108 ], $meetings, $contact);
109
110 $bookButton = $this->getBookAppointmentButton($contact);
111
112 if (empty($response['data'])) {
113 $sections['content_html'] = $bookButton . '<p style="padding:0 20px;">' . esc_html__('No scheduled meetings found for this contact.', 'fluent-booking') . '</p>';
114 return $sections;
115 }
116
117 $header = [];
118 foreach ($response['columns_config'] as $key => $col) {
119 $header[$key] = Arr::get($col, 'label', ucfirst($key));
120 }
121
122 $table = new TableBuilder();
123 $table->setHeader($header);
124 foreach ($response['data'] as $row) {
125 $table->addRow($row);
126 }
127
128 $sections['content_html'] = $bookButton . $table->getHtml() . $this->getViewAllLink($contact, $total, $limit);
129
130 return $sections;
131 }
132
133 private function getBookAppointmentButton(Subscriber $contact)
134 {
135 $url = admin_url('admin.php?page=fluent-booking#/scheduled-events?new_booking=1&crm_contact_id=' . (int) $contact->id);
136
137 return '<p class="fcal_crm_book_appointment" style="padding:0px 20px;margin-top:-36px;text-align:end;">'
138 . '<a class="el-button el-button--small" target="_blank" rel="noopener noreferrer" href="' . esc_url($url) . '">'
139 . esc_html__('Book Appointment', 'fluent-booking')
140 . '</a></p>';
141 }
142
143 private function mapMeetingRow($meeting, $host)
144 {
145 $groupRef = $meeting->group_id ?: $meeting->id;
146
147 return [
148 'id' => '#' . $groupRef,
149 'title' => $this->getBookingTitle($meeting, $host),
150 'status' => $meeting->status,
151 'meeting_at' => $this->getFormattedTime($meeting),
152 'action' => $this->getActionUrl($meeting),
153 ];
154 }
155
156 private function getViewAllLink(Subscriber $contact, $total, $limit)
157 {
158 if ($total <= $limit) {
159 return '';
160 }
161
162 $url = admin_url('admin.php?page=fluent-booking#/scheduled-events?email=' . rawurlencode($contact->email) . '&period=all&author=all');
163
164 return '<p class="fcal_crm_view_all"><a style="color:#2271b1;padding:0 12px;text-decoration:underline" href="' . esc_url($url) . '">'
165 /* translators: %d: total number of meetings */
166 . sprintf(esc_html__('View all meetings (%d)', 'fluent-booking'), (int) $total)
167 . '</a></p>';
168 }
169
170 private function getActionUrl($meeting)
171 {
172 $url = admin_url('admin.php?page=fluent-booking#/scheduled-events?booking_id=' . $meeting->id);
173
174 return '<a target="_blank" href="' . esc_url($url) . '">' . esc_html__('View', 'fluent-booking') . '</a>';
175 }
176
177 private function getFormattedTime($meeting)
178 {
179 return DateTimeHelper::convertToTimeZone($meeting->start_time, 'UTC', $meeting->calendar->author_timezone, 'j M Y, g:i A');
180 }
181
182 private function getBookingTitle($meeting, $host = null)
183 {
184 if ($host === null) {
185 $host = $meeting->calendar->getAuthorProfile();
186 }
187
188 return sprintf(
189 /* translators: 1: meeting title, 2: host name */
190 __('%1$s with %2$s', 'fluent-booking'),
191 (string) $meeting->slot->title,
192 (string) $host['name']
193 );
194 }
195 }
196