PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.10.01
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.10.01
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
fluent-booking / app / Services / Integrations / FluentCRM / Bootstrap.php

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

445 lines 15.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\Services\Integrations\FluentCRM;
4
5 use FluentCrm\App\Models\Tag;
6 use FluentCrm\App\Models\Lists;
7 use FluentCrm\App\Models\Subscriber;
8 use FluentBooking\Framework\Support\Arr;
9 use FluentCrm\App\Models\CustomContactField;
10 use FluentBooking\App\Http\Controllers\IntegrationManagerController;
11
12 class Bootstrap extends IntegrationManagerController
13 {
14 public $hasGlobalMenu = false;
15
16 public $disableGlobalSettings = 'yes';
17
18 public function __construct()
19 {
20 parent::__construct(
21 __('FluentCRM', 'fluent-booking'),
22 'fluentcrm',
23 '_fluent_booking_fluentcrm_settings',
24 'fluentcrm_feeds',
25 10
26 );
27
28 $this->logo = FLUENTCRM_PLUGIN_URL . 'assets/images/fluentcrm-logo.svg';
29
30 $this->description = __('Connect FluentCRM with Fluent Booking and subscribe a contact when a booking is created.', 'fluent-booking');
31
32 $this->registerAdminHooks();
33
34 add_filter('fluent_booking/notifying_async_fluentcrm', '__return_false');
35 }
36
37 public function pushIntegration($integrations, $calendarEventId)
38 {
39 $integrations[$this->integrationKey] = [
40 'title' => $this->title . ' ' . __('Integration', 'fluent-booking'),
41 'logo' => $this->logo,
42 'is_active' => $this->isConfigured(),
43 'configure_title' => __('Configuration required!', 'fluent-booking'),
44 'global_configure_url' => '#',
45 'configure_message' => __('FluentCRM is not configured yet! Please configure your FluentCRM api first', 'fluent-booking'),
46 'configure_button_text' => __('Set FluentCRM', 'fluent-booking'),
47 ];
48
49 return $integrations;
50 }
51
52 public function getIntegrationDefaults($settings, $calendarEventId)
53 {
54 return [
55 'name' => '',
56 'first_name' => '{{guest.first_name}}',
57 'last_name' => '{{guest.last_name}}',
58 'email' => '{{guest.email}}',
59 'other_fields' => [
60 [
61 'item_value' => '',
62 'label' => '',
63 ],
64 ],
65 'list_ids' => '',
66 'tag_ids' => [],
67 'skip_if_exists' => false,
68 'double_opt_in' => false,
69 'force_subscribe' => false,
70 'skip_primary_data' => false,
71 'conditionals' => [
72 'conditions' => [],
73 'status' => false,
74 'type' => 'all',
75 ],
76 'run_events_only' => [],
77 'remove_tags' => [],
78 'enabled' => true,
79 ];
80 }
81
82 public function getSettingsFields($settings, $slotId)
83 {
84 $fieldOptions = [];
85
86 foreach (Subscriber::mappables() as $key => $column) {
87 $fieldOptions[$key] = $column;
88 }
89
90 foreach ((new CustomContactField)->getGlobalFields()['fields'] as $field) {
91 $fieldOptions[$field['slug']] = $field['label'];
92 }
93
94 $fieldOptions['avatar'] = __('Profile Photo', 'fluent-booking');
95
96 unset($fieldOptions['email']);
97 unset($fieldOptions['first_name']);
98 unset($fieldOptions['last_name']);
99 unset($fieldOptions['prefix']);
100 unset($fieldOptions['full_name']);
101 unset($fieldOptions['company_id']);
102
103 $fields = [
104 [
105 'key' => 'name',
106 'label' => __('Feed Name', 'fluent-booking'),
107 'required' => true,
108 'placeholder' => __('Your Feed Name', 'fluent-booking'),
109 'component' => 'text',
110 ],
111 [
112 'key' => 'CustomFields',
113 'require_list' => false,
114 'label' => __('Map Primary Fields', 'fluent-booking'),
115 'tips' => __('Associate your FluentCRM merge tags to the appropriate Fluent Form fields by selecting the appropriate form field from the list.', 'fluent-booking'),
116 'component' => 'map_fields',
117 'field_label_remote' => __('FluentCRM Field', 'fluent-booking'),
118 'field_label_local' => __('Booking Field', 'fluent-booking'),
119 'primary_fields' => [
120 [
121 'key' => 'email',
122 'label' => __('Email Address', 'fluent-booking'),
123 'required' => true,
124 'input_options' => 'emails',
125 ],
126 [
127 'key' => 'first_name',
128 'label' => __('First Name', 'fluent-booking'),
129 ],
130 [
131 'key' => 'last_name',
132 'label' => __('Last Name', 'fluent-booking'),
133 ]
134 ],
135 ],
136 [
137 'key' => 'other_fields',
138 'require_list' => false,
139 'label' => __('Other Fields', 'fluent-booking'),
140 'tips' => __('Select which Fluent Form fields pair with their<br /> respective FlunentCRM fields.', 'fluent-booking'),
141 'component' => 'dropdown_many_fields',
142 'field_label_remote' => __('FluentCRM Field', 'fluent-booking'),
143 'field_label_local' => __('Form Field', 'fluent-booking'),
144 'options' => $fieldOptions,
145 ],
146 [
147 'key' => 'list_ids',
148 'label' => __('FluentCRM Lists', 'fluent-booking'),
149 'placeholder' => __('Select FluentCRM Lists', 'fluent-booking'),
150 'tips' => __('Select the FluentCRM Lists you would like to add your contacts to.', 'fluent-booking'),
151 'component' => 'select',
152 'is_multiple' => true,
153 'required' => false,
154 'options' => $this->getLists(),
155 ],
156 [
157 'key' => 'tag_ids',
158 'require_list' => false,
159 'label' => __('Contact Tags', 'fluent-booking'),
160 'placeholder' => __('Select Tags', 'fluent-booking'),
161 'component' => 'select',
162 'is_multiple' => true,
163 'options' => $this->getTags(),
164 ],
165 [
166 'key' => 'skip_if_exists',
167 'require_list' => false,
168 'checkbox_label' => __('Skip if contact already exist in FluentCRM', 'fluent-booking'),
169 'component' => 'checkbox-single',
170 ],
171 [
172 'key' => 'skip_primary_data',
173 'require_list' => false,
174 'checkbox_label' => __('Skip name update if existing contact have old data (per primary field)', 'fluent-booking'),
175 'component' => 'checkbox-single',
176 ],
177 [
178 'key' => 'double_opt_in',
179 'require_list' => false,
180 'checkbox_label' => __('Enable Double opt-in for new contacts', 'fluent-booking'),
181 'component' => 'checkbox-single',
182 ],
183 [
184 'key' => 'force_subscribe',
185 'require_list' => false,
186 'checkbox_label' => __('Enable Force Subscribe if contact is not in subscribed status (Existing contact only)', 'fluent-booking'),
187 'component' => 'checkbox-single',
188 'inline_tip' => __('If you enable this then contact will forcefully subscribed no matter in which status that contact had', 'fluent-booking'),
189 ],
190 [
191 'require_list' => false,
192 'required' => true,
193 'key' => 'event_trigger',
194 'options' => [
195 'after_booking_scheduled' => __('Booking Confirmed', 'fluent-booking'),
196 'booking_schedule_completed' => __('Booking Completed', 'fluent-booking'),
197 'booking_schedule_cancelled' => __('Booking Canceled', 'fluent-booking'),
198 'after_booking_rescheduled' => __('Booking Rescheduled', 'fluent-booking'),
199 'booking_schedule_rejected' => __('Booking Rejected', 'fluent-booking'),
200 ],
201 'tips' => __('Select in which booking stage you want to trigger this feed', 'fluent-booking'),
202 'label' => __('Event Trigger', 'fluent-booking'),
203 'component' => 'checkbox-multiple-text',
204 'checkbox_label' => __('Event Trigger For This Feed', 'fluent-booking'),
205 ]
206 ];
207
208 $fields[] = [
209 'require_list' => false,
210 'key' => 'remove_tags',
211 'label' => __('Remove Contact Tags', 'fluent-booking'),
212 'placeholder' => __('Select Tags (remove from contact)', 'fluent-booking'),
213 'tips' => __('(Optional) The selected tags will be removed from the contact (if exist)', 'fluent-booking'),
214 'component' => 'select',
215 'is_multiple' => true,
216 'required' => false,
217 'options' => $this->getTags(),
218 ];
219
220 $fields[] = [
221 'require_list' => false,
222 'key' => 'enabled',
223 'label' => __('Status', 'fluent-booking'),
224 'component' => 'checkbox-single',
225 'checkbox_label' => __('Enable This feed', 'fluent-booking'),
226 ];
227
228 return [
229 'fields' => $fields,
230 'button_require_list' => false,
231 'integration_title' => $this->title,
232 ];
233 }
234
235 public function getMergeFields($list, $listId, $slotId)
236 {
237 return [];
238 }
239
240 public function getConfigFieldOptions($settings, $slotId)
241 {
242 return [];
243 }
244
245 protected function getLists()
246 {
247 $lists = Lists::orderBy('title', 'ASC')->get();
248 $formattedLists = [];
249 foreach ($lists as $list) {
250 $formattedLists[$list->id] = $list->title;
251 }
252
253 return $formattedLists;
254 }
255
256 protected function getTags()
257 {
258 $tags = Tag::orderBy('title', 'ASC')->get();
259 $formattedTags = [];
260 foreach ($tags as $tag) {
261 $formattedTags[strval($tag->id)] = $tag->title;
262 }
263
264 return $formattedTags;
265 }
266
267 /*
268 * Submission Hooks Here
269 */
270 public function notify($feed, $booking, $calendarEvent)
271 {
272 $data = $feed['processedValues'];
273 $contact = Arr::only($data, ['first_name', 'last_name', 'email']);
274
275 if (empty($contact['email'])) {
276 return false;
277 }
278
279 foreach (Arr::get($data, 'other_fields') as $field) {
280 if ($field['item_value']) {
281 $contact[$field['label']] = $field['item_value'];
282 }
283 }
284
285 if ($booking->ip_address) {
286 $contact['ip'] = $booking->ip_address;
287 }
288
289 if (!is_email($contact['email'])) {
290 $this->addLog(
291 $feed['settings']['name'],
292 __('FluentCRM API called skipped because no valid email available', 'fluent-booking'),
293 $booking->id,
294 'failed'
295 );
296 return false;
297 }
298
299 $subscriber = Subscriber::where('email', $contact['email'])->first();
300 if ($subscriber && Arr::isTrue($data, 'skip_if_exists')) {
301 $this->addLog(
302 $feed['settings']['name'],
303 __('Contact creation has been skipped because contact already exist in the database', 'fluent-booking'),
304 $booking->id,
305 'failed'
306 );
307 return false;
308 }
309
310 if (!empty($contact['avatar'])) {
311 // validate the avatar photo
312 $validUrl = '';
313 if (false !== filter_var($contact['avatar'], FILTER_VALIDATE_URL)) {
314 $url = $contact['avatar'];
315 $dots = explode('.', $url);
316 $ext = strtolower(end($dots));
317
318 if (in_array($ext, ['png', 'jpg', 'jpeg', 'webp', 'gif'])) {
319 $validUrl = $contact['avatar'];
320 }
321 }
322
323 if (!$validUrl) {
324 unset($contact['avatar']);
325 }
326 }
327
328 if ($subscriber) {
329 if ($subscriber->ip && isset($contact['ip'])) {
330 unset($contact['ip']);
331 }
332
333 if (Arr::isTrue($data, 'skip_primary_data')) {
334 if ($subscriber->first_name) {
335 unset($contact['first_name']);
336 unset($contact['last_name']);
337 }
338 }
339 } else {
340 if (empty($contact['source'])) {
341 $contact['source'] = 'FluentBooking';
342 }
343 if (Arr::isTrue($data, 'double_opt_in')) {
344 $contact['status'] = 'pending';
345 } else {
346 $contact['status'] = 'subscribed';
347 }
348 }
349
350 $user = get_user_by('email', $contact['email']);
351 if ($user) {
352 $contact['user_id'] = $user->ID;
353 }
354
355 if (!empty($data['tag_ids'])) {
356 $contact['tags'] = $data['tag_ids'];
357 }
358
359 if (!empty($data['list_ids'])) {
360 $contact['lists'] = $data['list_ids'];
361 }
362
363 if (!$subscriber) {
364 if (Arr::isTrue($data, 'double_opt_in')) {
365 $contact['status'] = 'pending';
366 } else {
367 $contact['status'] = 'subscribed';
368 }
369
370 $subscriber = FluentCrmApi('contacts')->createOrUpdate($contact, false, false);
371
372 if (!$subscriber) {
373 return false;
374 }
375
376 if ($subscriber->status == 'pending') {
377 $subscriber->sendDoubleOptinEmail();
378 }
379
380 if ($removeTags = Arr::get($feed, 'settings.remove_tags', [])) {
381 $subscriber->detachTags($removeTags);
382 }
383
384 $this->addLog(
385 $feed['settings']['name'],
386 __('Contact has been created in FluentCRM. Contact ID: ', 'fluent-booking') . $subscriber->id,
387 $booking->id,
388 'success'
389 );
390
391 do_action('fluent_crm/contact_added_by_fluent_booking', $subscriber, $booking, $calendarEvent, $feed);
392 return true;
393 }
394
395 // We have subscriber here
396
397 $hasDouBleOptIn = Arr::isTrue($data, 'double_opt_in');
398
399 $forceSubscribed = !$hasDouBleOptIn && ($subscriber->status != 'subscribed');
400
401 if (!$forceSubscribed) {
402 $forceSubscribed = Arr::isTrue($data, 'force_subscribe');
403 }
404
405 if ($forceSubscribed) {
406 $contact['status'] = 'subscribed';
407 }
408
409 $subscriber = FluentCrmApi('contacts')->createOrUpdate($contact, $forceSubscribed, false);
410
411 if (!$subscriber) {
412 return false;
413 }
414
415 if ($hasDouBleOptIn && ($subscriber->status == 'pending' || $subscriber->status == 'unsubscribed')) {
416 $subscriber->sendDoubleOptinEmail();
417 }
418
419 do_action('fluent_crm/contact_added_by_fluent_booking', $subscriber, $booking, $calendarEvent, $feed);
420
421 if ($removeTags = Arr::get($feed, 'settings.remove_tags', [])) {
422 $subscriber->detachTags($removeTags);
423 }
424
425 $this->addLog(
426 $feed['settings']['name'],
427 __('Contact has been updated in FluentCRM. Contact ID: ', 'fluent-booking') . $subscriber->id,
428 $booking->id,
429 'success'
430 );
431
432 return true;
433 }
434
435 public function isConfigured()
436 {
437 return true;
438 }
439
440 public function isEnabled()
441 {
442 return true;
443 }
444 }
445