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 +1012 -431 3.6.64 → 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,10 +77,10 @@
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
@@ -73,27 +85,29 @@
73 85 );
74 86
75 87 // Date Pickckr Style
76 88 //fix for essential addon event picker conflict
77 - if (!wp_script_is( 'flatpickr', 'registered' )) {
89 + if (!wp_script_is('flatpickr', 'registered')) {
78 90 wp_register_style(
79 91 'flatpickr',
80 - $app->publicUrl('libs/flatpickr/flatpickr.min.css')
92 + fluentFormMix('libs/flatpickr/flatpickr.min.css'),
93 + [],
94 + '4.6.9'
81 95 );
82 96 }
83 97 // Date Pickckr Script
84 98 wp_register_script(
85 99 'flatpickr',
86 - $app->publicUrl('libs/flatpickr/flatpickr.js'),
87 - array('jquery'),
88 - false,
100 + fluentFormMix('libs/flatpickr/flatpickr.min.js'),
101 + ['jquery'],
102 + '4.6.9',
89 103 true
90 104 );
91 105
92 106 wp_register_script(
93 107 'choices',
94 - $app->publicUrl('libs/choices/choices.min.js'),
95 - array(),
108 + fluentFormMix('libs/choices/choices.min.js'),
109 + [],
96 110 '9.0.1',
97 111 true
98 112 );
99 113
@@ -98,15 +112,33 @@
98 112 );
99 113
100 114 wp_register_style(
101 115 'ff_choices',
102 - $app->publicUrl('css/choices.css'),
116 + fluentFormMix('css/choices.css'),
103 117 [],
104 118 FLUENTFORM_VERSION
105 119 );
106 120
107 - 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 + );
108 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 +
109 141 $this->maybeLoadFluentFormStyles();
110 142 }
111 143
112 144 protected function maybeLoadFluentFormStyles()
@@ -112,49 +144,110 @@
112 144 protected function maybeLoadFluentFormStyles()
113 145 {
114 146 global $post;
115 147
116 - if (!$post) {
148 + $postId = isset($post->ID) ? $post->ID : false;
149 + if (!$postId) {
117 150 return;
118 151 }
152 + $fluentFormIds = get_post_meta($postId, '_has_fluentform', true);
153 + $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds;
119 154
120 - $fluentFormIds = get_post_meta($post->ID, '_has_fluentform', true);
121 - $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 + );
122 165
123 - if ($hasFluentformMeta || apply_filters('fluentform_load_styles', false, $post)) {
166 + if ($hasFluentformMeta || apply_filters('fluentform/load_styles', $loadStyle, $post)) {
124 167 wp_enqueue_style('fluent-form-styles');
125 - wp_enqueue_style('fluentform-public-default');
126 - do_action('fluentform_pre_load_scripts', $post);
127 - 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 + }
128 199 }
129 200 }
130 201
131 202 /**
132 203 * Get all the available components
204 + * @deprecated Use \FluentForm\App\Http\Controllers\FormController::resources
205 + * @return void
133 206 *
134 - * @return void
135 207 * @throws \Exception
136 208 * @throws \FluentForm\Framework\Exception\UnResolveableEntityException
137 209 */
138 210 public function index()
139 211 {
140 - $this->app->doAction(
212 + $formId = intval($this->app->request->get('formId'));
213 +
214 + $components = $this->app->make('components');
215 +
216 + do_action_deprecated(
141 217 'fluent_editor_init',
142 - $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.'
143 224 );
144 225
226 + $this->app->doAction('fluentform/editor_init', $components);
227 +
145 228 $editorComponents = $components->sort()->toArray();
146 - $editorComponents = $this->app->applyFilters('fluent_editor_components', $editorComponents);
147 - $countries = $this->app->load($this->app->appPath('Services/FormBuilder/CountryNames.php'));
148 229
149 - wp_send_json_success(array(
150 - 'countries' => $countries,
151 - 'components' => $editorComponents,
152 - 'disabled_components' => $this->getDisabledComponents()
153 - ));
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 + ]);
154 248 }
155 249
156 -
157 250 /**
158 251 * Get disabled components
159 252 *
160 253 * @return array
@@ -161,82 +254,185 @@
161 254 */
162 255 private function getDisabledComponents()
163 256 {
164 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);
165 260
166 - $disabled = array(
167 - 'recaptcha' => array(
168 - 'contentComponent' => 'recaptcha',
169 - 'disabled' => $isReCaptchaDisabled
170 - ),
171 - 'input_image' => array(
172 - 'disabled' => true
173 - ),
174 - 'input_file' => array(
175 - 'disabled' => true
176 - ),
177 - 'shortcode' => array(
178 - 'disabled' => true
179 - ),
180 - 'action_hook' => array(
181 - 'disabled' => true
182 - ),
183 - 'form_step' => array(
184 - 'disabled' => true
185 - )
186 - );
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 + ];
187 316
188 - if (!defined('FLUENTFORMPRO')) {
189 - $disabled['ratings'] = array(
190 - 'disabled' => true
191 - );
192 - $disabled['tabular_grid'] = array(
193 - 'disabled' => true
194 - );
195 - $disabled['phone'] = array(
196 - 'disabled' => true
197 - );
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 + }
198 424
199 - $disabled['net_promoter_score'] = array(
200 - 'disabled' => true
201 - );
202 -
203 - $disabled['repeater_field'] = array(
204 - 'disabled' => true
205 - );
206 -
207 - $disabled['custom_submit_button'] = array(
208 - 'disabled' => true
209 - );
210 -
211 - $disabled['rangeslider'] = array(
212 - 'disabled' => true
213 - );
214 -
215 - $disabled['color-picker'] = array(
216 - 'disabled' => true
217 - );
218 -
219 - $disabled['multi_payment_component'] = array(
220 - 'disabled' => true,
221 - 'is_payment' => true
222 - );
223 - $disabled['custom_payment_component'] = array(
224 - 'disabled' => true,
225 - 'is_payment' => true
226 - );
227 -
228 - $disabled['item_quantity_component'] = array(
229 - 'disabled' => true,
230 - 'is_payment' => true
231 - );
232 -
233 - $disabled['payment_method'] = array(
234 - 'disabled' => true,
235 - 'is_payment' => true
236 - );
237 - }
238 - 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);
239 435 }
240 436
241 437 /**
242 438 * Get available shortcodes for editor
@@ -241,8 +437,9 @@
241 437 /**
242 438 * Get available shortcodes for editor
243 439 *
244 440 * @return void
441 + *
245 442 * @throws \Exception
246 443 */
247 444 public function getEditorShortcodes()
248 445 {
@@ -250,11 +447,13 @@
250 447 wp_send_json_success(['shortcodes' => $editor_shortcodes], 200);
251 448 }
252 449
253 450 /**
451 + * @deprecated Use \FluentForm\App\Services\Form\FormService::shortcodes
254 452 * Get all available shortcodes for editor
255 453 *
256 454 * @return void
455 + *
257 456 * @throws \Exception
258 457 */
259 458 public function getAllEditorShortcodes()
260 459 {
@@ -265,222 +464,116 @@
265 464
266 465 /**
267 466 * Register the form renderer shortcode
268 467 *
269 - * @return void
468 + * @return void
270 469 */
271 470 public function addFluentFormShortCode()
272 471 {
273 -
274 - add_action('wp_enqueue_scripts', array($this, 'registerScripts'), 999);
472 + add_action('wp_enqueue_scripts', [$this, 'registerScripts'], 9);
275 473
276 474 $this->app->addShortCode('fluentform', function ($atts, $content) {
277 - $shortcodeDefaults = apply_filters('fluentform_shortcode_defaults', array(
278 - 'id' => null,
279 - 'title' => null,
280 - 'permission' => '',
475 + $data = [
476 + 'id' => null,
477 + 'title' => null,
478 + 'css_classes' => '',
479 + 'permission' => '',
480 + 'type' => 'classic',
481 + 'theme' => '',
281 482 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform')
282 - ), $atts);
483 + ];
484 + /* This filter is deprecated, will be removed soon */
485 + $data = apply_filters('fluentform_shortcode_defaults', $data, $atts );
283 486
284 - $atts = shortcode_atts($shortcodeDefaults, $atts);
285 - return $this->renderForm($atts);
286 - });
487 + $shortcodeDefaults = apply_filters('fluentform/shortcode_defaults', $data, $atts);
287 488
288 - $this->app->addShortCode('fluentform_info', function ($atts) {
289 - $shortcodeDefaults = apply_filters('fluentform_info_shortcode_defaults', array(
290 - 'id' => null, // This is the form id
291 - 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total
292 - 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read
293 - 'with_trashed' => 'no', // yes | no
294 - 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"]
295 - 'hide_on_zero' => 'no',
296 - 'payment_status' => 'paid', // it can be all / specific payment status
297 - 'currency_formatted' => 'yes',
298 - 'date_format' => ''
299 - ), $atts);
300 -
301 489 $atts = shortcode_atts($shortcodeDefaults, $atts);
302 - $formId = $atts['id'];
303 - $form = wpFluent()->table('fluentform_forms')->find($formId);
304 490
305 - if (!$form) {
306 - return '';
307 - }
308 -
309 - if ($atts['info'] == 'submission_count') {
310 - $countQuery = wpFluent()->table('fluentform_submissions')
311 - ->where('form_id', $formId);
312 -
313 - if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
314 - $countQuery = $countQuery->where('status', '!=', 'trashed');
315 - }
316 -
317 - if ($atts['status'] == 'all') {
318 - // ...
319 - } else if ($atts['status'] == 'favourites') {
320 - $countQuery = $countQuery->where('is_favourite', '=', 1);
321 - } else {
322 - $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status']));
323 - }
324 -
325 - $total = $countQuery->count();
326 -
327 - if ($atts['substract_from']) {
328 - $total = intval($atts['substract_from']) - $total;
329 - }
330 -
331 - if ($atts['hide_on_zero'] == 'yes' && !$total || $total < 0) {
332 - return '';
333 - }
334 -
335 - return $total;
336 - } else if ($atts['info'] == 'created_at') {
337 - if ($atts['date_format']) {
338 - $dateFormat = $atts['date_format'];
339 - } else {
340 - $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
341 - }
342 - return date($dateFormat, strtotime($form->created_at));
343 - } else if ($atts['info'] == 'updated_at') {
344 - if ($atts['date_format']) {
345 - $dateFormat = $atts['date_format'];
346 - } else {
347 - $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
348 - }
349 - return date($dateFormat, strtotime($form->updated_at));
350 - } else if ($atts['info'] == 'payment_total') {
351 -
352 - if (!defined('FLUENTFORMPRO')) {
353 - return '';
354 - }
355 -
356 - global $wpdb;
357 - $countQuery = wpFluent()
358 - ->table('fluentform_submissions')
359 - ->select(wpFluent()->raw('SUM(total_paid) as payment_total'))
360 - ->where('form_id', $formId);
361 -
362 - if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
363 - $countQuery = $countQuery->where('status', '!=', 'trashed');
364 - }
365 -
366 - if ($atts['status'] == 'all') {
367 - // ...
368 - } else if ($atts['status'] == 'favourites') {
369 - $countQuery = $countQuery->where('is_favourite', '=', 1);
370 - } else {
371 - $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status']));
372 - }
373 -
374 - if ($atts['payment_status'] == 'all') {
375 - // ...
376 - } else if ($atts['payment_status']) {
377 - $countQuery = $countQuery->where('payment_status', '=', sanitize_text_field($atts['payment_status']));
378 - }
379 -
380 - $row = $countQuery->first();
381 -
382 - $total = 0;
383 - if ($row) {
384 - $total = $row->payment_total;
385 - }
386 -
387 - if ($atts['substract_from']) {
388 - $total = intval($atts['substract_from'] * 100) - $total;
389 - }
390 -
391 - if ($atts['hide_on_zero'] == 'yes' && !$total) {
392 - return '';
393 - }
394 -
395 - if ($atts['currency_formatted'] == 'yes') {
396 - $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId);
397 - return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency);
398 - }
399 -
400 - if (!$total) {
401 - return 0;
402 - }
403 -
404 - return $total / 100;
405 - }
406 -
407 - return '';
491 + return $this->renderForm($atts);
408 492 });
409 -
410 - $this->app->addShortCode('ff_get', function ($atts) {
411 - $atts = shortcode_atts(array(
412 - 'param' => '',
413 - ), $atts);
414 - if ($atts['param'] && isset($_GET[$atts['param']])) {
415 - $value = $_GET[$atts['param']];
416 - if (is_array($value)) {
417 - return implode(', ', $value);
418 - }
419 - return esc_html($value);
420 - }
421 - return '';
422 - });
423 -
493 +
494 + $this->registerHelperShortCodes();
424 495 }
425 496
426 497 public function renderForm($atts)
427 498 {
428 499 $form_id = $atts['id'];
429 -
500 + $query = wpFluent()->table('fluentform_forms');
501 +
502 + if (! $this->app->request->get('preview_id')) {
503 + $query->where('status', 'published');
504 + }
505 +
430 506 if ($form_id) {
431 - $form = wpFluent()->table('fluentform_forms')->find($form_id);
432 - } else if ($formTitle = $atts['title']) {
433 - $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();
434 510 } else {
435 - return;
511 + return '';
436 512 }
437 513
438 514 if (!$form) {
439 - return;
515 + return '';
440 516 }
441 517
442 518 if (!empty($atts['permission'])) {
443 519 if (!current_user_can($atts['permission'])) {
444 - 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']);
445 521 }
446 522 }
447 523
448 - if(is_feed()) {
524 + if (is_feed()) {
449 525 global $post;
450 - $feedText = sprintf( __( 'The form can be filled in the actual <a href="%s">website url</a>.', 'fluentform' ), get_permalink($post));
451 - $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);
452 541 return $feedText;
453 542 }
543 +
544 + $form->settings = Helper::getFormMeta($form->id, 'formSettings', []);
454 545
455 - $formSettings = wpFluent()
456 - ->table('fluentform_form_meta')
457 - ->where('form_id', $form_id)
458 - ->where('meta_key', 'formSettings')
459 - ->first();
460 -
461 - if (!$formSettings) {
462 - return;
546 + if (empty($form->settings)) {
547 + return '';
463 548 }
464 549
465 550 $form->fields = json_decode($form->form_fields, true);
466 -
467 - if (!$form->fields['fields']) {
468 - return;
551 + if (!is_array($form->fields) || empty($form->fields['fields'])) {
552 + return '';
469 553 }
470 554
471 - $form->settings = json_decode($formSettings->value, true);
472 - $form = $this->app->applyFilters('fluentform_rendering_form', $form);
473 -
474 - $isRenderable = array(
475 - 'status' => true,
476 - '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.'
477 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);
478 573
479 - $isRenderable = $this->app->applyFilters('fluentform_is_form_renderable', $isRenderable, $form);
480 -
481 574 if (is_array($isRenderable) && !$isRenderable['status']) {
482 - return "<div id='ff_form_{$form->id}' class='ff_form_not_render'>{$isRenderable['message']}</div>";
575 + return $this->getNotRenderableHtml($form->id, $isRenderable['message']);
483 576 }
484 577
485 578 $instanceCssClass = Helper::getFormInstaceClass($form->id);
486 579
@@ -486,10 +579,21 @@
486 579
487 580 $form->instance_css_class = $instanceCssClass;
488 581 $form->instance_index = Helper::$formInstance;
489 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 +
490 590 $formBuilder = $this->app->make('formBuilder');
491 - $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 +
492 596 $output = $this->replaceEditorSmartCodes($output, $form);
493 597
494 598 if (!wp_script_is('fluent-form-submission', 'registered')) {
495 599 $this->registerScripts();
@@ -495,9 +599,22 @@
495 599 $this->registerScripts();
496 600 }
497 601
498 602 wp_enqueue_style('fluent-form-styles');
499 - 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)) {
500 617 wp_enqueue_style('fluentform-public-default');
501 618 }
502 619 /*
503 620 * We will load fluentform-advanced if the form has certain fields or feature
@@ -502,167 +619,331 @@
502 619 /*
503 620 * We will load fluentform-advanced if the form has certain fields or feature
504 621 */
505 622 $this->maybeHasAdvandedFields($form, $formBuilder);
506 - wp_enqueue_script('fluent-form-submission');
623 + if (!Helper::isElementorEditor()) {
624 + wp_enqueue_script('fluent-form-submission');
625 + }
507 626
627 + /* translators: %activeStep% is the current step number, %totalStep% is the total number of steps, %stepTitle% is the step title */
508 628 $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', 'fluentform');
509 - $stepText = apply_filters('fluentform_step_string', $stepText);
510 - $vars = apply_filters('fluentform_global_form_vars', array(
511 - 'ajaxUrl' => admin_url('admin-ajax.php'),
512 - 'forms' => array(),
513 - 'step_text' => $stepText,
514 - 'is_rtl' => is_rtl(),
515 - 'date_i18n' => $this->getDatei18n(),
516 - 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false,
517 - 'fluentform_version' => FLUENTFORM_VERSION,
518 - 'force_init' => false,
519 - 'stepAnimationDuration' => 350,
520 - 'upload_completed_txt' => __('100% Completed', 'fluentform'),
521 - 'upload_start_txt' => __('0% Completed', 'fluentform'),
522 - 'uploading_txt' => __('Uploading', 'fluentform'),
523 - 'choice_js_vars' => [
524 - 'noResultsText' => __('No results found', 'fluentform'),
525 - 'loadingText' => __('Loading...', 'fluentform'),
526 - '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'),
527 660 'itemSelectText' => __('Press to select', 'fluentform'),
528 - 'maxItemTextLang' => 'Only %%maxItemCount%% values can be added'
529 - ]
530 - ));
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 + );
531 684
532 - wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars);
685 + $vars = apply_filters('fluentform/global_form_vars', $data);
533 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 +
534 714 $formSettings = $form->settings;
535 715
536 716 $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']);
537 717
718 + // Ensure restrictions array exists before setting denyEmptySubmission
719 + if (!isset($formSettings['restrictions']) || !is_array($formSettings['restrictions'])) {
720 + $formSettings['restrictions'] = [];
721 + }
722 +
538 723 $formSettings['restrictions']['denyEmptySubmission'] = [
539 - 'enabled' => false
724 + 'enabled' => false,
540 725 ];
541 726
542 - $form_vars = array(
543 - 'id' => $form->id,
544 - 'settings' => $formSettings,
545 - '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,
546 738 'form_id_selector' => 'fluentform_' . $form->id,
547 - 'rules' => $formBuilder->validationRules
548 - );
739 + 'rules' => $formBuilder->validationRules,
740 + 'debounce_time' => apply_filters('fluentform/show_hide_elements_debounce_time', 300),
741 + ];
549 742
550 743 if ($conditionals = $formBuilder->conditions) {
551 744 $form_vars['conditionals'] = $conditionals;
552 745 }
553 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 +
554 755 if ($form->has_payment) {
555 - 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);
556 766 }
557 767
558 768 $otherScripts = '';
559 - ob_start();
560 - ?>
561 - <script type="text/javascript">
562 - window.fluent_form_<?php echo $instanceCssClass; ?> = <?php echo json_encode($form_vars);?>;
563 - <?php if(wp_doing_ajax()): ?>
564 - function initFFInstance_<?php echo $form_vars['id']; ?>() {
565 - if(!window.fluentFormApp) {
566 - console.log('No fluentFormApp found');
567 - 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 + }
568 788 }
569 - var ajax_formInstance = window.fluentFormApp(jQuery('form.<?php echo $form_vars['form_instance']; ?>'));
570 - if (ajax_formInstance) {
571 - ajax_formInstance.initFormHandlers();
572 - }
573 - }
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 + }
574 801
575 - initFFInstance_<?php echo $form_vars['id']; ?>();
576 - <?php endif; ?>
577 - </script>
578 - <?php
579 - $this->addInlineVars();
580 - $otherScripts .= ob_get_clean();
581 802
582 - 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)) {
583 814 if (!Acl::hasAnyFormPermission($form->id)) {
584 - (new \FluentForm\App\Modules\Form\Analytics($this->app))->record($form->id);
815 + (new \FluentForm\App\Services\Analytics\AnalyticsService())->store($form->id);
585 816 }
586 817 }
818 +
587 819 return $output . $otherScripts;
588 820 }
589 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 +
590 829 /**
591 830 * Process the output HTML to generate the default values.
592 831 *
593 - * @param string $output
832 + * @param string $output
594 833 * @param \stdClass $form
834 + *
595 835 * @return string
596 836 */
597 837 public function replaceEditorSmartCodes($output, $form)
598 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 +
599 849 // Get the patterns for default values from the output HTML string.
600 850 // The example of a pattern would be for user ID: {user.ID}
601 851 preg_match_all('/{(.*?)}/', $output, $matches);
602 852 $patterns = array_unique($matches[0]);
603 853
604 -
605 854 $attrDefaultValues = [];
606 855
607 856 foreach ($patterns as $pattern) {
608 857 // The default value for each pattern will be resolved here.
609 - $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);
610 870 }
611 871
612 872 // Raising an event so that others can hook into it and modify the default values later.
613 - $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 + );
614 882
883 + $attrDefaultValues = (array) apply_filters('fluentform/parse_default_values', $attrDefaultValues);
884 +
615 885 if (isset($attrDefaultValues['{payment_total}'])) {
616 886 $attrDefaultValues['{payment_total}'] = '<span class="ff_order_total"></span>';
617 887 }
618 888
619 - // Finally, replace the patterns with the replacements and return the output HTML.
620 - 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);
621 900 }
622 901
623 902 /**
624 903 * Register renderer actions for compiling each element
625 904 *
626 - * @return void
905 + * @return void
627 906 */
628 907 public function addRendererActions()
629 908 {
630 909 $actionMappings = [
631 - 'Select@compile' => ['fluentform_render_item_select'],
632 - 'Rating@compile' => ['fluentform_render_item_ratings'],
633 - 'Address@compile' => ['fluentform_render_item_address'],
634 - 'Name@compile' => ['fluentform_render_item_input_name'],
635 - 'TextArea@compile' => ['fluentform_render_item_textarea'],
636 - 'DateTime@compile' => ['fluentform_render_item_input_date'],
637 - 'Recaptcha@compile' => ['fluentform_render_item_recaptcha'],
638 - 'Container@compile' => ['fluentform_render_item_container'],
639 - 'CustomHtml@compile' => ['fluentform_render_item_custom_html'],
640 - 'SectionBreak@compile' => ['fluentform_render_item_section_break'],
641 - 'SubmitButton@compile' => ['fluentform_render_item_submit_button'],
642 - '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'],
643 924
644 925 'TermsAndConditions@compile' => [
645 - 'fluentform_render_item_terms_and_condition',
646 - 'fluentform_render_item_gdpr_agreement'
926 + 'fluentform/render_item_terms_and_condition',
927 + 'fluentform/render_item_gdpr_agreement',
647 928 ],
648 929
649 930 'TabularGrid@compile' => [
650 - 'fluentform_render_item_tabular_grid'
931 + 'fluentform/render_item_tabular_grid',
651 932 ],
652 933
653 934 'Checkable@compile' => [
654 - 'fluentform_render_item_input_radio',
655 - 'fluentform_render_item_input_checkbox',
935 + 'fluentform/render_item_input_radio',
936 + 'fluentform/render_item_input_checkbox',
656 937 ],
657 938
658 939 'Text@compile' => [
659 - 'fluentform_render_item_input_url',
660 - 'fluentform_render_item_input_text',
661 - 'fluentform_render_item_input_email',
662 - 'fluentform_render_item_input_number',
663 - 'fluentform_render_item_input_hidden',
664 - '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',
665 946 ],
666 947 ];
667 948
668 949 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
@@ -668,10 +949,10 @@
668 949 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
669 950 foreach ($actionMappings as $handler => $actions) {
670 951 foreach ($actions as $action) {
671 952 $this->app->addAction($action, function () use ($path, $handler) {
672 - list($class, $method) = $this->app->parseHandler($path . $handler);
673 - 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());
674 955 }, 10, 2);
675 956 }
676 957 }
677 958 }
@@ -678,30 +959,47 @@
678 959
679 960 /**
680 961 * Register dynamic value shortcode parser (filter default value)
681 962 *
682 - * @return void
963 + * @return void
683 964 */
684 965 public function addFluentFormDefaultValueParser()
685 966 {
686 - $this->app->addFilter('fluentform_parse_default_value', function ($value, $form) {
967 + $this->app->addFilter('fluentform/parse_default_value', function ($value, $form) {
687 968 return EditorShortcodeParser::filter($value, $form);
688 969 }, 10, 2);
689 970 }
690 971
691 972 /**
692 - * Register filter to check whether the form is renderable
973 + * Register filter to check whether the form is renderable or active
693 974 *
694 - * @return mixed
975 + * @return mixed
695 976 */
696 977 public function addIsRenderableFilter()
697 978 {
698 - $this->app->addFilter('fluentform_is_form_renderable', function ($isRenderable, $form) {
699 - $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 + }
700 986
701 - 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) {
702 1000 if (in_array($key, $checkables)) {
703 - $isRenderable['status'] = $this->{$key}($restrictions, $form, $isRenderable);
1001 + $isRenderable['status'] = $this->{$key}($restrictionSettings, $form, $isRenderable);
704 1002 if (!$isRenderable['status']) {
705 1003 $isRenderable['status'] = false;
706 1004 return $isRenderable;
707 1005 }
@@ -706,8 +1004,12 @@
706 1004 return $isRenderable;
707 1005 }
708 1006 }
709 1007 }
1008 + if($form->status == 'unpublished'){
1009 + $isRenderable['status'] = false;
1010 + $isRenderable['message'] = apply_filters('fluentform/unpublished_form_submission_message',__('Invalid Form!', 'fluentform'));
1011 + }
710 1012
711 1013 return $isRenderable;
712 1014 }, 10, 2);
713 1015 }
@@ -720,12 +1022,14 @@
720 1022 * @return bool
721 1023 */
722 1024 private function limitNumberOfEntries($restrictions, $form, &$isRenderable)
723 1025 {
724 - if (!$restrictions['enabled']) {
1026 +
1027 + if (!Arr::isTrue($restrictions, 'enabled') || !isset($restrictions['period']) || !isset($restrictions['numberOfEntries'])) {
725 1028 return true;
726 1029 }
727 1030
1031 +
728 1032 $col = 'created_at';
729 1033 $period = $restrictions['period'];
730 1034 $maxAllowedEntries = $restrictions['numberOfEntries'];
731 1035
@@ -736,27 +1040,27 @@
736 1040 $query = wpFluent()->table('fluentform_submissions')
737 1041 ->where('form_id', $form->id)
738 1042 ->where('status', '!=', 'trashed');
739 1043
740 - if ($period == 'day') {
1044 + if ('day' == $period) {
741 1045 $year = "YEAR(`{$col}`) = YEAR(NOW())";
742 1046 $month = "MONTH(`{$col}`) = MONTH(NOW())";
743 1047 $day = "DAY(`{$col}`) = DAY(NOW())";
744 - $query->where(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
745 - } elseif ($period == 'week') {
746 - $query->where(
1048 + $query->whereRaw(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
1049 + } elseif ('week' == $period) {
1050 + $query->whereRaw(
747 1051 wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)")
748 1052 );
749 - } elseif ($period == 'month') {
1053 + } elseif ('month' == $period) {
750 1054 $year = "YEAR(`{$col}`) = YEAR(NOW())";
751 1055 $month = "MONTH(`{$col}`) = MONTH(NOW())";
752 - $query->where(wpFluent()->raw("{$year} AND {$month}"));
753 - } elseif ($period == 'year') {
754 - $query->where(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())"));
755 - } 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) {
756 1060 $ip = $this->app->request->getIp();
757 1061 $query->where('ip', $ip);
758 - } else if ($period == 'per_user_id') {
1062 + } elseif ('per_user_id' == $period) {
759 1063 $userId = get_current_user_id();
760 1064 if (!$userId) {
761 1065 return true;
762 1066 }
@@ -764,11 +1068,10 @@
764 1068 }
765 1069
766 1070 $count = $query->count();
767 1071
768 -
769 1072 if ($count >= $maxAllowedEntries) {
770 - $isRenderable['message'] = $restrictions['limitReachedMsg'];
1073 + $isRenderable['message'] = apply_filters('fluentform/entry_limit_reached_message', $restrictions['limitReachedMsg'], $form);
771 1074 return false;
772 1075 }
773 1076
774 1077 return true;
@@ -774,9 +1077,9 @@
774 1077 return true;
775 1078 }
776 1079
777 1080 /**
778 - * Check if form has scheduled date and open for submission
1081 + * Check if form has scheduled date & weekdays and open for submission
779 1082 *
780 1083 * @param array $restrictions
781 1084 *
782 1085 * @return bool
@@ -782,9 +1085,9 @@
782 1085 * @return bool
783 1086 */
784 1087 private function scheduleForm($restrictions, $form, &$isRenderable)
785 1088 {
786 - if (!$restrictions['enabled']) {
1089 + if (!Arr::isTrue($restrictions, 'enabled')) {
787 1090 return true;
788 1091 }
789 1092
790 1093 $time = time();
@@ -791,16 +1094,23 @@
791 1094 $start = strtotime($restrictions['start']);
792 1095 $end = strtotime($restrictions['end']);
793 1096
794 1097 if ($time < $start) {
795 - $isRenderable['message'] = $restrictions['pendingMsg'];
1098 + $isRenderable['message'] = apply_filters('fluentform/schedule_form_pending_message', $restrictions['pendingMsg'], $form->id);
1099 + return false;
1100 + }
796 1101
1102 + if ($time >= $end) {
1103 + $isRenderable['message'] = apply_filters('fluentform/schedule_form_expired_message', $restrictions['expiredMsg'], $form->id);
1104 +
797 1105 return false;
798 1106 }
799 1107
800 - 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)) {
801 1112 $isRenderable['message'] = $restrictions['expiredMsg'];
802 -
803 1113 return false;
804 1114 }
805 1115
806 1116 return true;
@@ -814,14 +1124,14 @@
814 1124 * @return bool
815 1125 */
816 1126 private function requireLogin($restrictions, $form, &$isRenderable)
817 1127 {
818 - if (!$restrictions['enabled']) {
1128 + if (!Arr::isTrue($restrictions, 'enabled')) {
819 1129 return true;
820 1130 }
821 1131
822 1132 if (!($isLoggedIn = is_user_logged_in())) {
823 - $isRenderable['message'] = $restrictions['requireLoginMsg'];
1133 + $isRenderable['message'] = apply_filters('fluentform/form_requires_login_message', $restrictions['requireLoginMsg'], $form);
824 1134 }
825 1135
826 1136 return $isLoggedIn;
827 1137 }
@@ -828,9 +1138,9 @@
828 1138
829 1139 /**
830 1140 * Register fluentform_submission_inserted actions
831 1141 *
832 - * @return void
1142 + * @return void
833 1143 */
834 1144 public function addFluentformSubmissionInsertedFilter()
835 1145 {
836 1146 (new EmailNotificationActions($this->app))->register();
@@ -838,16 +1148,22 @@
838 1148
839 1149 /**
840 1150 * Add inline scripts [Add localized script using same var]
841 1151 *
842 - * @return void
1152 + * @return void
843 1153 */
844 1154 private function addInlineVars()
845 1155 {
846 - if (!defined('ELEMENTOR_PRO_VERSION')) {
1156 + if (!defined('ELEMENTOR_PRO_VERSION') || $this->elementorPopUpHandler) {
847 1157 return '';
848 1158 }
849 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 +
850 1166 $actionName = 'wp_footer';
851 1167 if (is_admin()) {
852 1168 $actionName = 'admin_footer';
853 1169 }
@@ -854,13 +1170,28 @@
854 1170
855 1171 add_action($actionName, function () {
856 1172 ?>
857 1173 <script type="text/javascript">
858 - <?php if(defined('ELEMENTOR_PRO_VERSION')): ?>
859 - jQuery(document).on('elementor/popup/show', function (event, id, instance) {
860 - 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 + }
861 1192 if (ffForms.length) {
862 - jQuery.each(ffForms, function (index, ffForm) {
1193 + jQuery.each(ffForms, function(index, ffForm) {
863 1194 jQuery(ffForm).trigger('reInitExtras');
864 1195 jQuery(document).trigger('ff_reinit', [ffForm]);
865 1196 });
866 1197 }
@@ -871,14 +1202,14 @@
871 1202 }, 999);
872 1203 return '';
873 1204 }
874 1205
875 - private function getDatei18n()
1206 + public static function getDatei18n()
876 1207 {
877 - $i18n = array(
1208 + $i18n = [
878 1209 'previousMonth' => __('Previous Month', 'fluentform'),
879 - 'nextMonth' => __('Next Month', 'fluentform'),
880 - 'months' => [
1210 + 'nextMonth' => __('Next Month', 'fluentform'),
1211 + 'months' => [
881 1212 'shorthand' => [
882 1213 __('Jan', 'fluentform'),
883 1214 __('Feb', 'fluentform'),
884 1215 __('Mar', 'fluentform'),
@@ -889,9 +1220,9 @@
889 1220 __('Aug', 'fluentform'),
890 1221 __('Sep', 'fluentform'),
891 1222 __('Oct', 'fluentform'),
892 1223 __('Nov', 'fluentform'),
893 - __('Dec', 'fluentform')
1224 + __('Dec', 'fluentform'),
894 1225 ],
895 1226 'longhand' => [
896 1227 __('January', 'fluentform'),
897 1228 __('February', 'fluentform'),
@@ -903,13 +1234,13 @@
903 1234 __('August', 'fluentform'),
904 1235 __('September', 'fluentform'),
905 1236 __('October', 'fluentform'),
906 1237 __('November', 'fluentform'),
907 - __('December', 'fluentform')
908 - ]
1238 + __('December', 'fluentform'),
1239 + ],
909 1240 ],
910 1241 'weekdays' => [
911 - 'longhand' => array(
1242 + 'longhand' => [
912 1243 __('Sunday', 'fluentform'),
913 1244 __('Monday', 'fluentform'),
914 1245 __('Tuesday', 'fluentform'),
915 1246 __('Wednesday', 'fluentform'),
@@ -914,11 +1245,11 @@
914 1245 __('Tuesday', 'fluentform'),
915 1246 __('Wednesday', 'fluentform'),
916 1247 __('Thursday', 'fluentform'),
917 1248 __('Friday', 'fluentform'),
918 - __('Saturday', 'fluentform')
919 - ),
920 - 'shorthand' => array(
1249 + __('Saturday', 'fluentform'),
1250 + ],
1251 + 'shorthand' => [
921 1252 __('Sun', 'fluentform'),
922 1253 __('Mon', 'fluentform'),
923 1254 __('Tue', 'fluentform'),
924 1255 __('Wed', 'fluentform'),
@@ -923,10 +1254,10 @@
923 1254 __('Tue', 'fluentform'),
924 1255 __('Wed', 'fluentform'),
925 1256 __('Thu', 'fluentform'),
926 1257 __('Fri', 'fluentform'),
927 - __('Sat', 'fluentform')
928 - )
1258 + __('Sat', 'fluentform'),
1259 + ],
929 1260 ],
930 1261 'daysInMonth' => [
931 1262 31,
932 1263 28,
@@ -938,20 +1269,21 @@
938 1269 31,
939 1270 30,
940 1271 31,
941 1272 30,
942 - 31
1273 + 31,
943 1274 ],
944 - 'rangeSeparator' => __(' to ', 'fluentform'),
1275 + 'rangeSeparator' => __(' to ', 'fluentform'),
945 1276 'weekAbbreviation' => __('Wk', 'fluentform'),
946 - 'scrollTitle' => __('Scroll to increment', 'fluentform'),
947 - 'toggleTitle' => __('Click to toggle', 'fluentform'),
948 - 'amPM' => [
1277 + 'scrollTitle' => __('Scroll to increment', 'fluentform'),
1278 + 'toggleTitle' => __('Click to toggle', 'fluentform'),
1279 + 'amPM' => [
949 1280 __('AM', 'fluentform'),
950 - __('PM', 'fluentform')
1281 + __('PM', 'fluentform'),
951 1282 ],
952 - 'yearAriaLabel' => __('Year', 'fluentform')
953 - );
1283 + 'yearAriaLabel' => __('Year', 'fluentform'),
1284 + 'firstDayOfWeek' => (int) get_option('start_of_week'),
1285 + ];
954 1286
955 1287 return apply_filters('fluentform/date_i18n', $i18n);
956 1288 }
957 1289
@@ -964,12 +1296,14 @@
964 1296 'form_step',
965 1297 'input_file',
966 1298 'input_image',
967 1299 'net_promoter_score',
968 - 'featured_image'
1300 + 'featured_image',
969 1301 ];
970 -
971 - 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))) {
972 1306 wp_enqueue_script('fluentform-advanced');
973 1307 }
974 1308 }
975 1309
@@ -974,17 +1308,264 @@
974 1308 }
975 1309
976 1310 public function registerInputSanitizers()
977 1311 {
978 - add_filter('fluentform_input_data_input_number', array($this, 'getNumericInputValue'), 10, 2);
979 - 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);
980 1314 }
981 1315
982 1316 public function getNumericInputValue($value, $field)
983 1317 {
984 1318 $formatter = ArrayHelper::get($field, 'raw.settings.numeric_formatter');
985 - if(!$formatter) {
1319 + if (!$formatter) {
986 1320 return $value;
987 1321 }
988 1322 return Helper::getNumericValue($value, $formatter);
1323 + }
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);
989 1570 }
990 1571 }