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
fluentform / app / Modules / Component / Component.php

Component.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.15, at app/Modules/Component/Component.php

1,572 lines 61.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Modules\Component;
4
5 defined('ABSPATH') or die;
6
7 use FluentForm\App\Helpers\Helper;
8 use FluentForm\App\Modules\Acl\Acl;
9 use FluentForm\App\Modules\Form\FormDataParser;
10 use FluentForm\App\Services\FormBuilder\EditorShortcodeParser;
11 use FluentForm\App\Services\FormBuilder\Notifications\EmailNotificationActions;
12 use FluentForm\Framework\Foundation\Application;
13 use FluentForm\Framework\Helpers\ArrayHelper;
14 use FluentForm\Framework\Helpers\ArrayHelper as Arr;
15
16
17 class Component
18 {
19 /**
20 * FluentForm\Framework\Foundation\Application
21 *
22 * @var $app
23 */
24 protected $app = null;
25
26 /**
27 * Determine whether to register Elementor PopUp handler.
28 *
29 * @var bool
30 */
31 protected $elementorPopUpHandler = false;
32
33 /**
34 * Biuld the instance of this class
35 *
36 * @param \FluentForm\Framework\Foundation\Application $app
37 */
38 public function __construct(Application $app)
39 {
40 $this->app = $app;
41 }
42
43 public function registerScripts()
44 {
45 $app = $this->app;
46
47 // We will just register the scripts here. We will not load any scripts from here
48
49 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public.css');
50 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default.css');
51
52 if (is_rtl()) {
53 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public-rtl.css');
54 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default-rtl.css');
55 }
56
57 wp_register_style(
58 'fluent-form-styles',
59 $fluentFormPublicCss,
60 [],
61 FLUENTFORM_VERSION
62 );
63
64 wp_register_style(
65 'fluentform-public-default',
66 $fluentFormPublicDefaultCss,
67 [],
68 FLUENTFORM_VERSION
69 );
70
71 wp_register_script(
72 'fluent-form-submission',
73 fluentFormMix('js/form-submission.js'),
74 ['jquery'],
75 FLUENTFORM_VERSION,
76 true
77 );
78
79 wp_register_script(
80 'fluentform-advanced',
81 fluentFormMix('js/fluentform-advanced.js'),
82 ['jquery'],
83 FLUENTFORM_VERSION,
84 true
85 );
86
87 // Date Pickckr Style
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 }
97 // Date Pickckr Script
98 wp_register_script(
99 'flatpickr',
100 fluentFormMix('libs/flatpickr/flatpickr.min.js'),
101 ['jquery'],
102 '4.6.9',
103 true
104 );
105
106 wp_register_script(
107 'choices',
108 fluentFormMix('libs/choices/choices.min.js'),
109 [],
110 '9.0.1',
111 true
112 );
113
114 wp_register_style(
115 'ff_choices',
116 fluentFormMix('css/choices.css'),
117 [],
118 FLUENTFORM_VERSION
119 );
120
121 wp_register_script(
122 'form-save-progress',
123 fluentFormMix('js/form-save-progress.js'),
124 ['jquery'],
125 FLUENTFORM_VERSION,
126 true
127 );
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
141 $this->maybeLoadFluentFormStyles();
142 }
143
144 protected function maybeLoadFluentFormStyles()
145 {
146 global $post;
147
148 $postId = isset($post->ID) ? $post->ID : false;
149 if (!$postId) {
150 return;
151 }
152 $fluentFormIds = get_post_meta($postId, '_has_fluentform', true);
153 $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds;
154
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 );
165
166 if ($hasFluentformMeta || apply_filters('fluentform/load_styles', $loadStyle, $post)) {
167 wp_enqueue_style('fluent-form-styles');
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 }
199 }
200 }
201
202 /**
203 * Get all the available components
204 * @deprecated Use \FluentForm\App\Http\Controllers\FormController::resources
205 * @return void
206 *
207 * @throws \Exception
208 * @throws \FluentForm\Framework\Exception\UnResolveableEntityException
209 */
210 public function index()
211 {
212 $formId = intval($this->app->request->get('formId'));
213
214 $components = $this->app->make('components');
215
216 do_action_deprecated(
217 'fluent_editor_init',
218 [
219 $components
220 ],
221 FLUENTFORM_FRAMEWORK_UPGRADE,
222 'fluentform/editor_init',
223 'Use fluentform/editor_init instead of fluent_editor_init.'
224 );
225
226 $this->app->doAction('fluentform/editor_init', $components);
227
228 $editorComponents = $components->sort()->toArray();
229
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 ]);
248 }
249
250 /**
251 * Get disabled components
252 *
253 * @return array
254 */
255 private function getDisabledComponents()
256 {
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);
260
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 ];
316
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 }
424
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);
435 }
436
437 /**
438 * Get available shortcodes for editor
439 *
440 * @return void
441 *
442 * @throws \Exception
443 */
444 public function getEditorShortcodes()
445 {
446 $editor_shortcodes = fluentFormEditorShortCodes();
447 wp_send_json_success(['shortcodes' => $editor_shortcodes], 200);
448 }
449
450 /**
451 * @deprecated Use \FluentForm\App\Services\Form\FormService::shortcodes
452 * Get all available shortcodes for editor
453 *
454 * @return void
455 *
456 * @throws \Exception
457 */
458 public function getAllEditorShortcodes()
459 {
460 wp_send_json(fluentFormGetAllEditorShortCodes(
461 $this->app->request->get('formId')
462 ), 200);
463 }
464
465 /**
466 * Register the form renderer shortcode
467 *
468 * @return void
469 */
470 public function addFluentFormShortCode()
471 {
472 add_action('wp_enqueue_scripts', [$this, 'registerScripts'], 9);
473
474 $this->app->addShortCode('fluentform', function ($atts, $content) {
475 $data = [
476 'id' => null,
477 'title' => null,
478 'css_classes' => '',
479 'permission' => '',
480 'type' => 'classic',
481 'theme' => '',
482 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform')
483 ];
484 /* This filter is deprecated, will be removed soon */
485 $data = apply_filters('fluentform_shortcode_defaults', $data, $atts );
486
487 $shortcodeDefaults = apply_filters('fluentform/shortcode_defaults', $data, $atts);
488
489 $atts = shortcode_atts($shortcodeDefaults, $atts);
490
491 return $this->renderForm($atts);
492 });
493
494 $this->registerHelperShortCodes();
495 }
496
497 public function renderForm($atts)
498 {
499 $form_id = $atts['id'];
500 $query = wpFluent()->table('fluentform_forms');
501
502 if (! $this->app->request->get('preview_id')) {
503 $query->where('status', 'published');
504 }
505
506 if ($form_id) {
507 $form = $query->find($form_id);
508 } elseif ($formTitle = $atts['title']) {
509 $form = $query->where('title', $formTitle)->first();
510 } else {
511 return '';
512 }
513
514 if (!$form) {
515 return '';
516 }
517
518 if (!empty($atts['permission'])) {
519 if (!current_user_can($atts['permission'])) {
520 return $this->getNotRenderableHtml($form->id, $atts['permission_message']);
521 }
522 }
523
524 if (is_feed()) {
525 global $post;
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);
541 return $feedText;
542 }
543
544 $form->settings = Helper::getFormMeta($form->id, 'formSettings', []);
545
546 if (empty($form->settings)) {
547 return '';
548 }
549
550 $form->fields = json_decode($form->form_fields, true);
551 if (!is_array($form->fields) || empty($form->fields['fields'])) {
552 return '';
553 }
554
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.'
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);
573
574 if (is_array($isRenderable) && !$isRenderable['status']) {
575 return $this->getNotRenderableHtml($form->id, $isRenderable['message']);
576 }
577
578 $instanceCssClass = Helper::getFormInstaceClass($form->id);
579
580 $form->instance_css_class = $instanceCssClass;
581 $form->instance_index = Helper::$formInstance;
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
590 $formBuilder = $this->app->make('formBuilder');
591
592 $cssClasses = trim($instanceCssClass . ' ff-form-loading');
593
594 $output = $formBuilder->build($form, $cssClasses, $instanceCssClass, $atts);
595
596 $output = $this->replaceEditorSmartCodes($output, $form);
597
598 if (!wp_script_is('fluent-form-submission', 'registered')) {
599 $this->registerScripts();
600 }
601
602 wp_enqueue_style('fluent-form-styles');
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)) {
617 wp_enqueue_style('fluentform-public-default');
618 }
619 /*
620 * We will load fluentform-advanced if the form has certain fields or feature
621 */
622 $this->maybeHasAdvandedFields($form, $formBuilder);
623 if (!Helper::isElementorEditor()) {
624 wp_enqueue_script('fluent-form-submission');
625 }
626
627 /* translators: %activeStep% is the current step number, %totalStep% is the total number of steps, %stepTitle% is the step title */
628 $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', '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'),
660 'itemSelectText' => __('Press to select', 'fluentform'),
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 );
684
685 $vars = apply_filters('fluentform/global_form_vars', $data);
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
714 $formSettings = $form->settings;
715
716 $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']);
717
718 // Ensure restrictions array exists before setting denyEmptySubmission
719 if (!isset($formSettings['restrictions']) || !is_array($formSettings['restrictions'])) {
720 $formSettings['restrictions'] = [];
721 }
722
723 $formSettings['restrictions']['denyEmptySubmission'] = [
724 'enabled' => false,
725 ];
726
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,
738 'form_id_selector' => 'fluentform_' . $form->id,
739 'rules' => $formBuilder->validationRules,
740 'debounce_time' => apply_filters('fluentform/show_hide_elements_debounce_time', 300),
741 ];
742
743 if ($conditionals = $formBuilder->conditions) {
744 $form_vars['conditionals'] = $conditionals;
745 }
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
755 if ($form->has_payment) {
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);
766 }
767
768 $otherScripts = '';
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 }
788 }
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 }
801
802
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)) {
814 if (!Acl::hasAnyFormPermission($form->id)) {
815 (new \FluentForm\App\Services\Analytics\AnalyticsService())->store($form->id);
816 }
817 }
818
819 return $output . $otherScripts;
820 }
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
829 /**
830 * Process the output HTML to generate the default values.
831 *
832 * @param string $output
833 * @param \stdClass $form
834 *
835 * @return string
836 */
837 public function replaceEditorSmartCodes($output, $form)
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
849 // Get the patterns for default values from the output HTML string.
850 // The example of a pattern would be for user ID: {user.ID}
851 preg_match_all('/{(.*?)}/', $output, $matches);
852 $patterns = array_unique($matches[0]);
853
854 $attrDefaultValues = [];
855
856 foreach ($patterns as $pattern) {
857 // The default value for each pattern will be resolved here.
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);
870 }
871
872 // Raising an event so that others can hook into it and modify the default values later.
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 );
882
883 $attrDefaultValues = (array) apply_filters('fluentform/parse_default_values', $attrDefaultValues);
884
885 if (isset($attrDefaultValues['{payment_total}'])) {
886 $attrDefaultValues['{payment_total}'] = '<span class="ff_order_total"></span>';
887 }
888
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);
900 }
901
902 /**
903 * Register renderer actions for compiling each element
904 *
905 * @return void
906 */
907 public function addRendererActions()
908 {
909 $actionMappings = [
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'],
924
925 'TermsAndConditions@compile' => [
926 'fluentform/render_item_terms_and_condition',
927 'fluentform/render_item_gdpr_agreement',
928 ],
929
930 'TabularGrid@compile' => [
931 'fluentform/render_item_tabular_grid',
932 ],
933
934 'Checkable@compile' => [
935 'fluentform/render_item_input_radio',
936 'fluentform/render_item_input_checkbox',
937 ],
938
939 'Text@compile' => [
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',
946 ],
947 ];
948
949 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
950 foreach ($actionMappings as $handler => $actions) {
951 foreach ($actions as $action) {
952 $this->app->addAction($action, function () use ($path, $handler) {
953 list($class, $method) = $this->app->parseHookHandler($path . $handler);
954 call_user_func_array([$class, $method], func_get_args());
955 }, 10, 2);
956 }
957 }
958 }
959
960 /**
961 * Register dynamic value shortcode parser (filter default value)
962 *
963 * @return void
964 */
965 public function addFluentFormDefaultValueParser()
966 {
967 $this->app->addFilter('fluentform/parse_default_value', function ($value, $form) {
968 return EditorShortcodeParser::filter($value, $form);
969 }, 10, 2);
970 }
971
972 /**
973 * Register filter to check whether the form is renderable or active
974 *
975 * @return mixed
976 */
977 public function addIsRenderableFilter()
978 {
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 }
986
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) {
1000 if (in_array($key, $checkables)) {
1001 $isRenderable['status'] = $this->{$key}($restrictionSettings, $form, $isRenderable);
1002 if (!$isRenderable['status']) {
1003 $isRenderable['status'] = false;
1004 return $isRenderable;
1005 }
1006 }
1007 }
1008 if($form->status == 'unpublished'){
1009 $isRenderable['status'] = false;
1010 $isRenderable['message'] = apply_filters('fluentform/unpublished_form_submission_message',__('Invalid Form!', 'fluentform'));
1011 }
1012
1013 return $isRenderable;
1014 }, 10, 2);
1015 }
1016
1017 /**
1018 * Check if limit is set on form submits and it's valid yet
1019 *
1020 * @param array $restrictions
1021 *
1022 * @return bool
1023 */
1024 private function limitNumberOfEntries($restrictions, $form, &$isRenderable)
1025 {
1026
1027 if (!Arr::isTrue($restrictions, 'enabled') || !isset($restrictions['period']) || !isset($restrictions['numberOfEntries'])) {
1028 return true;
1029 }
1030
1031
1032 $col = 'created_at';
1033 $period = $restrictions['period'];
1034 $maxAllowedEntries = $restrictions['numberOfEntries'];
1035
1036 if (!$maxAllowedEntries) {
1037 return true;
1038 }
1039
1040 $query = wpFluent()->table('fluentform_submissions')
1041 ->where('form_id', $form->id)
1042 ->where('status', '!=', 'trashed');
1043
1044 if ('day' == $period) {
1045 $year = "YEAR(`{$col}`) = YEAR(NOW())";
1046 $month = "MONTH(`{$col}`) = MONTH(NOW())";
1047 $day = "DAY(`{$col}`) = DAY(NOW())";
1048 $query->whereRaw(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
1049 } elseif ('week' == $period) {
1050 $query->whereRaw(
1051 wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)")
1052 );
1053 } elseif ('month' == $period) {
1054 $year = "YEAR(`{$col}`) = YEAR(NOW())";
1055 $month = "MONTH(`{$col}`) = MONTH(NOW())";
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) {
1060 $ip = $this->app->request->getIp();
1061 $query->where('ip', $ip);
1062 } elseif ('per_user_id' == $period) {
1063 $userId = get_current_user_id();
1064 if (!$userId) {
1065 return true;
1066 }
1067 $query->where('user_id', $userId);
1068 }
1069
1070 $count = $query->count();
1071
1072 if ($count >= $maxAllowedEntries) {
1073 $isRenderable['message'] = apply_filters('fluentform/entry_limit_reached_message', $restrictions['limitReachedMsg'], $form);
1074 return false;
1075 }
1076
1077 return true;
1078 }
1079
1080 /**
1081 * Check if form has scheduled date & weekdays and open for submission
1082 *
1083 * @param array $restrictions
1084 *
1085 * @return bool
1086 */
1087 private function scheduleForm($restrictions, $form, &$isRenderable)
1088 {
1089 if (!Arr::isTrue($restrictions, 'enabled')) {
1090 return true;
1091 }
1092
1093 $time = time();
1094 $start = strtotime($restrictions['start']);
1095 $end = strtotime($restrictions['end']);
1096
1097 if ($time < $start) {
1098 $isRenderable['message'] = apply_filters('fluentform/schedule_form_pending_message', $restrictions['pendingMsg'], $form->id);
1099 return false;
1100 }
1101
1102 if ($time >= $end) {
1103 $isRenderable['message'] = apply_filters('fluentform/schedule_form_expired_message', $restrictions['expiredMsg'], $form->id);
1104
1105 return false;
1106 }
1107
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)) {
1112 $isRenderable['message'] = $restrictions['expiredMsg'];
1113 return false;
1114 }
1115
1116 return true;
1117 }
1118
1119 /**
1120 * * Check if form requires loged in user and user is logged in
1121 *
1122 * @param array $restrictions
1123 *
1124 * @return bool
1125 */
1126 private function requireLogin($restrictions, $form, &$isRenderable)
1127 {
1128 if (!Arr::isTrue($restrictions, 'enabled')) {
1129 return true;
1130 }
1131
1132 if (!($isLoggedIn = is_user_logged_in())) {
1133 $isRenderable['message'] = apply_filters('fluentform/form_requires_login_message', $restrictions['requireLoginMsg'], $form);
1134 }
1135
1136 return $isLoggedIn;
1137 }
1138
1139 /**
1140 * Register fluentform_submission_inserted actions
1141 *
1142 * @return void
1143 */
1144 public function addFluentformSubmissionInsertedFilter()
1145 {
1146 (new EmailNotificationActions($this->app))->register();
1147 }
1148
1149 /**
1150 * Add inline scripts [Add localized script using same var]
1151 *
1152 * @return void
1153 */
1154 private function addInlineVars()
1155 {
1156 if (!defined('ELEMENTOR_PRO_VERSION') || $this->elementorPopUpHandler) {
1157 return '';
1158 }
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
1166 $actionName = 'wp_footer';
1167 if (is_admin()) {
1168 $actionName = 'admin_footer';
1169 }
1170
1171 add_action($actionName, function () {
1172 ?>
1173 <script type="text/javascript">
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 }
1192 if (ffForms.length) {
1193 jQuery.each(ffForms, function(index, ffForm) {
1194 jQuery(ffForm).trigger('reInitExtras');
1195 jQuery(document).trigger('ff_reinit', [ffForm]);
1196 });
1197 }
1198 });
1199 <?php endif; ?>
1200 </script>
1201 <?php
1202 }, 999);
1203 return '';
1204 }
1205
1206 public static function getDatei18n()
1207 {
1208 $i18n = [
1209 'previousMonth' => __('Previous Month', 'fluentform'),
1210 'nextMonth' => __('Next Month', 'fluentform'),
1211 'months' => [
1212 'shorthand' => [
1213 __('Jan', 'fluentform'),
1214 __('Feb', 'fluentform'),
1215 __('Mar', 'fluentform'),
1216 __('Apr', 'fluentform'),
1217 __('May', 'fluentform'),
1218 __('Jun', 'fluentform'),
1219 __('Jul', 'fluentform'),
1220 __('Aug', 'fluentform'),
1221 __('Sep', 'fluentform'),
1222 __('Oct', 'fluentform'),
1223 __('Nov', 'fluentform'),
1224 __('Dec', 'fluentform'),
1225 ],
1226 'longhand' => [
1227 __('January', 'fluentform'),
1228 __('February', 'fluentform'),
1229 __('March', 'fluentform'),
1230 __('April', 'fluentform'),
1231 __('May', 'fluentform'),
1232 __('June', 'fluentform'),
1233 __('July', 'fluentform'),
1234 __('August', 'fluentform'),
1235 __('September', 'fluentform'),
1236 __('October', 'fluentform'),
1237 __('November', 'fluentform'),
1238 __('December', 'fluentform'),
1239 ],
1240 ],
1241 'weekdays' => [
1242 'longhand' => [
1243 __('Sunday', 'fluentform'),
1244 __('Monday', 'fluentform'),
1245 __('Tuesday', 'fluentform'),
1246 __('Wednesday', 'fluentform'),
1247 __('Thursday', 'fluentform'),
1248 __('Friday', 'fluentform'),
1249 __('Saturday', 'fluentform'),
1250 ],
1251 'shorthand' => [
1252 __('Sun', 'fluentform'),
1253 __('Mon', 'fluentform'),
1254 __('Tue', 'fluentform'),
1255 __('Wed', 'fluentform'),
1256 __('Thu', 'fluentform'),
1257 __('Fri', 'fluentform'),
1258 __('Sat', 'fluentform'),
1259 ],
1260 ],
1261 'daysInMonth' => [
1262 31,
1263 28,
1264 31,
1265 30,
1266 31,
1267 30,
1268 31,
1269 31,
1270 30,
1271 31,
1272 30,
1273 31,
1274 ],
1275 'rangeSeparator' => __(' to ', 'fluentform'),
1276 'weekAbbreviation' => __('Wk', 'fluentform'),
1277 'scrollTitle' => __('Scroll to increment', 'fluentform'),
1278 'toggleTitle' => __('Click to toggle', 'fluentform'),
1279 'amPM' => [
1280 __('AM', 'fluentform'),
1281 __('PM', 'fluentform'),
1282 ],
1283 'yearAriaLabel' => __('Year', 'fluentform'),
1284 'firstDayOfWeek' => (int) get_option('start_of_week'),
1285 ];
1286
1287 return apply_filters('fluentform/date_i18n', $i18n);
1288 }
1289
1290 protected function maybeHasAdvandedFields($form, $formBuilder)
1291 {
1292 $advancedFields = [
1293 'step_start',
1294 'repeater_field',
1295 'ratings',
1296 'form_step',
1297 'input_file',
1298 'input_image',
1299 'net_promoter_score',
1300 'featured_image',
1301 ];
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))) {
1306 wp_enqueue_script('fluentform-advanced');
1307 }
1308 }
1309
1310 public function registerInputSanitizers()
1311 {
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);
1314 }
1315
1316 public function getNumericInputValue($value, $field)
1317 {
1318 $formatter = ArrayHelper::get($field, 'raw.settings.numeric_formatter');
1319 if (!$formatter) {
1320 return $value;
1321 }
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);
1570 }
1571 }
1572