PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.25
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.25
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 / BookingFieldService.php

BookingFieldService.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.25, at app/Services/BookingFieldService.php

392 lines 13.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;
4
5 use FluentBooking\App\Models\Booking;
6 use FluentBooking\App\Models\CalendarSlot;
7 use FluentBooking\Framework\Support\Arr;
8
9 class BookingFieldService
10 {
11 public static function getCustomFieldsData($postedData, CalendarSlot $slot)
12 {
13 $customFields = self::getCustomFields($slot, true);
14
15 $errors = [];
16
17 $formattedValues = [];
18
19 foreach ($customFields as $fieldKey => $customField) {
20 $value = wp_unslash(Arr::get($postedData, $fieldKey));
21 if (!$value && Arr::isTrue($customField, 'required')) {
22 // translators: %s is the label of the required field
23 $errors[$fieldKey . '.required'] = sprintf(__('%s is required', 'fluent-booking'), $customField['label']);
24 continue;
25 }
26
27 if (is_array($value)) {
28 if ($customField['type'] === 'multi-select') {
29 $value = array_map(function ($item) {
30 return sanitize_text_field(Arr::get($item, 'value'));
31 },$value);
32 } else if ($customField['type'] === 'file') {
33 $maxField = Arr::get($customField, 'max_file_allow', 1);
34 $value = array_slice($value, 0, $maxField);
35 $value = array_map('sanitize_text_field', $value);
36 } else {
37 $value = array_map('sanitize_text_field', $value);
38 }
39 } else if ($customField['type'] == 'textarea') {
40 $value = sanitize_textarea_field($value);
41 } else {
42 $value = sanitize_text_field($value);
43 }
44
45 $formattedValues[$fieldKey] = $value;
46 }
47
48 if ($errors) {
49 return new \WP_Error('required_field', __('Please fill up the required data', 'fluent-booking'), $errors);
50 }
51
52 return $formattedValues;
53 }
54
55 public static function getBookingFields(CalendarSlot $calendarSlot)
56 {
57 $requiredIndexes = ['name', 'email', 'message', 'cancellation_reason', 'rescheduling_reason'];
58
59 $defaultFields = [
60 'name' => [
61 'index' => 1,
62 'type' => 'text',
63 'name' => 'name',
64 'label' => __('Your Name', 'fluent-booking'),
65 'required' => true,
66 'enabled' => true,
67 'system_defined' => true,
68 'disable_alter' => true,
69 'is_visible' => true,
70 'placeholder' => __('Your Name', 'fluent-booking'),
71 'help_text' => ''
72 ],
73 'email' => [
74 'index' => 2,
75 'type' => 'email',
76 'name' => 'email',
77 'label' => __('Your Email', 'fluent-booking'),
78 'required' => true,
79 'enabled' => true,
80 'system_defined' => true,
81 'disable_alter' => true,
82 'is_visible' => true,
83 'placeholder' => __('Your Email', 'fluent-booking'),
84 'help_text' => ''
85 ],
86 'message' => [
87 'index' => 3,
88 'type' => 'textarea',
89 'name' => 'message',
90 'label' => __('What is this meeting about?', 'fluent-booking'),
91 'required' => false,
92 'enabled' => true,
93 'system_defined' => true,
94 'disable_alter' => false,
95 'help_text' => ''
96 ],
97 'cancellation_reason' => [
98 'index' => 4,
99 'type' => 'textarea',
100 'name' => 'cancellation_reason',
101 'label' => __('Reason for cancellation', 'fluent-booking'),
102 'placeholder' => __('Why are you cancelling?', 'fluent-booking'),
103 'required' => true,
104 'enabled' => true,
105 'system_defined' => true,
106 'disable_alter' => false,
107 'help_text' => ''
108 ],
109 'rescheduling_reason' => [
110 'index' => 5,
111 'type' => 'textarea',
112 'name' => 'rescheduling_reason',
113 'label' => __('Reason for reschedule', 'fluent-booking'),
114 'placeholder' => __('Let others know why you need to reschedule', 'fluent-booking'),
115 'required' => true,
116 'enabled' => true,
117 'system_defined' => true,
118 'disable_alter' => false,
119 'help_text' => ''
120 ],
121 ];
122
123 if ($calendarSlot->isGuestFieldRequired()) {
124 $requiredIndexes[] = 'guests';
125 $defaultFields['guests'] = [
126 'index' => 6,
127 'type' => 'multi-guests',
128 'name' => 'guests',
129 'label' => __('Additional Guests', 'fluent-booking'),
130 'limit' => 10,
131 'required' => false,
132 'enabled' => false,
133 'system_defined' => true,
134 'disable_alter' => false
135 ];
136 }
137 if ($calendarSlot->isLocationFieldRequired()) {
138 $requiredIndexes[] = 'location';
139 $defaultFields['location'] = [
140 'index' => 7,
141 'type' => 'radio',
142 'name' => 'location',
143 'label' => __('Location', 'fluent-booking'),
144 'options' => LocationService::getLocationOptions($calendarSlot),
145 'required' => true,
146 'enabled' => true,
147 'system_defined' => true,
148 'disable_alter' => true,
149 'placeholder' => esc_attr__('Location', 'fluent-booking')
150 ];
151 } else if ($calendarSlot->isPhoneRequired()) {
152 $requiredIndexes[] = 'phone_number';
153 $defaultFields['phone_number'] = [
154 'index' => 8,
155 'type' => 'phone',
156 'name' => 'phone_number',
157 'label' => __('Your Phone Number', 'fluent-booking'),
158 'required' => true,
159 'enabled' => true,
160 'system_defined' => true,
161 'disable_alter' => true,
162 'is_sms_number' => true,
163 'help_text' => ''
164 ];
165 } else if ($calendarSlot->isAddressRequired()) {
166 $requiredIndexes[] = 'address';
167 $defaultFields['address'] = [
168 'index' => 9,
169 'type' => 'text',
170 'name' => 'address',
171 'label' => __('Your Address', 'fluent-booking'),
172 'required' => true,
173 'enabled' => true,
174 'system_defined' => true,
175 'disable_alter' => true,
176 'placeholder' => esc_attr__('Address', 'fluent-booking'),
177 'help_text' => ''
178 ];
179 }
180
181 $dbFields = $calendarSlot->getMeta('booking_fields', []);
182
183 if (!$dbFields) {
184 $dbFields = array_values($defaultFields);
185 }
186
187 $existingFields = [];
188 foreach ($dbFields as $dbField) {
189 $name = $dbField['name'];
190 $existingFields[$name] = $dbField;
191 }
192
193 if (empty($defaultFields['location'])) {
194 unset($existingFields['location']);
195 } else {
196 if (empty($existingFields['location'])) {
197 $existingFields['location'] = $defaultFields['location'];
198 } else {
199 $existingFields['location']['options'] = $defaultFields['location']['options'];
200 }
201 }
202
203 if (empty($defaultFields['phone_number'])) {
204 unset($existingFields['phone_number']);
205 }
206
207 if (empty($defaultFields['address'])) {
208 unset($existingFields['address']);
209 }
210
211 foreach ($requiredIndexes as $index) {
212 if (empty($existingFields[$index]) && !empty($defaultFields[$index])) {
213 $existingFields[$index] = $defaultFields[$index];
214 }
215 }
216
217 $paymentField = apply_filters('fluent_booking/payment_booking_field', [], $calendarSlot, $existingFields);
218
219 if (!$paymentField) {
220 unset($existingFields['payment_method']);
221 } else {
222 $existingFields['payment_method'] = $paymentField;
223 }
224
225 $existingFields['email']['disabled'] = false;
226
227 return array_values($existingFields);
228 }
229
230 public static function getBookingFieldLabels(CalendarSlot $calendarSlot, $enabledOnly = false)
231 {
232 $fields = self::getBookingFields($calendarSlot);
233 $labels = [];
234
235 foreach ($fields as $field) {
236 if ($enabledOnly && !Arr::isTrue($field, 'enabled')) {
237 continue;
238 }
239
240 $labels[$field['name']] = $field['label'];
241 }
242
243 return $labels;
244 }
245
246 public static function generateFieldName($calendarEvent, $fieldLabel)
247 {
248 $fieldName = 'custom_' . sanitize_title($fieldLabel);
249 $bookingFields = self::getBookingFields($calendarEvent);
250
251 $matched = 0;
252 foreach ($bookingFields as $field) {
253 if (strpos($field['name'], $fieldName) !== false) {
254 $matched++;
255 }
256 }
257
258 if ($matched) {
259 $fieldName .= '_' . $matched;
260 }
261 return $fieldName;
262 }
263
264 public static function maybeGenerateFieldName($calendarEvent, $fieldValue)
265 {
266 $bookingFields = self::getBookingFields($calendarEvent);
267
268 foreach ($bookingFields as $field) {
269 if ($field['name'] == $fieldValue['name'] && $field['index'] != $fieldValue['index']) {
270 return self::generateFieldName($calendarEvent, $fieldValue['label']);
271 }
272 }
273
274 return sanitize_text_field($fieldValue['name']);
275 }
276
277 public static function getFormattedCustomBookingData(Booking $booking, $htmlSupport = true, $isPublic = false)
278 {
279 $customFormData = $booking->getMeta('custom_fields_data', []);
280 if (!$customFormData) {
281 return [];
282 }
283
284 $labels = self::getBookingFieldLabels($booking->calendar_event);
285
286 $formattedData = [];
287
288 foreach ($customFormData as $dataKey => $value) {
289 $label = $labels[$dataKey] ?? $dataKey;
290
291 $formattedValue = is_array($value) ? implode(', ', $value) : $value;
292
293 $field = self::getBookingFieldByName($booking->calendar_event, $dataKey);
294
295 $fieldType = Arr::get($field, 'type');
296
297 if ($fieldType == 'file' && is_array($value)) {
298 $formattedValue = self::getUploadedFiles($value, $htmlSupport);
299 }
300
301 if ($fieldType == 'hidden') {
302 if ($isPublic) continue;
303 $formattedValue = EditorShortcodeParser::parse($formattedValue, $booking);
304 }
305
306 $formattedData[$dataKey] = [
307 'label' => $label,
308 'value' => $formattedValue
309 ];
310 }
311
312 return $formattedData;
313 }
314
315 public static function getCustomFields($calendarEvent, $withConfig = false)
316 {
317 $existingFields = $calendarEvent->getMeta('booking_fields', []);
318
319 if (!$existingFields) {
320 return [];
321 }
322
323 $customFields = [];
324
325 foreach ($existingFields as $existingField) {
326 if (Arr::get($existingField, 'system_defined') || !Arr::isTrue($existingField, 'enabled')) {
327 continue;
328 }
329 if ($withConfig) {
330 $customFields[$existingField['name']] = $existingField;
331 } else {
332 $customFields[$existingField['name']] = $existingField['label'];
333 }
334 }
335
336 return $customFields;
337 }
338
339 public static function getBookingFieldByName($calendarEvent, $name)
340 {
341 $fields = self::getBookingFields($calendarEvent);
342
343 foreach ($fields as $field) {
344 if (Arr::get($field, 'name') == $name) {
345 return $field;
346 }
347 }
348
349 return [];
350 }
351
352 public static function hasPhoneNumberField($fields)
353 {
354 if(!$fields) {
355 return false;
356 }
357
358 foreach ($fields as $field) {
359 if ($field['type'] == 'phone') {
360 return true;
361 } else if ($field['name'] == 'location') {
362 if (!empty($field['options'])) {
363 foreach ($field['options'] as $option) {
364 if (Arr::get($option, 'type') == 'phone_guest') {
365 return true;
366 }
367 }
368 }
369 }
370 }
371 return false;
372 }
373
374 public static function getUploadedFiles($fieldValue, $htmlSupport = true)
375 {
376 if (empty($fieldValue)) {
377 return '';
378 }
379
380 $files = array_map(function($file) use ($htmlSupport) {
381 if ($htmlSupport) {
382 return '<a href="' . esc_url($file) . '" target="_blank" download="' . esc_attr(basename($file)) . '">' . esc_html(basename($file)) . '</a>';
383 }
384 return $file;
385 }, $fieldValue);
386
387 $separator = $htmlSupport ? '<br>' : PHP_EOL;
388
389 return implode($separator, $files);
390 }
391 }
392