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

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

1,540 lines 60.0 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['color-picker'] = [
403 'disabled' => true,
404 'title' => __('Color Picker', 'fluentform'),
405 'description' => __('Color Picker is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
406 'image' => fluentformMix('img/pro-fields/color-picker.png'),
407 'video' => '',
408 ];
409 $disabled['payment_coupon'] = [
410 'disabled' => true,
411 'title' => __('Coupon', 'fluentform'),
412 'description' => __('Coupon is not available with the free version. Please upgrade to pro to get all the advanced features.', 'fluentform'),
413 'image' => fluentformMix('img/pro-fields/coupon.png'),
414 'video' => '',
415 ];
416 }
417
418 $disabled = apply_filters_deprecated(
419 'fluentform_disabled_components',
420 [
421 $disabled
422 ],
423 FLUENTFORM_FRAMEWORK_UPGRADE,
424 'fluentform/disabled_components',
425 'Use fluentform/disabled_components instead of fluentform_disabled_components.'
426 );
427 return $this->app->applyFilters('fluentform/disabled_components', $disabled);
428 }
429
430 /**
431 * Get available shortcodes for editor
432 *
433 * @return void
434 *
435 * @throws \Exception
436 */
437 public function getEditorShortcodes()
438 {
439 $editor_shortcodes = fluentFormEditorShortCodes();
440 wp_send_json_success(['shortcodes' => $editor_shortcodes], 200);
441 }
442
443 /**
444 * @deprecated Use \FluentForm\App\Services\Form\FormService::shortcodes
445 * Get all available shortcodes for editor
446 *
447 * @return void
448 *
449 * @throws \Exception
450 */
451 public function getAllEditorShortcodes()
452 {
453 wp_send_json(fluentFormGetAllEditorShortCodes(
454 $this->app->request->get('formId')
455 ), 200);
456 }
457
458 /**
459 * Register the form renderer shortcode
460 *
461 * @return void
462 */
463 public function addFluentFormShortCode()
464 {
465 add_action('wp_enqueue_scripts', [$this, 'registerScripts'], 9);
466
467 $this->app->addShortCode('fluentform', function ($atts, $content) {
468 $data = [
469 'id' => null,
470 'title' => null,
471 'css_classes' => '',
472 'permission' => '',
473 'type' => 'classic',
474 'theme' => '',
475 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform')
476 ];
477 /* This filter is deprecated, will be removed soon */
478 $data = apply_filters('fluentform_shortcode_defaults', $data, $atts );
479
480 $shortcodeDefaults = apply_filters('fluentform/shortcode_defaults', $data, $atts);
481
482 $atts = shortcode_atts($shortcodeDefaults, $atts);
483
484 return $this->renderForm($atts);
485 });
486
487 $this->registerHelperShortCodes();
488 }
489
490 public function renderForm($atts)
491 {
492 $form_id = $atts['id'];
493 $query = wpFluent()->table('fluentform_forms');
494
495 if (! $this->app->request->get('preview_id')) {
496 $query->where('status', 'published');
497 }
498
499 if ($form_id) {
500 $form = $query->find($form_id);
501 } elseif ($formTitle = $atts['title']) {
502 $form = $query->where('title', $formTitle)->first();
503 } else {
504 return '';
505 }
506
507 if (!$form) {
508 return '';
509 }
510
511 if (!empty($atts['permission'])) {
512 if (!current_user_can($atts['permission'])) {
513 return $this->getNotRenderableHtml($form->id, $atts['permission_message']);
514 }
515 }
516
517 if (is_feed()) {
518 global $post;
519 /* translators: %s is the website URL */
520 $feedText = sprintf(__('The form can be filled in the actual <a href="%s">website url</a>.', 'fluentform'), get_permalink($post));
521
522 $feedText = apply_filters_deprecated(
523 'fluentform_shortcode_feed_text',
524 [
525 $feedText,
526 $form
527 ],
528 FLUENTFORM_FRAMEWORK_UPGRADE,
529 'fluentform/shortcode_feed_text',
530 'Use fluentform/shortcode_feed_text instead of fluentform_shortcode_feed_text.'
531 );
532
533 $feedText = apply_filters('fluentform/shortcode_feed_text', $feedText, $form);
534 return $feedText;
535 }
536
537 $form->settings = Helper::getFormMeta($form->id, 'formSettings', []);
538
539 if (empty($form->settings)) {
540 return '';
541 }
542
543 $form->fields = json_decode($form->form_fields, true);
544 if (!is_array($form->fields) || empty($form->fields['fields'])) {
545 return '';
546 }
547
548 $form = apply_filters_deprecated(
549 'fluentform_rendering_form',
550 [
551 $form
552 ],
553 FLUENTFORM_FRAMEWORK_UPGRADE,
554 'fluentform/rendering_form',
555 'Use fluentform/rendering_form instead of fluentform_rendering_form.'
556 );
557 $form = $this->app->applyFilters('fluentform/rendering_form', $form);
558
559 $isRenderable = [
560 'status' => true,
561 'message' => '',
562 ];
563 $isRenderable = apply_filters('fluentform_is_form_renderable', $isRenderable, $form);
564
565 $isRenderable = $this->app->applyFilters('fluentform/is_form_renderable', $isRenderable, $form);
566
567 if (is_array($isRenderable) && !$isRenderable['status']) {
568 return $this->getNotRenderableHtml($form->id, $isRenderable['message']);
569 }
570
571 $instanceCssClass = Helper::getFormInstaceClass($form->id);
572
573 $form->instance_css_class = $instanceCssClass;
574 $form->instance_index = Helper::$formInstance;
575
576 if ('conversational' == $atts['type']) {
577 if (!Helper::isElementorEditor()) {
578 $this->addInlineVars();
579 }
580 return (new \FluentForm\App\Services\FluentConversational\Classes\Form())->renderShortcode($form);
581 }
582
583 $formBuilder = $this->app->make('formBuilder');
584
585 $cssClasses = trim($instanceCssClass . ' ff-form-loading');
586
587 $output = $formBuilder->build($form, $cssClasses, $instanceCssClass, $atts);
588
589 $output = $this->replaceEditorSmartCodes($output, $form);
590
591 if (!wp_script_is('fluent-form-submission', 'registered')) {
592 $this->registerScripts();
593 }
594
595 wp_enqueue_style('fluent-form-styles');
596 $postId = get_the_ID() ?: 0;
597 $loadStyle = apply_filters_deprecated(
598 'fluentform_load_default_public',
599 [
600 true,
601 $form,
602 $postId
603 ],
604 FLUENTFORM_FRAMEWORK_UPGRADE,
605 'fluentform/load_default_public',
606 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
607 );
608
609 if (apply_filters('fluentform/load_default_public', $loadStyle, $form, $postId)) {
610 wp_enqueue_style('fluentform-public-default');
611 }
612 /*
613 * We will load fluentform-advanced if the form has certain fields or feature
614 */
615 $this->maybeHasAdvandedFields($form, $formBuilder);
616 if (!Helper::isElementorEditor()) {
617 wp_enqueue_script('fluent-form-submission');
618 }
619
620 /* translators: %activeStep% is the current step number, %totalStep% is the total number of steps, %stepTitle% is the step title */
621 $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', 'fluentform');
622
623 $stepText = apply_filters_deprecated(
624 'fluentform_step_string',
625 [
626 $stepText
627 ],
628 FLUENTFORM_FRAMEWORK_UPGRADE,
629 'fluentform/step_string',
630 'Use fluentform/step_string instead of fluentform_step_string.'
631 );
632
633 $stepText = apply_filters('fluentform/step_string', $stepText);
634
635 $data = [
636 'ajaxUrl' => admin_url('admin-ajax.php'),
637 'forms' => [],
638 'step_text' => $stepText,
639 'is_rtl' => is_rtl(),
640 'date_i18n' => self::getDatei18n(),
641 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false,
642 'fluentform_version' => FLUENTFORM_VERSION,
643 'force_init' => false,
644 'stepAnimationDuration' => 350,
645 'upload_completed_txt' => __('100% Completed', 'fluentform'),
646 'upload_start_txt' => __('0% Completed', 'fluentform'),
647 'uploading_txt' => __('Uploading', 'fluentform'),
648 'choice_js_vars' => [
649 'noResultsText' => __('No results found', 'fluentform'),
650 'loadingText' => __('Loading...', 'fluentform'),
651 'noChoicesText' => __('No choices to choose from', 'fluentform'),
652 'itemSelectText' => __('Press to select', 'fluentform'),
653 'maxItemTextSingular' => __('Only %%maxItemCount%% option can be added', 'fluentform'),
654 'maxItemTextPlural' => __('Only %%maxItemCount%% options can be added', 'fluentform'),
655 ],
656 'input_mask_vars' => [
657 'clearIfNotMatch' => false,
658 ],
659 'nonce' => wp_create_nonce(),
660 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete'),
661 'form_id' => $form_id,
662 'step_change_focus' => true,
663 'has_cleantalk' => \FluentForm\App\Modules\Form\CleanTalkHandler::isCleantalkActivated(),
664 'pro_payment_script_compatible' => Helper::isProPaymentScriptCompatible(),
665 ];
666
667 $data = apply_filters_deprecated(
668 'fluentform_global_form_vars',
669 [
670 $data
671 ],
672 FLUENTFORM_FRAMEWORK_UPGRADE,
673 'fluentform/global_form_vars',
674 'Use fluentform/global_form_vars instead of fluentform_global_form_vars.'
675 );
676
677 $vars = apply_filters('fluentform/global_form_vars', $data);
678
679 if (!Helper::isElementorEditor()) {
680 wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars);
681 }
682
683 // Localize JavaScript messages for translation
684 $this->localizeJavaScriptMessages($form);
685
686 // Add global messages (only once)
687 if (!wp_script_is('fluent-form-submission', 'done')) {
688 $globalMessages = [
689 'javascript_handler_failed' => __('Javascript handler could not be loaded. Form submission has been failed. Reload the page and try again', 'fluentform')
690 ];
691 $globalMessages = apply_filters('fluentform/form_submission_messages', $globalMessages, $form);
692 wp_localize_script('fluent-form-submission', 'fluentform_submission_messages_global', $globalMessages);
693
694 // Add global address messages
695 $globalAddressMessages = [
696 'please_wait' => __('Please wait ...', 'fluentform'),
697 'location_not_determined' => __('Could not determine address from location.', 'fluentform'),
698 'address_fetch_failed' => __('Failed to fetch address from coordinates.', 'fluentform'),
699 'geolocation_failed' => __('Geolocation failed or was denied.', 'fluentform'),
700 'geolocation_not_supported' => __('Geolocation is not supported by this browser.', 'fluentform')
701 ];
702 $globalAddressMessages = apply_filters('fluentform/address_autocomplete_messages', $globalAddressMessages, $form);
703 wp_localize_script('fluent-form-submission', 'fluentform_address_messages_global', $globalAddressMessages);
704 }
705
706 $formSettings = $form->settings;
707
708 $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']);
709
710 // Ensure restrictions array exists before setting denyEmptySubmission
711 if (!isset($formSettings['restrictions']) || !is_array($formSettings['restrictions'])) {
712 $formSettings['restrictions'] = [];
713 }
714
715 $formSettings['restrictions']['denyEmptySubmission'] = [
716 'enabled' => false,
717 ];
718
719 if (!empty($formBuilder->validationRules)) {
720 $formBuilder->validationRules = fluentform_backend_sanitizer($formBuilder->validationRules, [
721 'message' => 'fluentform_sanitize_html'
722 ]);
723 }
724
725 $form_vars = [
726 'id' => $form->id,
727 'ajaxUrl' => admin_url('admin-ajax.php'),
728 'settings' => $formSettings,
729 'form_instance' => $instanceCssClass,
730 'form_id_selector' => 'fluentform_' . $form->id,
731 'rules' => $formBuilder->validationRules,
732 'debounce_time' => apply_filters('fluentform/show_hide_elements_debounce_time', 300),
733 ];
734
735 if ($conditionals = $formBuilder->conditions) {
736 $form_vars['conditionals'] = $conditionals;
737 }
738
739 $form_vars = apply_filters('fluentform/form_vars_for_JS', $form_vars, $form);
740
741 if ($form->has_payment) {
742 do_action_deprecated(
743 'fluentform_rendering_payment_form',
744 [
745 $form
746 ],
747 FLUENTFORM_FRAMEWORK_UPGRADE,
748 'fluentform/rendering_payment_form',
749 'Use fluentform/rendering_payment_form instead of fluentform_rendering_payment_form.'
750 );
751 do_action('fluentform/rendering_payment_form', $form);
752 }
753
754 $otherScripts = '';
755 $otherScriptsRenderImmediately = apply_filters('fluentform/load_form_instance_js_var_immediately', false);
756 if (!$otherScriptsRenderImmediately) {
757 ob_start();
758 }
759
760 if (!Helper::isElementorEditor()) {
761 ?>
762 <script type="text/javascript">
763 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.?>;
764 <?php if (wp_doing_ajax()): ?>
765 function initFFInstance_<?php echo esc_attr($form_vars['id']); ?>() {
766 if (!window.fluentFormApp) {
767 console.log('No fluentFormApp found');
768 return;
769 }
770 var ajax_formInstance = window.fluentFormApp(jQuery('form.<?php echo esc_attr($form_vars['form_instance']); ?>'));
771 if (ajax_formInstance) {
772 ajax_formInstance.initFormHandlers();
773 }
774 }
775
776 initFFInstance_<?php echo esc_attr($form_vars['id']); ?>();
777 <?php endif; ?>
778 </script>
779 <?php
780 }
781 if (!Helper::isElementorEditor()) {
782 $this->addInlineVars();
783 }
784 if (!$otherScriptsRenderImmediately) {
785 $otherScripts .= ob_get_clean();
786 }
787
788
789 $disableAnalytics = apply_filters_deprecated(
790 'fluentform-disabled_analytics',
791 [
792 true
793 ],
794 FLUENTFORM_FRAMEWORK_UPGRADE,
795 'fluentform/disabled_analytics',
796 'Use fluentform/disabled_analytics instead of fluentform-disabled_analytics.'
797 );
798
799 if (!$this->app->applyFilters('fluentform/disabled_analytics', $disableAnalytics)) {
800 if (!Acl::hasAnyFormPermission($form->id)) {
801 (new \FluentForm\App\Services\Analytics\AnalyticsService())->store($form->id);
802 }
803 }
804
805 return $output . $otherScripts;
806 }
807
808 protected function getNotRenderableHtml($formId, $message)
809 {
810 return "<div id='ff_form_" . esc_attr($formId) . "' class='ff_form_not_render'>"
811 . wp_kses_post($message)
812 . "</div>";
813 }
814
815 /**
816 * Process the output HTML to generate the default values.
817 *
818 * @param string $output
819 * @param \stdClass $form
820 *
821 * @return string
822 */
823 public function replaceEditorSmartCodes($output, $form)
824 {
825 // Return early if output is null or empty
826 if ($output === null || $output === '') {
827 return $output;
828 }
829
830 // Return early if form is null to prevent errors
831 if ($form === null) {
832 return $output;
833 }
834
835 // Get the patterns for default values from the output HTML string.
836 // The example of a pattern would be for user ID: {user.ID}
837 preg_match_all('/{(.*?)}/', $output, $matches);
838 $patterns = array_unique($matches[0]);
839
840 $attrDefaultValues = [];
841
842 foreach ($patterns as $pattern) {
843 // The default value for each pattern will be resolved here.
844 $attrDefaultValues[$pattern] = apply_filters_deprecated(
845 'fluentform_parse_default_value',
846 [
847 $pattern,
848 $form
849 ],
850 FLUENTFORM_FRAMEWORK_UPGRADE,
851 'fluentform/parse_default_value',
852 'Use fluentform/parse_default_value instead of fluentform_parse_default_value.'
853 );
854
855 $attrDefaultValues[$pattern] = apply_filters('fluentform/parse_default_value', $attrDefaultValues[$pattern], $form);
856 }
857
858 // Raising an event so that others can hook into it and modify the default values later.
859 $attrDefaultValues = apply_filters_deprecated(
860 'fluentform_parse_default_values',
861 [
862 $attrDefaultValues
863 ],
864 FLUENTFORM_FRAMEWORK_UPGRADE,
865 'fluentform/parse_default_values',
866 'Use fluentform/parse_default_values instead of fluentform_parse_default_values.'
867 );
868
869 $attrDefaultValues = (array) apply_filters('fluentform/parse_default_values', $attrDefaultValues);
870
871 if (isset($attrDefaultValues['{payment_total}'])) {
872 $attrDefaultValues['{payment_total}'] = '<span class="ff_order_total"></span>';
873 }
874
875 // Finally, replace the patterns with the replacements and return the output HTML.
876 return str_replace(array_keys($attrDefaultValues), array_values($attrDefaultValues), $output);
877 }
878
879 /**
880 * Register renderer actions for compiling each element
881 *
882 * @return void
883 */
884 public function addRendererActions()
885 {
886 $actionMappings = [
887 'Select@compile' => ['fluentform/render_item_select'],
888 'Rating@compile' => ['fluentform/render_item_ratings'],
889 'Address@compile' => ['fluentform/render_item_address'],
890 'Name@compile' => ['fluentform/render_item_input_name'],
891 'TextArea@compile' => ['fluentform/render_item_textarea'],
892 'DateTime@compile' => ['fluentform/render_item_input_date'],
893 'Recaptcha@compile' => ['fluentform/render_item_recaptcha'],
894 'Hcaptcha@compile' => ['fluentform/render_item_hcaptcha'],
895 'Turnstile@compile' => ['fluentform/render_item_turnstile'],
896 'Container@compile' => ['fluentform/render_item_container'],
897 'CustomHtml@compile' => ['fluentform/render_item_custom_html'],
898 'SectionBreak@compile' => ['fluentform/render_item_section_break'],
899 'SubmitButton@compile' => ['fluentform/render_item_submit_button'],
900 'SelectCountry@compile' => ['fluentform/render_item_select_country'],
901
902 'TermsAndConditions@compile' => [
903 'fluentform/render_item_terms_and_condition',
904 'fluentform/render_item_gdpr_agreement',
905 ],
906
907 'TabularGrid@compile' => [
908 'fluentform/render_item_tabular_grid',
909 ],
910
911 'Checkable@compile' => [
912 'fluentform/render_item_input_radio',
913 'fluentform/render_item_input_checkbox',
914 ],
915
916 'Text@compile' => [
917 'fluentform/render_item_input_url',
918 'fluentform/render_item_input_text',
919 'fluentform/render_item_input_email',
920 'fluentform/render_item_input_number',
921 'fluentform/render_item_input_hidden',
922 'fluentform/render_item_input_password',
923 ],
924 ];
925
926 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
927 foreach ($actionMappings as $handler => $actions) {
928 foreach ($actions as $action) {
929 $this->app->addAction($action, function () use ($path, $handler) {
930 list($class, $method) = $this->app->parseHookHandler($path . $handler);
931 call_user_func_array([$class, $method], func_get_args());
932 }, 10, 2);
933 }
934 }
935 }
936
937 /**
938 * Register dynamic value shortcode parser (filter default value)
939 *
940 * @return void
941 */
942 public function addFluentFormDefaultValueParser()
943 {
944 $this->app->addFilter('fluentform/parse_default_value', function ($value, $form) {
945 return EditorShortcodeParser::filter($value, $form);
946 }, 10, 2);
947 }
948
949 /**
950 * Register filter to check whether the form is renderable or active
951 *
952 * @return mixed
953 */
954 public function addIsRenderableFilter()
955 {
956 $this->app->addFilter('fluentform/is_form_renderable', function ($isRenderable, $form) {
957 $checkables = ['limitNumberOfEntries', 'scheduleForm', 'requireLogin'];
958
959 // Ensure settings is an array
960 if (!isset($form->settings) || !is_array($form->settings)) {
961 $form->settings = [];
962 }
963
964 // Ensure restrictions exists and is an array before iterating
965 $restrictions = isset($form->settings['restrictions']) && is_array($form->settings['restrictions'])
966 ? $form->settings['restrictions']
967 : [];
968
969 foreach ($restrictions as $key => $restrictionSettings) {
970 if (in_array($key, $checkables)) {
971 $isRenderable['status'] = $this->{$key}($restrictionSettings, $form, $isRenderable);
972 if (!$isRenderable['status']) {
973 $isRenderable['status'] = false;
974 return $isRenderable;
975 }
976 }
977 }
978 if($form->status == 'unpublished'){
979 $isRenderable['status'] = false;
980 $isRenderable['message'] = apply_filters('fluentform/unpublished_form_submission_message',__('Invalid Form!', 'fluentform'));
981 }
982
983 return $isRenderable;
984 }, 10, 2);
985 }
986
987 /**
988 * Check if limit is set on form submits and it's valid yet
989 *
990 * @param array $restrictions
991 *
992 * @return bool
993 */
994 private function limitNumberOfEntries($restrictions, $form, &$isRenderable)
995 {
996
997 if (!$restrictions['enabled'] || !isset($restrictions['period']) || !isset($restrictions['numberOfEntries'])) {
998 return true;
999 }
1000
1001
1002 $col = 'created_at';
1003 $period = $restrictions['period'];
1004 $maxAllowedEntries = $restrictions['numberOfEntries'];
1005
1006 if (!$maxAllowedEntries) {
1007 return true;
1008 }
1009
1010 $query = wpFluent()->table('fluentform_submissions')
1011 ->where('form_id', $form->id)
1012 ->where('status', '!=', 'trashed');
1013
1014 if ('day' == $period) {
1015 $year = "YEAR(`{$col}`) = YEAR(NOW())";
1016 $month = "MONTH(`{$col}`) = MONTH(NOW())";
1017 $day = "DAY(`{$col}`) = DAY(NOW())";
1018 $query->whereRaw(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
1019 } elseif ('week' == $period) {
1020 $query->whereRaw(
1021 wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)")
1022 );
1023 } elseif ('month' == $period) {
1024 $year = "YEAR(`{$col}`) = YEAR(NOW())";
1025 $month = "MONTH(`{$col}`) = MONTH(NOW())";
1026 $query->whereRaw(wpFluent()->raw("{$year} AND {$month}"));
1027 } elseif ('year' == $period) {
1028 $query->whereRaw(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())"));
1029 } elseif ('per_user_ip' == $period) {
1030 $ip = $this->app->request->getIp();
1031 $query->where('ip', $ip);
1032 } elseif ('per_user_id' == $period) {
1033 $userId = get_current_user_id();
1034 if (!$userId) {
1035 return true;
1036 }
1037 $query->where('user_id', $userId);
1038 }
1039
1040 $count = $query->count();
1041
1042 if ($count >= $maxAllowedEntries) {
1043 $isRenderable['message'] = apply_filters('fluentform/entry_limit_reached_message', $restrictions['limitReachedMsg'], $form);
1044 return false;
1045 }
1046
1047 return true;
1048 }
1049
1050 /**
1051 * Check if form has scheduled date & weekdays and open for submission
1052 *
1053 * @param array $restrictions
1054 *
1055 * @return bool
1056 */
1057 private function scheduleForm($restrictions, $form, &$isRenderable)
1058 {
1059 if (!$restrictions['enabled']) {
1060 return true;
1061 }
1062
1063 $time = time();
1064 $start = strtotime($restrictions['start']);
1065 $end = strtotime($restrictions['end']);
1066
1067 if ($time < $start) {
1068 $isRenderable['message'] = apply_filters('fluentform/schedule_form_pending_message', $restrictions['pendingMsg'], $form->id);
1069 return false;
1070 }
1071
1072 if ($time >= $end) {
1073 $isRenderable['message'] = apply_filters('fluentform/schedule_form_expired_message', $restrictions['expiredMsg'], $form->id);
1074
1075 return false;
1076 }
1077
1078 $weekDayToday = date('l'); //day of the week
1079 $selectedWeekDays = ArrayHelper::get($restrictions, 'selectedDays');
1080 //skip if it was not set initially and $selectedWeekDays is null
1081 if ($selectedWeekDays && is_array($selectedWeekDays) && !in_array($weekDayToday, $selectedWeekDays)) {
1082 $isRenderable['message'] = $restrictions['expiredMsg'];
1083 return false;
1084 }
1085
1086 return true;
1087 }
1088
1089 /**
1090 * * Check if form requires loged in user and user is logged in
1091 *
1092 * @param array $restrictions
1093 *
1094 * @return bool
1095 */
1096 private function requireLogin($restrictions, $form, &$isRenderable)
1097 {
1098 if (!$restrictions['enabled']) {
1099 return true;
1100 }
1101
1102 if (!($isLoggedIn = is_user_logged_in())) {
1103 $isRenderable['message'] = apply_filters('fluentform/form_requires_login_message', $restrictions['requireLoginMsg'], $form);
1104 }
1105
1106 return $isLoggedIn;
1107 }
1108
1109 /**
1110 * Register fluentform_submission_inserted actions
1111 *
1112 * @return void
1113 */
1114 public function addFluentformSubmissionInsertedFilter()
1115 {
1116 (new EmailNotificationActions($this->app))->register();
1117 }
1118
1119 /**
1120 * Add inline scripts [Add localized script using same var]
1121 *
1122 * @return void
1123 */
1124 private function addInlineVars()
1125 {
1126 if (!defined('ELEMENTOR_PRO_VERSION') || $this->elementorPopUpHandler) {
1127 return '';
1128 }
1129
1130 // Previously this handler was registered for every form
1131 // in a single page. So multiple event handlers were
1132 // registered. This flag ensures the handler is
1133 // registered just once, since one is enough!
1134 $this->elementorPopUpHandler = true;
1135
1136 $actionName = 'wp_footer';
1137 if (is_admin()) {
1138 $actionName = 'admin_footer';
1139 }
1140
1141 add_action($actionName, function () {
1142 ?>
1143 <script type="text/javascript">
1144 <?php if (defined('ELEMENTOR_PRO_VERSION')): ?>
1145
1146 window.addEventListener('elementor/popup/show', function (e) {
1147 var ffForms = jQuery('#elementor-popup-modal-' + e.detail.id).find('form.frm-fluent-form');
1148
1149 /**
1150 * Support conversation form in elementor popup
1151 * No regular form found, check for conversational form
1152 */
1153 if (!ffForms.length) {
1154 const elements = document.getElementsByClassName('ffc_conv_form');
1155 if (elements.length) {
1156 let jsEvent = new CustomEvent('ff-elm-conv-form-event', {
1157 detail: elements
1158 });
1159 document.dispatchEvent(jsEvent);
1160 }
1161 }
1162 if (ffForms.length) {
1163 jQuery.each(ffForms, function(index, ffForm) {
1164 jQuery(ffForm).trigger('reInitExtras');
1165 jQuery(document).trigger('ff_reinit', [ffForm]);
1166 });
1167 }
1168 });
1169 <?php endif; ?>
1170 </script>
1171 <?php
1172 }, 999);
1173 return '';
1174 }
1175
1176 public static function getDatei18n()
1177 {
1178 $i18n = [
1179 'previousMonth' => __('Previous Month', 'fluentform'),
1180 'nextMonth' => __('Next Month', 'fluentform'),
1181 'months' => [
1182 'shorthand' => [
1183 __('Jan', 'fluentform'),
1184 __('Feb', 'fluentform'),
1185 __('Mar', 'fluentform'),
1186 __('Apr', 'fluentform'),
1187 __('May', 'fluentform'),
1188 __('Jun', 'fluentform'),
1189 __('Jul', 'fluentform'),
1190 __('Aug', 'fluentform'),
1191 __('Sep', 'fluentform'),
1192 __('Oct', 'fluentform'),
1193 __('Nov', 'fluentform'),
1194 __('Dec', 'fluentform'),
1195 ],
1196 'longhand' => [
1197 __('January', 'fluentform'),
1198 __('February', 'fluentform'),
1199 __('March', 'fluentform'),
1200 __('April', 'fluentform'),
1201 __('May', 'fluentform'),
1202 __('June', 'fluentform'),
1203 __('July', 'fluentform'),
1204 __('August', 'fluentform'),
1205 __('September', 'fluentform'),
1206 __('October', 'fluentform'),
1207 __('November', 'fluentform'),
1208 __('December', 'fluentform'),
1209 ],
1210 ],
1211 'weekdays' => [
1212 'longhand' => [
1213 __('Sunday', 'fluentform'),
1214 __('Monday', 'fluentform'),
1215 __('Tuesday', 'fluentform'),
1216 __('Wednesday', 'fluentform'),
1217 __('Thursday', 'fluentform'),
1218 __('Friday', 'fluentform'),
1219 __('Saturday', 'fluentform'),
1220 ],
1221 'shorthand' => [
1222 __('Sun', 'fluentform'),
1223 __('Mon', 'fluentform'),
1224 __('Tue', 'fluentform'),
1225 __('Wed', 'fluentform'),
1226 __('Thu', 'fluentform'),
1227 __('Fri', 'fluentform'),
1228 __('Sat', 'fluentform'),
1229 ],
1230 ],
1231 'daysInMonth' => [
1232 31,
1233 28,
1234 31,
1235 30,
1236 31,
1237 30,
1238 31,
1239 31,
1240 30,
1241 31,
1242 30,
1243 31,
1244 ],
1245 'rangeSeparator' => __(' to ', 'fluentform'),
1246 'weekAbbreviation' => __('Wk', 'fluentform'),
1247 'scrollTitle' => __('Scroll to increment', 'fluentform'),
1248 'toggleTitle' => __('Click to toggle', 'fluentform'),
1249 'amPM' => [
1250 __('AM', 'fluentform'),
1251 __('PM', 'fluentform'),
1252 ],
1253 'yearAriaLabel' => __('Year', 'fluentform'),
1254 'firstDayOfWeek' => (int) get_option('start_of_week'),
1255 ];
1256
1257 return apply_filters('fluentform/date_i18n', $i18n);
1258 }
1259
1260 protected function maybeHasAdvandedFields($form, $formBuilder)
1261 {
1262 $advancedFields = [
1263 'step_start',
1264 'repeater_field',
1265 'ratings',
1266 'form_step',
1267 'input_file',
1268 'input_image',
1269 'net_promoter_score',
1270 'featured_image',
1271 ];
1272 $advancedFields = apply_filters('fluentform/fields_requiring_advanced_script', $advancedFields);
1273
1274 // Only enqueue advanced script if NOT in Elementor editor mode
1275 if (!Helper::isElementorEditor() && ($formBuilder->conditions || array_intersect($formBuilder->fieldLists, $advancedFields))) {
1276 wp_enqueue_script('fluentform-advanced');
1277 }
1278 }
1279
1280 public function registerInputSanitizers()
1281 {
1282 add_filter('fluentform/input_data_input_number', [$this, 'getNumericInputValue'], 10, 2);
1283 add_filter('fluentform/input_data_custom_payment_component', [$this, 'getNumericInputValue'], 10, 2);
1284 }
1285
1286 public function getNumericInputValue($value, $field)
1287 {
1288 $formatter = ArrayHelper::get($field, 'raw.settings.numeric_formatter');
1289 if (!$formatter) {
1290 return $value;
1291 }
1292 return Helper::getNumericValue($value, $formatter);
1293 }
1294
1295
1296 public function registerHelperShortCodes()
1297 {
1298 $this->app->addShortCode('fluentform_info', function ($atts) {
1299 $data = [
1300 'id' => null, // This is the form id
1301 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total
1302 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read
1303 'with_trashed' => 'no', // yes | no
1304 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"]
1305 'hide_on_zero' => 'no',
1306 'payment_status' => 'all', // it can be all / specific payment status
1307 'currency_formatted' => 'yes',
1308 'date_format' => '',
1309 ];
1310 /* This filter is deprecated, will be removed soon */
1311 $data = apply_filters('fluentform_info_shortcode_defaults', $data, $atts );
1312
1313 $shortcodeDefaults = apply_filters('fluentform/info_shortcode_defaults', $data, $atts);
1314
1315 $atts = shortcode_atts($shortcodeDefaults, $atts);
1316 $formId = $atts['id'];
1317 $form = wpFluent()->table('fluentform_forms')->find($formId);
1318
1319 if (!$form) {
1320 return '';
1321 }
1322
1323 if ('submission_count' == $atts['info']) {
1324 $countQuery = wpFluent()->table('fluentform_submissions')
1325 ->where('form_id', $formId);
1326
1327 if ('trashed' != $atts['status'] && 'no' == $atts['with_trashed']) {
1328 $countQuery = $countQuery->where('status', '!=', 'trashed');
1329 }
1330
1331 if ('all' == $atts['status']) {
1332 // ...
1333 } elseif ('favourites' == $atts['status']) {
1334 $countQuery = $countQuery->where('is_favourite', '=', 1);
1335 } else {
1336 $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
1337 }
1338 if ($atts['payment_status'] && defined('FLUENTFORMPRO') && 'all' != $atts['payment_status']) {
1339 $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
1340 }
1341
1342 $total = $countQuery->count();
1343
1344 if ($atts['substract_from']) {
1345 $total = intval($atts['substract_from']) - $total;
1346 }
1347
1348 if ('yes' == $atts['hide_on_zero'] && !$total || $total < 0) {
1349 return '';
1350 }
1351
1352 return $total;
1353 } elseif ('created_at' == $atts['info']) {
1354 if ($atts['date_format']) {
1355 $dateFormat = $atts['date_format'];
1356 } else {
1357 $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
1358 }
1359 return date($dateFormat, strtotime($form->created_at));
1360 } elseif ('updated_at' == $atts['info']) {
1361 if ($atts['date_format']) {
1362 $dateFormat = $atts['date_format'];
1363 } else {
1364 $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
1365 }
1366 return date($dateFormat, strtotime($form->updated_at));
1367 } elseif ('payment_total' == $atts['info']) {
1368 if (!defined('FLUENTFORMPRO')) {
1369 return '';
1370 }
1371
1372 global $wpdb;
1373 $countQuery = wpFluent()
1374 ->table('fluentform_submissions')
1375 ->select(wpFluent()->raw('SUM(payment_total) as payment_total'))
1376 ->where('form_id', $formId);
1377
1378 if ('trashed' != $atts['status'] && 'no' == $atts['with_trashed']) {
1379 $countQuery = $countQuery->where('status', '!=', 'trashed');
1380 }
1381
1382 if ('all' == $atts['status']) {
1383 // ...
1384 } elseif ('favourites' == $atts['status']) {
1385 $countQuery = $countQuery->where('is_favourite', '=', 1);
1386 } else {
1387 $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
1388 }
1389
1390 if ('all' == $atts['payment_status']) {
1391 // ...
1392 } elseif ($atts['payment_status']) {
1393 $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
1394 }
1395
1396 $row = $countQuery->first();
1397
1398 $total = 0;
1399 if ($row) {
1400 $total = $row->payment_total;
1401 }
1402
1403 if ($atts['substract_from']) {
1404 $total = intval($atts['substract_from'] * 100) - $total;
1405 }
1406
1407 if ('yes' == $atts['hide_on_zero'] && !$total) {
1408 return '';
1409 }
1410
1411 if ('yes' == $atts['currency_formatted']) {
1412 $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId);
1413 return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency);
1414 }
1415
1416 if (!$total) {
1417 return 0;
1418 }
1419
1420 return $total / 100;
1421 }
1422
1423 return '';
1424 });
1425
1426 $this->app->addShortCode('ff_get', function ($atts) {
1427 $atts = shortcode_atts([
1428 'param' => '',
1429 ], $atts);
1430
1431 $value = $this->app->request->get($atts['param']);
1432
1433 if ($atts['param'] && $value) {
1434 if (is_array($value)) {
1435 return implode(', ', $value);
1436 }
1437 return esc_html($value);
1438 }
1439 return '';
1440 });
1441
1442 $this->app->addShortcode('ff_entry',function($atts){
1443 ob_start();
1444
1445 $atts = shortcode_atts([
1446 'form_id' => '',
1447 'serial_number' => '',
1448 'field' => '',
1449 'is_html' => true,
1450 ], $atts);
1451
1452 if (empty($atts['form_id']) || empty($atts['field'])) {
1453 return '';
1454 }
1455
1456
1457 $formId = (int) $atts['form_id'];
1458 $form = wpFluent()->table('fluentform_forms')->find($formId);
1459 if (!$form) {
1460 return __('Form not found.', 'fluentform');
1461 }
1462 $isHtml = $atts['is_html'] === 'true' ? true : false;
1463 $submission = (new \FluentForm\App\Services\Submission\SubmissionService())->findBySerialID($formId, $atts['serial_number'],$isHtml);
1464 if (!$submission) {
1465 return __('No entry found.', 'fluentform');
1466 }
1467
1468 $input = $submission->user_inputs;
1469 $field = sanitize_text_field($atts['field']);
1470 $fieldVal = ArrayHelper::get($input, $field, '');
1471
1472 $response = FormDataParser::formatValue($fieldVal);
1473 echo $atts['is_html'] ? wp_kses_post($response) : esc_html($response);
1474
1475 return ob_get_clean();
1476 });
1477
1478 }
1479
1480 private function localizeJavaScriptMessages($form)
1481 {
1482 // Form submission messages
1483 $submissionMessages = [
1484 'file_upload_in_progress' => __('File upload in progress. Please wait...', 'fluentform'),
1485 'javascript_handler_failed' => __('Javascript handler could not be loaded. Form submission has been failed. Reload the page and try again', 'fluentform')
1486 ];
1487 $submissionMessages = apply_filters('fluentform/form_submission_messages', $submissionMessages, $form);
1488 wp_localize_script('fluent-form-submission', 'fluentform_submission_messages_' . $form->id, $submissionMessages);
1489
1490 // Payment handler messages
1491 $paymentMessages = [
1492 'stock_out_message' => __('This Item is Stock Out', 'fluentform'),
1493 'item_label' => __('Item', 'fluentform'),
1494 'price_label' => __('Price', 'fluentform'),
1495 'qty_label' => __('Qty', 'fluentform'),
1496 'line_total_label' => __('Line Total', 'fluentform'),
1497 'sub_total_label' => __('Sub Total', 'fluentform'),
1498 'discount_label' => __('Discount', 'fluentform'),
1499 'total_label' => __('Total', 'fluentform'),
1500 'signup_fee_label' => __('Signup Fee', 'fluentform'),
1501 'trial_label' => __('Trial', 'fluentform'),
1502 'processing_text' => __('Processing...', 'fluentform'),
1503 'confirming_text' => __('Confirming...', 'fluentform')
1504 ];
1505 $paymentMessages = apply_filters('fluentform/payment_handler_messages', $paymentMessages, $form);
1506 wp_localize_script('fluent-form-submission', 'fluentform_payment_messages_' . $form->id, $paymentMessages);
1507
1508 // Form save progress messages
1509 $saveProgressMessages = [
1510 'copy_button' => __('Copy', 'fluentform'),
1511 'email_button' => __('Email', 'fluentform'),
1512 'email_placeholder' => __('Your Email Here', 'fluentform'),
1513 'copy_success' => __('Copied', 'fluentform')
1514 ];
1515 $saveProgressMessages = apply_filters('fluentform/form_save_progress_messages', $saveProgressMessages, $form);
1516 wp_localize_script('fluent-form-submission', 'fluentform_save_progress_messages_' . $form->id, $saveProgressMessages);
1517
1518 // Address autocomplete messages
1519 $addressMessages = [
1520 'please_wait' => __('Please wait ...', 'fluentform'),
1521 'location_not_determined' => __('Could not determine address from location.', 'fluentform'),
1522 'address_fetch_failed' => __('Failed to fetch address from coordinates.', 'fluentform'),
1523 'geolocation_failed' => __('Geolocation failed or was denied.', 'fluentform'),
1524 'geolocation_not_supported' => __('Geolocation is not supported by this browser.', 'fluentform')
1525 ];
1526 $addressMessages = apply_filters('fluentform/address_autocomplete_messages', $addressMessages, $form);
1527 wp_localize_script('fluent-form-submission', 'fluentform_address_messages_' . $form->id, $addressMessages);
1528
1529 // Payment gateway messages
1530 $gatewayMessages = [
1531 'request_failed' => __('Request failed. Please try again', 'fluentform'),
1532 'payment_failed' => __('Payment process failed!', 'fluentform'),
1533 'no_method_found' => __('No method found', 'fluentform'),
1534 'processing_text' => __('Processing...', 'fluentform')
1535 ];
1536 $gatewayMessages = apply_filters('fluentform/payment_gateway_messages', $gatewayMessages, $form);
1537 wp_localize_script('fluent-form-submission', 'fluentform_gateway_messages_' . $form->id, $gatewayMessages);
1538 }
1539 }
1540