PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 4.3.6
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v4.3.6
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 3.6.66 All 195 releases
fluentform / app / Modules / Component / Component.php

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

1,052 lines 35.7 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 use FluentForm\App\Helpers\Helper;
6 use FluentForm\App\Modules\Acl\Acl;
7 use FluentForm\App\Services\FormBuilder\EditorShortcodeParser;
8 use FluentForm\App\Services\FormBuilder\Notifications\EmailNotificationActions;
9 use FluentForm\Framework\Foundation\Application;
10 use FluentForm\Framework\Helpers\ArrayHelper;
11
12 class Component
13 {
14 /**
15 * FluentForm\Framework\Foundation\Application
16 *
17 * @var $app
18 */
19 protected $app = null;
20
21 /**
22 * Determine whether to register Elementor PopUp handler.
23 *
24 * @var bool
25 */
26 protected $elementorPopUpHandler = false;
27
28 /**
29 * Biuld the instance of this class
30 *
31 * @param \FluentForm\Framework\Foundation\Application $app
32 */
33 public function __construct(Application $app)
34 {
35 $this->app = $app;
36 }
37
38 public function registerScripts()
39 {
40 $app = $this->app;
41
42 // We will just register the scripts here. We will not load any scripts from here
43
44 $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public.css');
45 $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default.css');
46
47 if (is_rtl()) {
48 $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public-rtl.css');
49 $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default-rtl.css');
50 }
51
52 wp_register_style(
53 'fluent-form-styles',
54 $fluentFormPublicCss,
55 array(),
56 FLUENTFORM_VERSION
57 );
58
59 wp_register_style(
60 'fluentform-public-default',
61 $fluentFormPublicDefaultCss,
62 array(),
63 FLUENTFORM_VERSION
64 );
65
66 wp_register_script(
67 'fluent-form-submission',
68 $app->publicUrl('js/form-submission.js'),
69 array('jquery'),
70 FLUENTFORM_VERSION,
71 true
72 );
73
74 wp_register_script(
75 'fluentform-advanced',
76 $app->publicUrl('js/fluentform-advanced.js'),
77 array('jquery'),
78 FLUENTFORM_VERSION,
79 true
80 );
81
82 // Date Pickckr Style
83 //fix for essential addon event picker conflict
84 if (!wp_script_is('flatpickr', 'registered')) {
85 wp_register_style(
86 'flatpickr',
87 $app->publicUrl('libs/flatpickr/flatpickr.min.css')
88 );
89 }
90 // Date Pickckr Script
91 wp_register_script(
92 'flatpickr',
93 $app->publicUrl('libs/flatpickr/flatpickr.js'),
94 array('jquery'),
95 false,
96 true
97 );
98
99 wp_register_script(
100 'choices',
101 $app->publicUrl('libs/choices/choices.min.js'),
102 array(),
103 '9.0.1',
104 true
105 );
106
107 wp_register_style(
108 'ff_choices',
109 $app->publicUrl('css/choices.css'),
110 [],
111 FLUENTFORM_VERSION
112 );
113
114 do_action('fluentform_scripts_registered');
115
116 $this->maybeLoadFluentFormStyles();
117 }
118
119 protected function maybeLoadFluentFormStyles()
120 {
121 global $post;
122
123 $postId = isset( $post->ID ) ? $post->ID : false;
124 if (!$postId) {
125 return;
126 }
127 $fluentFormIds = get_post_meta($postId, '_has_fluentform', true);
128 $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds;
129
130 if ($hasFluentformMeta || apply_filters('fluentform_load_styles', false, $post)) {
131 wp_enqueue_style('fluent-form-styles');
132 wp_enqueue_style('fluentform-public-default');
133 do_action('fluentform_pre_load_scripts', $post);
134 wp_enqueue_script('fluent-form-submission');
135 }
136 }
137
138 /**
139 * Get all the available components
140 *
141 * @return void
142 * @throws \Exception
143 * @throws \FluentForm\Framework\Exception\UnResolveableEntityException
144 */
145 public function index()
146 {
147 $formId = intval($_REQUEST['formId']);
148 $components = $this->app->make('components');
149
150 $this->app->doAction('fluent_editor_init', $components);
151
152 $editorComponents = $components->sort()->toArray();
153 $editorComponents = apply_filters('fluent_editor_components', $editorComponents, $formId);
154
155 $countries = $this->app->load($this->app->appPath('Services/FormBuilder/CountryNames.php'));
156
157 wp_send_json_success(array(
158 'countries' => $countries,
159 'components' => $editorComponents,
160 'disabled_components' => $this->getDisabledComponents()
161 ));
162 }
163
164
165 /**
166 * Get disabled components
167 *
168 * @return array
169 */
170 private function getDisabledComponents()
171 {
172 $isReCaptchaDisabled = !get_option('_fluentform_reCaptcha_keys_status', false);
173 $isHCaptchaDisabled = !get_option('_fluentform_hCaptcha_keys_status', false);
174
175 $disabled = array(
176 'recaptcha' => array(
177 'contentComponent' => 'recaptcha',
178 'disabled' => $isReCaptchaDisabled
179 ),
180 'hcaptcha' => array(
181 'contentComponent' => 'hcaptcha',
182 'disabled' => $isHCaptchaDisabled
183 ),
184 'input_image' => array(
185 'disabled' => true
186 ),
187 'input_file' => array(
188 'disabled' => true
189 ),
190 'shortcode' => array(
191 'disabled' => true
192 ),
193 'action_hook' => array(
194 'disabled' => true
195 ),
196 'form_step' => array(
197 'disabled' => true
198 )
199 );
200
201 if (!defined('FLUENTFORMPRO')) {
202 $disabled['ratings'] = array(
203 'disabled' => true
204 );
205 $disabled['tabular_grid'] = array(
206 'disabled' => true
207 );
208 $disabled['phone'] = array(
209 'disabled' => true
210 );
211
212 $disabled['net_promoter_score'] = array(
213 'disabled' => true
214 );
215
216 $disabled['repeater_field'] = array(
217 'disabled' => true
218 );
219
220 $disabled['rangeslider'] = array(
221 'disabled' => true
222 );
223
224 $disabled['color-picker'] = array(
225 'disabled' => true
226 );
227
228 $disabled['multi_payment_component'] = array(
229 'disabled' => true,
230 'is_payment' => true
231 );
232 $disabled['custom_payment_component'] = array(
233 'disabled' => true,
234 'is_payment' => true
235 );
236
237 $disabled['item_quantity_component'] = array(
238 'disabled' => true,
239 'is_payment' => true
240 );
241
242 $disabled['payment_method'] = array(
243 'disabled' => true,
244 'is_payment' => true
245 );
246 }
247 return $this->app->applyFilters('fluentform_disabled_components', $disabled);
248 }
249
250 /**
251 * Get available shortcodes for editor
252 *
253 * @return void
254 * @throws \Exception
255 */
256 public function getEditorShortcodes()
257 {
258 $editor_shortcodes = fluentFormEditorShortCodes();
259 wp_send_json_success(['shortcodes' => $editor_shortcodes], 200);
260 }
261
262 /**
263 * Get all available shortcodes for editor
264 *
265 * @return void
266 * @throws \Exception
267 */
268 public function getAllEditorShortcodes()
269 {
270 wp_send_json(fluentFormGetAllEditorShortCodes(
271 $this->app->request->get('formId')
272 ), 200);
273 }
274
275 /**
276 * Register the form renderer shortcode
277 *
278 * @return void
279 */
280 public function addFluentFormShortCode()
281 {
282
283 add_action('wp_enqueue_scripts', array($this, 'registerScripts'), 9);
284
285 $this->app->addShortCode('fluentform', function ($atts, $content) {
286 $shortcodeDefaults = apply_filters('fluentform_shortcode_defaults', array(
287 'id' => null,
288 'title' => null,
289 'css_classes' => '',
290 'permission' => '',
291 'type' => 'classic',
292 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform')
293 ), $atts);
294
295 $atts = shortcode_atts($shortcodeDefaults, $atts);
296
297 return $this->renderForm($atts);
298 });
299
300 $this->app->addShortCode('fluentform_info', function ($atts) {
301 $shortcodeDefaults = apply_filters('fluentform_info_shortcode_defaults', array(
302 'id' => null, // This is the form id
303 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total
304 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read
305 'with_trashed' => 'no', // yes | no
306 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"]
307 'hide_on_zero' => 'no',
308 'payment_status' => 'paid', // it can be all / specific payment status
309 'currency_formatted' => 'yes',
310 'date_format' => ''
311 ), $atts);
312
313 $atts = shortcode_atts($shortcodeDefaults, $atts);
314 $formId = $atts['id'];
315 $form = wpFluent()->table('fluentform_forms')->find($formId);
316
317 if (!$form) {
318 return '';
319 }
320
321 if ($atts['info'] == 'submission_count') {
322 $countQuery = wpFluent()->table('fluentform_submissions')
323 ->where('form_id', $formId);
324
325 if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
326 $countQuery = $countQuery->where('status', '!=', 'trashed');
327 }
328
329 if ($atts['status'] == 'all') {
330 // ...
331 } else if ($atts['status'] == 'favourites') {
332 $countQuery = $countQuery->where('is_favourite', '=', 1);
333 } else {
334 $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
335 }
336 if ($atts['payment_status'] && defined('FLUENTFORMPRO') && $atts['payment_status'] != 'all') {
337 $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
338 }
339
340 $total = $countQuery->count();
341
342 if ($atts['substract_from']) {
343 $total = intval($atts['substract_from']) - $total;
344 }
345
346 if ($atts['hide_on_zero'] == 'yes' && !$total || $total < 0) {
347 return '';
348 }
349
350 return $total;
351 } else if ($atts['info'] == 'created_at') {
352 if ($atts['date_format']) {
353 $dateFormat = $atts['date_format'];
354 } else {
355 $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
356 }
357 return date($dateFormat, strtotime($form->created_at));
358 } else if ($atts['info'] == 'updated_at') {
359 if ($atts['date_format']) {
360 $dateFormat = $atts['date_format'];
361 } else {
362 $dateFormat = get_option('date_format') . ' ' . get_option('time_format');
363 }
364 return date($dateFormat, strtotime($form->updated_at));
365 } else if ($atts['info'] == 'payment_total') {
366
367 if (!defined('FLUENTFORMPRO')) {
368 return '';
369 }
370
371 global $wpdb;
372 $countQuery = wpFluent()
373 ->table('fluentform_submissions')
374 ->select(wpFluent()->raw('SUM(total_paid) as payment_total'))
375 ->where('form_id', $formId);
376
377 if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') {
378 $countQuery = $countQuery->where('status', '!=', 'trashed');
379 }
380
381 if ($atts['status'] == 'all') {
382 // ...
383 } else if ($atts['status'] == 'favourites') {
384 $countQuery = $countQuery->where('is_favourite', '=', 1);
385 } else {
386 $countQuery = $countQuery->where('status', '=', sanitize_key($atts['status']));
387 }
388
389 if ($atts['payment_status'] == 'all') {
390 // ...
391 } else if ($atts['payment_status']) {
392 $countQuery = $countQuery->where('payment_status', '=', sanitize_key($atts['payment_status']));
393 }
394
395 $row = $countQuery->first();
396
397 $total = 0;
398 if ($row) {
399 $total = $row->payment_total;
400 }
401
402 if ($atts['substract_from']) {
403 $total = intval($atts['substract_from'] * 100) - $total;
404 }
405
406 if ($atts['hide_on_zero'] == 'yes' && !$total) {
407 return '';
408 }
409
410 if ($atts['currency_formatted'] == 'yes') {
411 $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId);
412 return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency);
413 }
414
415 if (!$total) {
416 return 0;
417 }
418
419 return $total / 100;
420 }
421
422 return '';
423 });
424
425 $this->app->addShortCode('ff_get', function ($atts) {
426 $atts = shortcode_atts(array(
427 'param' => '',
428 ), $atts);
429 if ($atts['param'] && isset($_GET[$atts['param']])) {
430 $value = $_GET[$atts['param']];
431 if (is_array($value)) {
432 return implode(', ', $value);
433 }
434 return esc_html($value);
435 }
436 return '';
437 });
438
439 }
440
441 public function renderForm($atts)
442 {
443 $form_id = $atts['id'];
444 $query = wpFluent()->table('fluentform_forms');
445 if (!isset($_GET['preview_id'])) {
446 $query->where('status', 'published');
447 }
448 if ($form_id) {
449 $form = $query->find($form_id);
450 } elseif ($formTitle = $atts['title']) {
451 $form = $query->where('title', $formTitle)->first();
452 } else {
453 return '';
454 }
455
456 if (!$form) {
457 return '';
458 }
459
460 if (!empty($atts['permission'])) {
461 if (!current_user_can($atts['permission'])) {
462 return "<div id='ff_form_{$form->id}' class='ff_form_not_render'>{$atts['permission_message']}</div>";
463 }
464 }
465
466 if (is_feed()) {
467 global $post;
468 $feedText = sprintf(__('The form can be filled in the actual <a href="%s">website url</a>.', 'fluentform'), get_permalink($post));
469 $feedText = apply_filters('fluentform_shortcode_feed_text', $feedText, $form);
470 return $feedText;
471 }
472
473 $formSettings = wpFluent()
474 ->table('fluentform_form_meta')
475 ->where('form_id', $form_id)
476 ->where('meta_key', 'formSettings')
477 ->first();
478
479 if (!$formSettings) {
480 return '';
481 }
482
483 $form->fields = json_decode($form->form_fields, true);
484
485 if (!$form->fields['fields']) {
486 return '';
487 }
488
489 $form->settings = json_decode($formSettings->value, true);
490 $form = $this->app->applyFilters('fluentform_rendering_form', $form);
491
492 $isRenderable = array(
493 'status' => true,
494 'message' => ''
495 );
496
497 $isRenderable = $this->app->applyFilters('fluentform_is_form_renderable', $isRenderable, $form);
498
499 if (is_array($isRenderable) && !$isRenderable['status']) {
500 return "<div id='ff_form_{$form->id}' class='ff_form_not_render'>{$isRenderable['message']}</div>";
501 }
502
503 $instanceCssClass = Helper::getFormInstaceClass($form->id);
504
505 $form->instance_css_class = $instanceCssClass;
506 $form->instance_index = Helper::$formInstance;
507
508
509 if ($atts['type'] == 'conversational') {
510 return (new \FluentForm\App\Services\FluentConversational\Classes\Form())->renderShortcode($form);
511 }
512
513 $formBuilder = $this->app->make('formBuilder');
514
515 $cssClasses = trim($instanceCssClass . ' ff-form-loading');
516
517 $output = $formBuilder->build($form, $cssClasses, $instanceCssClass, $atts);
518
519 $output = $this->replaceEditorSmartCodes($output, $form);
520
521 if (!wp_script_is('fluent-form-submission', 'registered')) {
522 $this->registerScripts();
523 }
524
525 wp_enqueue_style('fluent-form-styles');
526 if (apply_filters('fluentform_load_default_public', true, $form)) {
527 wp_enqueue_style('fluentform-public-default');
528 }
529 /*
530 * We will load fluentform-advanced if the form has certain fields or feature
531 */
532 $this->maybeHasAdvandedFields($form, $formBuilder);
533 wp_enqueue_script('fluent-form-submission');
534
535 $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', 'fluentform');
536 $stepText = apply_filters('fluentform_step_string', $stepText);
537 $vars = apply_filters('fluentform_global_form_vars', array(
538 'ajaxUrl' => admin_url('admin-ajax.php'),
539 'forms' => array(),
540 'step_text' => $stepText,
541 'is_rtl' => is_rtl(),
542 'date_i18n' => $this->getDatei18n(),
543 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false,
544 'fluentform_version' => FLUENTFORM_VERSION,
545 'force_init' => false,
546 'stepAnimationDuration' => 350,
547 'upload_completed_txt' => __('100% Completed', 'fluentform'),
548 'upload_start_txt' => __('0% Completed', 'fluentform'),
549 'uploading_txt' => __('Uploading', 'fluentform'),
550 'choice_js_vars' => [
551 'noResultsText' => __('No results found', 'fluentform'),
552 'loadingText' => __('Loading...', 'fluentform'),
553 'noChoicesText' => __('No choices to choose from', 'fluentform'),
554 'itemSelectText' => __('Press to select', 'fluentform'),
555 'maxItemText' => __('Only %%maxItemCount%% options can be added', 'fluentform'),
556 ],
557 'jquery_mask_vars' => [
558 'clearIfNotMatch' => false,
559 ]
560 ));
561
562 wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars);
563
564 $formSettings = $form->settings;
565
566 $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']);
567
568 $formSettings['restrictions']['denyEmptySubmission'] = [
569 'enabled' => false
570 ];
571
572 $form_vars = array(
573 'id' => $form->id,
574 'settings' => $formSettings,
575 'form_instance' => $instanceCssClass,
576 'form_id_selector' => 'fluentform_' . $form->id,
577 'rules' => $formBuilder->validationRules
578 );
579
580 if ($conditionals = $formBuilder->conditions) {
581 $form_vars['conditionals'] = $conditionals;
582 }
583
584 $form_vars = apply_filters('fluentform/form_vars_for_JS', $form_vars, $form);
585
586 if ($form->has_payment) {
587 do_action('fluentform_rendering_payment_form', $form);
588 }
589
590 $otherScripts = '';
591 ob_start();
592 ?>
593 <script type="text/javascript">
594 window.fluent_form_<?php echo esc_attr($instanceCssClass); ?> = <?php echo wp_json_encode($form_vars);?>;
595 <?php if(wp_doing_ajax()): ?>
596 function initFFInstance_<?php echo esc_attr($form_vars['id']); ?>() {
597 if (!window.fluentFormApp) {
598 console.log('No fluentFormApp found');
599 return;
600 }
601 var ajax_formInstance = window.fluentFormApp(jQuery('form.<?php echo esc_attr($form_vars['form_instance']); ?>'));
602 if (ajax_formInstance) {
603 ajax_formInstance.initFormHandlers();
604 }
605 }
606
607 initFFInstance_<?php echo esc_attr($form_vars['id']); ?>();
608 <?php endif; ?>
609 </script>
610 <?php
611 $this->addInlineVars();
612 $otherScripts .= ob_get_clean();
613
614 if (!apply_filters('fluentform-disabled_analytics', false)) {
615 if (!Acl::hasAnyFormPermission($form->id)) {
616 (new \FluentForm\App\Modules\Form\Analytics($this->app))->record($form->id);
617 }
618 }
619
620 return $output . $otherScripts;
621 }
622
623 /**
624 * Process the output HTML to generate the default values.
625 *
626 * @param string $output
627 * @param \stdClass $form
628 * @return string
629 */
630 public function replaceEditorSmartCodes($output, $form)
631 {
632 // Get the patterns for default values from the output HTML string.
633 // The example of a pattern would be for user ID: {user.ID}
634 preg_match_all('/{(.*?)}/', $output, $matches);
635 $patterns = array_unique($matches[0]);
636
637
638 $attrDefaultValues = [];
639
640 foreach ($patterns as $pattern) {
641 // The default value for each pattern will be resolved here.
642 $attrDefaultValues[$pattern] = apply_filters('fluentform_parse_default_value', $pattern, $form);
643 }
644
645 // Raising an event so that others can hook into it and modify the default values later.
646 $attrDefaultValues = (array)apply_filters('fluentform_parse_default_values', $attrDefaultValues);
647
648 if (isset($attrDefaultValues['{payment_total}'])) {
649 $attrDefaultValues['{payment_total}'] = '<span class="ff_order_total"></span>';
650 }
651
652 // Finally, replace the patterns with the replacements and return the output HTML.
653 return str_replace(array_keys($attrDefaultValues), array_values($attrDefaultValues), $output);
654 }
655
656 /**
657 * Register renderer actions for compiling each element
658 *
659 * @return void
660 */
661 public function addRendererActions()
662 {
663 $actionMappings = [
664 'Select@compile' => ['fluentform_render_item_select'],
665 'Rating@compile' => ['fluentform_render_item_ratings'],
666 'Address@compile' => ['fluentform_render_item_address'],
667 'Name@compile' => ['fluentform_render_item_input_name'],
668 'TextArea@compile' => ['fluentform_render_item_textarea'],
669 'DateTime@compile' => ['fluentform_render_item_input_date'],
670 'Recaptcha@compile' => ['fluentform_render_item_recaptcha'],
671 'Hcaptcha@compile' => ['fluentform_render_item_hcaptcha'],
672 'Container@compile' => ['fluentform_render_item_container'],
673 'CustomHtml@compile' => ['fluentform_render_item_custom_html'],
674 'SectionBreak@compile' => ['fluentform_render_item_section_break'],
675 'SubmitButton@compile' => ['fluentform_render_item_submit_button'],
676 'SelectCountry@compile' => ['fluentform_render_item_select_country'],
677
678 'TermsAndConditions@compile' => [
679 'fluentform_render_item_terms_and_condition',
680 'fluentform_render_item_gdpr_agreement'
681 ],
682
683 'TabularGrid@compile' => [
684 'fluentform_render_item_tabular_grid'
685 ],
686
687 'Checkable@compile' => [
688 'fluentform_render_item_input_radio',
689 'fluentform_render_item_input_checkbox',
690 ],
691
692 'Text@compile' => [
693 'fluentform_render_item_input_url',
694 'fluentform_render_item_input_text',
695 'fluentform_render_item_input_email',
696 'fluentform_render_item_input_number',
697 'fluentform_render_item_input_hidden',
698 'fluentform_render_item_input_password',
699 ],
700 ];
701
702 $path = 'FluentForm\App\Services\FormBuilder\Components\\';
703 foreach ($actionMappings as $handler => $actions) {
704 foreach ($actions as $action) {
705 $this->app->addAction($action, function () use ($path, $handler) {
706 list($class, $method) = $this->app->parseHandler($path . $handler);
707 call_user_func_array(array($class, $method), func_get_args());
708 }, 10, 2);
709 }
710 }
711 }
712
713 /**
714 * Register dynamic value shortcode parser (filter default value)
715 *
716 * @return void
717 */
718 public function addFluentFormDefaultValueParser()
719 {
720 $this->app->addFilter('fluentform_parse_default_value', function ($value, $form) {
721 return EditorShortcodeParser::filter($value, $form);
722 }, 10, 2);
723 }
724
725 /**
726 * Register filter to check whether the form is renderable
727 *
728 * @return mixed
729 */
730 public function addIsRenderableFilter()
731 {
732 $this->app->addFilter('fluentform_is_form_renderable', function ($isRenderable, $form) {
733 $checkables = array('limitNumberOfEntries', 'scheduleForm', 'requireLogin');
734
735 foreach ($form->settings['restrictions'] as $key => $restrictions) {
736 if (in_array($key, $checkables)) {
737 $isRenderable['status'] = $this->{$key}($restrictions, $form, $isRenderable);
738 if (!$isRenderable['status']) {
739 $isRenderable['status'] = false;
740 return $isRenderable;
741 }
742 }
743 }
744
745 return $isRenderable;
746 }, 10, 2);
747 }
748
749 /**
750 * Check if limit is set on form submits and it's valid yet
751 *
752 * @param array $restrictions
753 *
754 * @return bool
755 */
756 private function limitNumberOfEntries($restrictions, $form, &$isRenderable)
757 {
758 if (!$restrictions['enabled']) {
759 return true;
760 }
761
762 $col = 'created_at';
763 $period = $restrictions['period'];
764 $maxAllowedEntries = $restrictions['numberOfEntries'];
765
766 if (!$maxAllowedEntries) {
767 return true;
768 }
769
770 $query = wpFluent()->table('fluentform_submissions')
771 ->where('form_id', $form->id)
772 ->where('status', '!=', 'trashed');
773
774 if ($period == 'day') {
775 $year = "YEAR(`{$col}`) = YEAR(NOW())";
776 $month = "MONTH(`{$col}`) = MONTH(NOW())";
777 $day = "DAY(`{$col}`) = DAY(NOW())";
778 $query->where(wpFluent()->raw("{$year} AND {$month} AND {$day}"));
779 } elseif ($period == 'week') {
780 $query->where(
781 wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)")
782 );
783 } elseif ($period == 'month') {
784 $year = "YEAR(`{$col}`) = YEAR(NOW())";
785 $month = "MONTH(`{$col}`) = MONTH(NOW())";
786 $query->where(wpFluent()->raw("{$year} AND {$month}"));
787 } elseif ($period == 'year') {
788 $query->where(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())"));
789 } else if ($period == 'per_user_ip') {
790 $ip = $this->app->request->getIp();
791 $query->where('ip', $ip);
792 } else if ($period == 'per_user_id') {
793 $userId = get_current_user_id();
794 if (!$userId) {
795 return true;
796 }
797 $query->where('user_id', $userId);
798 }
799
800 $count = $query->count();
801
802
803 if ($count >= $maxAllowedEntries) {
804 $isRenderable['message'] = $restrictions['limitReachedMsg'];
805 return false;
806 }
807
808 return true;
809 }
810
811 /**
812 * Check if form has scheduled date & weekdays and open for submission
813 *
814 * @param array $restrictions
815 *
816 * @return bool
817 */
818 private function scheduleForm($restrictions, $form, &$isRenderable)
819 {
820 if (!$restrictions['enabled']) {
821 return true;
822 }
823
824 $time = time();
825 $start = strtotime($restrictions['start']);
826 $end = strtotime($restrictions['end']);
827
828 if ($time < $start) {
829 $isRenderable['message'] = $restrictions['pendingMsg'];
830 return false;
831 }
832
833 if ($time >= $end) {
834 $isRenderable['message'] = $restrictions['expiredMsg'];
835
836 return false;
837 }
838
839 $weekDayToday = date("l"); //day of the week
840 $selectedWeekDays = ArrayHelper::get($restrictions, 'selectedDays');
841 //skip if it was not set initially and $selectedWeekDays is null
842 if ($selectedWeekDays && is_array($selectedWeekDays) && !in_array($weekDayToday, $selectedWeekDays)) {
843 $isRenderable['message'] = $restrictions['expiredMsg'];
844 return false;
845 }
846
847 return true;
848 }
849
850 /**
851 * * Check if form requires loged in user and user is logged in
852 *
853 * @param array $restrictions
854 *
855 * @return bool
856 */
857 private function requireLogin($restrictions, $form, &$isRenderable)
858 {
859 if (!$restrictions['enabled']) {
860 return true;
861 }
862
863 if (!($isLoggedIn = is_user_logged_in())) {
864 $isRenderable['message'] = $restrictions['requireLoginMsg'];
865 }
866
867 return $isLoggedIn;
868 }
869
870 /**
871 * Register fluentform_submission_inserted actions
872 *
873 * @return void
874 */
875 public function addFluentformSubmissionInsertedFilter()
876 {
877 (new EmailNotificationActions($this->app))->register();
878 }
879
880 /**
881 * Add inline scripts [Add localized script using same var]
882 *
883 * @return void
884 */
885 private function addInlineVars()
886 {
887 if (!defined('ELEMENTOR_PRO_VERSION') || $this->elementorPopUpHandler) {
888 return '';
889 }
890
891 // Previously this handler was registered for every form
892 // in a single page. So multiple event handlers were
893 // registered. This flag ensures the handler is
894 // registered just once, since one is enough!
895 $this->elementorPopUpHandler = true;
896
897 $actionName = 'wp_footer';
898 if (is_admin()) {
899 $actionName = 'admin_footer';
900 }
901
902 add_action($actionName, function () {
903 ?>
904 <script type="text/javascript">
905 <?php if(defined('ELEMENTOR_PRO_VERSION')): ?>
906 jQuery(document).on('elementor/popup/show', function (event, id, instance) {
907 var ffForms = jQuery('#elementor-popup-modal-' + id).find('form.frm-fluent-form');
908
909 /**
910 * Support conversation form in elementor popup
911 * No regular form found, check for conversational form
912 */
913 if (!ffForms.length) {
914 const elements = document.getElementsByClassName('ffc_conv_form');
915 if (elements.length) {
916 let jsEvent = new CustomEvent('ff-elm-conv-form-event', {
917 detail: elements[0]
918 });
919 document.dispatchEvent(jsEvent);
920 }
921 }
922 if (ffForms.length) {
923 jQuery.each(ffForms, function (index, ffForm) {
924 jQuery(ffForm).trigger('reInitExtras');
925 jQuery(document).trigger('ff_reinit', [ffForm]);
926 });
927 }
928 });
929 <?php endif; ?>
930 </script>
931 <?php
932 }, 999);
933 return '';
934 }
935
936 public static function getDatei18n()
937 {
938 $i18n = array(
939 'previousMonth' => __('Previous Month', 'fluentform'),
940 'nextMonth' => __('Next Month', 'fluentform'),
941 'months' => [
942 'shorthand' => [
943 __('Jan', 'fluentform'),
944 __('Feb', 'fluentform'),
945 __('Mar', 'fluentform'),
946 __('Apr', 'fluentform'),
947 __('May', 'fluentform'),
948 __('Jun', 'fluentform'),
949 __('Jul', 'fluentform'),
950 __('Aug', 'fluentform'),
951 __('Sep', 'fluentform'),
952 __('Oct', 'fluentform'),
953 __('Nov', 'fluentform'),
954 __('Dec', 'fluentform')
955 ],
956 'longhand' => [
957 __('January', 'fluentform'),
958 __('February', 'fluentform'),
959 __('March', 'fluentform'),
960 __('April', 'fluentform'),
961 __('May', 'fluentform'),
962 __('June', 'fluentform'),
963 __('July', 'fluentform'),
964 __('August', 'fluentform'),
965 __('September', 'fluentform'),
966 __('October', 'fluentform'),
967 __('November', 'fluentform'),
968 __('December', 'fluentform')
969 ]
970 ],
971 'weekdays' => [
972 'longhand' => array(
973 __('Sunday', 'fluentform'),
974 __('Monday', 'fluentform'),
975 __('Tuesday', 'fluentform'),
976 __('Wednesday', 'fluentform'),
977 __('Thursday', 'fluentform'),
978 __('Friday', 'fluentform'),
979 __('Saturday', 'fluentform')
980 ),
981 'shorthand' => array(
982 __('Sun', 'fluentform'),
983 __('Mon', 'fluentform'),
984 __('Tue', 'fluentform'),
985 __('Wed', 'fluentform'),
986 __('Thu', 'fluentform'),
987 __('Fri', 'fluentform'),
988 __('Sat', 'fluentform')
989 )
990 ],
991 'daysInMonth' => [
992 31,
993 28,
994 31,
995 30,
996 31,
997 30,
998 31,
999 31,
1000 30,
1001 31,
1002 30,
1003 31
1004 ],
1005 'rangeSeparator' => __(' to ', 'fluentform'),
1006 'weekAbbreviation' => __('Wk', 'fluentform'),
1007 'scrollTitle' => __('Scroll to increment', 'fluentform'),
1008 'toggleTitle' => __('Click to toggle', 'fluentform'),
1009 'amPM' => [
1010 __('AM', 'fluentform'),
1011 __('PM', 'fluentform')
1012 ],
1013 'yearAriaLabel' => __('Year', 'fluentform')
1014 );
1015
1016 return apply_filters('fluentform/date_i18n', $i18n);
1017 }
1018
1019 protected function maybeHasAdvandedFields($form, $formBuilder)
1020 {
1021 $advancedFields = [
1022 'step_start',
1023 'repeater_field',
1024 'ratings',
1025 'form_step',
1026 'input_file',
1027 'input_image',
1028 'net_promoter_score',
1029 'featured_image'
1030 ];
1031
1032 if ($formBuilder->conditions || array_intersect($formBuilder->fieldLists, $advancedFields)) {
1033 wp_enqueue_script('fluentform-advanced');
1034 }
1035 }
1036
1037 public function registerInputSanitizers()
1038 {
1039 add_filter('fluentform_input_data_input_number', array($this, 'getNumericInputValue'), 10, 2);
1040 add_filter('fluentform_input_data_custom_payment_component', array($this, 'getNumericInputValue'), 10, 2);
1041 }
1042
1043 public function getNumericInputValue($value, $field)
1044 {
1045 $formatter = ArrayHelper::get($field, 'raw.settings.numeric_formatter');
1046 if (!$formatter) {
1047 return $value;
1048 }
1049 return Helper::getNumericValue($value, $formatter);
1050 }
1051 }
1052