PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.3.18
UiCore Elements – Free widgets and templates for Elementor v1.3.18
1.3.18 1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 All 42 releases
uicore-elements / includes / widgets / contact-form.php

contact-form.php in UiCore Elements – Free widgets and templates for Elementor 1.3.18, at includes/widgets/contact-form.php

1,401 lines 51.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace UiCoreElements;
4
5 use UiCoreElements\Helper;
6 use UiCoreElements\Utils\Contact_Form_Service;
7 use UiCoreElements\Utils\Form_Component;
8 use UiCoreElements\Utils\Newsletter_Services;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Icons_Manager;
12 use Elementor\Utils;
13 use Elementor\Repeater;
14 use Elementor\Group_Control_Typography;
15 use Elementor\Group_Control_Border;
16 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
17 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
18
19
20 defined('ABSPATH') || exit();
21
22 /**
23 * Contact Form
24 *
25 * @author Lucas Marini Falbo <[email protected]>
26 * @since 1.0.5
27 */
28
29 class ContactForm extends UiCoreWidget
30 {
31
32 use Form_Component;
33
34 public function get_name()
35 {
36 return 'uicore-contact-form';
37 }
38
39 public function get_title()
40 {
41 return __('Contact Form', 'uicore-elements');
42 }
43
44 public function get_icon()
45 {
46 return 'eicon-form-horizontal ui-e-widget';
47 }
48 public function get_categories()
49 {
50 return ['uicore'];
51 }
52 public function get_keywords()
53 {
54 return ['form', 'forms', 'contact', 'mail', 'send', 'field', 'button', 'recaptcha',];
55 }
56 public function get_styles()
57 {
58 return ['contact-form'];
59 }
60 public function get_scripts()
61 {
62 return [
63 'contact-form',
64 'recaptcha' => [
65 'custom_condition' => $this->check_recaptcha_version('v2')
66 ],
67 'recaptcha-v3' => [
68 'custom_condition' => $this->check_recaptcha_version('v3')
69 ],
70 'repeater-custom-key' => [
71 'custom_condition' => $this->is_edit_mode()
72 ]
73 ];
74 }
75 public function has_widget_inner_wrapper(): bool
76 {
77 // TODO: remove after Optmized Markup experiment is merged to the core
78 return ! \Elementor\Plugin::$instance->experiments->is_feature_active('e_optimized_markup');;
79 }
80 function check_recaptcha_version($version)
81 {
82
83 if ($this->is_edit_mode()) {
84 return true;
85 }
86 $settings = $this->get_settings_for_display();
87 foreach ($settings['form_fields'] as $field) {
88 $version_to_check = $version === 'v2' ? 'recaptcha' : 'recaptcha_v3';
89 if ($field['field_type'] === $version_to_check) {
90 return true;
91 }
92 }
93 return false;
94 }
95
96 // Helper Functions
97 function get_field_types()
98 {
99 return [
100 'text' => esc_html__('Text', 'uicore-elements'),
101 'email' => esc_html__('Email', 'uicore-elements'),
102 'textarea' => esc_html__('Textarea', 'uicore-elements'),
103 'url' => esc_html__('URL', 'uicore-elements'),
104 'tel' => esc_html__('Tel', 'uicore-elements'),
105 'radio' => esc_html__('Radio', 'uicore-elements'),
106 'select' => esc_html__('Select', 'uicore-elements'),
107 'checkbox' => esc_html__('Checkbox', 'uicore-elements'),
108 'acceptance' => esc_html__('Acceptance', 'uicore-elements'),
109 'number' => esc_html__('Number', 'uicore-elements'),
110 'date' => esc_html__('Date', 'uicore-elements'),
111 'time' => esc_html__('Time', 'uicore-elements'),
112 'file' => esc_html__('File Upload', 'uicore-elements'),
113 'password' => esc_html__('Password', 'uicore-elements'),
114 'address' => esc_html__('Honeypot', 'uicore-elements'),
115 'recaptcha' => esc_html__('reCAPTCHA', 'uicore-elements'),
116 'recaptcha_v3' => esc_html__('reCAPTCHA V3', 'uicore-elements'),
117 'html' => esc_html__('HTML', 'uicore-elements'),
118 'hidden' => esc_html__('Hidden', 'uicore-elements'),
119 ];
120 }
121
122 function get_attribute_name($item)
123 {
124 return "form_fields[{$item['custom_id']}]";
125 }
126 function get_attribute_id($item)
127 {
128 return 'form-field-' . $item['custom_id'];
129 }
130 function add_required_attribute($element, $js_verication = false)
131 {
132
133 // Used for elements (eg: checkbox) that aren't natively supported by the browsers validations
134 if ($js_verication) {
135 $this->add_render_attribute($element, 'data-ui-e-required', 'true');
136 return;
137 }
138
139 // Default method
140 $this->add_render_attribute($element, 'required', 'required');
141 $this->add_render_attribute($element, 'aria-required', 'true');
142 }
143
144 // Field Render Functions
145 function build_honeypot_field($item, $item_index)
146 {
147 $this->add_render_attribute('honeypot' . $item_index, [
148 'class' => [
149 'ui-e-field',
150 'ui-e-h-p',
151 esc_attr($item['css_classes']),
152 ],
153 'name' => 'ui-e-h-p',
154 'id' => 'ui-e-h-p',
155 'autocomplete' => 'off',
156 ]);
157
158 if ($item['placeholder']) {
159 $this->add_render_attribute('honeypot' . $item_index, 'placeholder', $item['placeholder']);
160 }
161
162 if ($item['required']) {
163 $this->add_required_attribute('honeypot' . $item_index);
164 }
165
166 $value = empty($item['field_value']) ? '' : $item['field_value'];
167
168 return '<input ' . $this->get_render_attribute_string('honeypot' . $item_index) . ' tabindex="-1">' . esc_html($value) . '</input>';
169 }
170 function build_textarea_field($item, $item_index)
171 {
172 $this->add_render_attribute('textarea' . $item_index, [
173 'class' => [
174 'ui-e-field',
175 esc_attr($item['css_classes']),
176 ],
177 'name' => $this->get_attribute_name($item),
178 'id' => $this->get_attribute_id($item),
179 'rows' => $item['rows'],
180 ]);
181
182 if ($item['placeholder']) {
183 $this->add_render_attribute('textarea' . $item_index, 'placeholder', $item['placeholder']);
184 }
185
186 if ($item['required']) {
187 $this->add_required_attribute('textarea' . $item_index);
188 }
189
190 $value = empty($item['field_value']) ? '' : $item['field_value'];
191
192 return '<textarea ' . $this->get_render_attribute_string('textarea' . $item_index) . '>' . esc_textarea($value) . '</textarea>';
193 }
194 function build_select_field($item, $i)
195 {
196 $this->add_render_attribute(
197 [
198 'select-wrapper' . $i => [
199 'class' => [
200 'ui-e-field',
201 'ui-e-field-select',
202 'ui-e-field-subgroup',
203 esc_attr($item['css_classes']),
204 ],
205 ],
206 'select' . $i => [
207 'name' => $this->get_attribute_name($item) . (! empty($item['allow_multiple']) ? '[]' : ''),
208 'id' => $this->get_attribute_id($item),
209 'class' => [
210 'ui-e-field-textual',
211 ],
212 ],
213 ]
214 );
215
216 if ($item['required']) {
217 $this->add_required_attribute('select' . $i);
218 }
219
220 if ($item['allow_multiple']) {
221 $this->add_render_attribute('select' . $i, 'multiple');
222 if (! empty($item['select_size'])) {
223 $this->add_render_attribute('select' . $i, 'size', $item['select_size']);
224 }
225 }
226
227 $options = preg_split("/\\r\\n|\\r|\\n/", $item['field_options']);
228
229 if (! $options) {
230 return '';
231 }
232
233 ob_start();
234 ?>
235 <div <?php $this->print_render_attribute_string('select-wrapper' . $i); ?>>
236 <select <?php $this->print_render_attribute_string('select' . $i); ?>>
237 <?php
238 foreach ($options as $key => $option) {
239 $option_id = $item['custom_id'] . $key;
240 $option_value = esc_attr($option);
241 $option_label = esc_html($option);
242
243 if (false !== strpos($option, '|')) {
244 list($label, $value) = explode('|', $option);
245 $option_value = esc_attr($value);
246 $option_label = esc_html($label);
247 }
248
249 $this->add_render_attribute($option_id, 'value', $option_value);
250
251 // Support multiple selected values
252 if (! empty($item['field_value']) && in_array($option_value, explode(',', $item['field_value']))) {
253 $this->add_render_attribute($option_id, 'selected', 'selected');
254 } ?>
255 <option <?php $this->print_render_attribute_string($option_id); ?>><?php
256 // PHPCS - $option_label is already escaped
257 echo $option_label; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
258 ?></option>
259 <?php } ?>
260 </select>
261 </div>
262 <?php
263
264 $select = ob_get_clean();
265 return $select;
266 }
267 function build_radio_checkbox_field($item, $item_index, $type)
268 {
269 $options = preg_split("/\\r\\n|\\r|\\n/", $item['field_options']);
270 $html = '';
271 if ($options) {
272 $html .= '<div class="ui-e-field-subgroup ' . esc_attr($item['css_classes']) . ' ' . esc_attr($item['inline_list']) . '">';
273 foreach ($options as $key => $option) {
274 $element_id = $item['custom_id'] . $key;
275 $html_id = $this->get_attribute_id($item) . '-' . $key;
276 $option_label = $option;
277 $option_value = $option;
278 if (false !== strpos($option, '|')) {
279 list($option_label, $option_value) = explode('|', $option);
280 }
281
282 $this->add_render_attribute(
283 $element_id,
284 [
285 'type' => $type,
286 'value' => $option_value,
287 'id' => $html_id,
288 'name' => $this->get_attribute_name($item) . (('checkbox' === $type && count($options) > 1) ? '[]' : ''),
289 ]
290 );
291
292 if ($item['required']) {
293 $this->add_required_attribute($element_id, true);
294 }
295
296 if (! empty($item['field_value']) && $option_value === $item['field_value']) {
297 $this->add_render_attribute($element_id, 'checked', 'checked');
298 }
299
300 if ($item['required'] && 'radio' === $type) {
301 $this->add_required_attribute($element_id);
302 }
303
304 $html .= '<span class="ui-e-field-option">';
305 $html .= '<input ' . $this->get_render_attribute_string($element_id) . '>';
306 $html .= '<label for="' . $html_id . '">';
307 $html .= esc_html($option_label);
308 $html .= '</label></span>';
309 }
310 $html .= '</div>';
311 }
312
313 return $html;
314 }
315 function build_acceptance_field($item, $item_index)
316 {
317 $text = '';
318 $this->add_render_attribute('input' . $item_index, 'class', 'ui-e-acceptance-field');
319 $this->add_render_attribute('input' . $item_index, 'type', 'checkbox', true);
320
321 if (! empty($item['acceptance_text'])) {
322 $text = '<label for="' . $this->get_attribute_id($item) . '">' . Helper::esc_string($item['acceptance_text']) . '</label>';
323 }
324
325 if (! empty($item['checked_by_default'])) {
326 $this->add_render_attribute('input' . $item_index, 'checked', 'checked');
327 }
328
329 ?>
330 <div class="ui-e-field-subgroup <?php echo esc_attr($item['css_classes']); ?>">
331 <input <?php $this->print_render_attribute_string('input' . $item_index); ?>>
332 <?php // PHPCS - the variables $text is safe.
333 echo $text; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
334 ?>
335 </div>
336 <?php
337 }
338 function form_fields_render_attributes($i, $instance, $item)
339 {
340 $this->add_render_attribute(
341 [
342 'field-group' . $i => [
343 'class' => [
344 'ui-e-field-type-' . $item['field_type'],
345 'ui-e-field-group',
346 'elementor-column',
347 'ui-e-field-group-' . $item['custom_id'],
348 ],
349 ],
350 'input' . $i => [
351 'type' => $item['field_type'],
352 'name' => $this->get_attribute_name($item),
353 'id' => $this->get_attribute_id($item),
354 'class' => [
355 'ui-e-field',
356 empty($item['css_classes']) ? '' : esc_attr($item['css_classes']),
357 ],
358 ],
359 'label' . $i => [
360 'for' => $this->get_attribute_id($item),
361 'class' => 'ui-e-label',
362 ],
363 ]
364 );
365
366 if (empty($item['width'])) {
367 $item['width'] = '100';
368 }
369
370 $this->add_render_attribute('field-group' . $i, 'class', 'elementor-col-' . $item['width']);
371
372 if (! empty($item['width_tablet'])) {
373 $this->add_render_attribute('field-group' . $i, 'class', 'elementor-md-' . $item['width_tablet']);
374 }
375
376 if ($item['allow_multiple']) {
377 $this->add_render_attribute('field-group' . $i, 'class', 'ui-e-field-type-' . $item['field_type'] . '-multiple');
378 }
379
380 if (! empty($item['width_mobile'])) {
381 $this->add_render_attribute('field-group' . $i, 'class', 'elementor-sm-' . $item['width_mobile']);
382 }
383
384 // Allow zero as placeholder.
385 if (! Utils::is_empty($item['placeholder'])) {
386 $this->add_render_attribute('input' . $i, 'placeholder', $item['placeholder']);
387 }
388
389 if (! empty($item['field_value'])) {
390 $this->add_render_attribute('input' . $i, 'value', $item['field_value']);
391 }
392
393 if (! $instance['show_labels']) {
394 $this->add_render_attribute('label' . $i, 'class', 'elementor-screen-only');
395 }
396
397 if (! empty($item['required'])) {
398 $class = '';
399 if (! empty($instance['mark_required'])) {
400 $class .= ' ui-e-required';
401 }
402 $this->add_render_attribute('field-group' . $i, 'class', $class);
403 $this->add_required_attribute('input' . $i);
404 }
405 }
406
407 protected function register_controls()
408 {
409
410 // Content Controls
411 // Repeater Controls used by `form_fields` control
412 $repeater = new Repeater();
413 $repeater->start_controls_tabs('form_fields_tabs');
414
415 $repeater->start_controls_tab(
416 'form_fields_content_tab',
417 [
418 'label' => esc_html__('Content', 'uicore-elements'),
419 ]
420 );
421
422 $repeater->add_control(
423 'field_type',
424 [
425 'label' => esc_html__('Type', 'uicore-elements'),
426 'type' => Controls_Manager::SELECT,
427 'options' => $this->get_field_types(),
428 'default' => 'text',
429 ]
430 );
431 $repeater->add_control(
432 'field_label',
433 [
434 'label' => esc_html__('Label', 'uicore-elements'),
435 'type' => Controls_Manager::TEXT,
436 'default' => '',
437 'dynamic' => [
438 'active' => true,
439 ],
440 ]
441 );
442 $repeater->add_control(
443 'placeholder',
444 [
445 'label' => esc_html__('Placeholder', 'uicore-elements'),
446 'type' => Controls_Manager::TEXT,
447 'default' => '',
448 'conditions' => [
449 'terms' => [
450 [
451 'name' => 'field_type',
452 'operator' => 'in',
453 'value' => [
454 'tel',
455 'text',
456 'email',
457 'textarea',
458 'number',
459 'url',
460 'password',
461 ],
462 ],
463 ],
464 ],
465 'dynamic' => [
466 'active' => true,
467 ],
468 ]
469 );
470 $repeater->add_control(
471 'required',
472 [
473 'label' => esc_html__('Required', 'uicore-elements'),
474 'type' => Controls_Manager::SWITCHER,
475 'return_value' => 'true',
476 'default' => '',
477 'conditions' => [
478 'terms' => [
479 [
480 'name' => 'field_type',
481 'operator' => '!in',
482 'value' => [
483 'recaptcha',
484 'recaptcha_v3',
485 'hidden',
486 'html',
487 ],
488 ],
489 ],
490 ],
491 ]
492 );
493 $repeater->add_control(
494 'field_options',
495 [
496 'label' => esc_html__('Options', 'uicore-elements'),
497 'type' => Controls_Manager::TEXTAREA,
498 'default' => '',
499 'description' => esc_html__('Enter each option in a separate line. To differentiate between label and value, separate them with a pipe char ("|"). For example: First Name|f_name', 'uicore-elements'),
500 'conditions' => [
501 'terms' => [
502 [
503 'name' => 'field_type',
504 'operator' => 'in',
505 'value' => [
506 'select',
507 'checkbox',
508 'radio',
509 ],
510 ],
511 ],
512 ],
513 ]
514 );
515 $repeater->add_control(
516 'allow_multiple',
517 [
518 'label' => esc_html__('Multiple Selection', 'uicore-elements'),
519 'type' => Controls_Manager::SWITCHER,
520 'return_value' => 'true',
521 'conditions' => [
522 'terms' => [
523 [
524 'name' => 'field_type',
525 'value' => 'select',
526 ],
527 ],
528 ],
529 ]
530 );
531 $repeater->add_control(
532 'select_size',
533 [
534 'label' => esc_html__('Rows', 'uicore-elements'),
535 'type' => Controls_Manager::NUMBER,
536 'min' => 2,
537 'step' => 1,
538 'conditions' => [
539 'terms' => [
540 [
541 'name' => 'field_type',
542 'value' => 'select',
543 ],
544 [
545 'name' => 'allow_multiple',
546 'value' => 'true',
547 ],
548 ],
549 ],
550 ]
551 );
552 $repeater->add_control(
553 'inline_list',
554 [
555 'label' => esc_html__('Inline List', 'uicore-elements'),
556 'type' => Controls_Manager::SWITCHER,
557 'return_value' => 'ui-e-subgroup-inline',
558 'default' => '',
559 'conditions' => [
560 'terms' => [
561 [
562 'name' => 'field_type',
563 'operator' => 'in',
564 'value' => [
565 'checkbox',
566 'radio',
567 ],
568 ],
569 ],
570 ],
571 ]
572 );
573 $repeater->add_control(
574 'field_html',
575 [
576 'label' => esc_html__('HTML', 'uicore-elements'),
577 'type' => Controls_Manager::TEXTAREA,
578 'dynamic' => [
579 'active' => true,
580 ],
581 'conditions' => [
582 'terms' => [
583 [
584 'name' => 'field_type',
585 'value' => 'html',
586 ],
587 ],
588 ],
589 ]
590 );
591 $repeater->add_control(
592 'acceptance_text',
593 [
594 'label' => esc_html__('Acceptance Text', 'uicore-elements'),
595 'type' => Controls_Manager::TEXTAREA,
596 'condition' => [
597 'field_type' => 'acceptance',
598 ],
599 ],
600 );
601 $repeater->add_control(
602 'checked_by_default',
603 [
604 'label' => esc_html__('Checked by Default', 'uicore-elements'),
605 'type' => Controls_Manager::SWITCHER,
606 'condition' => [
607 'field_type' => 'acceptance',
608 ],
609 ],
610 );
611 $repeater->add_responsive_control(
612 'width',
613 [
614 'label' => esc_html__('Column Width', 'uicore-elements'),
615 'type' => Controls_Manager::SELECT,
616 'options' => [
617 '' => esc_html__('Default', 'uicore-elements'),
618 '100' => '100%',
619 '80' => '80%',
620 '75' => '75%',
621 '70' => '70%',
622 '66' => '66%',
623 '60' => '60%',
624 '50' => '50%',
625 '40' => '40%',
626 '33' => '33%',
627 '30' => '30%',
628 '25' => '25%',
629 '20' => '20%',
630 ],
631 'default' => '100',
632 'conditions' => [
633 'terms' => [
634 [
635 'name' => 'field_type',
636 'operator' => '!in',
637 'value' => [
638 'hidden',
639 'recaptcha',
640 'recaptcha_v3'
641 ],
642 ],
643 ],
644 ],
645 ]
646 );
647 $repeater->add_control(
648 'rows',
649 [
650 'label' => esc_html__('Rows', 'uicore-elements'),
651 'type' => Controls_Manager::NUMBER,
652 'default' => 4,
653 'conditions' => [
654 'terms' => [
655 [
656 'name' => 'field_type',
657 'value' => 'textarea',
658 ],
659 ],
660 ],
661 ]
662 );
663 $repeater->add_control(
664 'recaptcha_hide',
665 [
666 'label' => esc_html__('Badge', 'uicore-elements'),
667 'type' => Controls_Manager::SELECT,
668 'default' => 'hidden',
669 'options' => [
670 'hidden' => esc_html__('Hidden', 'uicore-elements'),
671 'visible' => esc_html__('Visible', 'uicore-elements')
672 ],
673 'condition' => [
674 'field_type' => 'recaptcha_v3',
675 ],
676 'selectors' => [
677 '.grecaptcha-badge' => 'visibility: {{VALUE}};',
678 ],
679 ]
680 );
681 $recaptcha_keys = (!get_option('uicore_elements_recaptcha_secret_key') && !get_option('uicore_elements_recaptcha_site_key')) ? true : false; // Check if recaptcha API keys were set
682 $repeater->add_control(
683 'recaptcha_warning',
684 [
685 'type' => Controls_Manager::ALERT,
686 'alert_type' => 'warning',
687 'dismissible' => false,
688 'heading' => esc_html__("You haven't set your reCAPTCHA API keys yet.", 'uicore-elements'),
689 'content' => Helper::get_admin_settings_url(esc_html__("Click here to configure your API keys.", 'uicore-elements')),
690 'condition' => [
691 'field_type' => $recaptcha_keys ? ['recaptcha', 'recaptcha_v3'] : [],
692 ]
693 ]
694 );
695
696 $repeater->end_controls_tab();
697
698 $repeater->start_controls_tab(
699 'form_fields_advanced_tab',
700 [
701 'label' => esc_html__('Advanced', 'uicore-elements'),
702 'condition' => [
703 'field_type!' => ['html', 'address'],
704 ],
705 ]
706 );
707
708 $repeater->add_control(
709 'field_value',
710 [
711 'label' => esc_html__('Default Value', 'uicore-elements'),
712 'type' => Controls_Manager::TEXT,
713 'default' => '',
714 'dynamic' => [
715 'active' => true,
716 ],
717 'ai' => [
718 'active' => false,
719 ],
720 'conditions' => [
721 'terms' => [
722 [
723 'name' => 'field_type',
724 'operator' => 'in',
725 'value' => [
726 'text',
727 'email',
728 'textarea',
729 'url',
730 'tel',
731 'radio',
732 'select',
733 'number',
734 'date',
735 'time',
736 'hidden',
737 ],
738 ],
739 ],
740 ],
741 ]
742 );
743 $repeater->add_control(
744 'custom_id',
745 [
746 'label' => esc_html__('ID', 'uicore-elements'),
747 'type' => Controls_Manager::TEXT,
748 'description' => esc_html__('Please make sure the ID is unique and not used elsewhere in this form. This field allows `A-z 0-9` & underscore chars without spaces.', 'uicore-elements'),
749 'render_type' => 'none',
750 'required' => true,
751 'dynamic' => [
752 'active' => true,
753 ],
754 'ai' => [
755 'active' => false,
756 ],
757 ]
758 );
759 $repeater->add_control(
760 'css_classes',
761 [
762 'label' => esc_html__('Custom Class', 'uicore-elements'),
763 'type' => Controls_Manager::TEXT,
764 'default' => '',
765 'ai' => [
766 'active' => false,
767 ],
768 'placeholder' => esc_html__('e.g: my-class', 'uicore-elements'),
769 ]
770 );
771 $shortcode_template = '{{ view.container.settings.get( \'custom_id\' ) }}';
772 $repeater->add_control(
773 'shortcode',
774 [
775 'label' => esc_html__('Shortcode', 'uicore-elements'),
776 'type' => Controls_Manager::RAW_HTML,
777 'classes' => 'forms-field-shortcode',
778 'raw' => '<input class="elementor-form-field-shortcode" value=\'[field id="' . $shortcode_template . '"]\' readonly />',
779 'label_block' => false,
780 ]
781 );
782
783 $repeater->end_controls_tab();
784
785 $repeater->end_controls_tabs();
786
787 $this->start_controls_section(
788 'section_form_fields',
789 [
790 'label' => esc_html__('Form Fields', 'uicore-elements'),
791 ]
792 );
793
794
795 $this->add_control(
796 'form_name',
797 [
798 'label' => esc_html__('Form Name', 'uicore-elements'),
799 'type' => Controls_Manager::TEXT,
800 'default' => esc_html__('New Form', 'uicore-elements'),
801 'placeholder' => esc_html__('Form Name', 'uicore-elements'),
802 ]
803 );
804 $this->add_control(
805 'form_fields',
806 [
807 'type' => Controls_Manager::REPEATER,
808 'fields' => $repeater->get_controls(),
809 'default' => [
810 [
811 'custom_id' => 'name',
812 'field_type' => 'text',
813 'field_label' => esc_html__('Name', 'uicore-elements'),
814 'placeholder' => esc_html__('Name', 'uicore-elements'),
815 'width' => '100',
816 'dynamic' => [
817 'active' => true,
818 ],
819 ],
820 [
821 'custom_id' => 'email',
822 'field_type' => 'email',
823 'required' => 'true',
824 'field_label' => esc_html__('Email', 'uicore-elements'),
825 'placeholder' => esc_html__('Email', 'uicore-elements'),
826 'width' => '100',
827 ],
828 [
829 'custom_id' => 'address',
830 'field_type' => 'address',
831 'field_label' => esc_html__('address (honeypot)', 'uicore-elements'),
832 'placeholder' => esc_html__('address', 'uicore-elements'),
833 'width' => '100',
834 ],
835 [
836 'custom_id' => 'message',
837 'field_type' => 'textarea',
838 'field_label' => esc_html__('Message', 'uicore-elements'),
839 'placeholder' => esc_html__('Message', 'uicore-elements'),
840 'width' => '100',
841 ],
842 ],
843 'title_field' => '{{ field_label }}',
844 ]
845 );
846 $this->add_control(
847 'show_labels',
848 [
849 'label' => esc_html__('Label', 'uicore-elements'),
850 'type' => Controls_Manager::SWITCHER,
851 'label_on' => esc_html__('Show', 'uicore-elements'),
852 'label_off' => esc_html__('Hide', 'uicore-elements'),
853 'return_value' => 'true',
854 'default' => 'true',
855 'separator' => 'before',
856 ]
857 );
858 $this->add_control(
859 'mark_required',
860 [
861 'label' => esc_html__('Required Mark', 'uicore-elements'),
862 'type' => Controls_Manager::SWITCHER,
863 'label_on' => esc_html__('Show', 'uicore-elements'),
864 'label_off' => esc_html__('Hide', 'uicore-elements'),
865 'default' => '',
866 'render_type' => 'template',
867 'condition' => [
868 'show_labels!' => '',
869 ],
870 ]
871 );
872
873 $this->end_controls_section();
874
875 $this->start_controls_section(
876 'section_buttons',
877 [
878 'label' => esc_html__('Button', 'uicore-elements'),
879 ]
880 );
881
882 $this->add_responsive_control(
883 'button_width',
884 [
885 'label' => esc_html__('Column Width', 'uicore-elements'),
886 'type' => Controls_Manager::SELECT,
887 'options' => [
888 '' => esc_html__('Default', 'uicore-elements'),
889 '100' => '100%',
890 '80' => '80%',
891 '75' => '75%',
892 '70' => '70%',
893 '66' => '66%',
894 '60' => '60%',
895 '50' => '50%',
896 '40' => '40%',
897 '33' => '33%',
898 '30' => '30%',
899 '25' => '25%',
900 '20' => '20%',
901 ],
902 'default' => '100',
903 ]
904 );
905 $this->add_responsive_control(
906 'button_align',
907 [
908 'label' => esc_html__('Alignment', 'uicore-elements'),
909 'type' => Controls_Manager::CHOOSE,
910 'options' => [
911 'left' => [
912 'title' => esc_html__('Left', 'uicore-elements'),
913 'icon' => 'eicon-text-align-left',
914 ],
915 'center' => [
916 'title' => esc_html__('Center', 'uicore-elements'),
917 'icon' => 'eicon-text-align-center',
918 ],
919 'right' => [
920 'title' => esc_html__('Right', 'uicore-elements'),
921 'icon' => 'eicon-text-align-right',
922 ],
923 'stretch' => [
924 'title' => esc_html__('Justified', 'uicore-elements'),
925 'icon' => 'eicon-text-align-justify',
926 ],
927 ],
928 'default' => 'stretch',
929 'prefix_class' => 'ui-e-submit-align-%s-',
930 ]
931 );
932 $this->add_control(
933 'button_text',
934 [
935 'label' => esc_html__('Submit', 'uicore-elements'),
936 'type' => Controls_Manager::TEXT,
937 'default' => esc_html__('Send', 'uicore-elements'),
938 'placeholder' => esc_html__('Send', 'uicore-elements'),
939 'dynamic' => [
940 'active' => true,
941 ],
942 'ai' => [
943 'active' => false,
944 ],
945 ]
946 );
947 $this->add_control(
948 'selected_button_icon',
949 [
950 'label' => esc_html__('Icon', 'uicore-elements'),
951 'type' => Controls_Manager::ICONS,
952 'skin' => 'inline',
953 'label_block' => false,
954 ]
955 );
956 $this->add_control(
957 'button_icon_align',
958 [
959 'label' => esc_html__('Icon Position', 'uicore-elements'),
960 'type' => Controls_Manager::SELECT,
961 'default' => 'left',
962 'options' => [
963 'left' => esc_html__('Before', 'uicore-elements'),
964 'right' => esc_html__('After', 'uicore-elements'),
965 ],
966 'condition' => [
967 'selected_button_icon[value]!' => '',
968 ],
969 ]
970 );
971 $this->add_control(
972 'button_icon_indent',
973 [
974 'label' => esc_html__('Icon Spacing', 'uicore-elements'),
975 'type' => Controls_Manager::SLIDER,
976 'size_units' => ['px', 'em', 'rem', 'custom'],
977 'range' => [
978 'px' => [
979 'max' => 100,
980 ],
981 'em' => [
982 'max' => 10,
983 ],
984 'rem' => [
985 'max' => 10,
986 ],
987 ],
988 'condition' => [
989 'selected_button_icon[value]!' => '',
990 ],
991 'selectors' => [
992 '{{WRAPPER}} .elementor-button .ui-e-align-right' => 'margin-left: {{SIZE}}{{UNIT}};',
993 '{{WRAPPER}} .elementor-button .ui-e-align-left' => 'margin-right: {{SIZE}}{{UNIT}};',
994 ],
995 ]
996 );
997 $this->add_control(
998 'button_css_id',
999 [
1000 'label' => esc_html__('Button ID', 'uicore-elements'),
1001 'type' => Controls_Manager::TEXT,
1002 'default' => '',
1003 'ai' => [
1004 'active' => false,
1005 ],
1006 'title' => esc_html__('Add your custom id WITHOUT the Pound key. e.g: my-id', 'uicore-elements'),
1007 'description' => esc_html__('Please make sure the ID is unique and not used elsewhere on the page this form is displayed. This field allows `A-z 0-9` & underscore chars without spaces.', 'uicore-elements'),
1008 'separator' => 'before',
1009 'dynamic' => [
1010 'active' => true,
1011 ],
1012 ]
1013 );
1014
1015
1016 $this->end_controls_section();
1017
1018 $this->TRAIT_register_submit_actions_controls(Contact_Form_Service::get_form_submit_options());
1019
1020 // Submit sections
1021 $this->start_controls_section(
1022 'section_email',
1023 [
1024 'label' => esc_html__('Email', 'uicore-elements'),
1025 'condition' => [
1026 'submit_actions' => 'email',
1027 ],
1028 ]
1029 );
1030
1031 $this->TRAIT_register_submit_email_controls($this);
1032
1033 $this->end_controls_section();
1034
1035 $this->start_controls_section(
1036 'section_email_2',
1037 [
1038 'label' => esc_html__('Email 2', 'uicore-elements'),
1039 'condition' => [
1040 'submit_actions' => 'email_2',
1041 ],
1042 ]
1043 );
1044
1045 $this->TRAIT_register_submit_email_controls($this, '_2');
1046
1047 $this->end_controls_section();
1048
1049 $this->TRAIT_register_submit_redirect_controls();
1050 $this->TRAIT_register_submit_popup_controls($this);
1051 $this->TRAIT_register_submit_webhook_controls();
1052 $this->TRAIT_register_submit_newsletter_services_controls(Newsletter_Services::get_services_list('keys'), true);
1053 $default_messages = Contact_Form_Service::get_default_messages();
1054 $this->TRAIT_register_additional_controls($default_messages);
1055
1056 $this->TRAIT_register_all_form_style_controls();
1057
1058 // Custom Fields additional Controls injection
1059 $this->start_injection([
1060 'of' => 'redirect_message',
1061 'at' => 'before',
1062 ]);
1063 $this->add_control(
1064 'required_fields_message',
1065 [
1066 'label' => esc_html__('Required Fields', 'uicore-elements'),
1067 'type' => Controls_Manager::TEXT,
1068 'default' => $default_messages['required'],
1069 'placeholder' => $default_messages['required'],
1070 'label_block' => true,
1071 'conditions' => [
1072 'terms' => [
1073 [
1074 'name' => 'custom_messages',
1075 'operator' => '!=',
1076 'value' => '',
1077 ],
1078 ],
1079 ],
1080 'render_type' => 'none',
1081 'dynamic' => [
1082 'active' => true,
1083 ],
1084 ]
1085 );
1086 $this->end_injection();
1087
1088 // Specific Form style controls
1089 $this->start_injection([
1090 'of' => 'form_styles_component_divider',
1091 'at' => 'after',
1092 ]);
1093
1094 $this->add_control(
1095 'heading_html',
1096 [
1097 'label' => esc_html__('HTML Field', 'uicore-elements'),
1098 'type' => Controls_Manager::HEADING,
1099 ]
1100 );
1101 $this->add_control(
1102 'html_spacing',
1103 [
1104 'label' => esc_html__('Spacing', 'uicore-elements'),
1105 'type' => Controls_Manager::SLIDER,
1106 'size_units' => ['px', 'em', 'rem', 'custom'],
1107 'default' => [
1108 'size' => 0,
1109 ],
1110 'range' => [
1111 'px' => [
1112 'max' => 60,
1113 ],
1114 'em' => [
1115 'max' => 6,
1116 ],
1117 'rem' => [
1118 'max' => 6,
1119 ],
1120 ],
1121 'selectors' => [
1122 '{{WRAPPER}} .ui-e-field-type-html' => 'padding-bottom: {{SIZE}}{{UNIT}};',
1123 ],
1124 ]
1125 );
1126 $this->add_control(
1127 'html_color',
1128 [
1129 'label' => esc_html__('Color', 'uicore-elements'),
1130 'type' => Controls_Manager::COLOR,
1131 'selectors' => [
1132 '{{WRAPPER}} .ui-e-field-type-html' => 'color: {{VALUE}};',
1133 ],
1134 ]
1135 );
1136 $this->add_group_control(
1137 Group_Control_Typography::get_type(),
1138 [
1139 'name' => 'html_typography',
1140 'selector' => '{{WRAPPER}} .ui-e-field-type-html',
1141 'global' => [
1142 'default' => Global_Typography::TYPOGRAPHY_TEXT,
1143 ],
1144 ]
1145 );
1146
1147 $this->add_control(
1148 'heading_file',
1149 [
1150 'label' => esc_html__('Upload File Field', 'uicore-elements'),
1151 'type' => Controls_Manager::HEADING,
1152 'separator' => 'before',
1153 ]
1154 );
1155 $this->add_control(
1156 'file_color',
1157 [
1158 'label' => esc_html__('Color', 'uicore-elements'),
1159 'type' => Controls_Manager::COLOR,
1160 'selectors' => [
1161 '{{WRAPPER}} .ui-e-field-type-file input.ui-e-field' => 'color: {{VALUE}};',
1162 ],
1163 'default' => 'var(--e-global-color-uicore_body)',
1164
1165 ]
1166 );
1167 $this->end_injection();
1168 }
1169 function recaptcha_js()
1170 {
1171 ?>
1172 <script>
1173 window.uicore_elements_recaptcha = '<?php echo esc_html(get_option('uicore_elements_recaptcha_site_key')); ?>';
1174 </script>
1175 <?php
1176 }
1177
1178 protected function render()
1179 {
1180
1181 $instance = $this->get_settings_for_display();
1182 $is_recaptcha_required = false;
1183
1184 // Save widget settings so form API can retrieve them
1185 set_transient('ui_e_form_widget_settings_' . $this->get_id(), $instance, DAY_IN_SECONDS);
1186
1187 // Render Form Atts
1188 $this->add_render_attribute(
1189 [
1190 'wrapper' => [
1191 'class' => [
1192 'ui-e-fields-wrp',
1193 ],
1194 ],
1195 'submit-group' => [
1196 'class' => [
1197 'ui-e-field-group',
1198 'elementor-column',
1199 'ui-e-field-type-submit',
1200 ],
1201 ],
1202 'button' => [
1203 'class' => 'elementor-button',
1204 ],
1205 'icon-align' => [
1206 'class' => [
1207 empty($instance['button_icon_align']) ? '' : 'ui-e-icon ui-e-align-' . $instance['button_icon_align'],
1208 ],
1209 ],
1210 ]
1211 );
1212
1213 // Fallback for empty control values
1214 if (empty($instance['button_width'])) {
1215 $instance['button_width'] = '100';
1216 }
1217
1218 // Button atts
1219 $this->add_render_attribute('submit-group', 'class', 'elementor-col-' . $instance['button_width'] . ' e-form__buttons');
1220
1221 if (! empty($instance['button_width_tablet'])) {
1222 $this->add_render_attribute('submit-group', 'class', 'elementor-md-' . $instance['button_width_tablet']);
1223 }
1224 if (! empty($instance['button_width_mobile'])) {
1225 $this->add_render_attribute('submit-group', 'class', 'elementor-sm-' . $instance['button_width_mobile']);
1226 }
1227 if ($instance['button_hover_animation']) {
1228 $this->add_render_attribute('button', 'class', 'elementor-animation-' . $instance['button_hover_animation']);
1229 }
1230
1231 // Form atts
1232 if (! empty($instance['form_id'])) {
1233 $this->add_render_attribute('form', 'id', $instance['form_id']);
1234 }
1235 if (! empty($instance['form_name'])) {
1236 $this->add_render_attribute('form', 'name', $instance['form_name']);
1237 }
1238 if ('no' === $instance['form_validation']) {
1239 $this->add_render_attribute('form', 'novalidate');
1240 }
1241 if (! empty($instance['button_css_id'])) {
1242 $this->add_render_attribute('button', 'id', $instance['button_css_id']);
1243 }
1244
1245 $referer_title = trim(wp_title('', false));
1246 if (! $referer_title && is_home()) {
1247 $referer_title = get_option('blogname');
1248 }
1249
1250 // Get default messages
1251 $messages = Contact_Form_Service::get_default_messages();
1252
1253 // Set frontend validation message
1254 $front_msg_required = isset($instance['required_fields_message'])
1255 ? $instance['required_fields_message']
1256 : $messages['required'];
1257 ?>
1258
1259 <form class="ui-e-form" method="post" <?php $this->print_render_attribute_string('form'); ?>>
1260
1261 <input type="hidden" name="post_id" value="<?php echo esc_attr(get_the_ID()); ?>" />
1262 <input type="hidden" name="widget_type" value="contact-form">
1263
1264 <input type="hidden" name="required_fields_message" value="<?php echo esc_html($front_msg_required); ?>">
1265
1266 <div <?php $this->print_render_attribute_string('wrapper'); ?>>
1267
1268 <?php foreach ($instance['form_fields'] as $item_index => $item) :
1269 $this->form_fields_render_attributes($item_index, $instance, $item);
1270
1271 $field_type = $item['field_type'];
1272
1273 if ($field_type === 'recaptcha' || $field_type === 'recaptcha_v3') {
1274 $is_recaptcha_required = true;
1275 }
1276
1277 $print_label = ! in_array($item['field_type'], ['hidden', 'html'], true);
1278 ?>
1279
1280 <div <?php $this->print_render_attribute_string('field-group' . $item_index); ?>>
1281 <?php
1282 // Print label (excepts if recaptcha)
1283 if ($print_label && $item['field_label'] && $item['field_type'] !== 'recaptcha' && $item['field_type'] !== 'recaptcha_v3') {
1284 ?>
1285 <label <?php $this->print_render_attribute_string('label' . $item_index); ?>>
1286 <?php // PHPCS - the variable $item['field_label'] is safe.
1287 echo Helper::esc_string($item['field_label']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1288 ?>
1289 </label>
1290 <?php
1291 }
1292
1293 // Print field
1294 switch ($item['field_type']):
1295 case 'html':
1296 echo wp_kses_post(do_shortcode($item['field_html']));
1297 break;
1298
1299 case 'textarea':
1300 // PHPCS - the method build_textarea_field is safe.
1301 echo $this->build_textarea_field($item, $item_index); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1302 break;
1303
1304 case 'select':
1305 // PHPCS - the method build_select_field is safe.
1306 echo $this->build_select_field($item, $item_index); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1307 break;
1308
1309 case 'acceptance':
1310 // PHPCS - the method build_select_field is safe.
1311 $this->build_acceptance_field($item, $item_index); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1312 break;
1313
1314 case 'radio':
1315 case 'checkbox':
1316 // PHPCS - the method build_radio_checkbox_field is safe.
1317 echo $this->build_radio_checkbox_field($item, $item_index, $item['field_type']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1318 break;
1319
1320 case 'address': // is actually honeypot
1321 // PHPCS - the method build_honeypot_field is safe.
1322 echo $this->build_honeypot_field($item, $item_index); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1323 break;
1324
1325 case 'recaptcha':
1326 // get widget ID
1327 echo '<input type="hidden" name="recaptcha"/> <div id="ui-e-recaptcha-' . esc_attr($this->get_ID()) . '"></div>';
1328 break;
1329
1330 case 'recaptcha_v3':
1331 echo '<input type="hidden" name="recaptcha_v3"/>';
1332 break;
1333
1334 // All other cases are covered by the add_render_atribute()
1335 default:
1336 $this->add_render_attribute('input' . $item_index, 'class', 'ui-e-field-textual');
1337 ?>
1338 <input size="1" <?php $this->print_render_attribute_string('input' . $item_index); ?>>
1339 <?php
1340 break;
1341
1342 endswitch;
1343 ?>
1344 </div>
1345
1346 <?php endforeach; ?>
1347
1348 <div <?php $this->print_render_attribute_string('submit-group'); ?>>
1349 <button type="submit" <?php $this->print_render_attribute_string('button'); ?>>
1350 <span <?php $this->print_render_attribute_string('content-wrapper'); ?>>
1351 <?php if (! empty($instance['button_icon']) || ! empty($instance['selected_button_icon'])) : ?>
1352 <span <?php $this->print_render_attribute_string('icon-align'); ?>>
1353 <?php Icons_Manager::render_icon($instance['selected_button_icon'], ['aria-hidden' => 'true']); ?>
1354 <?php if (empty($instance['button_text'])) : ?>
1355 <span class="elementor-screen-only"><?php echo esc_html__('Submit', 'uicore-elements'); ?></span>
1356 <?php endif; ?>
1357 </span>
1358 <?php endif; ?>
1359 <?php if (! empty($instance['button_text'])) : ?>
1360 <span class="ui-e-text"><?php $this->print_unescaped_setting('button_text'); ?></span>
1361 <?php endif; ?>
1362 </span>
1363 </button>
1364 </div>
1365
1366 </div>
1367
1368 <div class="ui-e-message <?php echo $this->is_edit_mode() ? 'elementor-hidden' : ''; ?>">
1369 <?php if ($this->is_edit_mode()) :
1370 // Get custom messages if set, else use default
1371 $success = isset($instance['success_message'])
1372 ? $instance['success_message']
1373 : $messages['success'];
1374 $error = isset($instance['error_message'])
1375 ? $instance['error_message']
1376 : $messages['error'];
1377 ?>
1378 <span class="success"> <?php echo esc_html($success); ?> </span> <br>
1379 <span class="error"> <?php echo esc_html($error); ?> </span>
1380 <?php endif; ?>
1381 </div>
1382 </form>
1383 <?php
1384
1385 //add js to footer if recaptcha is enabled
1386 if ($is_recaptcha_required) {
1387 add_action('wp_footer', [$this, 'recaptcha_js'], 999);
1388 }
1389
1390 // Add frontend validation messages to js var
1391 ?>
1392 <script>
1393 window.ui_e_form_validation_messages = <?php echo json_encode([
1394 'required_fields' => esc_html($front_msg_required),
1395 ]); ?>;
1396 </script>
1397 <?php
1398 }
1399 }
1400 \Elementor\Plugin::instance()->widgets_manager->register(new ContactForm());
1401