HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/contact.tar
assets/banner.svg000064400000003366151537353760010063 0ustar00<svg enable-background="new 55 277 240 240" viewBox="55 277 240 240" xmlns="http://www.w3.org/2000/svg"><path d="m55 277h240v240h-240z" fill="#1880b6"/><path d="m139 337h72c2.2 0 4 1.8 4 4v46.2l-40 29.3-40-29.3v-46.2c0-2.2 1.8-4 4-4z" fill="#f2f0da"/><g fill="#8ed9ef"><path d="m233.2 373.3c-.4-.2-.8-.4-1.2-.7-.1-.1-5.6-3.1-13-7.2v18.8l14.6-10.7c-.1 0-.2-.1-.4-.2z"/><path d="m131 365.4c-7.4 4.1-12.9 7.1-13 7.2-.5.3-.9.5-1.3.7-.1.1-.2.1-.3.1l14.6 10.7z"/><path d="m176.2 420.6c-.4.3-.8.4-1.2.4s-.8-.1-1.2-.4l-58.8-43.1v75.5c0 2.1 1.8 4 4 4h112c2.1 0 4-1.7 4-4v-75.5z"/><path d="m155 365h40v8h-40z"/><path d="m190.7 405 4.3-3.1v-4.9h-40v4.9l4.3 3.1z"/></g><g fill="#324249"><path d="m151.6 417.6-28 28c-.8.8-.8 2 0 2.8.4.4.9.6 1.4.6s1-.2 1.4-.6l28-28c.8-.8.8-2 0-2.8s-2-.8-2.8 0z"/><path d="m223.6 448.4c.4.4.9.6 1.4.6s1-.2 1.4-.6c.8-.8.8-2 0-2.8l-27.4-27.4c-.8-.8-2-.8-2.8 0s-.8 2 0 2.8z"/><path d="m235.1 369.8c-.3-.2-.7-.4-1.1-.6-.6-.4-6.9-3.9-15-8.4v-19.9c0-4.3-3.5-7.9-7.9-7.9h-72.3c-4.3 0-7.9 3.5-7.9 7.9v19.9c-8.1 4.5-14.4 8.1-15 8.4-.4.3-.9.5-1.2.7-1.8 1-3.8 2-3.8 5v78.1c0 4.2 3.6 8 8 8h112c4.1 0 8-3.7 8-8v-78.1c.1-3-2.1-4.2-3.8-5.1zm-16.1-4.4c7.4 4.1 12.8 7.2 13 7.2.4.2.8.5 1.2.7.2.1.3.2.4.2l-14.6 10.8zm-84-24.4c0-2.2 1.8-4 4-4h72c2.2 0 4 1.8 4 4v46.2l-16 11.7v-5.9h-48v5.9l-16-11.7zm55.7 64h-31.4l-4.3-3.1v-4.9h40v4.9zm-5.4 4-10.3 7.5-10.3-7.5zm-68.6-35.6c.4-.2.9-.5 1.3-.7.1-.1 5.6-3.1 13-7.2v18.8l-14.6-10.7c.1-.1.2-.1.3-.2zm118.3 79.6c0 2.3-1.9 4-4 4h-112c-2.2 0-4-1.9-4-4v-75.5l58.8 43.1c.4.3.8.4 1.2.4s.8-.1 1.2-.4l58.8-43.1z"/><path d="m199 361h-48v16h48zm-4 12h-40v-8h40z"/></g><g opacity=".2"><path d="m153 357h20c1.1 0 2-.9 2-2s-.9-2-2-2h-20c-1.1 0-2 .9-2 2s.9 2 2 2z"/><path d="m173 385h-20c-1.1 0-2 .9-2 2s.9 2 2 2h20c1.1 0 2-.9 2-2s-.9-2-2-2z"/></g></svg>assets/icon.svg000064400000002172151537353760007540 0ustar00<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m13.0127 2.39111c-.61523-.41895-1.41064-.41943-2.02588.00049l-7.50293 5.11133c-.49268.33496-.78662.89111-.78662 1.4873v11.13135c0 .50171.20758.95508.5401 1.28168.00079.00073.0011.00177.00189.0025.00128.0011.00293.0014.00421.0025.32428.31573.76544.51215 1.25262.51215h15.00781c.48877 0 .93158-.19745 1.25616-.51501.00006-.00006.00012-.00006.00018-.00012l.00012-.00012c.33374-.32678.54236-.78082.54236-1.28357v-11.13135c0-.59619-.29395-1.15234-.78613-1.48682l-7.50391-5.1123zm6.79003 16.80103-4.45831-5.03656 4.45831-3.59698zm-15.60546-8.63355 4.45831 3.59698-4.45831 5.0365zm5.62683 4.5398 1.7052 1.37573c.03247.02625.07019.0387.10529.05865.0271.01538.05121.03253.07971.04437.09216.03839.18774.06348.28522.06348.00018 0 .00031-.00012.00049-.00012s.00031.00012.00049.00012c.09747 0 .19305-.02509.28522-.06348.0285-.01184.05261-.02899.07971-.04437.0351-.01996.07281-.03241.10529-.05865l1.7052-1.37573 4.711 5.32202h-13.77388zm2.00695-11.46704c.05127-.03516.11035-.05273.16895-.05273s.11719.01758.16846.05225l7.49994 5.10962-7.6684 6.18689-7.66852-6.18701 7.49957-5.10901z"/></svg>contact.php000064400000223322151537353760006733 0ustar00<?php
/*
Widget Name: Contact Form
Description: Add a contact form with custom fields, design options, spam protection, and email notifications.
Author: SiteOrigin
Author URI: https://siteorigin.com
Documentation: https://siteorigin.com/widgets-bundle/contact-form-widget/
*/

$field_ids = array();
class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
	public $instance_hash;

	private $dev_emails = array(
		'ibrossiter@gmail.com',
		'amisplon@gmail.com',
		'test@example.com',
		'greg@siteorigin.com',
		'wordpress@layouts.siteorigin.com',
		'support@siteorigin.com',
	);

	public function __construct() {
		parent::__construct(
			'sow-contact-form',
			__( 'SiteOrigin Contact Form', 'so-widgets-bundle' ),
			array(
				'description' => __( 'Add a contact form with custom fields, design options, spam protection, and email notifications.', 'so-widgets-bundle' ),
				'help' => 'https://siteorigin.com/widgets-bundle/contact-form-widget/',
				'instance_storage' => true,
			),
			array(),
			false,
			plugin_dir_path( __FILE__ )
		);
	}

	/**
	 * Initialize the contact form widget
	 */
	public function initialize() {
		$this->register_frontend_scripts(
			array(
				array(
					'sow-contact',
					plugin_dir_url( __FILE__ ) . 'js/contact' . SOW_BUNDLE_JS_SUFFIX . '.js',
					array( 'jquery' ),
					SOW_BUNDLE_VERSION,
				),
			)
		);
		add_filter( 'siteorigin_widgets_sanitize_field_multiple_emails', array( $this, 'sanitize_multiple_emails' ) );
		add_action( 'siteorigin_widgets_enqueue_frontend_scripts_sow-contact-form', array( $this, 'enqueue_widget_scripts' ) );

		add_filter( 'siteorigin_widgets_contact_body', array( $this, 'format_email_body' ), 10, 2 );
	}

	public function enqueue_widget_scripts() {
		$global_settings = $this->get_global_settings();
		wp_localize_script(
			'sow-contact',
			'sowContact',
			array(
				'scrollto' => ! empty( $global_settings['scrollto'] ),
				'scrollto_offset' => (int) apply_filters( 'siteorigin_widgets_contact_scrollto_offset', 0 ),
			)
		);
	}

	public function enqueue_admin_scripts() {
		wp_enqueue_script(
			'sow-contact-form-admin',
			plugin_dir_url( __FILE__ ) . 'js/contact-form-admin' . SOW_BUNDLE_JS_SUFFIX . '.js',
			array( 'jquery' ),
			SOW_BUNDLE_VERSION
		);

		wp_localize_script(
			'sow-contact-form-admin',
			'sowContactAdmin',
			array(
				'error' =>  sprintf(
					esc_html__( "The 'To' and 'From' email addresses cannot be the same. This can cause email delivery issues or trigger spam filters. %sLearn why and how to fix this%s.", 'so-widgets-bundle' ),
					'<a href="https://siteorigin.com/widgets-bundle/contact-form-widget/#heading-avoiding-issues-with-the-to-and-from-email-fields" target="_blank" rel="noopener noreferrer">',
					'</a>'
				),
			)
		);
	}

	public function get_widget_form() {
		$useable_units = array(
			'px',
			'%',
		);

		$form_options = array(
			'title' => array(
				'type'    => 'text',
				'label'   => __( 'Title', 'so-widgets-bundle' ),
				'default' => __( 'Contact Us', 'so-widgets-bundle' ),
			),

			'display_title' => array(
				'type'  => 'checkbox',
				'label' => __( 'Display Title', 'so-widgets-bundle' ),
			),

			'settings' => array(
				'type'   => 'section',
				'label'  => __( 'Settings', 'so-widgets-bundle' ),
				'hide'   => true,
				'fields' => array(
					'to'                               => array(
						'type'        => 'text',
						'label'       => __( 'To Email Address', 'so-widgets-bundle' ),
						'description' => __( 'Where contact emails will be delivered to. You can send to multiple emails by separating the emails with a comma (,)', 'so-widgets-bundle' ),
						'sanitize'    => 'multiple_emails',
					),
					'from'                               => array(
						'type'        => 'text',
						'label'       => __( 'From Email Address', 'so-widgets-bundle' ),
						'description' => __( 'It will appear as if emails are sent from this address. Ideally, this should be in the same domain as this server to avoid spam filters.', 'so-widgets-bundle' ),
						'sanitize'    => 'email',
					),
					'default_subject'                  => array(
						'type'        => 'text',
						'label'       => __( 'Default Subject', 'so-widgets-bundle' ),
						'description' => __( "Subject to use when there isn't one supplied by the user. If you make use of this option it won't be possible to set the Subject field as required because the default subject will be used as a fallback.", 'so-widgets-bundle' ),
					),
					'subject_prefix'                   => array(
						'type'        => 'text',
						'label'       => __( 'Subject Prefix', 'so-widgets-bundle' ),
						'description' => __( 'Prefix added to all incoming email subjects.', 'so-widgets-bundle' ),
					),
					'success_message'                  => array(
						'type'        => 'tinymce',
						'label'       => __( 'Success Message', 'so-widgets-bundle' ),
						'description' => __( 'Message to display after message successfully sent.', 'so-widgets-bundle' ),
						'default'     => __( "Thanks for contacting us. We'll get back to you shortly.", 'so-widgets-bundle' ),
					),
					'submit_text'                      => array(
						'type'    => 'text',
						'label'   => __( 'Submit Button Text', 'so-widgets-bundle' ),
						'default' => __( 'Contact Us', 'so-widgets-bundle' ),
					),
					'submit_id' => array(
						'type' => 'text',
						'label' => __( 'Button ID', 'so-widgets-bundle' ),
						'description' => __( 'An ID attribute allows you to target this button in JavaScript.', 'so-widgets-bundle' ),
					),
					'on_click' => array(
						'type'        => 'text',
						'label'       => __( 'Onclick', 'so-widgets-bundle' ),
						'description' => __( 'Run this JavaScript when the button is clicked. Ideal for tracking.', 'so-widgets-bundle' ),
						'onclick' => true,
					),
					'required_field_indicator'         => array(
						'type'          => 'checkbox',
						'label'         => __( 'Indicate Required Fields With Asterisk (*)', 'so-widgets-bundle' ),
						'state_emitter' => array(
							'callback' => 'conditional',
							'args'     => array(
								'required_fields[show]: val',
								'required_fields[hide]: ! val',
							),
						),
					),
					'required_field_indicator_message' => array(
						'type'          => 'text',
						'label'         => __( 'Required Field Indicator Message', 'so-widgets-bundle' ),
						'default'       => __( 'Fields marked with * are required', 'so-widgets-bundle' ),
						'state_handler' => array(
							'required_fields[show]' => array( 'show' ),
							'required_fields[hide]' => array( 'hide' ),
						),
					),
					'log_ip_address' => array(
						'type' => 'checkbox',
						'label' => __( 'Log IP Addresses', 'so-widgets-bundle' ),
						'description' => __( 'List in contact emails, the IP address of the form sender.', 'so-widgets-bundle' ),
						'default' => false,
					),
				),
			),

			'fields' => array(
				'type'       => 'repeater',
				'label'      => __( 'Fields', 'so-widgets-bundle' ),
				'item_name'  => __( 'Field', 'so-widgets-bundle' ),
				'item_label' => array(
					'selector' => "[id*='label']",
				),
				'fields'     => array(
					'type' => array(
						'type'    => 'select',
						'label'   => __( 'Field Type', 'so-widgets-bundle' ),
						'prompt'  => __( 'Select Field Type', 'so-widgets-bundle' ),
						'options' => array(
							'name'       => __( 'Name', 'so-widgets-bundle' ),
							'email'      => __( 'Email', 'so-widgets-bundle' ),
							'tel'        => __( 'Phone Number', 'so-widgets-bundle' ),
							'number'     => __( 'Number', 'so-widgets-bundle' ),
							'subject'    => __( 'Subject', 'so-widgets-bundle' ),
							'text'       => __( 'Text', 'so-widgets-bundle' ),
							'textarea'   => __( 'Text Area', 'so-widgets-bundle' ),
							'select'     => __( 'Dropdown Select', 'so-widgets-bundle' ),
							'checkboxes' => __( 'Checkboxes', 'so-widgets-bundle' ),
							'radio'      => __( 'Radio', 'so-widgets-bundle' ),
						),
						'state_emitter' => array(
							'callback' => 'select',
							'args'     => array( 'field_type_{$repeater}' ),
						),
					),

					'label' => array(
						'type'  => 'text',
						'label' => __( 'Label', 'so-widgets-bundle' ),
					),

					'description' => array(
						'type'        => 'text',
						'label'       => __( 'Description', 'so-widgets-bundle' ),
						'description' => __( 'This text will appear small beneath the input field.', 'so-widgets-bundle' ),
					),

					'required' => array(
						'type'   => 'section',
						'label'  => __( 'Required Field', 'so-widgets-bundle' ),
						'fields' => array(
							'required'        => array(
								'type'        => 'checkbox',
								'label'       => __( 'Required Field', 'so-widgets-bundle' ),
								'description' => __( 'Is this field required?', 'so-widgets-bundle' ),
							),
							'missing_message' => array(
								'type'        => 'text',
								'label'       => __( 'Missing Message', 'so-widgets-bundle' ),
								'description' => __( 'Error message to display if this field is missing.', 'so-widgets-bundle' ),
								'default'     => __( 'Required field', 'so-widgets-bundle' ),
							),
						),
					),

					'multiple_select' => array(
						'type'  => 'checkbox',
						'label' => __( 'Allow Multiple Selections', 'so-widgets-bundle' ),
						'state_handler' => array(
							'field_type_{$repeater}[select]' => array( 'show' ),
							'_else[field_type_{$repeater}]' => array( 'hide' ),
						),
					),

					// This are for select, radio, and checkboxes
					'options'  => array(
						'type'          => 'repeater',
						'label'         => __( 'Options', 'so-widgets-bundle' ),
						'item_name'     => __( 'Option', 'so-widgets-bundle' ),
						'item_label'    => array( 'selector' => "[id*='value']" ),
						'fields'        => array(
							'value' => array(
								'type'  => 'text',
								'label' => __( 'Value', 'so-widgets-bundle' ),
							),
							'default' => array(
								'type'  => 'checkbox',
								'label' => __( 'Enabled', 'so-widgets-bundle' ),
								'state_handler' => array(
									'field_type_{$repeater}[checkboxes]' => array( 'show' ),
									'_else[field_type_{$repeater}]'      => array( 'hide' ),
								),
							),
						),

						// These are only required for a few states
						'state_handler' => array(
							'field_type_{$repeater}[select,checkboxes,radio]' => array( 'show' ),
							'_else[field_type_{$repeater}]'                   => array( 'hide' ),
						),
					),
				),
			),

			'spam' => array(
				'type'   => 'section',
				'label'  => __( 'Spam Protection', 'so-widgets-bundle' ),
				'hide'   => true,
				'fields' => array(
					'honeypot' => array(
						'type'        => 'checkbox',
						'label'       => __( 'Honeypot', 'so-widgets-bundle' ),
						'default'     => true,
						'description' => __( 'Adds a hidden form field that only bots can see. The form will reject the submission if the hidden field is populated.', 'so-widgets-bundle' ),
					),
					'browser_check' => array(
						'type'        => 'checkbox',
						'label'       => __( 'Browser Check', 'so-widgets-bundle' ),
						'default'     => true,
						'description' => __( 'Runs a check on submission that confirms the submission came from a browser. Requires the user to have JavaScript enabled.', 'so-widgets-bundle' ),
					),
					'recaptcha' => array(
						'type'   => 'section',
						'label'  => __( 'reCAPTCHA', 'so-widgets-bundle' ),
						'fields' => array(
							'use_captcha' => array(
								'type'    => 'radio',
								'label'   => __( 'reCAPTCHA', 'so-widgets-bundle' ),
								'default' => false,
								'options' => array(
									''   => __( 'Disabled', 'so-widgets-bundle' ),
									'v2' => __( 'v2', 'so-widgets-bundle' ),
									'v3' => __( 'v3', 'so-widgets-bundle' ),
								),
								'description' => sprintf(
									__( 'Please make sure you register a new reCAPTCHA key %shere%s.', 'so-widgets-bundle' ),
									'<a href="https://www.google.com/recaptcha/admin/create" target="_blank" rel="noopener noreferrer">',
									'</a>'
								),
								'state_emitter' => array(
									'callback' => 'select',
									'args' => array( 'recaptcha_version' ),
								),
							),
							'site_key'    => array(
								'type'  => 'text',
								'label' => __( 'reCAPTCHA v2 Site Key', 'so-widgets-bundle' ),
								'state_handler' => array(
									'recaptcha_version[v2]' => array( 'show' ),
									'_else[recaptcha_version]' => array( 'hide' ),
								),
							),
							'secret_key'  => array(
								'type'  => 'text',
								'label' => __( 'reCAPTCHA v2 Secret Key', 'so-widgets-bundle' ),
								'state_handler' => array(
									'recaptcha_version[v2]' => array( 'show' ),
									'_else[recaptcha_version]' => array( 'hide' ),
								),
							),
							'site_key_v3'    => array(
								'type'  => 'text',
								'label' => __( 'reCAPTCHA v3 Site Key', 'so-widgets-bundle' ),
								'state_handler' => array(
									'recaptcha_version[v3]' => array( 'show' ),
									'_else[recaptcha_version]' => array( 'hide' ),
								),
							),
							'secret_key_v3'  => array(
								'type'  => 'text',
								'label' => __( 'reCAPTCHA v3 Secret Key', 'so-widgets-bundle' ),
								'state_handler' => array(
									'recaptcha_version[v3]' => array( 'show' ),
									'_else[recaptcha_version]' => array( 'hide' ),
								),
							),
							'theme'       => array(
								'type'    => 'select',
								'label'   => __( 'Theme', 'so-widgets-bundle' ),
								'default' => 'light',
								'options' => array(
									'light' => __( 'Light', 'so-widgets-bundle' ),
									'dark'  => __( 'Dark', 'so-widgets-bundle' ),
								),
								'state_handler' => array(
									'recaptcha_version[v2]' => array( 'slideDown' ),
									'_else[recaptcha_version]' => array( 'slideUp' ),
								),
							),
							'type'        => array(
								'type'    => 'select',
								'label'   => __( 'Challenge Type', 'so-widgets-bundle' ),
								'default' => 'image',
								'options' => array(
									'image' => __( 'Image', 'so-widgets-bundle' ),
									'audio' => __( 'Audio', 'so-widgets-bundle' ),
								),
								'state_handler' => array(
									'recaptcha_version[v2]' => array( 'slideDown' ),
									'_else[recaptcha_version]' => array( 'slideUp' ),
								),
							),
							'size'        => array(
								'type'    => 'select',
								'label'   => __( 'Size', 'so-widgets-bundle' ),
								'default' => 'normal',
								'options' => array(
									'normal'  => __( 'Normal', 'so-widgets-bundle' ),
									'compact' => __( 'Compact', 'so-widgets-bundle' ),
								),
								'state_handler' => array(
									'recaptcha_version[v2]' => array( 'slideDown' ),
									'_else[recaptcha_version]' => array( 'slideUp' ),
								),
							),
						),
					),

					'akismet' => array(
						'type'   => 'section',
						'label'  => __( 'Akismet', 'so-widgets-bundle' ),
						'fields' => array(
							'use_akismet' => array(
								'type'    => 'checkbox',
								'label'   => __( 'Akismet Filtering', 'so-widgets-bundle' ),
								'description' => sprintf(
									__( 'Use the %sAkismet%s plugin to filter spam submissions.', 'so-widgets-bundle' ),
									'<a href="https://wordpress.org/plugins/akismet/" target="_blank" rel="noopener noreferrer">',
									'</a>'
								),
								'default' => true,
							),
							'spam_action' => array(
								'type'        => 'select',
								'label'       => __( 'Spam Action', 'so-widgets-bundle' ),
								'options'     => array(
									'error' => __( 'Show error message', 'so-widgets-bundle' ),
									'tag'   => __( 'Tag as spam in subject', 'so-widgets-bundle' ),
								),
								'description' => __( 'How to handle submissions that are identified as spam.', 'so-widgets-bundle' ),
								'default'     => 'error',
							),
						),
					),
				),
			),

			'design' => array(
				'type'   => 'section',
				'label'  => __( 'Design', 'so-widgets-bundle' ),
				'hide'   => true,
				'fields' => array(
					'container' => array(
						'type'   => 'section',
						'label'  => __( 'Container', 'so-widgets-bundle' ),
						'fields' => array(
							'background'   => array(
								'type'    => 'color',
								'label'   => __( 'Background Color', 'so-widgets-bundle' ),
								'alpha'   => true,
								'default' => '#f2f2f2',
							),
							'padding'      => array(
								'type'    => 'measurement',
								'label'   => __( 'Padding', 'so-widgets-bundle' ),
								'default' => '10px',
							),
							'border_color' => array(
								'type'    => 'color',
								'label'   => __( 'Border Color', 'so-widgets-bundle' ),
								'default' => '#c0c0c0',
							),
							'border_width' => array(
								'type'    => 'measurement',
								'label'   => __( 'Border Width', 'so-widgets-bundle' ),
								'default' => '1px',
							),
							'border_style' => array(
								'type'    => 'select',
								'label'   => __( 'Border Style', 'so-widgets-bundle' ),
								'default' => 'solid',
								'options' => array(
									'none'   => __( 'None', 'so-widgets-bundle' ),
									'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
									'dotted' => __( 'Dotted', 'so-widgets-bundle' ),
									'dashed' => __( 'Dashed', 'so-widgets-bundle' ),
									'solid'  => __( 'Solid', 'so-widgets-bundle' ),
									'double' => __( 'Double', 'so-widgets-bundle' ),
									'groove' => __( 'Groove', 'so-widgets-bundle' ),
									'ridge'  => __( 'Ridge', 'so-widgets-bundle' ),
									'inset'  => __( 'Inset', 'so-widgets-bundle' ),
									'outset' => __( 'Outset', 'so-widgets-bundle' ),
								),
							),
						),
					),

					'labels' => array(
						'type'   => 'section',
						'label'  => __( 'Field Labels', 'so-widgets-bundle' ),
						'fields' => array(
							'font'     => array(
								'type'    => 'font',
								'label'   => __( 'Font', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'size'     => array(
								'type'    => 'measurement',
								'label'   => __( 'Font Size', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'color'    => array(
								'type'    => 'color',
								'label'   => __( 'Color', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'position' => array(
								'type'    => 'select',
								'label'   => __( 'Position', 'so-widgets-bundle' ),
								'default' => 'above',
								'options' => array(
									'above'  => __( 'Above', 'so-widgets-bundle' ),
									'below'  => __( 'Below', 'so-widgets-bundle' ),
									'left'   => __( 'Left', 'so-widgets-bundle' ),
									'right'  => __( 'Right', 'so-widgets-bundle' ),
									'inside' => __( 'Inside', 'so-widgets-bundle' ),
								),
							),
							'width'    => array(
								'type'    => 'measurement',
								'label'   => __( 'Width', 'so-widgets-bundle' ),
								'default' => '',
							),
							'align'    => array(
								'type'    => 'select',
								'label'   => __( 'Align', 'so-widgets-bundle' ),
								'default' => 'left',
								'options' => array(
									'left'    => __( 'Left', 'so-widgets-bundle' ),
									'right'   => __( 'Right', 'so-widgets-bundle' ),
									'center'  => __( 'Center', 'so-widgets-bundle' ),
									'justify' => __( 'Justify', 'so-widgets-bundle' ),
								),
							),
						),
					),

					'fields' => array(
						'type'   => 'section',
						'label'  => __( 'Fields', 'so-widgets-bundle' ),
						'fields' => array(
							'font'          => array(
								'type'    => 'font',
								'label'   => __( 'Font', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'font_size'     => array(
								'type'  => 'measurement',
								'label' => __( 'Font Size', 'so-widgets-bundle' ),
							),
							'color'         => array(
								'type'  => 'color',
								'label' => __( 'Text Color', 'so-widgets-bundle' ),
							),
							'multi_margin' => array(
								'type'  => 'multi-measurement',
								'label' => __( 'Margin', 'so-widgets-bundle' ),
								'default' => '0px 0px 15px 0px',
								'measurements' => array(
									'top' => array(
										'label' => __( 'Top', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'right' => array(
										'label' => __( 'Right', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'bottom' => array(
										'label' => __( 'Bottom', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'left' => array(
										'label' => __( 'Left', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
								),
							),
							'padding'       => array(
								'type'  => 'measurement',
								'label' => __( 'Padding', 'so-widgets-bundle' ),
							),
							'max_width'    => array(
								'type'    => 'measurement',
								'label'   => __( 'Max Width', 'so-widgets-bundle' ),
								'default' => '',
							),
							'height'        => array(
								'type'  => 'measurement',
								'label' => __( 'Height', 'so-widgets-bundle' ),
							),
							'height_textarea' => array(
								'type'  => 'measurement',
								'label' => __( 'Text Area Height', 'so-widgets-bundle' ),
							),
							'background'    => array(
								'type'  => 'color',
								'label' => __( 'Background', 'so-widgets-bundle' ),
							),
							'border_color'  => array(
								'type'    => 'color',
								'label'   => __( 'Border Color', 'so-widgets-bundle' ),
								'default' => '#c0c0c0',
							),
							'border_width'  => array(
								'type'    => 'measurement',
								'label'   => __( 'Border Width', 'so-widgets-bundle' ),
								'default' => '1px',
							),
							'border_style'  => array(
								'type'    => 'select',
								'label'   => __( ' Border Style', 'so-widgets-bundle' ),
								'default' => 'solid',
								'options' => array(
									'none'   => __( 'None', 'so-widgets-bundle' ),
									'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
									'dotted' => __( 'Dotted', 'so-widgets-bundle' ),
									'dashed' => __( 'Dashed', 'so-widgets-bundle' ),
									'solid'  => __( 'Solid', 'so-widgets-bundle' ),
									'double' => __( 'Double', 'so-widgets-bundle' ),
									'groove' => __( 'Groove', 'so-widgets-bundle' ),
									'ridge'  => __( 'Ridge', 'so-widgets-bundle' ),
									'inset'  => __( 'Inset', 'so-widgets-bundle' ),
									'outset' => __( 'Outset', 'so-widgets-bundle' ),
								),
							),
							'border_radius' => array(
								'type'    => 'slider',
								'label'   => __( 'Border Rounding', 'so-widgets-bundle' ),
								'default' => 0,
								'max'     => 50,
								'min'     => 0,
							),
						),
					),

					'descriptions' => array(
						'type'   => 'section',
						'label'  => __( 'Field Descriptions', 'so-widgets-bundle' ),
						'fields' => array(
							'size'  => array(
								'type'    => 'measurement',
								'label'   => __( 'Size', 'so-widgets-bundle' ),
								'default' => '0.9em',
							),
							'color' => array(
								'type'    => 'color',
								'label'   => __( 'Color', 'so-widgets-bundle' ),
								'default' => '#999999',
							),
							'style' => array(
								'type'    => 'select',
								'label'   => __( 'Style', 'so-widgets-bundle' ),
								'default' => 'italic',
								'options' => array(
									'italic' => __( 'Italic', 'so-widgets-bundle' ),
									'normal' => __( 'Normal', 'so-widgets-bundle' ),
								),
							),
							'top_margin' => array(
								'type'    => 'measurement',
								'label'   => __( 'Top Margin', 'so-widgets-bundle' ),
								'default' => '0.2em',
							)
						),
					),

					'errors' => array(
						'type'   => 'section',
						'label'  => __( 'Error Messages', 'so-widgets-bundle' ),
						'fields' => array(
							'background'   => array(
								'type'    => 'color',
								'label'   => __( 'Error Background Color', 'so-widgets-bundle' ),
								'default' => '#fce4e5',
							),
							'border_color' => array(
								'type'    => 'color',
								'label'   => __( 'Error Border Color', 'so-widgets-bundle' ),
								'default' => '#ec666a',
							),
							'text_color'   => array(
								'type'    => 'color',
								'label'   => __( 'Error Text Color', 'so-widgets-bundle' ),
								'default' => '#ec666a',
							),
							'padding'      => array(
								'type'    => 'measurement',
								'label'   => __( 'Error Padding', 'so-widgets-bundle' ),
								'default' => '5px',
							),
							'margin'       => array(
								'type'    => 'measurement',
								'label'   => __( 'Error Margin', 'so-widgets-bundle' ),
								'default' => '10px',
							),
						),
					),

					'submit' => array(
						'type'   => 'section',
						'label'  => __( 'Submit Button', 'so-widgets-bundle' ),
						'fields' => array(
							'styled' => array(
								'type'        => 'checkbox',
								'label'       => __( 'Style Submit Button', 'so-widgets-bundle' ),
								'description' => __( 'Style the button or leave it with default theme styling.', 'so-widgets-bundle' ),
								'default'     => true,
							),

							'background_color'    => array(
								'type'    => 'color',
								'label'   => __( 'Background Color', 'so-widgets-bundle' ),
								'default' => '#eeeeee',
							),
							'background_color_hover'    => array(
								'type'    => 'color',
								'label'   => __( 'Background Hover Color', 'so-widgets-bundle' ),
							),
							'background_gradient' => array(
								'type'    => 'slider',
								'label'   => __( 'Gradient Intensity', 'so-widgets-bundle' ),
								'default' => 10,
							),
							'border_color'        => array(
								'type'    => 'color',
								'label'   => __( 'Border Color', 'so-widgets-bundle' ),
								'default' => '#989a9c',
							),
							'border_color_hover'    => array(
								'type'    => 'color',
								'label'   => __( 'Border Hover Color', 'so-widgets-bundle' ),
							),
							'border_style'        => array(
								'type'    => 'select',
								'label'   => __( 'Border Style', 'so-widgets-bundle' ),
								'default' => 'solid',
								'options' => array(
									'none'   => __( 'None', 'so-widgets-bundle' ),
									'solid'  => __( 'Solid', 'so-widgets-bundle' ),
									'dotted' => __( 'Dotted', 'so-widgets-bundle' ),
									'dashed' => __( 'Dashed', 'so-widgets-bundle' ),
								),
							),
							'border_width'        => array(
								'type'    => 'measurement',
								'label'   => __( 'Border Width', 'so-widgets-bundle' ),
								'default' => '1px',
							),
							'border_radius'       => array(
								'type'    => 'slider',
								'label'   => __( 'Border Rounding', 'so-widgets-bundle' ),
								'default' => 3,
								'max'     => 50,
								'min'     => 0,
							),
							'text_color'          => array(
								'type'    => 'color',
								'label'   => __( 'Text Color', 'so-widgets-bundle' ),
								'default' => '#5a5a5a',
							),
							'text_color_hover'    => array(
								'type'    => 'color',
								'label'   => __( 'Text Hover Color', 'so-widgets-bundle' ),
							),
							'font_size'           => array(
								'type'    => 'measurement',
								'label'   => __( 'Font Size', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'weight'              => array(
								'type'    => 'select',
								'label'   => __( 'Font Weight', 'so-widgets-bundle' ),
								'default' => '500',
								'options' => array(
									'normal' => __( 'Normal', 'so-widgets-bundle' ),
									'500'    => __( 'Semi-bold', 'so-widgets-bundle' ),
									'bold'   => __( 'Bold', 'so-widgets-bundle' ),
								),
							),
							'padding'             => array(
								'type'    => 'measurement',
								'label'   => __( 'Padding', 'so-widgets-bundle' ),
								'default' => '10px',
							),
							'width' => array(
								'type'    => 'measurement',
								'label'   => __( 'Width', 'so-widgets-bundle' ),
							),
							'align'    => array(
								'type'    => 'select',
								'label'   => __( 'Align', 'so-widgets-bundle' ),
								'default' => 'left',
								'options' => array(
									'left'    => __( 'Left', 'so-widgets-bundle' ),
									'right'   => __( 'Right', 'so-widgets-bundle' ),
									'center'  => __( 'Center', 'so-widgets-bundle' ),
								),
							),
							'inset_highlight'     => array(
								'type'        => 'slider',
								'label'       => __( 'Inset Highlight', 'so-widgets-bundle' ),
								'description' => __( 'The white highlight at the bottom of the button', 'so-widgets-bundle' ),
								'default'     => 50,
								'max'         => 100,
								'min'         => 0,
							),
						),
					),

					'focus' => array(
						'type'   => 'section',
						'label'  => __( 'Input Focus', 'so-widgets-bundle' ),
						'fields' => array(
							'style' => array(
								'type'    => 'select',
								'label'   => __( 'Style', 'so-widgets-bundle' ),
								'default' => 'solid',
								'options' => array(
									'dotted' => __( 'Dotted', 'so-widgets-bundle' ),
									'dashed' => __( 'Dashed', 'so-widgets-bundle' ),
									'solid'  => __( 'Solid', 'so-widgets-bundle' ),
									'double' => __( 'Double', 'so-widgets-bundle' ),
									'groove' => __( 'Groove', 'so-widgets-bundle' ),
									'ridge'  => __( 'Ridge', 'so-widgets-bundle' ),
									'inset'  => __( 'Inset', 'so-widgets-bundle' ),
									'outset' => __( 'Outset', 'so-widgets-bundle' ),
									'none'   => __( 'None', 'so-widgets-bundle' ),
									'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
								),
							),
							'color' => array(
								'type'    => 'color',
								'label'   => __( 'Color', 'so-widgets-bundle' ),
								'default' => 'default',
							),
							'width' => array(
								'type'    => 'measurement',
								'label'   => __( 'Width', 'so-widgets-bundle' ),
								'default' => '1px',
							),
						),
					),

					'success' => array(
						'type' => 'section',
						'label'=> __( 'Success Message', 'so-widgets-bundle' ),
						'fields' => array(
							'font'	 => array(
								'type' => 'font',
								'label' => __( 'Font', 'so-widgets-bundle' ),
							),
							'font_size' => array(
								'type' => 'measurement',
								'label' => __( 'Font Size', 'so-widgets-bundle' ),
							),
							'color' => array(
								'type' => 'color',
								'label' => __( 'Text Color', 'so-widgets-bundle' ),
							),
							'background_color' => array(
								'type' => 'color',
								'label' => __( 'Background Color', 'so-widgets-bundle' ),
							),
							'padding' => array(
								'type' => 'multi-measurement',
								'label' => __( 'Padding', 'so-widgets-bundle' ),
								'measurements' => array(
									'top' => array(
										'label' => __( 'Top', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'right' => array(
										'label' => __( 'Right', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'bottom' => array(
										'label' => __( 'Bottom', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
									'left' => array(
										'label' => __( 'Left', 'so-widgets-bundle' ),
										'units' => $useable_units,
									),
								),
							),
							'border_color' => array(
								'type' => 'color',
								'label' => __( 'Border Color', 'so-widgets-bundle' ),
							),
							'border_width' => array(
								'type' => 'measurement',
								'label' => __( 'Border Width', 'so-widgets-bundle' ),
								'default' => '1px',
							),
							'border_style' => array(
								'type'  => 'select',
								'label' => __( 'Border Style', 'so-widgets-bundle' ),
								'default' => 'solid',
								'options' => array(
									'none'   => __( 'None', 'so-widgets-bundle' ),
									'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
									'dotted' => __( 'Dotted', 'so-widgets-bundle' ),
									'dashed' => __( 'Dashed', 'so-widgets-bundle' ),
									'solid'  => __( 'Solid', 'so-widgets-bundle' ),
									'double' => __( 'Double', 'so-widgets-bundle' ),
									'groove' => __( 'Groove', 'so-widgets-bundle' ),
									'ridge'  => __( 'Ridge', 'so-widgets-bundle' ),
									'inset'  => __( 'Inset', 'so-widgets-bundle' ),
									'outset' => __( 'Outset', 'so-widgets-bundle' ),
								),
							),
						),
					),
				),
			),
		);

		if ( function_exists( 'imagecreatetruecolor' ) ) {
			siteorigin_widgets_array_insert(
				$form_options['spam']['fields'],
				'akismet',
				array(
					'simple' => array(
						'type'   => 'section',
						'label'  => __( 'Really Simple CAPTCHA', 'so-widgets-bundle' ),
						'fields' => array(
							'enabled' => array(
								'type'    => 'checkbox',
								'label'   => __( 'Add Really Simple CAPTCHA', 'so-widgets-bundle' ),
								'description' => sprintf(
									__( 'The %sReally Simple CAPTCHA%s plugin is DSGVO compliant.', 'so-widgets-bundle' ),
									'<a href="https://wordpress.org/plugins/really-simple-captcha/" target="_blank">',
									'</a>'
								),
								'default' => false,
								'state_emitter' => array(
									'callback' => 'conditional',
									'args'     => array(
										'really_simple[show]: val',
										'really_simple[hide]: ! val'
									),
								)
							),
							'background'   => array(
								'type'    => 'color',
								'label'   => __( 'Background Color', 'so-widgets-bundle' ),
								'default' => '#ffffff',
								'state_handler' => array(
									'really_simple[show]' => array( 'slideDown' ),
									'really_simple[hide]' => array( 'slideUp' ),
								),
							),
							'color'   => array(
								'type'    => 'color',
								'label'   => __( 'Text Color', 'so-widgets-bundle' ),
								'default' => '#000000',
								'state_handler' => array(
									'really_simple[show]' => array( 'slideDown' ),
									'really_simple[hide]' => array( 'slideUp' ),
								),
							),
						)
					),
				)
			);
		}

		return $form_options;
	}

	public function sanitize_multiple_emails( $value ) {
		$values = explode( ',', $value );

		foreach ( $values as $i => $email ) {
			$values[ $i ] = sanitize_email( $email );
		}

		return implode( ',', $values );
	}

	public function modify_instance( $instance ) {
		// Use this to set up an initial version of the
		if ( empty( $instance['settings']['to'] ) || $this->is_dev_email( $instance['settings']['to'] ) ) {
			$current_user = wp_get_current_user();
			$instance['settings']['to'] = $current_user->user_email;
		}

		if ( empty( $instance['settings']['from'] ) || $this->is_dev_email( $instance['settings']['from'] ) ) {
			$instance['settings']['from'] = $this->default_from_address();
		}

		if ( empty( $instance['fields'] ) ) {
			$instance['fields'] = array(
				array(
					'type'     => 'name',
					'label'    => __( 'Your Name', 'so-widgets-bundle' ),
					'required' => array(
						'required'        => true,
						'missing_message' => __( 'Please enter your name', 'so-widgets-bundle' ),
					),
				),
				array(
					'type'     => 'email',
					'label'    => __( 'Your Email', 'so-widgets-bundle' ),
					'required' => array(
						'required'        => true,
						'missing_message' => __( 'Please enter a valid email address', 'so-widgets-bundle' ),
					),
				),
				array(
					'type'     => 'subject',
					'label'    => __( 'Subject', 'so-widgets-bundle' ),
					'required' => array(
						'required'        => true,
						'missing_message' => __( 'Please enter a subject', 'so-widgets-bundle' ),
					),
				),
				array(
					'type'     => 'textarea',
					'label'    => __( 'Message', 'so-widgets-bundle' ),
					'required' => array(
						'required'        => true,
						'missing_message' => __( 'Please write something', 'so-widgets-bundle' ),
					),
				),
			);
		}

		// Migrate onclick setting to prevent Wordfence flag.
		if (
			! empty( $instance['settings'] ) &&
			! empty( $instance['settings']['onclick'] )
		) {
			$instance['settings']['on_click'] = $instance['settings']['onclick'];
		}

		if ( ! empty( $instance['spam'] ) ) {
			// If using an older version of reCAPTCHA settings, migrate.
			if (
				! empty( $instance['spam']['recaptcha'] ) &&
				$instance['spam']['recaptcha']['use_captcha'] === true
			) {
				$instance['spam']['recaptcha']['use_captcha'] = 'v2';
			}

			if ( ! isset( $instance['spam']['honeypot'] ) ) {
				$instance['spam']['honeypot'] = false;
				$instance['spam']['browser_check'] = false;
			}
		}

		if (
			! empty( $instance['design'] ) &&
			! empty( $instance['design']['fields'] ) &&
			isset( $instance['design']['fields']['margin'] )
		) {
			$everything_else = ! empty( $instance['design']['fields']['margin'] ) ? (int) $instance['design']['fields']['margin'] : '0';
			$botton_margin = ( $everything_else + '15' ) . 'px';
			$everything_else .= 'px';
			$instance['design']['fields']['multi_margin'] = "$everything_else $everything_else $botton_margin $everything_else";
			unset( $instance['design']['fields']['margin'] );
		}

		return $instance;
	}

	public static function is_recaptcha_enabled( $settings, $use_v3 = false ) {
		return ! empty( $settings['use_captcha'] ) &&
			(
				! $use_v3 ||
				$settings['use_captcha'] == 'v3'
			) &&
			(
				// Check for v2
				(
					! $use_v3 &&
					! empty( $settings['site_key'] ) &&
					! empty( $settings['secret_key'] )
				) ||
				// Check for v3
				(
					! empty( $settings['site_key_v3'] ) &&
					! empty( $settings['secret_key_v3'] )
				)
			);
	}

	public function get_template_variables( $instance, $args ) {
		unset( $instance['title'] );
		unset( $instance['display_title'] );
		unset( $instance['design'] );
		unset( $instance['panels_info'] );

		static $form_id = 1;
		$instance['form_id'] = $form_id++;

		$template_vars = array(
			'onclick' => ! empty( $instance['settings']['on_click'] ) ? $instance['settings']['on_click'] : '',
		);

		$submit_attributes = array();

		$template_vars['result'] = $this->contact_form_action( $instance );
		unset( $instance['_sow_form_id'] );

		if ( ! empty( $instance['settings']['submit_id'] ) ) {
			$submit_attributes['id'] = $instance['settings']['submit_id'];
		}

		$template_vars['recaptcha'] = self::is_recaptcha_enabled( $instance['spam']['recaptcha'] );

		if ( $template_vars['recaptcha'] ) {
			// reCAPTCHA v3
			if ( self::is_recaptcha_enabled( $instance['spam']['recaptcha'], true ) ) {
				$submit_attributes['data-sitekey'] = $instance['spam']['recaptcha']['site_key_v3'];
				$submit_attributes['data-callback'] = 'soContactFormSubmit';
				$submit_attributes['data-action'] = 'submit';
			} else { // reCAPTCHA v2
				$template_vars['recaptcha_v2'] = array(
					'sitekey' => $instance['spam']['recaptcha']['site_key'],
					'theme'   => $instance['spam']['recaptcha']['theme'],
					'type'    => $instance['spam']['recaptcha']['type'],
					'size'    => $instance['spam']['recaptcha']['size'],
				);
			}
		}

		if ( ! empty( $instance['spam']['browser_check'] ) ) {
			$submit_attributes['data-js-key'] = md5( $instance['form_id'] );
		}

		$template_vars['submit_attributes'] = $submit_attributes;

		if ( ! empty( $instance['spam']['simple'] ) && ! empty( $instance['spam']['simple']['enabled'] ) ) {
			if ( ! class_exists( 'ReallySimpleCaptcha' ) || ! function_exists( 'imagecreatetruecolor' ) ) {
				$template_vars['really_simple_spam'] = 'missing';
			} else {
				$template_vars['really_simple_spam'] = new ReallySimpleCaptcha();

				// Apply the RSC colors.
				if ( ! class_exists( 'SiteOrigin_Widgets_Color_Object' ) ) {
					require plugin_dir_path( SOW_BUNDLE_BASE_FILE ) . 'base/inc/color.php';
				}

				if ( ! empty( $instance['spam']['simple']['background'] ) ) {
					$color = new SiteOrigin_Widgets_Color_Object( $instance['spam']['simple']['background'], 'hex' );
					$template_vars['really_simple_spam']->bg = $color->__get( 'rgb' );
				}

				if ( ! empty( $instance['spam']['simple']['color'] ) ) {
					$color = new SiteOrigin_Widgets_Color_Object( $instance['spam']['simple']['color'], 'hex' );
					$template_vars['really_simple_spam']->fg = $color->__get( 'rgb' );
				}

				// Allow other plugins to adjust Really Simple Captcha settings.
				$template_vars['really_simple_spam'] = apply_filters( 'siteorigin_widgets_contact_really_simple_captcha', $template_vars['really_simple_spam'] );
				$template_vars['really_simple_spam_prefix'] = wp_rand();
				$template_vars['really_simple_spam_image'] = $template_vars['really_simple_spam']->generate_image(
					$template_vars['really_simple_spam_prefix'],
					$template_vars['really_simple_spam']->generate_random_word()
				);

				if (
					! empty( $template_vars['result'] ) &&
					! empty( $template_vars['result']['errors'] ) &&
					! empty( $template_vars['result']['errors']['_general'] ) &&
					! empty( $template_vars['result']['errors']['_general']['simple'] )
				) {
					$template_vars['really_simple_spam_error'] = $template_vars['result']['errors']['_general']['simple'];
					unset( $template_vars['result']['errors'] );
				}
			}
		}

		$template_vars['honeypot'] = ! empty( $instance['spam']['honeypot'] );

		return $template_vars;
	}

	public function get_settings_form() {
		return array(
			'responsive_breakpoint' => array(
				'type'        => 'measurement',
				'label'       => __( 'Responsive Breakpoint', 'so-widgets-bundle' ),
				'default'     => '780px',
				'description' => __( 'This setting controls when the field max width will be disabled. The default value is 780px', 'so-widgets-bundle' ),
			),
			'scrollto' => array(
				'type'        => 'checkbox',
				'label'       => __( 'Scroll Top', 'so-widgets-bundle' ),
				'default'     => true,
				'description' => __( 'After submission, scroll the user to the top of the contact form.', 'so-widgets-bundle' ),
			),
		);
	}

	public function get_less_variables( $instance ) {
		if ( empty( $instance['design'] ) ) {
			return;
		}

		if ( empty( $instance['design']['labels']['font'] ) ) {
			$instance['design']['labels'] = array( 'font' => '' );
		}
		$label_font = siteorigin_widget_get_font( $instance['design']['labels']['font'] );
		$field_font = siteorigin_widget_get_font( $instance['design']['fields']['font'] );

		$label_position = $instance['design']['labels']['position'];

		if ( $label_position != 'left' && $label_position != 'right' ) {
			$label_position = 'default';
		}

		$vars = array(
			// All the container variables.
			'container_background'       => $instance['design']['container']['background'],
			'container_padding'          => $instance['design']['container']['padding'],
			'container_border_color'     => $instance['design']['container']['border_color'],
			'container_border_width'     => $instance['design']['container']['border_width'],
			'container_border_style'     => $instance['design']['container']['border_style'],

			// Field labels
			'label_font_family'          => $label_font['family'],
			'label_font_size'            => $instance['design']['labels']['size'],
			'label_font_color'           => $instance['design']['labels']['color'],
			'label_position'             => $label_position,
			'label_width'                => $instance['design']['labels']['width'],
			'label_align'                => $instance['design']['labels']['align'],

			// Fields
			'field_font_family'          => $field_font['family'],
			'field_font_size'            => $instance['design']['fields']['font_size'],
			'field_font_color'           => $instance['design']['fields']['color'],
			'field_margin'               => $instance['design']['fields']['multi_margin'],
			'field_padding'              => $instance['design']['fields']['padding'],
			'field_max_width'            => ! empty( $instance['design']['fields']['max_width'] ) ? $instance['design']['fields']['max_width'] : '',
			'field_height'               => $instance['design']['fields']['height'],
			'field_height_textarea'      => ! empty( $instance['design']['fields']['height_textarea'] ) ? $instance['design']['fields']['height_textarea'] : '',
			'field_background'           => $instance['design']['fields']['background'],
			'field_border_radius'        => $instance['design']['fields']['border_radius'] . 'px',

			// Field descriptions
			'description_font_size'      => $instance['design']['descriptions']['size'],
			'description_font_color'     => $instance['design']['descriptions']['color'],
			'description_font_style'     => $instance['design']['descriptions']['style'],
			'description_top_margin'     => ! empty( $instance['design']['descriptions']['top_margin'] ) ? $instance['design']['descriptions']['top_margin'] : '',

			// The error message styles
			'error_background'           => $instance['design']['errors']['background'],
			'error_border'               => $instance['design']['errors']['border_color'],
			'error_text'                 => $instance['design']['errors']['text_color'],
			'error_padding'              => $instance['design']['errors']['padding'],
			'error_margin'               => $instance['design']['errors']['margin'],

			// The submit button
			'submit_background_color'       => $instance['design']['submit']['background_color'],
			'submit_background_color_hover' => ! empty( $instance['design']['submit']['background_color_hover'] ) ? $instance['design']['submit']['background_color_hover'] : '',
			'submit_background_gradient'    => $instance['design']['submit']['background_gradient'] . '%',
			'submit_border_color'           => $instance['design']['submit']['border_color'],
			'submit_border_color_hover'     => ! empty( $instance['design']['submit']['border_color_hover'] ) ? $instance['design']['submit']['border_color_hover'] : '',
			'submit_border_style'           => $instance['design']['submit']['border_style'],
			'submit_border_width'           => $instance['design']['submit']['border_width'],
			'submit_border_radius'          => $instance['design']['submit']['border_radius'] . 'px',
			'submit_text_color'             => $instance['design']['submit']['text_color'],
			'submit_text_color_hover'       => ! empty( $instance['design']['submit']['text_color_hover'] ) ? $instance['design']['submit']['text_color_hover'] : '',
			'submit_font_size'              => $instance['design']['submit']['font_size'],
			'submit_weight'                 => $instance['design']['submit']['weight'],
			'submit_padding'                => $instance['design']['submit']['padding'],
			'submit_width'                  => ! empty( $instance['design']['submit']['width'] ) ? $instance['design']['submit']['width'] : '',
			'submit_align'                  => ! empty( $instance['design']['submit']['align'] ) ? $instance['design']['submit']['align'] : '',
			'submit_inset_highlight'        => $instance['design']['submit']['inset_highlight'] . '%',

			// Input focus styles
			'outline_style'              => $instance['design']['focus']['style'],
			'outline_color'              => $instance['design']['focus']['color'],
			'outline_width'              => $instance['design']['focus']['width'],

			// Success message styles.
			'success_font_size'          => ! empty( $instance['design']['success']['font_size'] ) ? $instance['design']['success']['font_size'] : '',
			'success_color'              => ! empty( $instance['design']['success']['color'] ) ? $instance['design']['success']['color'] : '',
			'success_background_color'   => ! empty( $instance['design']['success']['background_color'] ) ? $instance['design']['success']['background_color'] : '',
			'success_padding'            => ! empty( $instance['design']['success']['padding'] ) ? $instance['design']['success']['padding'] : '',
			'success_border_width'       => ! empty( $instance['design']['success']['border_width'] ) ? $instance['design']['success']['border_width'] : '',
			'success_border_color'       => ! empty( $instance['design']['success']['border_color'] ) ? $instance['design']['success']['border_color'] : '',
			'success_border_style'       => ! empty( $instance['design']['success']['border_style'] ) ? $instance['design']['success']['border_style'] : '',
		);

		// Ensure all border values exist before setting border
		// to prevent potential CSS error.
		if (
			! empty( $instance['design']['fields']['border_color'] ) &&
			! empty( $instance['design']['fields']['border_width'] ) &&
			! empty( $instance['design']['fields']['border_style'] )
		) {
			$vars['field_border'] = $instance['design']['fields']['border_width'] . ' ' . $instance['design']['fields']['border_color'] . ' ' . $instance['design']['fields']['border_style'];
		}

		if ( ! empty( $label_font['weight'] ) ) {
			$vars['label_font_weight'] = $label_font['weight_raw'];
			$vars['label_font_style'] = $label_font['style'];
		}

		if ( ! empty( $field_font['weight'] ) ) {
			$vars['field_font_weight'] = $field_font['weight_raw'];
			$vars['field_font_style'] = $field_font['style'];
		}

		$success_message_font = siteorigin_widget_get_font(
			! empty( $instance['design']['success']['font'] ) ? $instance['design']['success']['font'] : ''
		);

		if ( ! empty( $success_message_font ) && is_array( $success_message_font ) ) {
			$vars['success_font_family'] = $success_message_font['family'];
			$vars['success_font_weight'] = ! empty( $success_message_font['weight_raw'] ) ? $success_message_font['weight_raw'] : '';
			$vars['success_font_style'] = ! empty( $success_message_font['style'] ) ? $success_message_font['style'] : '';
		}

		$global_settings = $this->get_global_settings();

		if ( ! empty( $global_settings['responsive_breakpoint'] ) ) {
			$less_vars['responsive_breakpoint'] = $global_settings['responsive_breakpoint'];
		}

		return $vars;
	}

	public static function single() {
		static $single;

		return empty( $single ) ? $single = new self() : $single;
	}

	public function name_from_label(
		$label,
		$post_vars = array()
	) {
		$it = 1;

		$label = str_replace( ' ', '-', strtolower( $label ) );
		$label = sanitize_title( $label );

		// Is this a form submission?
		if ( ! empty( $post_vars ) ) {
			// Try to find the full label based on the submitted fields.
			foreach ( $post_vars as $key => $value ) {
				if ( strpos( $key, $label ) === 0 ) {
					return $key;
				}
			}

			// Couldn't find the field. Fallback to just the label.
			return $label;
		}

		global $field_ids;
		do {
			$id = $label . ( $it > 0 ? '-' . $it : '' );
			$it ++;
		} while ( ! empty( $field_ids[ $id ] ) );
		$field_ids[ $id ] = true;

		return $id;
	}

	/**
	 * Render the form fields
	 *
	 * @param array $errors
	 */
	public function render_form_fields( $fields, $result, $instance ) {
		$errors = ! empty( $result['errors'] ) ? $result['errors'] : array();

		$label_position = $instance['design']['labels']['position'];
		$valid_positions = array('above', 'below', 'left', 'right', 'inside');
		if ( ! in_array( $label_position, $valid_positions ) ) {
			$label_position = 'above'; // Default value.
		}

		$indicate_required_fields = $instance['settings']['required_field_indicator'];

		if ( ! empty( $indicate_required_fields ) ) {
			?>
            <p><em><?php echo esc_html( $instance['settings']['required_field_indicator_message'] ); ?></em></p>
			<?php
		}

		$fields = apply_filters( 'siteorigin_widgets_contact_fields', $fields );

		$field_output = apply_filters( 'siteorigin_widgets_contact_form_field_output', '', $fields, $result, $instance );
		if ( ! empty( $field_output ) ) {
			echo $field_output;
			return;
		}

		foreach ( $fields as $i => $field ) {
			if ( empty( $field['type'] ) ) {
				continue;
			}

			$this->render_form_field( $field, $errors, $label_position, $instance, $indicate_required_fields, $i );
		}
	}

	public function render_form_field(
		$field,
		$errors,
		$label_position,
		$instance,
		$indicate_required_fields,
		$i = 0
	) {
		$field_name = $this->name_from_label( ! empty( $field['label'] ) ? $field['label'] : $i );

		$field_id = 'sow-contact-form-field-' . $field_name;

		$value = '';

		if ( ! empty( $_POST[ $field_name ] ) && wp_verify_nonce( $_POST['_wpnonce'], '_contact_form_submit' ) ) {
			$value = stripslashes_deep( $_POST[ $field_name ] );
		} elseif ( ! empty( $field['value'] ) ) {
			$value = $field['value'];
		}

		?>
			<div class="sow-form-field sow-form-field-<?php echo sanitize_html_class( $field['type'] ); ?>">
				<?php
				$label = $field['label'];
				$indicate_as_required = $indicate_required_fields && ! empty( $field['required']['required'] );
				$no_placeholder_support = ( $field['type'] != 'radio' && $field['type'] != 'checkboxes' );
				// label should be rendered before the field, then CSS will do the exact positioning.
				$render_label_before_field = ( $label_position != 'below' && $label_position != 'inside' ) || ( $label_position == 'inside' && ! $no_placeholder_support );

				if ( empty( $label_position ) || $render_label_before_field ) {
					$this->render_form_label( $field_id, $label, $label_position, $indicate_as_required );
				}

				$show_placeholder = $label_position == 'inside';

				if ( $show_placeholder && $indicate_as_required ) {
					$label .= '*';
				}

				if ( is_array( $errors ) && ! empty( $errors[ $field_name ] ) ) {
					?>
	                <div class="sow-error">
						<?php echo wp_kses_post( $errors[ $field_name ] ); ?>
	                </div>
					<?php
				}
				?>
				<div class="sow-field-container">
					<?php
					$class_name = empty( $field['type'] ) ? '' : 'SiteOrigin_Widget_ContactForm_Field_' . ucwords( $field['type'] );

					$has_description = ! empty( $field['description'] );
					// This does autoloading if required.
					if ( class_exists( $class_name ) ) {
						/**
						 * @var $contact_field SiteOrigin_Widget_ContactForm_Field_Base
						 */
						$field_input_options = array(
							'field'            => $field,
							'field_id'         => $field_id,
							'field_name'       => $field_name,
							'value'            => $value,
							'show_placeholder' => $show_placeholder,
							'label'            => $label,
							'has_description'  => $has_description,
						);
						$contact_field = new $class_name( $field_input_options );
						$contact_field->render();
					} else {
						echo '<input
							type="text"
							name="' . esc_attr( $field_name ) . '"
							id="' . esc_attr( $field_id ) . '"
							value="' . esc_attr( $value ) . '"
							class="sow-text-field" ' . ( $show_placeholder ? 'placeholder="' . esc_attr( $label ) . '"' : '' ) .'
							' . ( $has_description ? 'aria-describedby="' . esc_attr( $field_id ) . '-description"' : '' ) . '
							/>';
					}

					if ( ! empty( $field['description'] ) ) {
						?>
						<div
							class="sow-form-field-description"
							id="<?php echo esc_attr( $field_id ); ?>-description"
						>
							<?php echo wp_kses_post( $field['description'] ); ?>
						</div>
						<?php
					}
					?>
				</div>
				<?php

				if ( ! empty( $label_position ) && $label_position == 'below' ) {
					$this->render_form_label( $field_id, $label, $instance, $indicate_as_required );
				}
				?>
			</div>
			<?php
	}

	public function render_form_label( $field_id, $label, $position, $indicate_as_required = false ) {
		if ( ! empty( $label ) ) {
			$label_class = '';

			if ( ! empty( $position ) ) {
				$label_class = ' class="sow-form-field-label-' . $position . '"';
			}
			?><label<?php if ( ! empty( $label_class ) ) {
				echo $label_class;
			} ?> for="<?php echo esc_attr( $field_id ); ?>">
				<strong>
					<?php echo esc_html( $label ); ?>
					<?php if ( $indicate_as_required ) { ?>
						<span class="sow-form-field-required">*</span>
					<?php } ?>
				</strong>
			</label>
			<?php
		}
	}

	/**
	 * Ajax action handler to send the form
	 */
	public function contact_form_action( $instance ) {
		if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], '_contact_form_submit' ) ) {
			// Using `return false;` instead of `wp_die` because this function may sometimes be called as a side effect
			// of trying to enqueue scripts required for the front end or when previewing widgets e.g. in the block editor.
			// In those cases `$_POST['_wpnonce']` doesn't exist and calling `wp_die` will halt script execution and break things.
			return false;
		}

		// Ensure this contact form has fields.
		if ( empty( $instance['fields'] ) ) {
			return array(
				'status' => null,
			);
		}

		$post_vars = stripslashes_deep( $_POST );

		$instance_hash_field = $this->name_from_label( 'instance_hash', $post_vars );

		// If there is no instance hash, then we can't do anything.
		if ( empty( $post_vars[ $instance_hash_field ] ) ) {
			return array(
				'status' => null,
			);
		}

		// Let's check if this is the right form.
		$submitted_form_id = (int) explode( '-', $instance_hash_field )[1];
		if ( $submitted_form_id !== $instance['form_id'] ) {
			return array(
				'status' => null,
			);
		}

		$this->instance_hash = sanitize_text_field( $post_vars[ $instance_hash_field ] );

		// Make sure that this action only runs once per instance
		static $send_cache = array();
		$send_cache_hash = md5( serialize( $instance ) . '::' . $this->instance_hash );

		if ( isset( $send_cache[ $send_cache_hash ] ) ) {
			return $send_cache[ $send_cache_hash ];
		}

		$errors = array();
		$email_fields = array();

		$instance['fields'] = apply_filters( 'siteorigin_widgets_contact_fields', $instance['fields'] );

		foreach ( $instance['fields'] as $i => $field ) {
			if ( empty( $field['type'] ) ) {
				continue;
			}

			$field_name = $this->name_from_label(
				! empty( $field['label'] ) ? $field['label'] : $i,
				$post_vars
			);

			$value = isset( $post_vars[ $field_name ] ) ? $post_vars[ $field_name ] : '';

			// Can't just use `strlen` here as $value could be an array. E.g. for checkboxes field.
			if ( empty( $value ) && $value !== '0' ) {
				if ( $field['required']['required'] ) {
					// Add in the default subject
					if ( $field['type'] == 'subject' && ! empty( $instance['settings']['default_subject'] ) ) {
						$value = $instance['settings']['default_subject'];
					} else {
						$errors[ $field_name ] = ! empty( $field['required']['missing_message'] ) ? $field['required']['missing_message'] : __( 'Required field', 'so-widgets-bundle' );
						continue;
					}
				} else {
					continue; // Don't process an empty field that's not required
				}
			}

			// Type Validation
			switch ( $field['type'] ) {
				case 'email':
					if ( $value != sanitize_email( $value ) ) {
						$errors[ $field_name ] = __( 'Invalid email address.', 'so-widgets-bundle' );
					}
					$email_fields[ $field['type'] ] = $value;

					break;

				case 'name':
				case 'subject':
					$email_fields[ $field['type'] ] = $value;

					break;

				case 'checkboxes':
					$email_fields['message'][] = array(
						'label' => $field['label'],
						'value' => implode( ', ', $value ),
					);
					break;

				case 'tel':
					// Somewhat arbitrary basic phone number validation, checking for at least 3 digits, ignoring all
					// non-digit characters. Apparently, the lower limit for phone numbers is 3. See
					// https://github.com/siteorigin/so-widgets-bundle/issues/958#issuecomment-573139753
					$digits = preg_replace( '/\D/', '', $value );

					if ( strlen( $digits ) < 3 ) {
						$errors[ $field_name ] = __( 'Invalid phone number. It should contain at least three digits.', 'so-widgets-bundle' );
					} else {
						$email_fields['message'][] = array(
							'label' => $field['label'],
							'value' => $value,
						);
					}
					break;

				case 'number':
					if ( ! is_numeric( $value ) ) {
						$errors[ $field_name ] = __( 'Invalid number.', 'so-widgets-bundle' );
					} else {
						$email_fields[ $field['type'] ] = $value;
					}
					break;

				case 'select':
					if ( ! empty( $field['multiple_select'] ) && is_array( $value ) ) {
						$value = implode( ', ', $value );
					}

					$email_fields['message'][] = array(
						'label' => $field['label'],
						'value' => $value,
					);
					break;
				default:
					$email_fields['message'][] = array(
						'label' => $field['label'],
						'value' => $value,
					);
					break;
			}

			do_action( 'siteorigin_widgets_contact_post_var_field', $value, $field );
		}

		// Add in a default email address if no email field is defined in the form at all.
		if ( ! isset( $email_fields['email'] ) && ! empty( $instance['settings']['from'] ) ) {
			$email_fields['email'] = $instance['settings']['from'];
		}

		// Add in the default subject if no subject field is defined in the form at all.
		if ( ! isset( $email_fields['subject'] ) && ! empty( $instance['settings']['default_subject'] ) ) {
			$email_fields['subject'] = $instance['settings']['default_subject'];
		}

		// Add in the default subject prefix
		if ( ! empty( $email_fields['subject'] ) && ! empty( $instance['settings']['subject_prefix'] ) ) {
			$email_fields['subject'] = $instance['settings']['subject_prefix'] . ' ' . $email_fields['subject'];
		}

		// Now we do some email message validation
		if ( empty( $errors ) ) {
			$email_errors = $this->validate_mail( $email_fields );
			// Missing subject input and no default subject set. Revert to using a generic default 'SiteName Contact Form'
			if ( ! isset( $email_fields['subject'] ) && ! empty( $email_errors['subject'] ) ) {
				unset( $email_errors['subject'] );
				$email_fields['subject'] = get_bloginfo() . ' ' . __( 'Contact Form', 'so-widgets-bundle' );
			}

			if ( ! empty( $email_errors ) ) {
				$errors['_general'] = $email_errors;
			}
		}

		// And if we get this far, do some spam filtering and Captcha checking
		if ( empty( $errors ) ) {
			$spam_errors = $this->spam_check( $post_vars, $email_fields, $instance );

			if ( ! empty( $spam_errors ) ) {
				// Now we can decide how we want to handle this spam status
				if ( ! empty( $spam_errors['akismet'] ) && $instance['spam']['akismet']['spam_action'] == 'tag' ) {
					unset( $spam_errors['akismet'] );
					$email_fields['subject'] = '[spam] ' . $email_fields['subject'];
				}
			}

			if ( ! empty( $spam_errors ) ) {
				$errors['_general'] = $spam_errors;
			}
		}

		$errors = apply_filters( 'siteorigin_widgets_contact_validation', $errors, $post_vars, $email_fields, $instance );

		if ( empty( $errors ) ) {
			$email_fields = apply_filters( 'siteorigin_widgets_contact_email_fields', $email_fields, $post_vars, $instance );
			// We can send the email
			$success = $this->send_mail( $email_fields, $instance );

			if ( is_wp_error( $success ) ) {
				$errors['_general'] = array( 'send' => $success->get_error_message() );
			} elseif ( empty( $success ) ) {
				$errors['_general'] = array( 'send' => __( 'Error sending email, please try again later.', 'so-widgets-bundle' ) );
			} else {
				// This action will allow other plugins to run code when contact form has successfully been sent
				do_action( 'siteorigin_widgets_contact_sent', $instance, $email_fields );
			}
		}

		if ( ! empty( $errors ) ) {
			// This action will allow other plugins to run code when the contact form submission has resulted in error
			do_action( 'siteorigin_widgets_contact_error', $instance, $email_fields, $errors );
		}

		$send_cache[ $send_cache_hash ] = array(
			'status' => empty( $errors ) ? 'success' : 'fail',
			'errors' => $errors,
		);

		return $send_cache[ $send_cache_hash ];
	}

	/**
	 * Validate fields of an email message
	 */
	public function validate_mail( $email_fields ) {
		$errors = array();

		if ( empty( $email_fields['email'] ) ) {
			$errors['email'] = __( 'A valid email is required', 'so-widgets-bundle' );
		} elseif ( function_exists( 'filter_var' ) && ! filter_var( $email_fields['email'], FILTER_VALIDATE_EMAIL ) ) {
			$errors['email'] = __( 'The email address is invalid', 'so-widgets-bundle' );
		}

		if ( ! isset( $email_fields['subject'] ) ) {
			$errors['subject'] = __( 'Missing subject', 'so-widgets-bundle' );
		}

		return $errors;
	}

	/**
	 * Check the email for spam
	 *
	 * @return array
	 */
	public function spam_check( $post_vars, $email_fields, $instance ) {
		$errors = array();

		if ( self::is_recaptcha_enabled( $instance['spam']['recaptcha'] ) ) {
			$result = wp_remote_post(
				'https://www.google.com/recaptcha/api/siteverify',
				array(
					'body' => array(
						'secret'   => $instance['spam']['recaptcha']['use_captcha'] == 'v2' ? $instance['spam']['recaptcha']['secret_key'] : $instance['spam']['recaptcha']['secret_key_v3'],
						'response' => isset( $post_vars['g-recaptcha-response'] ) ? $post_vars['g-recaptcha-response'] : '',
						'remoteip' => isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null,
					),
				)
			);

			if ( ! is_wp_error( $result ) && ! empty( $result['body'] ) ) {
				$result = json_decode( $result['body'], true );

				if ( isset( $result['success'] ) && ! $result['success'] ) {
					$errors['recaptcha'] = __( 'Error validating your Captcha response.', 'so-widgets-bundle' );
				}
			}
		}

		if ( $instance['spam']['akismet']['use_akismet'] && class_exists( 'Akismet' ) ) {
			$comment = array();

			$message_text = array();

			if ( ! empty( $email_fields['message'] ) ) {
				foreach ( $email_fields['message'] as $m ) {
					$message_text[] = $m['value'];
				}
			}

			$comment['comment_content'] = $email_fields['subject'] . "\n\n" . implode( "\n\n", $message_text );
			$comment['comment_author'] = ! empty( $email_fields['name'] ) ? $email_fields['name'] : '';
			$comment['comment_author_email'] = $email_fields['email'];
			$comment['comment_post_ID'] = get_the_ID();

			$comment['comment_type'] = 'contact-form';

			$comment['user_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
			$comment['user_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
			$comment['referrer'] = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : null;
			$comment['blog'] = get_option( 'home' );
			$comment['blog_lang'] = get_locale();
			$comment['blog_charset'] = get_option( 'blog_charset' );

			// Check with Akismet.
			$response = Akismet::http_post( Akismet::build_query( $comment ), 'comment-check' );
			$is_spam = ! empty( $response[1] ) && $response[1] == 'true';

			if ( $is_spam ) {
				$errors['akismet'] = __( 'Unfortunately our system identified your message as spam.', 'so-widgets-bundle' );
			}
		}

		if ( ! empty( $instance['spam']['simple'] ) && ! empty( $instance['spam']['simple']['enabled'] ) ) {
			if ( ! class_exists( 'ReallySimpleCaptcha' ) ) {
				$template_vars['really_simple_spam'] = 'missing';
				$errors['simple'] = __( 'Error validating your Captcha response. Really Simple CAPTCHA missing.', 'so-widgets-bundle' );
			} else {
				$captcha = new ReallySimpleCaptcha();
				$prefix = $this->name_from_label( 'really-simple-captcha-prefix', $post_vars );
				$response = $this->name_from_label( 'really-simple-captcha', $post_vars );

				if ( ! $captcha->check(
					! empty( $post_vars[ $prefix ] ) ? $post_vars[ $prefix ] : '',
					! empty( $post_vars[ $response ] ) ? $post_vars[ $response ] : ''
				) ) {
					$errors['simple'] = __( 'Error validating your Captcha response. Please try again.', 'so-widgets-bundle' );
				}
				$captcha->remove( $prefix );
			}
		}

		if (
			! empty( $instance['spam']['honeypot'] ) &&
			! empty( $_POST['sow-name'] )
		) {
			$errors['spam-js'] = __( 'Unfortunately, our system identified your message as spam.', 'so-widgets-bundle' );
		}

		if ( ! empty( $instance['spam']['browser_check'] ) ) {
			if (
				empty( $_POST['sow-js'] ) ||
				$_POST['sow-js'] !== md5( $instance['form_id'] )
			) {
				$errors['spam-honeypot'] = __( 'Unfortunately, our system identified your message as spam.', 'so-widgets-bundle' );
			}
		}

		$errors = apply_filters( 'siteorigin_widgets_contact_spam_check', $errors, $post_vars, $email_fields, $instance );

		return $errors;
	}

	/**
	 * Format an email address with an optional name.
	 *
	 * This method formats an email address with an optional name.
	 * If a name is provided, it sanitizes both the name and the email address
	 * and returns them in the format "Name <email@example.com>".
	 * If no name is provided, it returns the sanitized email address.
	 *
	 * If the email field contains multiple email addresses separated by commas,
	 * it formats each email address with the optional name and returns them
	 * as a comma-separated string.
	 *
	 * @param string $email The email address or addresses to format.
	 * @param string|null $name The optional name to include with the email address.
	 *
	 * @return string The formatted email address or addresses with the optional name.
	 */
	private function format_email( $email, $name = null ) {
		if ( empty( $name ) ) {
			return sanitize_email( $email );
		}

		// If this field has multiple emails, format them all.
		if ( strpos( $email, ',' ) !== false ) {
			$emails = explode( ',', $email );

			foreach ( $emails as $key => $email ) {
				$emails[ $key ] = $this->format_email( $email, $name );
			}

			return implode( ', ', $emails );
		}

		return $this->sanitize_header( $name ) . ' <' . sanitize_email( $email ) . '>';
	}

	public function send_mail( $email_fields, $instance ) {
		if ( ! empty( $email_fields['name'] ) || ! empty( $email_fields['email'] ) ) {
			$body = '<strong>' . _x( 'From', 'The name of who sent this email', 'so-widgets-bundle' ) . ':</strong> ';

			if ( ! empty( $email_fields['email'] ) ) {
				$body .= '<a href="mailto:' . sanitize_email( $email_fields['email'] ) . '">';
			}

			if ( ! empty( $email_fields['name'] ) ) {
				$body .= esc_html( $email_fields['name'] ) . ' ';
			}

			if ( ! empty( $email_fields['email'] ) ) {
				$body .= '&#60;' . sanitize_email( $email_fields['email'] ) . '&#62; </a> ';
			}

			if ( ! empty( $instance['settings']['log_ip_address'] ) ) {
				$body .= '( ' . $_SERVER['REMOTE_ADDR'] . ' )';
			}
			$body .= "\n\n";
		}

		if ( ! empty( $email_fields['message'] ) ) {
			foreach ( $email_fields['message'] as $m ) {
				$body .= '<strong>' . $m['label'] . ':</strong>';
				$body .= "\n";
				$body .= htmlspecialchars( $m['value'] );
				$body .= "\n\n";
			}
		}
		$body = wpautop( trim( $body ) );

		if ( $this->is_dev_email( $instance['settings']['to'] ) || empty( $instance['settings']['to'] ) ) {
			// Replace default and empty email address.
			// Also replaces the email address that comes from the prebuilt layout directory and SiteOrigin Support Email
			$instance['settings']['to'] = get_option( 'admin_email' );
		}

		if (
			$this->is_dev_email( $instance['settings']['from'] ) ||
			empty( $instance['settings']['from'] ) ||
			$instance['settings']['from'] == $instance['settings']['to']
		) {
			$instance['settings']['from'] = $this->default_from_address();
		}

		$to_email = $this->format_email(
			$instance['settings']['to'],
			sprintf(
				__( '%s Contact Form', 'so-widgets-bundle' ),
				get_bloginfo( 'name' )
			)
		);

		$submitter_name = isset( $email_fields['name'] ) ? $email_fields['name'] : '';

		$headers = array(
			'Content-Type: text/html; charset=UTF-8',
			'From: ' . $this->format_email(
				$instance['settings']['from'],
				$submitter_name
			),
			'Reply-To: ' . $this->format_email(
				$email_fields['email'],
				$submitter_name
			)
		);

		// Check if this is a duplicated send
		$hash = md5( json_encode( array(
			'to'      => $to_email,
			'subject' => $email_fields['subject'],
			'body'    => $body,
			'headers' => $headers,
		) ) );
		$hash_check = get_option( 'so_contact_hashes', array() );
		// Remove expired hashes
		foreach ( $hash_check as $h => $t ) {
			if ( $t < time() - 5 * 60 ) {
				unset( $hash_check[ $h ] );
			}
		}

		if ( isset( $hash_check[ $hash ] ) ) {
			// Store the version with the expired hashes removed
			update_option( 'so_contact_hashes', $hash_check, true );

			// This message has already been sent successfully
			return true;
		}

		$formatted_body = apply_filters(
			'siteorigin_widgets_contact_body',
			$body,
			$email_fields['subject'],
			$instance
		);

		if ( empty( $formatted_body ) ) {
			$formatted_body = $body;
		}

		$mail_success = wp_mail(
			$to_email,
			$email_fields['subject'],
			$formatted_body,
			apply_filters( 'siteorigin_widgets_contact_email_headers', $headers )
		);

		if ( $mail_success ) {
			$hash_check[ $hash ] = time();
			update_option( 'so_contact_hashes', $hash_check, true );
		}

		return $mail_success;
	}

	/**
	 * Sanitize a value for an email header.
	 *
	 * From Pear Mail https://pear.php.net/package/Mail (BSD Style license - https://pear.php.net/copyright.php).
	 *
	 * @return mixed
	 */
	public static function sanitize_header( $value ) {
		return preg_replace( '/(<CR>|<LF>|%0A|%0D|\\n|\\r)/i', '', sanitize_text_field( $value ) );
	}

	private function is_dev_email( $email ) {
		return in_array( $email, $this->dev_emails, true );
	}

	private function default_from_address() {
		// Get the site domain and get rid of www.
		$sitename = strtolower( $_SERVER['SERVER_NAME'] );

		if ( substr( $sitename, 0, 4 ) == 'www.' ) {
			$sitename = substr( $sitename, 4 );
		}

		return apply_filters( 'siteorigin_widgets_contact_default_email', 'wordpress@' . $sitename );
	}

	/**
	 * Format the email body before sending it.
	 *
	 * This method formats the email body to be a valid HTML document.
	 * It uses output buffering to capture the content of the template and
	 * returns it as a string.
	 *
	 * It uses the `siteorigin_widgets_contact_body` filter to do this.
	 *
	 * @param string $body The email body.
	 * @param string $subject The email subject.
	 *
	 * @return string The formatted email body.
	 */
	public function format_email_body( $body, $subject ) {
		ob_start();
		require plugin_dir_path( __FILE__ ) . 'tpl/email.php';
		return ob_get_clean();
	}

	public function get_form_teaser() {
		if ( class_exists( 'SiteOrigin_Premium' ) ) {
			return false;
		}

		return array(
			sprintf(
				__( 'Add a form autoresponder and additional fields, including a date and time picker with %sSiteOrigin Premium%s', 'so-widgets-bundle' ),
				'<a href="https://siteorigin.com/downloads/premium/?featured_addon=plugin/contact-form-fields" target="_blank">',
				'</a>'
			),
			sprintf(
				__( 'Use Google Fonts right inside the Contact Form Widget with %sSiteOrigin Premium%s', 'so-widgets-bundle' ),
				'<a href="https://siteorigin.com/downloads/premium/?featured_addon=plugin/contact-form-fields" target="_blank" rel="noopener noreferrer">',
				'</a>'
			),
		);
	}
}

siteorigin_widget_register( 'sow-contact-form', __FILE__, 'SiteOrigin_Widgets_ContactForm_Widget' );

// Tell the autoloader where to look for contactform field classes.
function contactform_fields_class_paths( $class_paths ) {
	$loader = SiteOrigin_Widget_Field_Class_Loader::single();

	$loader->add_class_prefixes(
		apply_filters( 'siteorigin_widgets_contact_form_field_class_prefixes', array(
			'SiteOrigin_Widget_ContactForm_Field_',
		) ),
		'contact-form'
	);

	$loader->add_class_paths(
		apply_filters( 'siteorigin_widgets_contact_form_field_class_paths', array(
			plugin_dir_path( __FILE__ ) . 'fields/',
		) ),
		'contact-form'
	);

	return $class_paths;
}

add_filter( 'init', 'contactform_fields_class_paths' );
fields/base.class.php000064400000002207151537353760010561 0ustar00<?php

abstract class SiteOrigin_Widget_ContactForm_Field_Base {
	/**
	 * The options for this field. Used when enqueueing styles and scripts and rendering the field.
	 *
	 * @var array
	 */
	protected $options;
	public $type;

	public function __construct( $options ) {
		$this->options = $options;
		$this->init();
	}

	private function init() {
		$this->initialize( $this->options );
	}

	protected function initialize( $options ) {
	}

	abstract protected function render_field( $options );

	public function render() {
		$this->render_field( $this->options );
	}

	public static function add_custom_attrs( $type, $options = array() ) {
		$attr = array();

		// If the field has a description, add the aria-describedby attribute.
		if (
			! empty( $options ) &&
			is_array( $options ) &&
			! empty( $options['has_description'] )
		) {
			$attr['aria-describedby'] = esc_attr( $options['field_id'] . '-description' );
		}

		$attr = apply_filters(
			'siteorigin_widgets_contact_field_attr',
			$attr,
			$type,
			$options
		);

		foreach ( $attr as $k => $v ) {
			echo siteorigin_sanitize_attribute_key( $k ) . '="' . esc_attr( $v ) . '" ';
		}
	}
}
fields/checkboxes.class.php000064400000002145151537353760011766 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Checkboxes extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		if ( ! empty( $options['field']['options'] ) ) {
			if ( empty( $options['value'] ) || ! is_array( $options['value'] ) ) {
				$options['value'] = array();
			}
			?>
			<ul>
				<?php foreach ( $options['field']['options'] as $i => $option ) { ?>
					<?php
					$is_checked = in_array( $option['value'], $options['value'] ) || ( isset( $option['default'] ) && $option['default'] );
					?>
					<li>
						<input
							type="checkbox"
							value="<?php echo esc_attr( $option['value'] ); ?>"
							name="<?php echo esc_attr( $options['field_name'] ); ?>[]"
							id="<?php echo esc_attr( $options['field_id'] ) . '-' . $i; ?>"
							<?php echo checked( $is_checked, true, false ); ?>
							<?php self::add_custom_attrs( 'checkboxes', $options ); ?>
						/>
						<label for="<?php echo esc_attr( $options['field_id'] ) . '-' . $i; ?>">
							<?php echo wp_kses_post( $option['value'] ); ?>
						</label>
					</li>
				<?php } ?>
			</ul>
		<?php
		}
	}
}
fields/email.class.php000064400000000510151537353760010731 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Email extends SiteOrigin_Widget_ContactForm_Field_Text {
	// Outside of the construct, this class just exists for autoloading purposes, but is the same as the text field.
	public function __construct( $options ) {
		$this->type = 'email';
		parent::__construct( $options );
	}
}
fields/name.class.php000064400000001056151537353760010570 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Name extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		?>
		<input
			type="text"
			name="<?php echo esc_attr( $options['field_name'] ); ?>"
			id="<?php echo esc_attr( $options['field_id'] ); ?>"
			value="<?php echo esc_attr( $options['value'] ); ?>"
			class="sow-text-field"
			<?php echo $options['show_placeholder'] ? 'placeholder="' . esc_attr( $options['label'] ) . '"' : ''; ?>
			<?php self::add_custom_attrs( 'name', $options ); ?>
		/>
		<?php
	}
}
fields/number.class.php000064400000000512151537353760011134 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Number extends SiteOrigin_Widget_ContactForm_Field_Text {
	// Outside of the construct, this class just exists for autoloading purposes, but is the same as the text field.
	public function __construct( $options ) {
		$this->type = 'number';
		parent::__construct( $options );
	}
}
fields/radio.class.php000064400000001453151537353760010747 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Radio extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		if ( ! empty( $options['field']['options'] ) ) {
			?>
			<ul>
				<?php foreach ( $options['field']['options'] as $i => $option ) { ?>
					<li>
						<label>
							<input
								type="radio"
								value="<?php echo esc_attr( $option['value'] ); ?>"
								name="<?php echo esc_attr( $options['field_name'] ); ?>"
								id="<?php echo esc_attr( $options['field_id'] ) . '-' . $i; ?>"
								<?php echo checked( $option['value'], $options['value'], false ); ?>
								<?php self::add_custom_attrs( 'radio', $options ); ?>
							/>
							<?php echo esc_html( $option['value'] ); ?>
						</label>
					</li>
				<?php } ?>
			</ul>
		<?php
		}
	}
}
fields/select.class.php000064400000003246151537353760011132 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Select extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		if ( ! empty( $options['field']['multiple_select'] ) ) {
			wp_enqueue_script( 'select2' );
			wp_enqueue_style( 'select2' );
		}
		?>
		<select
			name="<?php echo esc_attr( $options['field_name'] ); ?><?php echo ! empty( $options['field']['multiple_select'] ) ? '[]' : ''; ?>"
			id="<?php echo esc_attr( $options['field_id'] ); ?>"
			<?php self::add_custom_attrs( 'select', $options ); ?>
			<?php echo ! empty( $options['field']['multiple_select'] ) ? 'multiple' : ''; ?>
		>
			<?php
			if ( $options['show_placeholder'] && empty( $options['field']['multiple_select'] ) ) {
				?>
				<option selected disabled>
					<?php echo esc_html__( $options['field']['label'], 'so-widgets-bundle' ); ?>
				</option>
				<?php
			}

			if ( ! empty( $options['field']['options'] ) ) {
				if (
					! $options['show_placeholder'] &&
					$options['field']['required']['required'] &&
					empty( $options['field']['multiple_select'] )
				) {
					?>
					<option selected <?php if ( ! $options['field']['required']['required'] ) {
						echo 'disabled';
					} ?>></option>
					<?php
				}

				foreach ( $options['field']['options'] as $i => $option ) {
					$value = ! empty( $options['field']['multiple_select'] ) && is_array( $options['value'] ) ? $options['value'][ $i ] : $options['value'];
					?>
					<option
						value="<?php echo esc_attr( $option['value'] ); ?>"<?php echo selected( $option['value'], $value, false ); ?>>
						<?php echo esc_html( $option['value'] ); ?>
					</option>
				<?php
				}
			}
		?>
		</select>
		<?php
	}
}
fields/subject.class.php000064400000001064151537353760011306 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Subject extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		?>
		<input
			type="text"
			name="<?php echo esc_attr( $options['field_name'] ); ?>"
			id="<?php echo esc_attr( $options['field_id'] ); ?>"
			value="<?php echo esc_attr( $options['value'] ); ?>"
			class="sow-text-field"
			<?php echo $options['show_placeholder'] ? 'placeholder="' . esc_attr( $options['label'] ) . '"' : ''; ?>
			<?php self::add_custom_attrs( 'subject', $options ); ?>
		/>
		<?php
	}
}
fields/tel.class.php000064400000000504151537353760010431 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Tel extends SiteOrigin_Widget_ContactForm_Field_Text {
	// Outside of the construct, this class just exists for autoloading purposes, but is the same as the text field.
	public function __construct( $options ) {
		$this->type = 'tel';
		parent::__construct( $options );
	}
}
fields/text.class.php000064400000001425151537353760010634 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_Text extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function __construct( $options ) {
		$this->type = 'text';
		parent::__construct( $options );
	}

	public function render_field( $options ) {
		?>
		<input
			type="<?php echo $options['field']['type']; ?>"
			name="<?php echo esc_attr( $options['field_name'] ); ?>"
			id="<?php echo esc_attr( $options['field_id'] ); ?>"
			value="<?php echo esc_attr( $options['value'] ); ?>"
			class="sow-text-field"<?php echo $options['show_placeholder'] ? 'placeholder="' . esc_attr( $options['label'] ) . '"' : ''; ?>
			<?php self::add_custom_attrs( $this->type, $options ); ?>
			<?php if ( ! empty( $options['field']['readonly'] ) ) {
				echo 'readonly';
			} ?>
		/>
		<?php
	}
}
fields/textarea.class.php000064400000001044151537353760011462 0ustar00<?php

class SiteOrigin_Widget_ContactForm_Field_TextArea extends SiteOrigin_Widget_ContactForm_Field_Base {
	public function render_field( $options ) {
		?>
		<textarea
			name="<?php echo esc_attr( $options['field_name'] ); ?>"
			id="<?php echo esc_attr( $options['field_id'] ); ?>"
			rows="10"
			<?php echo $options['show_placeholder'] ? 'placeholder="' . esc_attr( $options['label'] ) . '"' : ''; ?>
			<?php self::add_custom_attrs( $this->type, $options ); ?>
		><?php
		echo esc_textarea( $options['value'] );
		?></textarea>
		<?php
	}
}
js/contact-form-admin.js000064400000002675151537353770011232 0ustar00jQuery( document ).on( 'sow_validate_widget_data', function( e, valid, form, id ) {
	if ( id !== 'sow-contact-form' ) {
		return valid;
	}

	const values = sowbForms.getWidgetFormValues( form );

	// If we don't have the required data to validate, don't attempt
	// to validate.
	if (
		! values ||
		! values.settings ||
		! values.settings.to.length ||
		! values.settings.from.length
	) {
		return valid;
	}

	// If the emails are different, we don't need to validate.
	if ( values.settings.to !== values.settings.from ) {
		return valid;
	}

	// Emails are the same. Let's show an error.
	const $settingsSection = form.find( '.siteorigin-widget-field-settings' );
	const $settingsSectionLabel = form.find( '.siteorigin-widget-field-label ' );
	if ( ! $settingsSectionLabel.hasClass( 'siteorigin-widget-section-visible' ) ) {
		$settingsSectionLabel.trigger( 'click' );
	}

	// Ensure the error message isn't already present.
	if ( form.find( '.siteorigin-widget-form-notification.sow-error' ).length ) {
		return false;
	}

	const $errorMessage = jQuery( `<div class="siteorigin-widget-form-notification sow-error">${ sowContactAdmin.error }</div>` );
	$settingsSection.prepend(
		$errorMessage
	);

	// Clear error message after either email field is changed.
	form.find( '.siteorigin-widget-field-to .siteorigin-widget-input, .siteorigin-widget-field-from .siteorigin-widget-input' )
		.one( 'change', () => {
		$errorMessage.remove();
	} );

	return false;
} );
js/contact-form-admin.min.js000064400000001421151537353770012000 0ustar00jQuery(document).on("sow_validate_widget_data",(function(i,t,e,n){if("sow-contact-form"!==n)return t;const o=sowbForms.getWidgetFormValues(e);if(!(o&&o.settings&&o.settings.to.length&&o.settings.from.length))return t;if(o.settings.to!==o.settings.from)return t;const r=e.find(".siteorigin-widget-field-settings"),s=e.find(".siteorigin-widget-field-label ");if(s.hasClass("siteorigin-widget-section-visible")||s.trigger("click"),e.find(".siteorigin-widget-form-notification.sow-error").length)return!1;const g=jQuery(`<div class="siteorigin-widget-form-notification sow-error">${sowContactAdmin.error}</div>`);return r.prepend(g),e.find(".siteorigin-widget-field-to .siteorigin-widget-input, .siteorigin-widget-field-from .siteorigin-widget-input").one("change",()=>{g.remove()}),!1}));js/contact.js000064400000010005151537353770007165 0ustar00/* globals sowb, jQuery */

window.sowb = window.sowb || {};

sowb.SiteOriginContactForm = {
	init: function ($, useRecaptcha) {
		var $contactForms = $('form.sow-contact-form,.sow-contact-form-success');
		$contactForms.each( function() {
			var $el = $( this );
			var formSubmitSuccess = $el.is( '.sow-contact-form-success' );
			var formSubmitted = $el.is( '.sow-contact-submitted' );
			if ( formSubmitted || formSubmitSuccess ) {
				// The form was submitted. Let's try to scroll to it so the user can see the result.
				if ( sowContact.scrollto ) {
					var formPosition = $el.offset().top;
					if ( $el.is( ':hidden' ) ) {
						// The form is hidden, so scroll to it's closest visible ancestor.
						var $container = $el.closest( ':visible' );
						formPosition = $container.offset().top;
						// If the closest visible ancestor is either SOWB Accordion or Tabs widget, try to open the panel.
						if ( $container.is( '.sow-accordion-panel' ) ) {
							$container.find( '> .sow-accordion-panel-header-container > .sow-accordion-panel-header' ).trigger( 'click' );
						} else if ( $container.is( '.sow-tabs-panel-container' ) ) {
							var tabIndex = $el.closest( '.sow-tabs-panel' ).index();
							$container.siblings( '.sow-tabs-tab-container' ).find( '> .sow-tabs-tab' ).eq( tabIndex ).trigger( 'click' );
						}
					}
					formPosition += parseInt( sowContact.scrollto_offset );
					$( 'html, body' ).scrollTop( formPosition );
				}

				if ( formSubmitSuccess ) {
					// The form was submitted successfully, so we don't need to do anything else.
					return;
				}
			}
			var $submitButton = $( this ).find( '.sow-submit-wrapper > .sow-submit' );

			if ( useRecaptcha && sowb.SiteOriginContactFormV2 ) {
				// Render recaptcha
				var $recaptchaDiv = $el.find('.sow-recaptcha');
				if ($recaptchaDiv.length) {
					var config = $recaptchaDiv.data('config');
					$submitButton.prop('disabled', true);
					grecaptcha.render($recaptchaDiv.get(0),
						{
							'sitekey': config.sitekey,
							'theme': config.theme,
							'type': config.type,
							'size': config.size,
							'callback': function (response) {
								// Enable the submit button once we have a response from recaptcha.
								$submitButton.prop('disabled', false);
							},
						}
					);
				}
			}

			// Disable the submit button on click to avoid multiple submits.
			$contactForms.on( 'submit', function() {
				$submitButton.prop( 'disabled', true );

				if ( $submitButton.data( 'js-key' ) ) {
					const js_key = $submitButton.data( 'js-key' );
					$( this ).append( `<input type="hidden" name="sow-js" value="${js_key}">` );
				}
			} );

			if ( typeof $.fn.select2 == 'function' ) {
				$( '.sow-form-field-select select[multiple]' ).select2();
			}
		} );
	},
};

function soContactFormInitialize() {
	sowb.SiteOriginContactForm.init(window.jQuery, true);
}

// reCAPTCHA v3 form submission.
function soContactFormSubmit( token, e ) {
	sowb.SiteOriginContactFormV3.parent().parent().trigger( 'submit' );
}

jQuery( function ( $ ) {
	const recaptcha = $( 'form.sow-contact-form .sow-recaptcha' );
	// Check if reCAPTCHA is being used.
	if ( ! recaptcha.length ) {
		sowb.SiteOriginContactForm.init( $, recaptcha );
		return;
	}

	let apiUrl = 'https://www.google.com/recaptcha/api.js?onload=soContactFormInitialize';
	// v2 requires a specific render type.
	if ( recaptcha.first().data( 'config' ) != undefined ) {
		sowb.SiteOriginContactFormV2 = true;
		apiUrl += '&render=explicit';
	} else {
		// v3 requires a click event for submission.
		$( 'button.sow-submit ' ).on( 'click', function( e ) {
			e.preventDefault();
			sowb.SiteOriginContactFormV3 = $( this );
		} );
	}

	$( 'body' ).append(
		'<script type="text/javascript" src="' + apiUrl + '" async defer>'
	);


	if ( typeof $.fn.select2 == 'function' ) {
		// We need to adjust the dropdown position, or it'll cover the field.
		$( document ).on( 'click', '.sow-form-field-select .select2-selection--multiple', function() {
			$( '.select2-container--open .select2-dropdown' ).css( 'top', '32px' );
		} );
	}
} );
js/contact.min.js000064400000004162151537353770007756 0ustar00function soContactFormInitialize(){sowb.SiteOriginContactForm.init(window.jQuery,!0)}function soContactFormSubmit(t,o){sowb.SiteOriginContactFormV3.parent().parent().trigger("submit")}window.sowb=window.sowb||{},sowb.SiteOriginContactForm={init:function(t,o){var e=t("form.sow-contact-form,.sow-contact-form-success");e.each((function(){var i=t(this),n=i.is(".sow-contact-form-success");if(i.is(".sow-contact-submitted")||n){if(sowContact.scrollto){var s=i.offset().top;if(i.is(":hidden")){var c=i.closest(":visible");if(s=c.offset().top,c.is(".sow-accordion-panel"))c.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").trigger("click");else if(c.is(".sow-tabs-panel-container")){var a=i.closest(".sow-tabs-panel").index();c.siblings(".sow-tabs-tab-container").find("> .sow-tabs-tab").eq(a).trigger("click")}}s+=parseInt(sowContact.scrollto_offset),t("html, body").scrollTop(s)}if(n)return}var r=t(this).find(".sow-submit-wrapper > .sow-submit");if(o&&sowb.SiteOriginContactFormV2){var l=i.find(".sow-recaptcha");if(l.length){var f=l.data("config");r.prop("disabled",!0),grecaptcha.render(l.get(0),{sitekey:f.sitekey,theme:f.theme,type:f.type,size:f.size,callback:function(t){r.prop("disabled",!1)}})}}e.on("submit",(function(){if(r.prop("disabled",!0),r.data("js-key")){const o=r.data("js-key");t(this).append(`<input type="hidden" name="sow-js" value="${o}">`)}})),"function"==typeof t.fn.select2&&t(".sow-form-field-select select[multiple]").select2()}))}},jQuery((function(t){const o=t("form.sow-contact-form .sow-recaptcha");if(!o.length)return void sowb.SiteOriginContactForm.init(t,o);let e="https://www.google.com/recaptcha/api.js?onload=soContactFormInitialize";null!=o.first().data("config")?(sowb.SiteOriginContactFormV2=!0,e+="&render=explicit"):t("button.sow-submit ").on("click",(function(o){o.preventDefault(),sowb.SiteOriginContactFormV3=t(this)})),t("body").append('<script type="text/javascript" src="'+e+'" async defer>'),"function"==typeof t.fn.select2&&t(document).on("click",".sow-form-field-select .select2-selection--multiple",(function(){t(".select2-container--open .select2-dropdown").css("top","32px")}))}));styles/default.less000064400000017744151537353770010440 0ustar00@import "../../../base/less/mixins";

.sow-form-field {
	display: block;
	.clearfix();

	label {
		display: block;
		margin-bottom: 5px;

		@label_width: default;
		@label_align: default;
		width: @label_width;
		text-align: @label_align;
		@label_font_color: default;
		color: @label_font_color;

		strong {
			@label_font_family: default;
			@label_font_weight: default;
			@label_font_style: default;
			.font(@label_font_family, @label_font_weight);
			font-style: @label_font_style;

			@label_font_size: default;
			font-size: @label_font_size;
		}

		&.sow-form-field-label-left {
			float: left;
			margin-right: 10px;
		}

		&.sow-form-field-label-right {
			float: right;
			margin-left: 10px;
		}
	}

	.sow-field-container {
		overflow: hidden;
		display: block;

		textarea:focus,
		input:focus,
		> :focus {
			@outline_style: solid;
			@outline_color: default;
			@outline_width: 1px;

			// NB: Do not optimize this into a single line, otherwise the removal of 'default' values won't work.
			outline-style: @outline_style;
			outline-color: @outline_color;
			outline-width: @outline_width;
		}
	}

	@field_font_family: default;
	@field_font_weight: default;
	@field_font_style: default;
	@field_font_size: default;
	@field_font_color: default;

	@field_background: default;

	@field_margin: default;
	@field_padding: default;
	@field_border_radius: default;
	@field_border: default;
	@field_max_width: default;
	@field_height: default;
	@field_height_textarea: default;
	@responsive_breakpoint: 780px;

	.sow-text-field {
		height: @field_height;
	}

	& when not ( @field_max_width = false ) {
		@media (min-width: @responsive_breakpoint) {
			.sow-text-field {
				max-width: @field_max_width;
			}

			&.sow-form-field-datepicker .sow-field-container,
			&.sow-form-field-location .sow-field-container {
				max-width: @field_max_width;
			}

			&.sow-form-field-datepicker .sow-text-field,
			&.sow-form-field-location .sow-text-field {
				max-width: none;
			}

			textarea {
				max-width: @field_max_width;
			}
		}
	}

	textarea {
		height: @field_height_textarea;
	}

	.sow-field-container {
		margin: @field_margin;
	}

	textarea,
	.sow-text-field {
		display: block;
		width: 100%;
		.box-sizing(border-box);
		border-radius: @field_border_radius;
		border: @field_border;
		padding: @field_padding;
		background: @field_background;
		color: @field_font_color;
		font-size: @field_font_size;
		.font(@field_font_family, @field_font_weight);
		font-style: @field_font_style;
	}

	&.sow-form-field-radio {

		ul {
			list-style: none;
			margin: 0;
			padding: 0;

			li {
				margin: 0;
			}

			label {
				margin-bottom: 0;
				display: flex;
				align-items: center;
			}

			input {
				float: left;
				margin-right: 0.5em;
				height: auto;
				flex: none;
			}
		}
	}

	&.sow-form-field-checkboxes {

		ul {
			list-style: none;
			margin: 0;
			padding: 0;

			li {
				align-items: center;
				display: flex;
				margin: 0;
			}

			label {
				margin-bottom: 0;
			}

			input {
				height: auto;
				margin-right: 0.5em;
				flex: none;
			}
		}
	}

	&.sow-form-field-select {

		select,
		.select2-container {
			.font(@field_font_family, @field_font_weight);
			background: @field_background;
			border-radius: @field_border_radius;
			border: @field_border;
			color: @field_font_color;
			font-size: @field_font_size;
			font-style: @field_font_style;
			padding: @field_padding;
		}

		.select2-container,
		.select2-search__field {
			width: 100% !important;
		}

		.select2-selection__rendered,
		.select2-search__field {
			padding: 0;
			margin: 0;

			&:focus {
				outline: none;
			}
		}

		.select2-search {
			margin-left: 3px;
		}

		.select2-selection__choice__remove {
			height: 100%;
		}

		.select2-selection__choice {
			margin-left: 2px;
			margin-top: 0;
		}

		.select2-selection--multiple {
			align-items: center;
			border: none;
			display: flex;
			padding: 0;
		}
	}

	@description_font_size: 0.9em;
	@description_font_color: #999;
	@description_font_style: italic;
	@description_top_margin: 0.2em;

	.sow-form-field-description {
		font-size: @description_font_size;
		margin-top: @description_top_margin;
		margin-left: 0.2em;
		color: @description_font_color;
		font-style: @description_font_style;
	}
}

.sow-recaptcha {
	margin-bottom: 1em;
}

.sow-contact-form {
	// Container Background.
	@container_background: default;
	@container_padding: 10px;

	// Container Border.
	@container_border_color: #c0c0c0;
	@container_border_width: 1px;
	@container_border_style: solid;

	padding: @container_padding;
	border: @container_border_color @container_border_style @container_border_width;
	background-color: @container_background;

	.sow-error {
		@error_background: #fce4e5;
		@error_border: #ec666a;
		@error_text: #ec666a;
		@error_padding: 5px;
		@error_margin: 10px;

		background: @error_background;
		border: 1px solid @error_border;
		color: @error_text;
		border-radius: 2px;
		padding: @error_padding;
		font-size: 0.8em;
		list-style: none;
		margin: 0 0 @error_margin 0;

		li {
			margin: 0;
		}
	}

	.sow-submit-styled {
		@submit_background_color: #eee;
		@submit_background_color_hover: default;
		@submit_background_gradient: 10%;
		@submit_border_color: #989a9c;
		@submit_border_color_hover: default;
		@submit_border_style: solid;
		@submit_border_width: 1px;
		@submit_border_radius: 3px;
		@submit_text_color: #5a5a5a;
		@submit_text_color_hover: default;
		@submit_font_size: default;
		@submit_weight: 500;
		@submit_padding: 10px;
		@submit_width: default;
		@submit_align: left;
		@submit_inset_highlight: 50%;
		text-align: @submit_align;

		.sow-submit {
			border-radius: @submit_border_radius;
			border: @submit_border_width @submit_border_style @submit_border_color;
			color: @submit_text_color;
			display: inline-block;
			font-size: @submit_font_size;
			font-weight: @submit_weight;
			padding: @submit_padding @submit_padding * 2;
			width: @submit_width;

			& when( @submit_background_gradient > 0% ) {
				.gradient(
					lighten(@submit_background_color, @submit_background_gradient),
					darken(@submit_background_color, @submit_background_gradient),
					lighten(@submit_background_color, @submit_background_gradient)
				);
			}

			& when( @submit_background_gradient = 0% ) {
				background: @submit_background_color;
			}

			&:hover,
			&:focus {
				border-color: @submit_border_color_hover;
				color: @submit_text_color_hover;

				& when not ( @submit_background_color_hover = default ) {
					& when( @submit_background_gradient > 0% ) {
						.gradient(
							lighten(@submit_background_color_hover, @submit_background_gradient),
							darken(@submit_background_color_hover, @submit_background_gradient),
							lighten(@submit_background_color_hover, @submit_background_gradient)
						);
					}

					& when( @submit_background_gradient = 0% ) {
						background: @submit_background_color_hover;
					}
				}
			}

			.sow-submit-box-shadow ( @percent ) when ( @percent > 0% ) {
				box-shadow: inset 0 -1px 0 fade( #fff, @percent );
			}

			.sow-submit-box-shadow( @submit_inset_highlight );
		}

		.sow-submit:disabled {
			color: lighten(@submit_text_color, 20%);
			cursor: not-allowed;
			background: lighten(@submit_background_color, 20%);
			border: @submit_border_width @submit_border_style lighten(@submit_border_color, 20%);
		}
	}
}

.sow-contact-form-success {
	@success_background_color: default;
	@success_border_color: default;
	@success_border_style: solid;
	@success_border_width: 1px;
	@success_color: default;
	@success_font_family: default;
	@success_font_size: default;
	@success_font_style: default;
	@success_font_weight: default;
	@success_padding: default;

	background-color: @success_background_color;
	color: @success_color;
	font-family: @success_font_family;
	font-size: @success_font_size;
	font-style: @success_font_style;
	font-weight: @success_font_weight;
	padding: @success_padding;

	& when not ( @success_border_color = default ) {
		border-color: @success_border_color;
		border-style: @success_border_style;
		border-width: @success_border_width;
	}

	p:last-of-type {
		margin-bottom: 0;
	}
}
tpl/default.php000064400000006372151537353770007530 0ustar00<?php
$this->instance_hash = $storage_hash;
$short_hash = substr( $this->instance_hash, 0, 4 );

// Display the title.
if ( $instance['display_title'] && ! empty( $instance['title'] ) ) {
	echo $args['before_title'] . wp_kses_post( $instance['title'] ) . $args['after_title'];
}

if ( is_array( $result ) && $result['status'] == 'success' ) {
	// Display the success message
	?>
	<div class="sow-contact-form-success" id="contact-form-<?php echo esc_attr( $short_hash ); ?>">
		<?php echo wp_kses_post( apply_filters( 'siteorigin_widgets_contact_success_message', $instance['settings']['success_message'] ) ); ?>
	</div>
	<?php
} else {
	if ( $recaptcha && ! empty( $recaptcha_v2 ) ) {
		$settings = array(
			'sitekey' => $recaptcha_config['site_key'],
			'theme'   => $recaptcha_config['theme'],
			'type'    => $recaptcha_config['type'],
			'size'    => $recaptcha_config['size'],
		);
	}
	$global_settings = $this->get_global_settings();
	?>
	<form
		action="<?php echo esc_url( add_query_arg( null, null ) ); ?>"
		method="POST"
		class="sow-contact-form<?php echo ! empty( $global_settings['scrollto'] ) && ! empty( $result ) ? ' sow-contact-submitted' : ''; ?>"
		id="contact-form-<?php echo esc_attr( $short_hash ); ?>"
	>

		<?php if ( ! empty( $result['errors']['_general'] ) ) { ?>
			<ul class="sow-error">
				<?php foreach ( $result['errors']['_general'] as $type => $message ) { ?>
					<li><?php echo esc_html( $message ); ?></li>
				<?php } ?>
			</ul>
		<?php } ?>

		<?php
		$this->render_form_fields( $instance['fields'], $result, $instance );

		if ( $template_vars['honeypot'] ) {
			?>
			<input
				type="text"
				name="sow-name"
				class="sow-text-field"
				style="display: none !important; visibility: hidden !important;"
				autocomplete="off"
				aria-hidden="true"
			>
		<?php } ?>

		<?php if ( $recaptcha ) { ?>
			<div class="sow-recaptcha"
				<?php if ( ! empty( $recaptcha_v2 ) ) { ?>
					data-config="<?php echo esc_attr( json_encode( $recaptcha_v2 ) ); ?>"
				<?php } ?>
			></div>
			<?php
		}

		if ( ! empty( $really_simple_spam ) ) {
			if ( $really_simple_spam == 'missing' ) {
				esc_html_e( 'Unable to detect Really Simple CAPTCHA plugin.', 'so-widgets-bundle' );
			} else {
				require 'simple.php';
			}
		}

		do_action( 'siteorigin_widgets_contact_before_submit', $instance, $result );
		?>

		<div class="sow-submit-wrapper <?php if ( $instance['design']['submit']['styled'] ) {
			echo 'sow-submit-styled';
		} ?>">

			<button
				type="submit"
				class="sow-submit<?php
				if ( $recaptcha && empty( $recaptcha_v2 ) ) {
					echo ' g-recaptcha';
				}
				?>"
				<?php
				foreach ( $submit_attributes as $name => $val ) {
					echo siteorigin_sanitize_attribute_key( $name ) . '="' . esc_attr( $val ) . '" ';
				}

				if ( ! empty( $onclick ) ) {
					echo 'onclick="' . siteorigin_widget_onclick( $onclick ) . '"';
				}
				?>
			>
				<?php echo esc_html( $instance['settings']['submit_text'] ); ?>
			</button>
		</div>
		<?php
		do_action( 'siteorigin_widgets_contact_after_submit', $instance, $result );
		?>
		<input
			type="hidden"
			name="<?php echo esc_attr( $this->name_from_label( 'instance_hash' ) ); ?>"
			value="<?php echo esc_attr( $this->instance_hash ); ?>"
		/>

		<?php wp_nonce_field( '_contact_form_submit' ); ?>
	</form>
	<?php
}
tpl/email.php000064400000000543151537353770007165 0ustar00<!DOCTYPE html>
<html lang="<?php echo esc_attr( get_bloginfo( 'language' ) ); ?>">
<head>
	<meta charset="<?php esc_attr( get_bloginfo( 'charset' ) ); ?>">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>
		<?php echo esc_html( $subject ); ?>
	</title>
</head>
<body>
	<?php echo wp_kses_post( $body ); ?>
</body>
</html>
tpl/simple.php000064400000003223151537353770007365 0ustar00<?php
$captcha_name = $this->name_from_label( 'really-simple-captcha' );
?>

<div class="sow-form-field sow-form-field-captcha">
	<?php if ( $instance['design']['labels']['position'] != 'below' ) { ?>
		<label
			class="sow-form-field-label-<?php echo esc_attr( $instance['design']['labels']['position'] != 'inside' ? $instance['design']['labels']['position'] : 'above' ); ?>"
			for="<?php echo esc_attr( $captcha_name ); ?>"
		>
			<strong>
				<?php echo esc_html__( 'Captcha', 'so-widgets-bundle' ); ?>
			</strong>
		</label>
	<?php } ?>

	<?php if ( ! empty( $template_vars['really_simple_spam_error'] ) ) { ?>
		<div class="sow-error">
			<?php echo esc_html( $template_vars['really_simple_spam_error'] ); ?>
		</div>
	<?php } ?>

	<img
		src="<?php echo esc_url( plugins_url() . '/really-simple-captcha/tmp/' . $really_simple_spam_image ); ?>"
		width="<?php echo esc_attr( $really_simple_spam->img_size[0] ); ?>"
		height="<?php echo esc_attr( $really_simple_spam->img_size[1] ); ?>"
	>
	<span class="sow-field-container">
		<input
			type="text"
			name="<?php echo esc_attr( $captcha_name ); ?>"
			id="<?php echo esc_attr( $captcha_name ); ?>"
			value=""
			class="sow-text-field"
		>
	</span>
	<?php if ( $instance['design']['labels']['position'] == 'below' ) { ?>
		<label
			class="sow-form-field-label-left"
			for="<?php echo esc_attr( $captcha_name ); ?>"
		>
			<strong>
				<?php echo esc_html__( 'Captcha', 'so-widgets-bundle' ); ?>
			</strong>
		</label>
	<?php } ?>
	<input
		type="hidden"
		name="<?php echo esc_attr( $this->name_from_label( 'really-simple-captcha-prefix' ) ); ?>"
		value="<?php echo esc_attr( $really_simple_spam_prefix ); ?>"
	/>
</div>