PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.13
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.13
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / FormBuilder / Components / DateTime.php

DateTime.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.13, at app/Services/FormBuilder/Components/DateTime.php

218 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\FormBuilder\Components;
4
5 defined('ABSPATH') || die;
6
7 use FluentForm\App\Helpers\Helper;
8 use FluentForm\Framework\Helpers\ArrayHelper;
9
10 class DateTime extends BaseComponent
11 {
12 /**
13 * Compile and echo the html element
14 *
15 * @param array $data [element data]
16 * @param \stdClass $form [Form Object]
17 *
18 * @return void
19 */
20 public function compile($data, $form)
21 {
22 $elementName = $data['element'];
23 $data = apply_filters_deprecated(
24 'fluentform_rendering_field_data_' . $elementName,
25 [
26 $data,
27 $form,
28 ],
29 FLUENTFORM_FRAMEWORK_UPGRADE,
30 'fluentform/rendering_field_data_' . $elementName,
31 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName
32 );
33 $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form);
34
35 wp_enqueue_script('flatpickr');
36 wp_enqueue_style('flatpickr');
37
38 $data['attributes']['class'] = trim(
39 'ff-el-form-control ff-el-datepicker ' . $data['attributes']['class']
40 );
41 $dateFormat = $data['settings']['date_format'];
42
43 $data['attributes']['id'] = $this->makeElementId($data, $form);
44
45 if ($tabIndex = Helper::getNextTabIndex()) {
46 $data['attributes']['tabindex'] = $tabIndex;
47 }
48
49 $atts = $this->buildAttributes($data['attributes']);
50
51 $ariaRequired = 'false';
52 if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) {
53 $ariaRequired = 'true';
54 }
55 $id = $data['attributes']['id'];
56
57 $ariaLabel = esc_html__(' Use arrow keys to navigate dates. Press enter to select a date.', 'fluentform');
58 $label = ArrayHelper::get($data, 'settings.label');
59 // SECURITY (FINDING-12): esc_attr the settings.label before interpolating it into the
60 // single-quoted aria-label; the save-time wp_kses does not encode quotes, so an unescaped
61 // label allows an attribute breakout (stored XSS).
62 $elMarkup = "<input aria-label='" . esc_attr($label) . $ariaLabel . "' aria-haspopup='dialog' data-type-datepicker data-format='" . esc_attr($dateFormat) . "' " . $atts . " aria-invalid='false' aria-required={$ariaRequired}>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $atts is escaped before being passed in.
63 $config = $this->getDateFormatConfigJSON($data['settings'], $form);
64 $customConfig = $this->getCustomConfig($data['settings'], $form);
65 $this->loadToFooter($config, $customConfig, $form, $id);
66 $html = $this->buildElementMarkup($elMarkup, $data, $form);
67
68 $html = apply_filters_deprecated(
69 'fluentform_rendering_field_html_' . $elementName,
70 [
71 $html,
72 $data,
73 $form,
74 ],
75 FLUENTFORM_FRAMEWORK_UPGRADE,
76 'fluentform/rendering_field_html_' . $elementName,
77 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName
78 );
79
80 $this->printContent('fluentform/rendering_field_html_' . $elementName, $html, $data, $form);
81 }
82
83 public function getAvailableDateFormats()
84 {
85 $dateFormats = apply_filters('fluentform/available_date_formats', [
86 'm/d/Y' => 'm/d/Y - (Ex: 04/28/2018)', // USA
87 'd/m/Y' => 'd/m/Y - (Ex: 28/04/2018)', // Canada, UK
88 'd.m.Y' => 'd.m.Y - (Ex: 28.04.2019)', // Germany
89 'n/j/y' => 'n/j/y - (Ex: 4/28/18)',
90 'm/d/y' => 'm/d/y - (Ex: 04/28/18)',
91 'M/d/Y' => 'M/d/Y - (Ex: Apr/28/2018)',
92 'y/m/d' => 'y/m/d - (Ex: 18/04/28)',
93 'Y-m-d' => 'Y-m-d - (Ex: 2018-04-28)',
94 'd-M-y' => 'd-M-y - (Ex: 28-Apr-18)',
95 'm/d/Y h:i K' => 'm/d/Y h:i K - (Ex: 04/28/2018 08:55 PM)', // USA
96 'm/d/Y H:i' => 'm/d/Y H:i - (Ex: 04/28/2018 20:55)', // USA
97 'd/m/Y h:i K' => 'd/m/Y h:i K - (Ex: 28/04/2018 08:55 PM)', // Canada, UK
98 'd/m/Y H:i' => 'd/m/Y H:i - (Ex: 28/04/2018 20:55)', // Canada, UK
99 'd.m.Y h:i K' => 'd.m.Y h:i K - (Ex: 28.04.2019 08:55 PM)', // Germany
100 'd.m.Y H:i' => 'd.m.Y H:i - (Ex: 28.04.2019 20:55)', // Germany
101 'h:i K' => 'h:i K (Only Time Ex: 08:55 PM)',
102 'H:i' => 'H:i (Only Time Ex: 20:55)',
103 ]);
104
105 $formatted = [];
106 foreach ($dateFormats as $format => $label) {
107 $formatted[] = [
108 'label' => $label,
109 'value' => $format,
110 ];
111 }
112 return $formatted;
113 }
114
115 public function getDateFormatConfigJSON($settings, $form)
116 {
117 $dateFormat = ArrayHelper::get($settings, 'date_format');
118
119 if (! $dateFormat) {
120 $dateFormat = 'm/d/Y';
121 }
122
123 $hasTime = $this->hasTime($dateFormat);
124 $time24 = false;
125
126 if ($hasTime && false !== strpos($dateFormat, 'H')) {
127 $time24 = true;
128 }
129
130 $config = apply_filters('fluentform/frontend_date_format', [
131 'dateFormat' => $dateFormat,
132 'ariaDateFormat' =>'F j, Y',
133 'enableTime' => $hasTime,
134 'noCalendar' => ! $this->hasDate($dateFormat),
135 'disableMobile' => true,
136 'time_24hr' => $time24,
137 ], $settings, $form);
138
139 return json_encode($config, JSON_FORCE_OBJECT);
140 }
141
142 public function getCustomConfig($settings, $form = null)
143 {
144 $customConfigObject = fluentform_sanitize_json_object(
145 (string) ArrayHelper::get($settings, 'date_config')
146 );
147
148 // Emitted JS is rebuilt from validated data tokens (ints only) — the raw setting never reaches the script sink.
149 $customConfigObject = fluentform_date_config_to_js($customConfigObject);
150
151 $customConfigObject = '' !== $customConfigObject ? $customConfigObject : '{}';
152
153 return apply_filters('fluentform/date_time_custom_config', $customConfigObject, $settings, $form);
154 }
155
156 private function loadToFooter($config, $customConfigObject, $form, $id)
157 {
158 add_action('wp_footer', function () use ($config, $customConfigObject, $id, $form) {
159 ?>
160 <script type="text/javascript">
161 jQuery(document).ready(function($) {
162 function initPicker() {
163 if (typeof flatpickr == 'undefined') {
164 return;
165 }
166 flatpickr.localize(window.fluentFormVars.date_i18n);
167 var config = <?php echo fluentform_kses_js($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $config is escaped using fluentform_kses_js ?> ;
168 try {
169 var customConfig = <?php echo fluentform_kses_js($customConfigObject); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $config is escaped using fluentform_kses_js ?>;
170 } catch (e) {
171 var customConfig = {};
172 }
173
174 var config = $.extend({}, config, customConfig);
175 if (!config.locale) {
176 config.locale = 'default';
177 }
178 if (jQuery('#<?php echo esc_attr($id); ?>').length) {
179 flatpickr('#<?php echo esc_attr($id); ?>', config);
180 }
181 }
182 initPicker();
183 $(document).on(
184 'reInitExtras',
185 '.<?php echo esc_attr($form->instance_css_class); ?>',
186 function() {
187 initPicker();
188 }
189 );
190 });
191 </script>
192 <?php
193 }, 99999);
194 }
195
196 private function hasTime($string)
197 {
198 $timeStrings = ['H', 'h', 'G', 'i', 'S', 's', 'K'];
199 foreach ($timeStrings as $timeString) {
200 if (false != strpos($string, $timeString)) {
201 return true;
202 }
203 }
204 return false;
205 }
206
207 private function hasDate($string)
208 {
209 $dateStrings = ['d', 'D', 'l', 'j', 'J', 'w', 'W', 'F', 'm', 'n', 'M', 'U', 'Y', 'y', 'Z'];
210 foreach ($dateStrings as $dateString) {
211 if (false != strpos($string, $dateString)) {
212 return 'true';
213 }
214 }
215 return false;
216 }
217 }
218