PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 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 All 197 releases
← All changes | app/Modules/Component/Component.php +1018 -434 3.6.60 → 6.2.15 View file →
@@ -1,15 +1,20 @@
1 1 <?php
2 2
3 3 namespace FluentForm\App\Modules\Component;
4 4
5 +defined('ABSPATH') or die;
6 +
5 7 use FluentForm\App\Helpers\Helper;
6 8 use FluentForm\App\Modules\Acl\Acl;
9 +use FluentForm\App\Modules\Form\FormDataParser;
7 10 use FluentForm\App\Services\FormBuilder\EditorShortcodeParser;
8 11 use FluentForm\App\Services\FormBuilder\Notifications\EmailNotificationActions;
9 12 use FluentForm\Framework\Foundation\Application;
10 13 use FluentForm\Framework\Helpers\ArrayHelper;
14 +use FluentForm\Framework\Helpers\ArrayHelper as Arr;
11 15
16 +
12 17 class Component
13 18 {
14 19 /**
15 20 * FluentForm\Framework\Foundation\Application
@@ -18,8 +23,15 @@
18 23 */
19 24 protected $app = null;
20 25
21 26 /**
27 + * Determine whether to register Elementor PopUp handler.
28 + *
29 + * @var bool
30 + */
31 + protected $elementorPopUpHandler = false;
32 +
33 + /**
22 34 * Biuld the instance of this class
23 35 *
24 36 * @param \FluentForm\Framework\Foundation\Application $app
25 37 */
@@ -33,20 +45,20 @@
33 45 $app = $this->app;
34 46
35 47 // We will just register the scripts here. We will not load any scripts from here
36 48
37 - $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public.css');
38 - $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default.css');
49 + $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public.css');
50 + $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default.css');
39 51
40 52 if (is_rtl()) {
41 - $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public-rtl.css');
42 - $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default-rtl.css');
53 + $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public-rtl.css');
54 + $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default-rtl.css');
43 55 }
44 56
45 57 wp_register_style(
46 58 'fluent-form-styles',
47 59 $fluentFormPublicCss,
48 - array(),
60 + [],
49 61 FLUENTFORM_VERSION
50 62 );
51 63
52 64 wp_register_style(
@@ -51,16 +63,16 @@
51 63
52 64 wp_register_style(
53 65 'fluentform-public-default',
54 66 $fluentFormPublicDefaultCss,
55 - array(),
67 + [],
56 68 FLUENTFORM_VERSION
57 69 );
58 70
59 71 wp_register_script(
60 72 'fluent-form-submission',
61 - $app->publicUrl('js/form-submission.js'),
62 - array('jquery'),
73 + fluentFormMix('js/form-submission.js'),
74 + ['jquery'],
63 75 FLUENTFORM_VERSION,
64 76 true
65 77 );
66 78
@@ -65,33 +77,37 @@
65 77 );
66 78
67 79 wp_register_script(
68 80 'fluentform-advanced',
69 - $app->publicUrl('js/fluentform-advanced.js'),
70 - array('jquery'),
81 + fluentFormMix('js/fluentform-advanced.js'),
82 + ['jquery'],
71 83 FLUENTFORM_VERSION,
72 84 true
73 85 );
74 86
75 87 // Date Pickckr Style
76 - wp_register_style(
77 - 'flatpickr',
78 - $app->publicUrl('libs/flatpickr/flatpickr.min.css')
79 - );
80 -
88 + //fix for essential addon event picker conflict
89 + if (!wp_script_is('flatpickr', 'registered')) {
90 + wp_register_style(
91 + 'flatpickr',
92 + fluentFormMix('libs/flatpickr/flatpickr.min.css'),
93 + [],
94 + '4.6.9'
95 + );
96 + }
81 97 // Date Pickckr Script
82 98 wp_register_script(
83 99 'flatpickr',
84 - $app->publicUrl('libs/flatpickr/flatpickr.js'),
85 - array('jquery'),
86 - false,
100 + fluentFormMix('libs/flatpickr/flatpickr.min.js'),
101 + ['jquery'],
102 + '4.6.9',
87 103 true
88 104 );
89 105
90 106 wp_register_script(
91 107 'choices',
92 - $app->publicUrl('libs/choices/choices.min.js'),
93 - array(),
108 + fluentFormMix('libs/choices/choices.min.js'),
109 + [],
94 110 '9.0.1',
95 111 true
96 112 );
97 113
@@ -96,15 +112,33 @@
96 112 );
97 113
98 114 wp_register_style(
99 115 'ff_choices',
100 - $app->publicUrl('css/choices.css'),
116 + fluentFormMix('css/choices.css'),
101 117 [],
102 118 FLUENTFORM_VERSION
103 119 );
104 120
105 - do_action('fluentform_scripts_registered');
121 + wp_register_script(
122 + 'form-save-progress',
123 + fluentFormMix('js/form-save-progress.js'),
124 + ['jquery'],
125 + FLUENTFORM_VERSION,
126 + true
127 + );
106 128
129 + do_action_deprecated(
130 + 'fluentform_scripts_registered',
131 + [
132 +
133 + ],
134 + FLUENTFORM_FRAMEWORK_UPGRADE,
135 + 'fluentform/scripts_registered',
136 + 'Use fluentform/scripts_registered instead of fluentform_scripts_registered.'
137 + );
138 +
139 + $this->app->doAction('fluentform/scripts_registered');
140 +
107 141 $this->maybeLoadFluentFormStyles();
108 142 }
109 143
110 144 protected function maybeLoadFluentFormStyles()
@@ -110,49 +144,110 @@
110 144 protected function maybeLoadFluentFormStyles()
111 145 {
112 146 global $post;
113 147
114 - if (!$post) {
148 + $postId = isset($post->ID) ? $post->ID : false;
149 + if (!$postId) {
115 150 return;
116 151 }
152 + $fluentFormIds = get_post_meta($postId, '_has_fluentform', true);
153 + $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds;
117 154
118 - $fluentFormIds = get_post_meta($post->ID, '_has_fluentform', true);
119 - $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds;
155 + $loadStyle = apply_filters_deprecated(
156 + 'fluentform_load_styles',
157 + [
158 + false,
159 + $post
160 + ],
161 + FLUENTFORM_FRAMEWORK_UPGRADE,
162 + 'fluentform/load_styles',
163 + 'Use fluentform/load_styles instead of fluentform_load_styles.'
164 + );
120 165
121 - if ($hasFluentformMeta || apply_filters('fluentform_load_styles', false, $post)) {
166 + if ($hasFluentformMeta || apply_filters('fluentform/load_styles', $loadStyle, $post)) {
122 167 wp_enqueue_style('fluent-form-styles');
123 - wp_enqueue_style('fluentform-public-default');
124 - do_action('fluentform_pre_load_scripts', $post);
125 - wp_enqueue_script('fluent-form-submission');
168 + $loadPublicStyle = apply_filters_deprecated(
169 + 'fluentform_load_default_public',
170 + [
171 + true,
172 + (object)[],
173 + $postId
174 + ],
175 + FLUENTFORM_FRAMEWORK_UPGRADE,
176 + 'fluentform/load_default_public',
177 + 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
178 + );
179 +
180 + if (apply_filters('fluentform/load_default_public', $loadPublicStyle, (object)[], $postId)) {
181 + wp_enqueue_style('fluentform-public-default');
182 + }
183 +
184 + do_action_deprecated(
185 + 'fluentform_pre_load_scripts',
186 + [
187 + $post
188 + ],
189 + FLUENTFORM_FRAMEWORK_UPGRADE,
190 + 'fluentform/pre_load_scripts',
191 + 'Use fluentform/pre_load_scripts instead of fluentform_pre_load_scripts.'
192 + );
193 +
194 + $this->app->doAction('fluentform/pre_load_scripts', $post);
195 +
196 + if (!Helper::isElementorEditor()) {
197 + wp_enqueue_script('fluent-form-submission');
198 + }
126 199 }
127 200 }
128 201
129 202 /**
130 203 * Get all the available components
204 + * @deprecated Use \FluentForm\App\Http\Controllers\FormController::resources
205 + * @return void
131 206 *
132 - * @return void
133 207 * @throws \Exception
134 208 * @throws \FluentForm\Framework\Exception\UnResolveableEntityException
135 209 */
136 210 public function index()
137 211 {
138 - $this->app->doAction(
212 + $formId = intval($this->app->request->get('formId'));
213 +
214 + $components = $this->app->make('components');
215 +
216 + do_action_deprecated(
139 217 'fluent_editor_init',
140 - $components = $this->app->make('components')
218 + [
219 + $components
220 + ],
221 + FLUENTFORM_FRAMEWORK_UPGRADE,
222 + 'fluentform/editor_init',
223 + 'Use fluentform/editor_init instead of fluent_editor_init.'
141 224 );
142 225
226 + $this->app->doAction('fluentform/editor_init', $components);
227 +
143 228 $editorComponents = $components->sort()->toArray();
144 - $editorComponents = $this->app->applyFilters('fluent_editor_components', $editorComponents);
145 - $countries = $this->app->load($this->app->appPath('Services/FormBuilder/CountryNames.php'));
146 229
147 - wp_send_json_success(array(
148 - 'countries' => $countries,
149 - 'components' => $editorComponents,
150 - 'disabled_components' => $this->getDisabledComponents()
151 - ));
230 + $editorComponents = apply_filters_deprecated(
231 + 'fluent_editor_components',
232 + [
233 + $editorComponents,
234 + $formId
235 + ],
236 + FLUENTFORM_FRAMEWORK_UPGRADE,
237 + 'fluentform/editor_components',
238 + 'Use fluentform/editor_components instead of fluent_editor_components.'
239 + );
240 +
241 + $editorComponents = apply_filters('fluentform/editor_components', $editorComponents, $formId);
242 +
243 + wp_send_json_success([
244 + 'countries' => getFluentFormCountryList(),
245 + 'components' => $editorComponents,
246 + 'disabled_components' => $this->getDisabledComponents(),
247 + ]);
152 248 }
153 249
154 -
155 250 /**
156 251 * Get disabled components
157 252 *
158 253 * @return array
@@ -159,82 +254,185 @@
159 254 */
160 255 private function getDisabledComponents()
161 256 {
162 257 $isReCaptchaDisabled = !get_option('_fluentform_reCaptcha_keys_status', false);
258 + $isHCaptchaDisabled = !get_option('_fluentform_hCaptcha_keys_status', false);
259 + $isTurnstileDisabled = !get_option('_fluentform_turnstile_keys_status', false);
163 260
164 - $disabled = array(
165 - 'recaptcha' => array(
166 - 'contentComponent' => 'recaptcha',
167 - 'disabled' => $isReCaptchaDisabled
168 - ),
169 - 'input_image' => array(
170 - 'disabled' => true
171 - ),
172 - 'input_file' => array(
173 - 'disabled' => true
174 - ),
175 - 'shortcode' => array(
176 - 'disabled' => true
177 - ),
178 - 'action_hook' => array(
179 - 'disabled' => true
180 - ),
181 - 'form_step' => array(
182 - 'disabled' => true
183 - )
184 - );
261 + $disabled = [
262 + 'recaptcha' => [
263 + 'disabled' => $isReCaptchaDisabled,
264 + 'title' => __('reCaptcha', 'fluentform'),
265 + 'description' => __('Please enter a valid API key on FluentForms->Settings->reCaptcha', 'fluentform'),
266 + 'hidePro' => true,
267 + ],
268 + 'hcaptcha' => [
269 + 'disabled' => $isHCaptchaDisabled,
270 + 'title' => __('hCaptcha', 'fluentform'),
271 + 'description' => __('Please enter a valid API key on FluentForms->Settings->hCaptcha', 'fluentform'),
272 + 'hidePro' => true,
273 + ],
274 + 'turnstile' => [
275 + 'disabled' => $isTurnstileDisabled,
276 + 'title' => __('Turnstile', 'fluentform'),
277 + 'description' => __('Please enter a valid API key on FluentForms->Settings->Turnstile', 'fluentform'),
278 + 'hidePro' => true,
279 + ],
280 + 'input_image' => [
281 + 'disabled' => true,
282 + 'title' => __('Image Upload', 'fluentform'),
283 + 'description' => __('Image Upload is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
284 + 'image' => '',
285 + 'video' => 'https://www.youtube.com/embed/Yb3FSoZl9Zg',
286 + ],
287 + 'input_file' => [
288 + 'disabled' => true,
289 + 'title' => __('File Upload', 'fluentform'),
290 + 'description' => __('File Upload is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
291 + 'image' => '',
292 + 'video' => 'https://www.youtube.com/embed/bXbTbNPM_4k',
293 + ],
294 + 'shortcode' => [
295 + 'disabled' => true,
296 + 'title' => __('Shortcode', 'fluentform'),
297 + 'description' => __('Shortcode is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
298 + 'image' => '',
299 + 'video' => 'https://www.youtube.com/embed/op3mEQxX1MM',
300 + ],
301 + 'action_hook' => [
302 + 'disabled' => true,
303 + 'title' => __('Action Hook', 'fluentform'),
304 + 'description' => __('Action Hook is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
305 + 'image' => fluentformMix('img/pro-fields/action-hook.png'),
306 + 'video' => '',
307 + ],
308 + 'form_step' => [
309 + 'disabled' => true,
310 + 'title' => __('Form Step', 'fluentform'),
311 + 'description' => __('Form Step is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
312 + 'image' => '',
313 + 'video' => 'https://www.youtube.com/embed/VQTWnM6BbRU',
314 + ],
315 + ];
185 316
186 - if (!defined('FLUENTFORMPRO')) {
187 - $disabled['ratings'] = array(
188 - 'disabled' => true
189 - );
190 - $disabled['tabular_grid'] = array(
191 - 'disabled' => true
192 - );
193 - $disabled['phone'] = array(
194 - 'disabled' => true
195 - );
317 + if (!Helper::hasPro()) {
318 + $disabled['ratings'] = [
319 + 'disabled' => true,
320 + 'title' => __('Ratings', 'fluentform'),
321 + 'description' => __('Ratings is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
322 + 'image' => '',
323 + 'video' => 'https://www.youtube.com/embed/YGdkNspMaEs',
324 + ];
325 + $disabled['tabular_grid'] = [
326 + 'disabled' => true,
327 + 'title' => __('Checkable Grid', 'fluentform'),
328 + 'description' => __('Checkable Grid is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
329 + 'image' => '',
330 + 'video' => 'https://www.youtube.com/embed/ayI3TzXXANA',
331 + ];
332 + $disabled['chained_select'] = [
333 + 'disabled' => true,
334 + 'title' => __('Chained Select Field', 'fluentform'),
335 + 'description' => __('Chained Select Field is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
336 + 'image' => fluentformMix('img/pro-fields/chained-select-field.png'),
337 + 'video' => '',
338 + ];
339 + $disabled['phone'] = [
340 + 'disabled' => true,
341 + 'title' => __('Phone Field', 'fluentform'),
342 + 'description' => __('Phone Field is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
343 + 'image' => fluentformMix('img/pro-fields/phone-field.png'),
344 + 'video' => '',
345 + ];
346 + $disabled['rich_text_input'] = [
347 + 'disabled' => true,
348 + 'title' => __('Rich Text Input', 'fluentform'),
349 + 'description' => __('Rich Text Input is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
350 + 'image' => fluentformMix('img/pro-fields/rich-text-input.png'),
351 + 'video' => '',
352 + ];
353 + $disabled['save_progress_button'] = [
354 + 'disabled' => true,
355 + 'title' => __('Save & Resume', 'fluentform'),
356 + 'description' => __('Save & Resume is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
357 + 'image' => fluentformMix('img/pro-fields/save-progress-button.png'),
358 + 'video' => '',
359 + ];
360 + $disabled['cpt_selection'] = [
361 + 'disabled' => true,
362 + 'title' => __('Post/CPT Selection', 'fluentform'),
363 + 'description' => __('Post/CPT Selection is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
364 + 'image' => fluentformMix('img/pro-fields/post-cpt-selection.png'),
365 + 'video' => '',
366 + ];
367 + $disabled['quiz_score'] = [
368 + 'disabled' => true,
369 + 'title' => __('Quiz Score', 'fluentform'),
370 + 'description' => __('Quiz Score is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
371 + 'image' => '',
372 + 'video' => 'https://www.youtube.com/embed/bPjDXR0y_Oo',
373 + ];
374 + $disabled['net_promoter_score'] = [
375 + 'disabled' => true,
376 + 'title' => __('Net Promoter Score', 'fluentform'),
377 + 'description' => __('Net Promoter Score is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
378 + 'image' => fluentformMix('img/pro-fields/net-promoter-score.png'),
379 + 'video' => '',
380 + ];
381 + $disabled['dynamic_field'] = [
382 + 'disabled' => true,
383 + 'title' => __('Dynamic Field', 'fluentform'),
384 + 'description' => __('Dynamic Field is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
385 + 'image' => '',
386 + 'video' => 'https://www.youtube.com/embed/cx3N5y1ddOQ',
387 + ];
388 + $disabled['repeater_field'] = [
389 + 'disabled' => true,
390 + 'title' => __('Repeat Field', 'fluentform'),
391 + 'description' => __('Repeat Field is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
392 + 'image' => '',
393 + 'video' => 'https://www.youtube.com/embed/BXo9Sk-OLnQ',
394 + ];
395 + $disabled['rangeslider'] = [
396 + 'disabled' => true,
397 + 'title' => __('Range Slider', 'fluentform'),
398 + 'description' => __('Range Slider is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
399 + 'image' => '',
400 + 'video' => 'https://www.youtube.com/embed/RaY2VcPWk6I',
401 + ];
402 + $disabled['input_ranking'] = [
403 + 'disabled' => true,
404 + 'title' => __('Ranking Field', 'fluentform'),
405 + 'description' => __('Ranking Field is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
406 + 'image' => '',
407 + 'video' => '',
408 + ];
409 + $disabled['color-picker'] = [
410 + 'disabled' => true,
411 + 'title' => __('Color Picker', 'fluentform'),
412 + 'description' => __('Color Picker is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
413 + 'image' => fluentformMix('img/pro-fields/color-picker.png'),
414 + 'video' => '',
415 + ];
416 + $disabled['payment_coupon'] = [
417 + 'disabled' => true,
418 + 'title' => __('Coupon', 'fluentform'),
419 + 'description' => __('Coupon is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
420 + 'image' => fluentformMix('img/pro-fields/coupon.png'),
421 + 'video' => '',
422 + ];
423 + }
196 424
197 - $disabled['net_promoter_score'] = array(
198 - 'disabled' => true
199 - );
200 -
201 - $disabled['repeater_field'] = array(
202 - 'disabled' => true
203 - );
204 -
205 - $disabled['custom_submit_button'] = array(
206 - 'disabled' => true
207 - );
208 -
209 - $disabled['rangeslider'] = array(
210 - 'disabled' => true
211 - );
212 -
213 - $disabled['color-picker'] = array(
214 - 'disabled' => true
215 - );
216 -
217 - $disabled['multi_payment_component'] = array(
218 - 'disabled' => true,
219 - 'is_payment' => true
220 - );
221 - $disabled['custom_payment_component'] = array(
222 - 'disabled' => true,
223 - 'is_payment' => true
224 - );
225 -
226 - $disabled['item_quantity_component'] = array(
227 - 'disabled' => true,
228 - 'is_payment' => true
229 - );
230 -
231 - $disabled['payment_method'] = array(
232 - 'disabled' => true,
233 - 'is_payment' => true
234 - );
235 - }
236 - return $this->app->applyFilters('fluentform_disabled_components', $disabled);
425 + $disabled = apply_filters_deprecated(
426 + 'fluentform_disabled_components',
427 + [
428 + $disabled
429 + ],
430 + FLUENTFORM_FRAMEWORK_UPGRADE,
431 + 'fluentform/disabled_components',
432 + 'Use fluentform/disabled_components instead of fluentform_disabled_components.'
433 + );
434 + return $this->app->applyFilters('fluentform/disabled_components', $disabled);
237 435 }
238 436
239 437 /**
240 438 * Get available shortcodes for editor
@@ -239,8 +437,9 @@
239 437 /**
240 438 * Get available shortcodes for editor
241 439 *
242 440 * @return void
441 + *
243 442 * @throws \Exception
244 443 */
245 444 public function getEditorShortcodes()
246 445 {
@@ -248,11 +447,13 @@
248 447 wp_send_json_success(['shortcodes' => $editor_shortcodes], 200);
249 448 }
250 449
251 450 /**
451 + * @deprecated Use \FluentForm\App\Services\Form\FormService::shortcodes
252 452 * Get all available shortcodes for editor
253 453 *
254 454 * @return void
455 + *
255 456 * @throws \Exception
256 457 */
257 458 public function getAllEditorShortcodes()
258 459 {
@@ -263,222 +464,116 @@
263 464
264 465 /**
265 466 * Register the form renderer shortcode
266 467 *
267 - * @return void
468 + * @return void
268 469 */
269 470 public function addFluentFormShortCode()
270 471 {
271 -
272 - add_action('wp_enqueue_scripts', array($this, 'registerScripts'), 999);
472 + add_action('wp_enqueue_scripts', [$this, 'registerScripts'], 9);
273 473
274 474 $this->app->addShortCode('fluentform', function ($atts, $content) {
275 - $shortcodeDefaults = apply_filters('fluentform_shortcode_defaults', array(
276 - 'id' => null,
277 - 'title' => null,
278 - 'permission' => '',
475 + $data = [
476 + 'id' => null,
477 + 'title' => null,
478 + 'css_classes' => '',
479 + 'permission' => '',
480 + 'type' => 'classic',
481 + 'theme' => '',
279 482 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform')
280 - ), $atts);
483 + ];
484 + /* This filter is deprecated, will be removed soon */
485 + $data = apply_filters('fluentform_shortcode_defaults', $data, $atts );
281 486
282 - $atts = shortcode_atts($shortcodeDefaults, $atts);
283 - return $this->renderForm($atts);
284 - });
487 + $shortcodeDefaults = apply_filters('fluentform/shortcode_defaults', $data, $atts);
285 488
286 - $this->app->addShortCode('fluentform_info', function ($atts) {
287 - $shortcodeDefaults = apply_filters('fluentform_info_shortcode_defaults', array(
288 - 'id' => null, // This is the form id
289 - 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total
290 - 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read
291 - 'with_trashed' => 'no', // yes | no
292 - 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"]
293 - 'hide_on_zero' => 'no',
294 - 'payment_status' => 'paid', // it can be all / specific payment status
295 - 'currency_formatted' => 'yes',
296 - 'date_format' => ''
297 - ), $atts);
298 -
299 489 $atts = shortcode_atts($shortcodeDefaults, $atts);
300 - $formId = $atts['id'];
301 - $form = wpFluent()->table('fluentform_forms')->find($formId);
302 490
303 - if (!$form) {
304 - return '';
305 - }
306 -
307 - if ($atts['info'] == 'submission_count') {
308 - $countQuery = wpFluent()->table('fluentform_submissions')
309 - ->where('form_id', $formId);
310 -
311 - if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
312 - $countQuery = $countQuery->where('status', '!=', 'trashed');
313 - }
314 -
315 - if ($atts['status'] == 'all') {
316 - // ...
317 - } else if ($atts['status'] == 'favourites') {
318 - $countQuery = $countQuery->where('is_favourite', '=', 1);
319 - } else {
320 - $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status']));
321 - }
322 -
323 - $total = $countQuery->count();
324 -
325 - if ($atts['substract_from']) {
326 - $total = intval($atts['substract_from']) - $total;
327 - }
328 -
329 - if ($atts['hide_on_zero'] == 'yes' && !$total || $total < 0) {
330 - return '';
331 - }
332 -
333 - return $total;
334 - } else if ($atts['info'] == 'created_at') {
335 - if ($atts['date_format']) {
336 - $dateFormat = $atts['date_format'];
337 - } else {
338 - $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
339 - }
340 - return date($dateFormat, strtotime($form->created_at));
341 - } else if ($atts['info'] == 'updated_at') {
342 - if ($atts['date_format']) {
343 - $dateFormat = $atts['date_format'];
344 - } else {
345 - $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
346 - }
347 - return date($dateFormat, strtotime($form->updated_at));
348 - } else if ($atts['info'] == 'payment_total') {
349 -
350 - if (!defined('FLUENTFORMPRO')) {
351 - return '';
352 - }
353 -
354 - global $wpdb;
355 - $countQuery = wpFluent()
356 - ->table('fluentform_submissions')
357 - ->select(wpFluent()->raw('SUM(total_paid) as payment_total'))
358 - ->where('form_id', $formId);
359 -
360 - if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
361 - $countQuery = $countQuery->where('status', '!=', 'trashed');
362 - }
363 -
364 - if ($atts['status'] == 'all') {
365 - // ...
366 - } else if ($atts['status'] == 'favourites') {
367 - $countQuery = $countQuery->where('is_favourite', '=', 1);
368 - } else {
369 - $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status']));
370 - }
371 -
372 - if ($atts['payment_status'] == 'all') {
373 - // ...
374 - } else if ($atts['payment_status']) {
375 - $countQuery = $countQuery->where('payment_status', '=', sanitize_text_field($atts['payment_status']));
376 - }
377 -
378 - $row = $countQuery->first();
379 -
380 - $total = 0;
381 - if ($row) {
382 - $total = $row->payment_total;
383 - }
384 -
385 - if ($atts['substract_from']) {
386 - $total = intval($atts['substract_from'] * 100) - $total;
387 - }
388 -
389 - if ($atts['hide_on_zero'] == 'yes' && !$total) {
390 - return '';
391 - }
392 -
393 - if ($atts['currency_formatted'] == 'yes') {
394 - $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId);
395 - return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency);
396 - }
397 -
398 - if (!$total) {
399 - return 0;
400 - }
401 -
402 - return $total / 100;
403 - }
404 -
405 - return '';
491 + return $this->renderForm($atts);
406 492 });
407 -
408 - $this->app->addShortCode('ff_get', function ($atts) {
409 - $atts = shortcode_atts(array(
410 - 'param' => '',
411 - ), $atts);
412 - if ($atts['param'] && isset($_GET[$atts['param']])) {
413 - $value = $_GET[$atts['param']];
414 - if (is_array($value)) {
415 - return implode(', ', $value);
416 - }
417 - return esc_html($value);
418 - }
419 - return '';
420 - });
421 -
493 +
494 + $this->registerHelperShortCodes();
422 495 }
423 496
424 497 public function renderForm($atts)
425 498 {
426 499 $form_id = $atts['id'];
427 -
500 + $query = wpFluent()->table('fluentform_forms');
501 +
502 + if (! $this->app->request->get('preview_id')) {
503 + $query->where('status', 'published');
504 + }
505 +
428 506 if ($form_id) {
429 - $form = wpFluent()->table('fluentform_forms')->find($form_id);
430 - } else if ($formTitle = $atts['title']) {
431 - $form = wpFluent()->table('fluentform_forms')->where('title', $formTitle)->first();
507 + $form = $query->find($form_id);
508 + } elseif ($formTitle = $atts['title']) {
509 + $form = $query->where('title', $formTitle)->first();
432 510 } else {
433 - return;
511 + return '';
434 512 }
435 513
436 514 if (!$form) {
437 - return;
515 + return '';
438 516 }
439 517
440 518 if (!empty($atts['permission'])) {
441 519 if (!current_user_can($atts['permission'])) {
442 - return "<div id='ff_form_{$form->id}' class='ff_form_not_render'>{$atts['permission_message']}</div>";
520 + return $this->getNotRenderableHtml($form->id, $atts['permission_message']);
443 521 }
444 522 }
445 523
446 - if(is_feed()) {
524 + if (is_feed()) {
447 525 global $post;
448 - $feedText = sprintf( __( 'The form can be filled in the actual <a href="%s">website url</a>.', 'fluentform' ), get_permalink($post));
449 - $feedText = apply_filters('fluentform_shortcode_feed_text', $feedText, $form);
526 + /* translators: %s is the website URL */
527 + $feedText = sprintf(__('The form can be filled in the actual <a href="%s">website url</a>.', 'fluentform'), get_permalink($post));
528 +
529 + $feedText = apply_filters_deprecated(
530 + 'fluentform_shortcode_feed_text',
531 + [
532 + $feedText,
533 + $form
534 + ],
535 + FLUENTFORM_FRAMEWORK_UPGRADE,
536 + 'fluentform/shortcode_feed_text',
537 + 'Use fluentform/shortcode_feed_text instead of fluentform_shortcode_feed_text.'
538 + );
539 +
540 + $feedText = apply_filters('fluentform/shortcode_feed_text', $feedText, $form);
450 541 return $feedText;
451 542 }
543 +
544 + $form->settings = Helper::getFormMeta($form->id, 'formSettings', []);
452 545
453 - $formSettings = wpFluent()
454 - ->table('fluentform_form_meta')
455 - ->where('form_id', $form_id)
456 - ->where('meta_key', 'formSettings')
457 - ->first();
458 -
459 - if (!$formSettings) {
460 - return;
546 + if (empty($form->settings)) {
547 + return '';
461 548 }
462 549
463 550 $form->fields = json_decode($form->form_fields, true);
464 -
465 - if (!$form->fields['fields']) {
466 - return;
551 + if (!is_array($form->fields) || empty($form->fields['fields'])) {
552 + return '';
467 553 }
468 554
469 - $form->settings = json_decode($formSettings->value, true);
470 - $form = $this->app->applyFilters('fluentform_rendering_form', $form);
471 -
472 - $isRenderable = array(
473 - 'status' => true,
474 - 'message' => ''
555 + $form = apply_filters_deprecated(
556 + 'fluentform_rendering_form',
557 + [
558 + $form
559 + ],
560 + FLUENTFORM_FRAMEWORK_UPGRADE,
561 + 'fluentform/rendering_form',
562 + 'Use fluentform/rendering_form instead of fluentform_rendering_form.'
475 563 );
564 + $form = $this->app->applyFilters('fluentform/rendering_form', $form);
565 +
566 + $isRenderable = [
567 + 'status' => true,
568 + 'message' => '',
569 + ];
570 + $isRenderable = apply_filters('fluentform_is_form_renderable', $isRenderable, $form);
571 +
572 + $isRenderable = $this->app->applyFilters('fluentform/is_form_renderable', $isRenderable, $form);
476 573
477 - $isRenderable = $this->app->applyFilters('fluentform_is_form_renderable', $isRenderable, $form);
478 -
479 574 if (is_array($isRenderable) && !$isRenderable['status']) {
480 - return "<div id='ff_form_{$form->id}' class='ff_form_not_render'>{$isRenderable['message']}</div>";
575 + return $this->getNotRenderableHtml($form->id, $isRenderable['message']);
481 576 }
482 577
483 578 $instanceCssClass = Helper::getFormInstaceClass($form->id);
484 579
@@ -484,10 +579,21 @@
484 579
485 580 $form->instance_css_class = $instanceCssClass;
486 581 $form->instance_index = Helper::$formInstance;
487 582
583 + if ('conversational' == $atts['type']) {
584 + if (!Helper::isElementorEditor()) {
585 + $this->addInlineVars();
586 + }
587 + return (new \FluentForm\App\Services\FluentConversational\Classes\Form())->renderShortcode($form);
588 + }
589 +
488 590 $formBuilder = $this->app->make('formBuilder');
489 - $output = $formBuilder->build($form, $instanceCssClass . ' ff-form-loading', $instanceCssClass);
591 +
592 + $cssClasses = trim($instanceCssClass . ' ff-form-loading');
593 +
594 + $output = $formBuilder->build($form, $cssClasses, $instanceCssClass, $atts);
595 +
490 596 $output = $this->replaceEditorSmartCodes($output, $form);
491 597
492 598 if (!wp_script_is('fluent-form-submission', 'registered')) {
493 599 $this->registerScripts();
@@ -493,9 +599,22 @@
493 599 $this->registerScripts();
494 600 }
495 601
496 602 wp_enqueue_style('fluent-form-styles');
497 - if (apply_filters('fluentform_load_default_public', true, $form)) {
603 + $postId = get_the_ID() ?: 0;
604 + $loadStyle = apply_filters_deprecated(
605 + 'fluentform_load_default_public',
606 + [
607 + true,
608 + $form,
609 + $postId
610 + ],
611 + FLUENTFORM_FRAMEWORK_UPGRADE,
612 + 'fluentform/load_default_public',
613 + 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
614 + );
615 +
616 + if (apply_filters('fluentform/load_default_public', $loadStyle, $form, $postId)) {
498 617 wp_enqueue_style('fluentform-public-default');
499 618 }
500 619 /*
501 620 * We will load fluentform-advanced if the form has certain fields or feature
@@ -500,166 +619,331 @@
500 619 /*
501 620 * We will load fluentform-advanced if the form has certain fields or feature
502 621 */
503 622 $this->maybeHasAdvandedFields($form, $formBuilder);
504 - wp_enqueue_script('fluent-form-submission');
623 + if (!Helper::isElementorEditor()) {
624 + wp_enqueue_script('fluent-form-submission');
625 + }
505 626
627 + /* translators: %activeStep% is the current step number, %totalStep% is the total number of steps, %stepTitle% is the step title */
506 628 $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', 'fluentform');
507 - $stepText = apply_filters('fluentform_step_string', $stepText);
508 - $vars = apply_filters('fluentform_global_form_vars', array(
509 - 'ajaxUrl' => admin_url('admin-ajax.php'),
510 - 'forms' => array(),
511 - 'step_text' => $stepText,
512 - 'is_rtl' => is_rtl(),
513 - 'date_i18n' => $this->getDatei18n(),
514 - 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false,
515 - 'fluentform_version' => FLUENTFORM_VERSION,
516 - 'force_init' => false,
517 - 'stepAnimationDuration' => 350,
518 - 'upload_completed_txt' => __('100% Completed', 'fluentform'),
519 - 'upload_start_txt' => __('0% Completed', 'fluentform'),
520 - 'uploading_txt' => __('Uploading', 'fluentform'),
521 - 'choice_js_vars' => [
522 - 'noResultsText' => __('No results found', 'fluentform'),
523 - 'loadingText' => __('Loading...', 'fluentform'),
524 - 'noChoicesText' => __('No choices to choose from', 'fluentform'),
629 +
630 + $stepText = apply_filters_deprecated(
631 + 'fluentform_step_string',
632 + [
633 + $stepText
634 + ],
635 + FLUENTFORM_FRAMEWORK_UPGRADE,
636 + 'fluentform/step_string',
637 + 'Use fluentform/step_string instead of fluentform_step_string.'
638 + );
639 +
640 + $stepText = apply_filters('fluentform/step_string', $stepText);
641 +
642 + $data = [
643 + 'ajaxUrl' => admin_url('admin-ajax.php'),
644 + 'forms' => [],
645 + 'step_text' => $stepText,
646 + 'step_completed_text' => __('Completed', 'fluentform'),
647 + 'is_rtl' => is_rtl(),
648 + 'date_i18n' => self::getDatei18n(),
649 + 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false,
650 + 'fluentform_version' => FLUENTFORM_VERSION,
651 + 'force_init' => false,
652 + 'stepAnimationDuration' => 350,
653 + 'upload_completed_txt' => __('100% Completed', 'fluentform'),
654 + 'upload_start_txt' => __('0% Completed', 'fluentform'),
655 + 'uploading_txt' => __('Uploading', 'fluentform'),
656 + 'choice_js_vars' => [
657 + 'noResultsText' => __('No results found', 'fluentform'),
658 + 'loadingText' => __('Loading...', 'fluentform'),
659 + 'noChoicesText' => __('No choices to choose from', 'fluentform'),
525 660 'itemSelectText' => __('Press to select', 'fluentform'),
526 - ]
527 - ));
661 + 'maxItemTextSingular' => __('Only %%maxItemCount%% option can be added', 'fluentform'),
662 + 'maxItemTextPlural' => __('Only %%maxItemCount%% options can be added', 'fluentform'),
663 + ],
664 + 'input_mask_vars' => [
665 + 'clearIfNotMatch' => false,
666 + ],
667 + 'nonce' => wp_create_nonce(),
668 + 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete'),
669 + 'form_id' => $form_id,
670 + 'step_change_focus' => true,
671 + 'has_cleantalk' => \FluentForm\App\Modules\Form\CleanTalkHandler::isCleantalkActivated(),
672 + 'pro_payment_script_compatible' => Helper::isProPaymentScriptCompatible(),
673 + ];
674 +
675 + $data = apply_filters_deprecated(
676 + 'fluentform_global_form_vars',
677 + [
678 + $data
679 + ],
680 + FLUENTFORM_FRAMEWORK_UPGRADE,
681 + 'fluentform/global_form_vars',
682 + 'Use fluentform/global_form_vars instead of fluentform_global_form_vars.'
683 + );
528 684
529 - wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars);
685 + $vars = apply_filters('fluentform/global_form_vars', $data);
530 686
687 + if (!Helper::isElementorEditor()) {
688 + wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars);
689 + }
690 +
691 + // Localize JavaScript messages for translation
692 + $this->localizeJavaScriptMessages($form);
693 +
694 + // Add global messages (only once)
695 + if (!wp_script_is('fluent-form-submission', 'done')) {
696 + $globalMessages = [
697 + 'javascript_handler_failed' => __('Javascript handler could not be loaded. Form submission has been failed. Reload the page and try again', 'fluentform')
698 + ];
699 + $globalMessages = apply_filters('fluentform/form_submission_messages', $globalMessages, $form);
700 + wp_localize_script('fluent-form-submission', 'fluentform_submission_messages_global', $globalMessages);
701 +
702 + // Add global address messages
703 + $globalAddressMessages = [
704 + 'please_wait' => __('Please wait ...', 'fluentform'),
705 + 'location_not_determined' => __('Could not determine address from location.', 'fluentform'),
706 + 'address_fetch_failed' => __('Failed to fetch address from coordinates.', 'fluentform'),
707 + 'geolocation_failed' => __('Geolocation failed or was denied.', 'fluentform'),
708 + 'geolocation_not_supported' => __('Geolocation is not supported by this browser.', 'fluentform')
709 + ];
710 + $globalAddressMessages = apply_filters('fluentform/address_autocomplete_messages', $globalAddressMessages, $form);
711 + wp_localize_script('fluent-form-submission', 'fluentform_address_messages_global', $globalAddressMessages);
712 + }
713 +
531 714 $formSettings = $form->settings;
532 715
533 716 $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']);
534 717
718 + // Ensure restrictions array exists before setting denyEmptySubmission
719 + if (!isset($formSettings['restrictions']) || !is_array($formSettings['restrictions'])) {
720 + $formSettings['restrictions'] = [];
721 + }
722 +
535 723 $formSettings['restrictions']['denyEmptySubmission'] = [
536 - 'enabled' => false
724 + 'enabled' => false,
537 725 ];
538 726
539 - $form_vars = array(
540 - 'id' => $form->id,
541 - 'settings' => $formSettings,
542 - 'form_instance' => $instanceCssClass,
727 + if (!empty($formBuilder->validationRules)) {
728 + $formBuilder->validationRules = fluentform_backend_sanitizer($formBuilder->validationRules, [
729 + 'message' => 'fluentform_sanitize_html'
730 + ]);
731 + }
732 +
733 + $form_vars = [
734 + 'id' => $form->id,
735 + 'ajaxUrl' => admin_url('admin-ajax.php'),
736 + 'settings' => $formSettings,
737 + 'form_instance' => $instanceCssClass,
543 738 'form_id_selector' => 'fluentform_' . $form->id,
544 - 'rules' => $formBuilder->validationRules
545 - );
739 + 'rules' => $formBuilder->validationRules,
740 + 'debounce_time' => apply_filters('fluentform/show_hide_elements_debounce_time', 300),
741 + ];
546 742
547 743 if ($conditionals = $formBuilder->conditions) {
548 744 $form_vars['conditionals'] = $conditionals;
549 745 }
550 746
747 + $form_vars['file_upload_settings'] = apply_filters(
748 + 'fluentform/file_upload_settings_for_js',
749 + [],
750 + $form
751 + );
752 +
753 + $form_vars = apply_filters('fluentform/form_vars_for_JS', $form_vars, $form);
754 +
551 755 if ($form->has_payment) {
552 - do_action('fluentform_rending_payment_form', $form);
756 + do_action_deprecated(
757 + 'fluentform_rendering_payment_form',
758 + [
759 + $form
760 + ],
761 + FLUENTFORM_FRAMEWORK_UPGRADE,
762 + 'fluentform/rendering_payment_form',
763 + 'Use fluentform/rendering_payment_form instead of fluentform_rendering_payment_form.'
764 + );
765 + do_action('fluentform/rendering_payment_form', $form);
553 766 }
554 767
555 768 $otherScripts = '';
556 - ob_start();
557 - ?>
558 - <script type="text/javascript">
559 - window.fluent_form_<?php echo $instanceCssClass; ?> = <?php echo json_encode($form_vars);?>;
560 - <?php if(wp_doing_ajax()): ?>
561 - function initFFInstance_<?php echo $form_vars['id']; ?>() {
562 - if(!window.fluentFormApp) {
563 - console.log('No fluentFormApp found');
564 - return;
769 + $otherScriptsRenderImmediately = apply_filters('fluentform/load_form_instance_js_var_immediately', false);
770 + if (!$otherScriptsRenderImmediately) {
771 + ob_start();
772 + }
773 +
774 + if (!Helper::isElementorEditor()) {
775 + ?>
776 + <script type="text/javascript">
777 + window.fluent_form_<?php echo esc_attr($instanceCssClass); ?> = <?php echo wp_json_encode($form_vars); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $form_vars is escaped before being passed in.?>;
778 + <?php if (wp_doing_ajax()): ?>
779 + function initFFInstance_<?php echo esc_attr($form_vars['id']); ?>() {
780 + if (!window.fluentFormApp) {
781 + console.log('No fluentFormApp found');
782 + return;
783 + }
784 + var ajax_formInstance = window.fluentFormApp(jQuery('form.<?php echo esc_attr($form_vars['form_instance']); ?>'));
785 + if (ajax_formInstance) {
786 + ajax_formInstance.initFormHandlers();
787 + }
565 788 }
566 - var ajax_formInstance = window.fluentFormApp(jQuery('form.<?php echo $form_vars['form_instance']; ?>'));
567 - if (ajax_formInstance) {
568 - ajax_formInstance.initFormHandlers();
569 - }
570 - }
789 +
790 + initFFInstance_<?php echo esc_attr($form_vars['id']); ?>();
791 + <?php endif; ?>
792 + </script>
793 + <?php
794 + }
795 + if (!Helper::isElementorEditor()) {
796 + $this->addInlineVars();
797 + }
798 + if (!$otherScriptsRenderImmediately) {
799 + $otherScripts .= ob_get_clean();
800 + }
571 801
572 - initFFInstance_<?php echo $form_vars['id']; ?>();
573 - <?php endif; ?>
574 - </script>
575 - <?php
576 - $this->addInlineVars();
577 - $otherScripts .= ob_get_clean();
578 802
579 - if (!apply_filters('fluentform-disabled_analytics', false)) {
803 + $disableAnalytics = apply_filters_deprecated(
804 + 'fluentform-disabled_analytics',
805 + [
806 + true
807 + ],
808 + FLUENTFORM_FRAMEWORK_UPGRADE,
809 + 'fluentform/disabled_analytics',
810 + 'Use fluentform/disabled_analytics instead of fluentform-disabled_analytics.'
811 + );
812 +
813 + if (!$this->app->applyFilters('fluentform/disabled_analytics', $disableAnalytics)) {
580 814 if (!Acl::hasAnyFormPermission($form->id)) {
581 - (new \FluentForm\App\Modules\Form\Analytics($this->app))->record($form->id);
815 + (new \FluentForm\App\Services\Analytics\AnalyticsService())->store($form->id);
582 816 }
583 817 }
818 +
584 819 return $output . $otherScripts;
585 820 }
586 821
822 + protected function getNotRenderableHtml($formId, $message)
823 + {
824 + return "<div id='ff_form_" . esc_attr($formId) . "' class='ff_form_not_render'>"
825 + . wp_kses_post($message)
826 + . "</div>";
827 + }
828 +
587 829 /**
588 830 * Process the output HTML to generate the default values.
589 831 *
590 - * @param string $output
832 + * @param string $output
591 833 * @param \stdClass $form
834 + *
592 835 * @return string
593 836 */
594 837 public function replaceEditorSmartCodes($output, $form)
595 838 {
839 + // Return early if output is null or empty
840 + if ($output === null || $output === '') {
841 + return $output;
842 + }
843 +
844 + // Return early if form is null to prevent errors
845 + if ($form === null) {
846 + return $output;
847 + }
848 +
596 849 // Get the patterns for default values from the output HTML string.
597 850 // The example of a pattern would be for user ID: {user.ID}
598 851 preg_match_all('/{(.*?)}/', $output, $matches);
599 852 $patterns = array_unique($matches[0]);
600 853
601 -
602 854 $attrDefaultValues = [];
603 855
604 856 foreach ($patterns as $pattern) {
605 857 // The default value for each pattern will be resolved here.
606 - $attrDefaultValues[$pattern] = apply_filters('fluentform_parse_default_value', $pattern, $form);
858 + $attrDefaultValues[$pattern] = apply_filters_deprecated(
859 + 'fluentform_parse_default_value',
860 + [
861 + $pattern,
862 + $form
863 + ],
864 + FLUENTFORM_FRAMEWORK_UPGRADE,
865 + 'fluentform/parse_default_value',
866 + 'Use fluentform/parse_default_value instead of fluentform_parse_default_value.'
867 + );
868 +
869 + $attrDefaultValues[$pattern] = apply_filters('fluentform/parse_default_value', $attrDefaultValues[$pattern], $form);
607 870 }
608 871
609 872 // Raising an event so that others can hook into it and modify the default values later.
610 - $attrDefaultValues = (array)apply_filters('fluentform_parse_default_values', $attrDefaultValues);
873 + $attrDefaultValues = apply_filters_deprecated(
874 + 'fluentform_parse_default_values',
875 + [
876 + $attrDefaultValues
877 + ],
878 + FLUENTFORM_FRAMEWORK_UPGRADE,
879 + 'fluentform/parse_default_values',
880 + 'Use fluentform/parse_default_values instead of fluentform_parse_default_values.'
881 + );
611 882
883 + $attrDefaultValues = (array) apply_filters('fluentform/parse_default_values', $attrDefaultValues);
884 +
612 885 if (isset($attrDefaultValues['{payment_total}'])) {
613 886 $attrDefaultValues['{payment_total}'] = '<span class="ff_order_total"></span>';
614 887 }
615 888
616 - // Finally, replace the patterns with the replacements and return the output HTML.
617 - return str_replace(array_keys($attrDefaultValues), array_values($attrDefaultValues), $output);
889 + // Replace in a single pass. str_replace() with arrays re-scans text an earlier key inserted,
890 + // so ?a=javascript{get.b}&b=:alert(1) would assemble a script URL from two escaped values.
891 + $replacements = [];
892 + foreach ($attrDefaultValues as $pattern => $replacement) {
893 + // strtr() returns false on an empty key before PHP 8.
894 + if ('' !== (string) $pattern && (is_scalar($replacement) || null === $replacement)) {
895 + $replacements[(string) $pattern] = (string) $replacement;
896 + }
897 + }
898 +
899 + return strtr($output, $replacements);
618 900 }
619 901
620 902 /**
621 903 * Register renderer actions for compiling each element
622 904 *
623 - * @return void
905 + * @return void
624 906 */
625 907 public function addRendererActions()
626 908 {
627 909 $actionMappings = [
628 - 'Select@compile' => ['fluentform_render_item_select'],
629 - 'Rating@compile' => ['fluentform_render_item_ratings'],
630 - 'Address@compile' => ['fluentform_render_item_address'],
631 - 'Name@compile' => ['fluentform_render_item_input_name'],
632 - 'TextArea@compile' => ['fluentform_render_item_textarea'],
633 - 'DateTime@compile' => ['fluentform_render_item_input_date'],
634 - 'Recaptcha@compile' => ['fluentform_render_item_recaptcha'],
635 - 'Container@compile' => ['fluentform_render_item_container'],
636 - 'CustomHtml@compile' => ['fluentform_render_item_custom_html'],
637 - 'SectionBreak@compile' => ['fluentform_render_item_section_break'],
638 - 'SubmitButton@compile' => ['fluentform_render_item_submit_button'],
639 - 'SelectCountry@compile' => ['fluentform_render_item_select_country'],
910 + 'Select@compile' => ['fluentform/render_item_select'],
911 + 'Rating@compile' => ['fluentform/render_item_ratings'],
912 + 'Address@compile' => ['fluentform/render_item_address'],
913 + 'Name@compile' => ['fluentform/render_item_input_name'],
914 + 'TextArea@compile' => ['fluentform/render_item_textarea'],
915 + 'DateTime@compile' => ['fluentform/render_item_input_date'],
916 + 'Recaptcha@compile' => ['fluentform/render_item_recaptcha'],
917 + 'Hcaptcha@compile' => ['fluentform/render_item_hcaptcha'],
918 + 'Turnstile@compile' => ['fluentform/render_item_turnstile'],
919 + 'Container@compile' => ['fluentform/render_item_container'],
920 + 'CustomHtml@compile' => ['fluentform/render_item_custom_html'],
921 + 'SectionBreak@compile' => ['fluentform/render_item_section_break'],
922 + 'SubmitButton@compile' => ['fluentform/render_item_submit_button'],
923 + 'SelectCountry@compile' => ['fluentform/render_item_select_country'],
640 924
641 925 'TermsAndConditions@compile' => [
642 - 'fluentform_render_item_terms_and_condition',
643 - 'fluentform_render_item_gdpr_agreement'
926 + 'fluentform/render_item_terms_and_condition',
927 + 'fluentform/render_item_gdpr_agreement',
644 928 ],
645 929
646 930 'TabularGrid@compile' => [
647 - 'fluentform_render_item_tabular_grid'
931 + 'fluentform/render_item_tabular_grid',
648 932 ],
649 933
650 934 'Checkable@compile' => [
651 - 'fluentform_render_item_input_radio',
652 - 'fluentform_render_item_input_checkbox',
935 + 'fluentform/render_item_input_radio',
936 + 'fluentform/render_item_input_checkbox',
653 937 ],
654 938
655 939 'Text@compile' => [
656 - 'fluentform_render_item_input_url',
657 - 'fluentform_render_item_input_text',
658 - 'fluentform_render_item_input_email',
659 - 'fluentform_render_item_input_number',
660 - 'fluentform_render_item_input_hidden',
661 - 'fluentform_render_item_input_password',
940 + 'fluentform/render_item_input_url',
941 + 'fluentform/render_item_input_text',
942 + 'fluentform/render_item_input_email',
943 + 'fluentform/render_item_input_number',
944 + 'fluentform/render_item_input_hidden',
945 + 'fluentform/render_item_input_password',
662 946 ],
663 947 ];
664 948
665 949 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
@@ -665,10 +949,10 @@
665 949 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
666 950 foreach ($actionMappings as $handler => $actions) {
667 951 foreach ($actions as $action) {
668 952 $this->app->addAction($action, function () use ($path, $handler) {
669 - list($class, $method) = $this->app->parseHandler($path . $handler);
670 - call_user_func_array(array($class, $method), func_get_args());
953 + list($class, $method) = $this->app->parseHookHandler($path . $handler);
954 + call_user_func_array([$class, $method], func_get_args());
671 955 }, 10, 2);
672 956 }
673 957 }
674 958 }
@@ -675,30 +959,47 @@
675 959
676 960 /**
677 961 * Register dynamic value shortcode parser (filter default value)
678 962 *
679 - * @return void
963 + * @return void
680 964 */
681 965 public function addFluentFormDefaultValueParser()
682 966 {
683 - $this->app->addFilter('fluentform_parse_default_value', function ($value, $form) {
967 + $this->app->addFilter('fluentform/parse_default_value', function ($value, $form) {
684 968 return EditorShortcodeParser::filter($value, $form);
685 969 }, 10, 2);
686 970 }
687 971
688 972 /**
689 - * Register filter to check whether the form is renderable
973 + * Register filter to check whether the form is renderable or active
690 974 *
691 - * @return mixed
975 + * @return mixed
692 976 */
693 977 public function addIsRenderableFilter()
694 978 {
695 - $this->app->addFilter('fluentform_is_form_renderable', function ($isRenderable, $form) {
696 - $checkables = array('limitNumberOfEntries', 'scheduleForm', 'requireLogin');
979 + $this->app->addFilter('fluentform/is_form_renderable', function ($isRenderable, $form) {
980 + if (
981 + $this->app->request->get('design_mode')
982 + && Acl::hasAnyFormPermission()
983 + ) {
984 + return $isRenderable;
985 + }
697 986
698 - foreach ($form->settings['restrictions'] as $key => $restrictions) {
987 + $checkables = ['limitNumberOfEntries', 'scheduleForm', 'requireLogin'];
988 +
989 + // Ensure settings is an array
990 + if (!isset($form->settings) || !is_array($form->settings)) {
991 + $form->settings = [];
992 + }
993 +
994 + // Ensure restrictions exists and is an array before iterating
995 + $restrictions = isset($form->settings['restrictions']) && is_array($form->settings['restrictions'])
996 + ? $form->settings['restrictions']
997 + : [];
998 +
999 + foreach ($restrictions as $key => $restrictionSettings) {
699 1000 if (in_array($key, $checkables)) {
700 - $isRenderable['status'] = $this->{$key}($restrictions, $form, $isRenderable);
1001 + $isRenderable['status'] = $this->{$key}($restrictionSettings, $form, $isRenderable);
701 1002 if (!$isRenderable['status']) {
702 1003 $isRenderable['status'] = false;
703 1004 return $isRenderable;
704 1005 }
@@ -703,8 +1004,12 @@
703 1004 return $isRenderable;
704 1005 }
705 1006 }
706 1007 }
1008 + if($form->status == 'unpublished'){
1009 + $isRenderable['status'] = false;
1010 + $isRenderable['message'] = apply_filters('fluentform/unpublished_form_submission_message',__('Invalid Form!', 'fluentform'));
1011 + }
707 1012
708 1013 return $isRenderable;
709 1014 }, 10, 2);
710 1015 }
@@ -717,12 +1022,14 @@
717 1022 * @return bool
718 1023 */
719 1024 private function limitNumberOfEntries($restrictions, $form, &$isRenderable)
720 1025 {
721 - if (!$restrictions['enabled']) {
1026 +
1027 + if (!Arr::isTrue($restrictions, 'enabled') || !isset($restrictions['period']) || !isset($restrictions['numberOfEntries'])) {
722 1028 return true;
723 1029 }
724 1030
1031 +
725 1032 $col = 'created_at';
726 1033 $period = $restrictions['period'];
727 1034 $maxAllowedEntries = $restrictions['numberOfEntries'];
728 1035
@@ -733,27 +1040,27 @@
733 1040 $query = wpFluent()->table('fluentform_submissions')
734 1041 ->where('form_id', $form->id)
735 1042 ->where('status', '!=', 'trashed');
736 1043
737 - if ($period == 'day') {
1044 + if ('day' == $period) {
738 1045 $year = "YEAR(`{$col}`) = YEAR(NOW())";
739 1046 $month = "MONTH(`{$col}`) = MONTH(NOW())";
740 1047 $day = "DAY(`{$col}`) = DAY(NOW())";
741 - $query->where(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
742 - } elseif ($period == 'week') {
743 - $query->where(
1048 + $query->whereRaw(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
1049 + } elseif ('week' == $period) {
1050 + $query->whereRaw(
744 1051 wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)")
745 1052 );
746 - } elseif ($period == 'month') {
1053 + } elseif ('month' == $period) {
747 1054 $year = "YEAR(`{$col}`) = YEAR(NOW())";
748 1055 $month = "MONTH(`{$col}`) = MONTH(NOW())";
749 - $query->where(wpFluent()->raw("{$year} AND {$month}"));
750 - } elseif ($period == 'year') {
751 - $query->where(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())"));
752 - } else if ($period == 'per_user_ip') {
1056 + $query->whereRaw(wpFluent()->raw("{$year} AND {$month}"));
1057 + } elseif ('year' == $period) {
1058 + $query->whereRaw(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())"));
1059 + } elseif ('per_user_ip' == $period) {
753 1060 $ip = $this->app->request->getIp();
754 1061 $query->where('ip', $ip);
755 - } else if ($period == 'per_user_id') {
1062 + } elseif ('per_user_id' == $period) {
756 1063 $userId = get_current_user_id();
757 1064 if (!$userId) {
758 1065 return true;
759 1066 }
@@ -761,11 +1068,10 @@
761 1068 }
762 1069
763 1070 $count = $query->count();
764 1071
765 -
766 1072 if ($count >= $maxAllowedEntries) {
767 - $isRenderable['message'] = $restrictions['limitReachedMsg'];
1073 + $isRenderable['message'] = apply_filters('fluentform/entry_limit_reached_message', $restrictions['limitReachedMsg'], $form);
768 1074 return false;
769 1075 }
770 1076
771 1077 return true;
@@ -771,9 +1077,9 @@
771 1077 return true;
772 1078 }
773 1079
774 1080 /**
775 - * Check if form has scheduled date and open for submission
1081 + * Check if form has scheduled date & weekdays and open for submission
776 1082 *
777 1083 * @param array $restrictions
778 1084 *
779 1085 * @return bool
@@ -779,9 +1085,9 @@
779 1085 * @return bool
780 1086 */
781 1087 private function scheduleForm($restrictions, $form, &$isRenderable)
782 1088 {
783 - if (!$restrictions['enabled']) {
1089 + if (!Arr::isTrue($restrictions, 'enabled')) {
784 1090 return true;
785 1091 }
786 1092
787 1093 $time = time();
@@ -788,16 +1094,23 @@
788 1094 $start = strtotime($restrictions['start']);
789 1095 $end = strtotime($restrictions['end']);
790 1096
791 1097 if ($time < $start) {
792 - $isRenderable['message'] = $restrictions['pendingMsg'];
1098 + $isRenderable['message'] = apply_filters('fluentform/schedule_form_pending_message', $restrictions['pendingMsg'], $form->id);
1099 + return false;
1100 + }
793 1101
1102 + if ($time >= $end) {
1103 + $isRenderable['message'] = apply_filters('fluentform/schedule_form_expired_message', $restrictions['expiredMsg'], $form->id);
1104 +
794 1105 return false;
795 1106 }
796 1107
797 - if ($time >= $end) {
1108 + $weekDayToday = date('l'); //day of the week
1109 + $selectedWeekDays = ArrayHelper::get($restrictions, 'selectedDays');
1110 + //skip if it was not set initially and $selectedWeekDays is null
1111 + if ($selectedWeekDays && is_array($selectedWeekDays) && !in_array($weekDayToday, $selectedWeekDays)) {
798 1112 $isRenderable['message'] = $restrictions['expiredMsg'];
799 -
800 1113 return false;
801 1114 }
802 1115
803 1116 return true;
@@ -811,14 +1124,14 @@
811 1124 * @return bool
812 1125 */
813 1126 private function requireLogin($restrictions, $form, &$isRenderable)
814 1127 {
815 - if (!$restrictions['enabled']) {
1128 + if (!Arr::isTrue($restrictions, 'enabled')) {
816 1129 return true;
817 1130 }
818 1131
819 1132 if (!($isLoggedIn = is_user_logged_in())) {
820 - $isRenderable['message'] = $restrictions['requireLoginMsg'];
1133 + $isRenderable['message'] = apply_filters('fluentform/form_requires_login_message', $restrictions['requireLoginMsg'], $form);
821 1134 }
822 1135
823 1136 return $isLoggedIn;
824 1137 }
@@ -825,9 +1138,9 @@
825 1138
826 1139 /**
827 1140 * Register fluentform_submission_inserted actions
828 1141 *
829 - * @return void
1142 + * @return void
830 1143 */
831 1144 public function addFluentformSubmissionInsertedFilter()
832 1145 {
833 1146 (new EmailNotificationActions($this->app))->register();
@@ -835,16 +1148,22 @@
835 1148
836 1149 /**
837 1150 * Add inline scripts [Add localized script using same var]
838 1151 *
839 - * @return void
1152 + * @return void
840 1153 */
841 1154 private function addInlineVars()
842 1155 {
843 - if (!defined('ELEMENTOR_PRO_VERSION')) {
1156 + if (!defined('ELEMENTOR_PRO_VERSION') || $this->elementorPopUpHandler) {
844 1157 return '';
845 1158 }
846 1159
1160 + // Previously this handler was registered for every form
1161 + // in a single page. So multiple event handlers were
1162 + // registered. This flag ensures the handler is
1163 + // registered just once, since one is enough!
1164 + $this->elementorPopUpHandler = true;
1165 +
847 1166 $actionName = 'wp_footer';
848 1167 if (is_admin()) {
849 1168 $actionName = 'admin_footer';
850 1169 }
@@ -851,13 +1170,28 @@
851 1170
852 1171 add_action($actionName, function () {
853 1172 ?>
854 1173 <script type="text/javascript">
855 - <?php if(defined('ELEMENTOR_PRO_VERSION')): ?>
856 - jQuery(document).on('elementor/popup/show', function (event, id, instance) {
857 - var ffForms = jQuery('#elementor-popup-modal-' + id).find('form.frm-fluent-form');
1174 + <?php if (defined('ELEMENTOR_PRO_VERSION')): ?>
1175 +
1176 + window.addEventListener('elementor/popup/show', function (e) {
1177 + var ffForms = jQuery('#elementor-popup-modal-' + e.detail.id).find('form.frm-fluent-form');
1178 +
1179 + /**
1180 + * Support conversation form in elementor popup
1181 + * No regular form found, check for conversational form
1182 + */
1183 + if (!ffForms.length) {
1184 + const elements = document.getElementsByClassName('ffc_conv_form');
1185 + if (elements.length) {
1186 + let jsEvent = new CustomEvent('ff-elm-conv-form-event', {
1187 + detail: elements
1188 + });
1189 + document.dispatchEvent(jsEvent);
1190 + }
1191 + }
858 1192 if (ffForms.length) {
859 - jQuery.each(ffForms, function (index, ffForm) {
1193 + jQuery.each(ffForms, function(index, ffForm) {
860 1194 jQuery(ffForm).trigger('reInitExtras');
861 1195 jQuery(document).trigger('ff_reinit', [ffForm]);
862 1196 });
863 1197 }
@@ -868,14 +1202,14 @@
868 1202 }, 999);
869 1203 return '';
870 1204 }
871 1205
872 - private function getDatei18n()
1206 + public static function getDatei18n()
873 1207 {
874 - $i18n = array(
1208 + $i18n = [
875 1209 'previousMonth' => __('Previous Month', 'fluentform'),
876 - 'nextMonth' => __('Next Month', 'fluentform'),
877 - 'months' => [
1210 + 'nextMonth' => __('Next Month', 'fluentform'),
1211 + 'months' => [
878 1212 'shorthand' => [
879 1213 __('Jan', 'fluentform'),
880 1214 __('Feb', 'fluentform'),
881 1215 __('Mar', 'fluentform'),
@@ -886,9 +1220,9 @@
886 1220 __('Aug', 'fluentform'),
887 1221 __('Sep', 'fluentform'),
888 1222 __('Oct', 'fluentform'),
889 1223 __('Nov', 'fluentform'),
890 - __('Dec', 'fluentform')
1224 + __('Dec', 'fluentform'),
891 1225 ],
892 1226 'longhand' => [
893 1227 __('January', 'fluentform'),
894 1228 __('February', 'fluentform'),
@@ -900,13 +1234,13 @@
900 1234 __('August', 'fluentform'),
901 1235 __('September', 'fluentform'),
902 1236 __('October', 'fluentform'),
903 1237 __('November', 'fluentform'),
904 - __('December', 'fluentform')
905 - ]
1238 + __('December', 'fluentform'),
1239 + ],
906 1240 ],
907 1241 'weekdays' => [
908 - 'longhand' => array(
1242 + 'longhand' => [
909 1243 __('Sunday', 'fluentform'),
910 1244 __('Monday', 'fluentform'),
911 1245 __('Tuesday', 'fluentform'),
912 1246 __('Wednesday', 'fluentform'),
@@ -911,11 +1245,11 @@
911 1245 __('Tuesday', 'fluentform'),
912 1246 __('Wednesday', 'fluentform'),
913 1247 __('Thursday', 'fluentform'),
914 1248 __('Friday', 'fluentform'),
915 - __('Saturday', 'fluentform')
916 - ),
917 - 'shorthand' => array(
1249 + __('Saturday', 'fluentform'),
1250 + ],
1251 + 'shorthand' => [
918 1252 __('Sun', 'fluentform'),
919 1253 __('Mon', 'fluentform'),
920 1254 __('Tue', 'fluentform'),
921 1255 __('Wed', 'fluentform'),
@@ -920,10 +1254,10 @@
920 1254 __('Tue', 'fluentform'),
921 1255 __('Wed', 'fluentform'),
922 1256 __('Thu', 'fluentform'),
923 1257 __('Fri', 'fluentform'),
924 - __('Sat', 'fluentform')
925 - )
1258 + __('Sat', 'fluentform'),
1259 + ],
926 1260 ],
927 1261 'daysInMonth' => [
928 1262 31,
929 1263 28,
@@ -935,20 +1269,21 @@
935 1269 31,
936 1270 30,
937 1271 31,
938 1272 30,
939 - 31
1273 + 31,
940 1274 ],
941 - 'rangeSeparator' => __(' to ', 'fluentform'),
1275 + 'rangeSeparator' => __(' to ', 'fluentform'),
942 1276 'weekAbbreviation' => __('Wk', 'fluentform'),
943 - 'scrollTitle' => __('Scroll to increment', 'fluentform'),
944 - 'toggleTitle' => __('Click to toggle', 'fluentform'),
945 - 'amPM' => [
1277 + 'scrollTitle' => __('Scroll to increment', 'fluentform'),
1278 + 'toggleTitle' => __('Click to toggle', 'fluentform'),
1279 + 'amPM' => [
946 1280 __('AM', 'fluentform'),
947 - __('PM', 'fluentform')
1281 + __('PM', 'fluentform'),
948 1282 ],
949 - 'yearAriaLabel' => __('Year', 'fluentform')
950 - );
1283 + 'yearAriaLabel' => __('Year', 'fluentform'),
1284 + 'firstDayOfWeek' => (int) get_option('start_of_week'),
1285 + ];
951 1286
952 1287 return apply_filters('fluentform/date_i18n', $i18n);
953 1288 }
954 1289
@@ -961,12 +1296,14 @@
961 1296 'form_step',
962 1297 'input_file',
963 1298 'input_image',
964 1299 'net_promoter_score',
965 - 'featured_image'
1300 + 'featured_image',
966 1301 ];
967 -
968 - if ($formBuilder->conditions || array_intersect($formBuilder->fieldLists, $advancedFields)) {
1302 + $advancedFields = apply_filters('fluentform/fields_requiring_advanced_script', $advancedFields);
1303 +
1304 + // Only enqueue advanced script if NOT in Elementor editor mode
1305 + if (!Helper::isElementorEditor() && ($formBuilder->conditions || array_intersect($formBuilder->fieldLists, $advancedFields))) {
969 1306 wp_enqueue_script('fluentform-advanced');
970 1307 }
971 1308 }
972 1309
@@ -971,17 +1308,264 @@
971 1308 }
972 1309
973 1310 public function registerInputSanitizers()
974 1311 {
975 - add_filter('fluentform_input_data_input_number', array($this, 'getNumericInputValue'), 10, 2);
976 - add_filter('fluentform_input_data_custom_payment_component', array($this, 'getNumericInputValue'), 10, 2);
1312 + add_filter('fluentform/input_data_input_number', [$this, 'getNumericInputValue'], 10, 2);
1313 + add_filter('fluentform/input_data_custom_payment_component', [$this, 'getNumericInputValue'], 10, 2);
977 1314 }
978 1315
979 1316 public function getNumericInputValue($value, $field)
980 1317 {
981 1318 $formatter = ArrayHelper::get($field, 'raw.settings.numeric_formatter');
982 - if(!$formatter) {
1319 + if (!$formatter) {
983 1320 return $value;
984 1321 }
985 1322 return Helper::getNumericValue($value, $formatter);
986 1323 }
987 -}
1324 +
1325 +
1326 + public function registerHelperShortCodes()
1327 + {
1328 + $this->app->addShortCode('fluentform_info', function ($atts) {
1329 + $data = [
1330 + 'id' => null, // This is the form id
1331 + 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total
1332 + 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read
1333 + 'with_trashed' => 'no', // yes | no
1334 + 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"]
1335 + 'hide_on_zero' => 'no',
1336 + 'payment_status' => 'all', // it can be all / specific payment status
1337 + 'currency_formatted' => 'yes',
1338 + 'date_format' => '',
1339 + ];
1340 + /* This filter is deprecated, will be removed soon */
1341 + $data = apply_filters('fluentform_info_shortcode_defaults', $data, $atts );
1342 +
1343 + $shortcodeDefaults = apply_filters('fluentform/info_shortcode_defaults', $data, $atts);
1344 +
1345 + $atts = shortcode_atts($shortcodeDefaults, $atts);
1346 + $formId = $atts['id'];
1347 + $form = wpFluent()->table('fluentform_forms')->find($formId);
1348 +
1349 + if (!$form) {
1350 + return '';
1351 + }
1352 +
1353 + if ('submission_count' == $atts['info']) {
1354 + $countQuery = wpFluent()->table('fluentform_submissions')
1355 + ->where('form_id', $formId);
1356 +
1357 + if ('trashed' != $atts['status'] && 'no' == $atts['with_trashed']) {
1358 + $countQuery = $countQuery->where('status', '!=', 'trashed');
1359 + }
1360 +
1361 + if ('all' == $atts['status']) {
1362 + // ...
1363 + } elseif ('favourites' == $atts['status']) {
1364 + $countQuery = $countQuery->where('is_favourite', '=', 1);
1365 + } else {
1366 + $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
1367 + }
1368 + if ($atts['payment_status'] && defined('FLUENTFORMPRO') && 'all' != $atts['payment_status']) {
1369 + $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
1370 + }
1371 +
1372 + $total = $countQuery->count();
1373 +
1374 + if ($atts['substract_from']) {
1375 + $total = intval($atts['substract_from']) - $total;
1376 + }
1377 +
1378 + if ('yes' == $atts['hide_on_zero'] && !$total || $total < 0) {
1379 + return '';
1380 + }
1381 +
1382 + return $total;
1383 + } elseif ('created_at' == $atts['info']) {
1384 + if ($atts['date_format']) {
1385 + $dateFormat = $atts['date_format'];
1386 + } else {
1387 + $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
1388 + }
1389 + return esc_html(date($dateFormat, strtotime($form->created_at)));
1390 + } elseif ('updated_at' == $atts['info']) {
1391 + if ($atts['date_format']) {
1392 + $dateFormat = $atts['date_format'];
1393 + } else {
1394 + $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
1395 + }
1396 + return esc_html(date($dateFormat, strtotime($form->updated_at)));
1397 + } elseif ('payment_total' == $atts['info']) {
1398 + if (!defined('FLUENTFORMPRO')) {
1399 + return '';
1400 + }
1401 +
1402 + global $wpdb;
1403 + $countQuery = wpFluent()
1404 + ->table('fluentform_submissions')
1405 + ->select(wpFluent()->raw('SUM(payment_total) as payment_total'))
1406 + ->where('form_id', $formId);
1407 +
1408 + if ('trashed' != $atts['status'] && 'no' == $atts['with_trashed']) {
1409 + $countQuery = $countQuery->where('status', '!=', 'trashed');
1410 + }
1411 +
1412 + if ('all' == $atts['status']) {
1413 + // ...
1414 + } elseif ('favourites' == $atts['status']) {
1415 + $countQuery = $countQuery->where('is_favourite', '=', 1);
1416 + } else {
1417 + $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
1418 + }
1419 +
1420 + if ('all' == $atts['payment_status']) {
1421 + // ...
1422 + } elseif ($atts['payment_status']) {
1423 + $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
1424 + }
1425 +
1426 + $row = $countQuery->first();
1427 +
1428 + $total = 0;
1429 + if ($row) {
1430 + $total = $row->payment_total;
1431 + }
1432 +
1433 + if ($atts['substract_from']) {
1434 + $total = intval($atts['substract_from'] * 100) - $total;
1435 + }
1436 +
1437 + if ('yes' == $atts['hide_on_zero'] && !$total) {
1438 + return '';
1439 + }
1440 +
1441 + if ('yes' == $atts['currency_formatted']) {
1442 + $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId);
1443 + return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency);
1444 + }
1445 +
1446 + if (!$total) {
1447 + return 0;
1448 + }
1449 +
1450 + return $total / 100;
1451 + }
1452 +
1453 + return '';
1454 + });
1455 +
1456 + $this->app->addShortCode('ff_get', function ($atts) {
1457 + $atts = shortcode_atts([
1458 + 'param' => '',
1459 + ], $atts);
1460 +
1461 + if ('' === $atts['param']) {
1462 + return '';
1463 + }
1464 +
1465 + $value = $this->app->request->get($atts['param']);
1466 +
1467 + if (null === $value || '' === $value) {
1468 + return '';
1469 + }
1470 +
1471 + return esc_html(Helper::flattenRequestValue($value));
1472 + });
1473 +
1474 + $this->app->addShortcode('ff_entry',function($atts){
1475 + ob_start();
1476 +
1477 + $atts = shortcode_atts([
1478 + 'form_id' => '',
1479 + 'serial_number' => '',
1480 + 'field' => '',
1481 + 'is_html' => true,
1482 + ], $atts);
1483 +
1484 + if (empty($atts['form_id']) || empty($atts['field'])) {
1485 + return '';
1486 + }
1487 +
1488 +
1489 + $formId = (int) $atts['form_id'];
1490 + $form = wpFluent()->table('fluentform_forms')->find($formId);
1491 + if (!$form) {
1492 + return __('Form not found.', 'fluentform');
1493 + }
1494 + $isHtml = $atts['is_html'] === 'true' ? true : false;
1495 + $submission = (new \FluentForm\App\Services\Submission\SubmissionService())->findBySerialID($formId, $atts['serial_number'],$isHtml);
1496 + if (!$submission) {
1497 + return __('No entry found.', 'fluentform');
1498 + }
1499 +
1500 + $input = $submission->user_inputs;
1501 + $field = sanitize_text_field($atts['field']);
1502 + $fieldVal = ArrayHelper::get($input, $field, '');
1503 +
1504 + $response = FormDataParser::formatValue($fieldVal);
1505 + echo $atts['is_html'] ? wp_kses_post($response) : esc_html($response);
1506 +
1507 + return ob_get_clean();
1508 + });
1509 +
1510 + }
1511 +
1512 + private function localizeJavaScriptMessages($form)
1513 + {
1514 + // Form submission messages
1515 + $submissionMessages = [
1516 + 'file_upload_in_progress' => __('File upload in progress. Please wait...', 'fluentform'),
1517 + 'javascript_handler_failed' => __('Javascript handler could not be loaded. Form submission has been failed. Reload the page and try again', 'fluentform')
1518 + ];
1519 + $submissionMessages = apply_filters('fluentform/form_submission_messages', $submissionMessages, $form);
1520 + wp_localize_script('fluent-form-submission', 'fluentform_submission_messages_' . $form->id, $submissionMessages);
1521 +
1522 + // Payment handler messages
1523 + $paymentMessages = [
1524 + 'stock_out_message' => __('This Item is Stock Out', 'fluentform'),
1525 + 'item_label' => __('Item', 'fluentform'),
1526 + 'price_label' => __('Price', 'fluentform'),
1527 + 'qty_label' => __('Qty', 'fluentform'),
1528 + 'line_total_label' => __('Line Total', 'fluentform'),
1529 + 'sub_total_label' => __('Sub Total', 'fluentform'),
1530 + 'discount_label' => __('Discount', 'fluentform'),
1531 + 'total_label' => __('Total', 'fluentform'),
1532 + 'signup_fee_label' => __('Signup Fee', 'fluentform'),
1533 + 'trial_label' => __('Trial', 'fluentform'),
1534 + 'processing_text' => __('Processing...', 'fluentform'),
1535 + 'confirming_text' => __('Confirming...', 'fluentform')
1536 + ];
1537 + $paymentMessages = apply_filters('fluentform/payment_handler_messages', $paymentMessages, $form);
1538 + wp_localize_script('fluent-form-submission', 'fluentform_payment_messages_' . $form->id, $paymentMessages);
1539 +
1540 + // Form save progress messages
1541 + $saveProgressMessages = [
1542 + 'copy_button' => __('Copy', 'fluentform'),
1543 + 'email_button' => __('Email', 'fluentform'),
1544 + 'email_placeholder' => __('Your Email Here', 'fluentform'),
1545 + 'copy_success' => __('Copied', 'fluentform')
1546 + ];
1547 + $saveProgressMessages = apply_filters('fluentform/form_save_progress_messages', $saveProgressMessages, $form);
1548 + wp_localize_script('fluent-form-submission', 'fluentform_save_progress_messages_' . $form->id, $saveProgressMessages);
1549 +
1550 + // Address autocomplete messages
1551 + $addressMessages = [
1552 + 'please_wait' => __('Please wait ...', 'fluentform'),
1553 + 'location_not_determined' => __('Could not determine address from location.', 'fluentform'),
1554 + 'address_fetch_failed' => __('Failed to fetch address from coordinates.', 'fluentform'),
1555 + 'geolocation_failed' => __('Geolocation failed or was denied.', 'fluentform'),
1556 + 'geolocation_not_supported' => __('Geolocation is not supported by this browser.', 'fluentform')
1557 + ];
1558 + $addressMessages = apply_filters('fluentform/address_autocomplete_messages', $addressMessages, $form);
1559 + wp_localize_script('fluent-form-submission', 'fluentform_address_messages_' . $form->id, $addressMessages);
1560 +
1561 + // Payment gateway messages
1562 + $gatewayMessages = [
1563 + 'request_failed' => __('Request failed. Please try again', 'fluentform'),
1564 + 'payment_failed' => __('Payment process failed!', 'fluentform'),
1565 + 'no_method_found' => __('No method found', 'fluentform'),
1566 + 'processing_text' => __('Processing...', 'fluentform')
1567 + ];
1568 + $gatewayMessages = apply_filters('fluentform/payment_gateway_messages', $gatewayMessages, $form);
1569 + wp_localize_script('fluent-form-submission', 'fluentform_gateway_messages_' . $form->id, $gatewayMessages);
1570 + }
1571 +}