FileMaster
Search
Toggle Dark Mode
Home
/
.
/
wp-content
/
plugins
/
sureforms
/
inc
/
page-builders
/
elementor
Edit File: form-widget.php
<?php /** * Elementor SureForms form widget. * * @package sureforms. * @since 0.0.5 */ namespace SRFM\Inc\Page_Builders\Elementor; use Elementor\Plugin; use Elementor\Widget_Base; use Spec_Gb_Helper; use SRFM\Inc\Generate_Form_Markup; use SRFM\Inc\Helper; use SRFM\Inc\Page_Builders\Page_Builders; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * SureForms widget that displays a form. */ class Form_Widget extends Widget_Base { /** * Whether we are in the preview mode. * * @var bool */ public $is_preview_mode; /** * Constructor. * * @param array<mixed> $data Widget data. * @param array<mixed> $args Widget arguments. */ public function __construct( $data = [], $args = null ) { parent::__construct( $data, $args ); // (Preview iframe) $this->is_preview_mode = \Elementor\Plugin::$instance->preview->is_preview_mode(); if ( $this->is_preview_mode ) { // enqueue common fields assets for the dropdown and phone fields. Page_Builders::enqueue_common_fields_assets(); wp_register_script( 'srfm-elementor-preview', SRFM_URL . 'inc/page-builders/elementor/assets/elementor-editor-preview.js', [ 'elementor-frontend' ], SRFM_VER, true ); wp_localize_script( 'srfm-elementor-preview', 'srfmElementorData', [ 'isProActive' => Helper::has_pro(), ] ); // Register styling preview script for live preview. wp_register_script( 'srfm-elementor-preview-styling', SRFM_URL . 'assets/build/elementorPreviewStyling.js', [ 'elementor-frontend' ], SRFM_VER, true ); wp_localize_script( 'srfm-elementor-preview-styling', 'srfmElementorStyling', [ 'fieldSpacingVars' => Helper::get_css_vars(), ] ); /** * Hook for Pro to register additional preview assets (scripts and styles). * * @since 2.7.0 */ do_action( 'srfm_elementor_register_preview_assets' ); } } /** * Get script depends. * * @since 0.0.5 * @return array<string> Script dependencies. */ public function get_script_depends() { if ( $this->is_preview_mode ) { $scripts = [ 'srfm-elementor-preview', 'srfm-elementor-preview-styling' ]; /** * Filter the widget's script dependencies. * Pro uses this to add its preview scripts. * * @param array<string> $scripts Script handles. * @since 2.7.0 */ return apply_filters( 'srfm_elementor_widget_script_depends', $scripts ); } return []; } /** * Get style depends. * * @since 2.7.0 * @return array<string> Style dependencies. */ public function get_style_depends() { $styles = []; /** * Filter the widget's style dependencies. * Pro uses this to add its custom-styles CSS. * * @param array<string> $styles Style handles. * @since 2.7.0 */ return apply_filters( 'srfm_elementor_widget_style_depends', $styles ); } /** * Get widget name. * * @since 0.0.5 * @return string Widget name. */ public function get_name() { return SRFM_FORMS_POST_TYPE; } /** * Get widget title. * * @since 0.0.5 * @return string Widget title. */ public function get_title() { return __( 'SureForms', 'sureforms' ); } /** * Get widget icon. * * @since 0.0.5 * @return string Widget icon. */ public function get_icon() { return 'eicon-form-horizontal srfm-elementor-widget-icon'; } /** * Get widget categories. Used to determine where to display the widget in the editor. * * @since 0.0.5 * @return array<string> Widget categories. */ public function get_categories() { return [ 'sureforms-elementor' ]; } /** * Get widget keywords. * * @since 0.0.5 * @return array<string> Widget keywords. */ public function get_keywords() { return [ 'sureforms', 'contact form', 'form', 'elementor form', ]; } /** * Static method to get color value from settings. * Can be used by Pro plugin to resolve global colors. * * @param array<string, mixed> $settings Widget settings. * @param string $control_key The control key. * @return string|null The color value or null if not set. * @since 2.7.0 */ public static function get_resolved_color( $settings, $control_key ) { // First check for a global color reference. $globals = isset( $settings['__globals__'] ) && is_array( $settings['__globals__'] ) ? $settings['__globals__'] : []; if ( ! empty( $globals[ $control_key ] ) ) { $global_key = is_string( $globals[ $control_key ] ) ? $globals[ $control_key ] : ''; // Use Elementor's data manager to resolve the global value. if ( $global_key && class_exists( '\Elementor\Plugin' ) && isset( Plugin::$instance->data_manager_v2 ) ) { $data = Plugin::$instance->data_manager_v2->run( $global_key ); if ( is_array( $data ) && ! empty( $data['value'] ) && is_string( $data['value'] ) ) { return $data['value']; } } } // Fall back to direct value. if ( isset( $settings[ $control_key ] ) && '' !== $settings[ $control_key ] && 'default' !== $settings[ $control_key ] ) { $value = $settings[ $control_key ]; return is_string( $value ) ? $value : null; } return null; } /** * Build CSS gradient string from Group_Control_Background settings. * * Constructs a CSS gradient value from Elementor's gradient control settings. * Supports both linear and radial gradients. Radial gradients use 'center center' position. * * @param array<string, mixed> $settings Widget settings containing gradient values. * @return string|null CSS gradient string or null if colors not set. * @since 2.7.0 */ public static function build_gradient_css( $settings ) { // Get gradient colors - resolve global colors if used. $color_1 = self::get_resolved_color( $settings, 'bgGradient_color' ); $color_2 = self::get_resolved_color( $settings, 'bgGradient_color_b' ); // Both colors are required. if ( ! $color_1 || ! $color_2 ) { return null; } // Get gradient settings with defaults - use Helper::get_string_value for type safety. $type = isset( $settings['bgGradient_gradient_type'] ) && '' !== $settings['bgGradient_gradient_type'] ? Helper::get_string_value( $settings['bgGradient_gradient_type'] ) : 'linear'; // Get angle settings. $angle_settings = isset( $settings['bgGradient_gradient_angle'] ) && is_array( $settings['bgGradient_gradient_angle'] ) ? $settings['bgGradient_gradient_angle'] : []; $angle = isset( $angle_settings['size'] ) ? Helper::get_string_value( $angle_settings['size'] ) : '180'; $angle_unit = isset( $angle_settings['unit'] ) ? Helper::get_string_value( $angle_settings['unit'] ) : 'deg'; // Get color 1 stop settings. $color_1_settings = isset( $settings['bgGradient_color_stop'] ) && is_array( $settings['bgGradient_color_stop'] ) ? $settings['bgGradient_color_stop'] : []; $color_1_stop = isset( $color_1_settings['size'] ) ? Helper::get_string_value( $color_1_settings['size'] ) : '0'; $color_1_unit = isset( $color_1_settings['unit'] ) ? Helper::get_string_value( $color_1_settings['unit'] ) : '%'; // Get color 2 stop settings. $color_2_settings = isset( $settings['bgGradient_color_b_stop'] ) && is_array( $settings['bgGradient_color_b_stop'] ) ? $settings['bgGradient_color_b_stop'] : []; $color_2_stop = isset( $color_2_settings['size'] ) ? Helper::get_string_value( $color_2_settings['size'] ) : '100'; $color_2_unit = isset( $color_2_settings['unit'] ) ? Helper::get_string_value( $color_2_settings['unit'] ) : '%'; // Build radial gradient: radial-gradient(at center center, color1 stop1, color2 stop2). if ( 'radial' === $type ) { return sprintf( 'radial-gradient(at center center, %s %s%s, %s %s%s)', esc_attr( $color_1 ), esc_attr( $color_1_stop ), esc_attr( $color_1_unit ), esc_attr( $color_2 ), esc_attr( $color_2_stop ), esc_attr( $color_2_unit ) ); } // Build linear gradient: linear-gradient(angle, color1 stop1, color2 stop2). return sprintf( 'linear-gradient(%s%s, %s %s%s, %s %s%s)', esc_attr( $angle ), esc_attr( $angle_unit ), esc_attr( $color_1 ), esc_attr( $color_1_stop ), esc_attr( $color_1_unit ), esc_attr( $color_2 ), esc_attr( $color_2_stop ), esc_attr( $color_2_unit ) ); } /** * Register form widget controls. * Adds different input fields to allow the user to change and customize the widget settings. * * @since 0.0.5 * @return void */ protected function register_controls() { $this->start_controls_section( 'section_form', [ 'label' => __( 'SureForms', 'sureforms' ), ] ); $this->add_control( 'srfm_form_block', [ 'label' => __( 'Select Form', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT2, 'options' => Helper::get_sureforms_title_with_ids(), 'default' => '', ] ); $this->add_control( 'srfm_show_form_title', [ 'label' => __( 'Form Title', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Show', 'sureforms' ), 'label_off' => __( 'Hide', 'sureforms' ), 'return_value' => 'true', 'condition' => [ 'srfm_form_block!' => [ '' ], ], ] ); $this->add_control( 'srfm_edit_form', [ 'label' => __( 'Edit Form', 'sureforms' ), 'separator' => 'before', 'type' => \Elementor\Controls_Manager::BUTTON, 'text' => __( 'Edit', 'sureforms' ), 'event' => 'sureforms:form:edit', 'condition' => [ 'srfm_form_block!' => [ '' ], ], ] ); $this->add_control( 'srfm_create_form', [ 'label' => __( 'Create New Form', 'sureforms' ), 'type' => \Elementor\Controls_Manager::BUTTON, 'text' => __( 'Create', 'sureforms' ), 'event' => 'sureforms:form:create', ] ); $this->add_control( 'srfm_form_submission_info', [ 'content' => __( 'Form submission will be possible on the frontend.', 'sureforms' ), 'type' => \Elementor\Controls_Manager::ALERT, 'condition' => [ 'srfm_form_block!' => [ '' ], ], ] ); $this->end_controls_section(); // Style Tab - Form Styling Section. $this->start_controls_section( 'srfm_style_section', [ 'label' => __( 'Form Styling', 'sureforms' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => [ 'srfm_form_block!' => '', ], ] ); // Form Theme Select. $this->add_control( 'formTheme', [ 'label' => __( 'Form Theme', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'inherit', 'options' => [ 'inherit' => __( "Inherit Form's Original Style", 'sureforms' ), 'default' => __( 'Default', 'sureforms' ), ], 'separator' => 'after', ] ); // Primary Color. $this->add_control( 'primaryColor', [ 'label' => __( 'Primary Color', 'sureforms' ), 'type' => \Elementor\Controls_Manager::COLOR, 'condition' => [ 'formTheme!' => 'inherit', ], ] ); // Text Color. $this->add_control( 'textColor', [ 'label' => __( 'Text Color', 'sureforms' ), 'type' => \Elementor\Controls_Manager::COLOR, 'condition' => [ 'formTheme!' => 'inherit', ], ] ); // Text on Primary (button text color). $this->add_control( 'textOnPrimaryColor', [ 'label' => __( 'Text on Primary', 'sureforms' ), 'type' => \Elementor\Controls_Manager::COLOR, 'condition' => [ 'formTheme!' => 'inherit', ], ] ); // Background Type Heading. $this->add_control( 'bgHeading', [ 'label' => __( 'Background', 'sureforms' ), 'type' => \Elementor\Controls_Manager::HEADING, 'condition' => [ 'formTheme!' => 'inherit', ], ] ); // Background Type. $this->add_control( 'bgType', [ 'label' => __( 'Type', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'color', 'options' => [ 'color' => __( 'Color', 'sureforms' ), 'gradient' => __( 'Gradient', 'sureforms' ), 'image' => __( 'Image', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'inherit', ], ] ); // Background Color. $this->add_control( 'bgColor', [ 'label' => __( 'Color', 'sureforms' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#FFFFFF', 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'color', ], ] ); // Background Gradient - using Group_Control_Background for visual gradient picker. // Position control is hidden - radial gradients use 'center center' position by default. $this->add_group_control( \Elementor\Group_Control_Background::get_type(), [ 'name' => 'bgGradient', 'types' => [ 'gradient' ], 'exclude' => [ 'image' ], 'fields_options' => [ 'background' => [ 'label' => __( 'Gradient', 'sureforms' ), 'default' => 'gradient', ], 'color' => [ 'label' => __( 'Color 1', 'sureforms' ), 'default' => '#FFC9B2', ], 'color_stop' => [ 'label' => __( 'Location 1', 'sureforms' ), 'size_units' => [ '%' ], 'responsive' => false, 'description' => '', ], 'color_b' => [ 'label' => __( 'Color 2', 'sureforms' ), 'default' => '#C7CBFF', ], 'color_b_stop' => [ 'label' => __( 'Location 2', 'sureforms' ), 'size_units' => [ '%' ], 'responsive' => false, 'description' => '', ], 'gradient_type' => [], 'gradient_angle' => [ 'label' => __( 'Angle', 'sureforms' ), 'size_units' => [ 'deg' ], 'responsive' => false, 'description' => '', ], // Hide position control - use 'center center' as default for radial gradients. 'gradient_position' => [ 'default' => 'center center', 'type' => \Elementor\Controls_Manager::HIDDEN, ], ], 'selector' => '{{WRAPPER}} .srfm-gradient-dummy-selector', // Dummy selector - we handle styling via CSS variables. 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'gradient', ], ] ); // Background Image. $this->add_control( 'bgImage', [ 'label' => __( 'Image', 'sureforms' ), 'type' => \Elementor\Controls_Manager::MEDIA, 'default' => [ 'url' => '', ], 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'image', ], ] ); // Background Image Size. $this->add_control( 'bgImageSize', [ 'label' => __( 'Size', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'cover', 'options' => [ 'cover' => __( 'Cover', 'sureforms' ), 'contain' => __( 'Contain', 'sureforms' ), 'auto' => __( 'Auto', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'image', ], ] ); // Background Image Position. $this->add_control( 'bgImagePosition', [ 'label' => __( 'Position', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'center center', 'options' => [ 'left top' => __( 'Left Top', 'sureforms' ), 'left center' => __( 'Left Center', 'sureforms' ), 'left bottom' => __( 'Left Bottom', 'sureforms' ), 'center top' => __( 'Center Top', 'sureforms' ), 'center center' => __( 'Center Center', 'sureforms' ), 'center bottom' => __( 'Center Bottom', 'sureforms' ), 'right top' => __( 'Right Top', 'sureforms' ), 'right center' => __( 'Right Center', 'sureforms' ), 'right bottom' => __( 'Right Bottom', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'image', ], ] ); // Background Image Repeat. $this->add_control( 'bgImageRepeat', [ 'label' => __( 'Repeat', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'no-repeat', 'options' => [ 'no-repeat' => __( 'No Repeat', 'sureforms' ), 'repeat' => __( 'Repeat', 'sureforms' ), 'repeat-x' => __( 'Repeat X', 'sureforms' ), 'repeat-y' => __( 'Repeat Y', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'image', ], ] ); // Background Image Attachment. $this->add_control( 'bgImageAttachment', [ 'label' => __( 'Attachment', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'scroll', 'options' => [ 'scroll' => __( 'Scroll', 'sureforms' ), 'fixed' => __( 'Fixed', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'inherit', 'bgType' => 'image', ], ] ); /** * Hook for Pro to add advanced styling controls. * * @param \Elementor\Widget_Base $widget The widget instance. * @since 2.7.0 */ do_action( 'srfm_elementor_after_basic_styling_controls', $this ); $this->end_controls_section(); // Style Tab - Layout Section. $this->start_controls_section( 'srfm_layout_section', [ 'label' => __( 'Layout', 'sureforms' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => [ 'srfm_form_block!' => '', 'formTheme!' => 'inherit', ], ] ); // Form Padding. $this->add_control( 'formPadding', [ 'label' => __( 'Form Padding', 'sureforms' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em' ], 'default' => [ 'top' => '0', 'right' => '0', 'bottom' => '0', 'left' => '0', 'unit' => 'px', 'isLinked' => true, ], 'separator' => 'after', ] ); // Form Border Radius. $this->add_control( 'formBorderRadius', [ 'label' => __( 'Form Border Radius', 'sureforms' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em' ], 'default' => [ 'top' => '0', 'right' => '0', 'bottom' => '0', 'left' => '0', 'unit' => 'px', 'isLinked' => true, ], ] ); /** * Hook for Pro to add additional layout controls. * * @param \Elementor\Widget_Base $widget The widget instance. * @since 2.7.0 */ do_action( 'srfm_elementor_layout_controls', $this ); $this->end_controls_section(); // Style Tab - Button Section. $this->start_controls_section( 'srfm_button_section', [ 'label' => __( 'Button', 'sureforms' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => [ 'srfm_form_block!' => '', 'formTheme!' => 'inherit', ], ] ); // Button Alignment. $this->add_control( 'buttonAlignment', [ 'label' => __( 'Alignment', 'sureforms' ), 'type' => \Elementor\Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => __( 'Left', 'sureforms' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => __( 'Center', 'sureforms' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => __( 'Right', 'sureforms' ), 'icon' => 'eicon-text-align-right', ], 'justify' => [ 'title' => __( 'Full Width', 'sureforms' ), 'icon' => 'eicon-text-align-justify', ], ], 'default' => '', 'toggle' => true, ] ); /** * Hook for Pro to add additional button controls. * * @param \Elementor\Widget_Base $widget The widget instance. * @since 2.7.0 */ do_action( 'srfm_elementor_button_controls', $this ); $this->end_controls_section(); // Style Tab - Fields Section. $this->start_controls_section( 'srfm_field_section', [ 'label' => __( 'Fields', 'sureforms' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => [ 'srfm_form_block!' => '', 'formTheme!' => 'inherit', ], ] ); // Field Spacing. // Hidden when custom theme is selected (Pro provides Row Gap/Column Gap controls). $this->add_control( 'fieldSpacing', [ 'label' => __( 'Field Spacing', 'sureforms' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'medium', 'options' => [ 'small' => __( 'Small', 'sureforms' ), 'medium' => __( 'Medium', 'sureforms' ), 'large' => __( 'Large', 'sureforms' ), ], 'condition' => [ 'formTheme!' => 'custom', ], ] ); /** * Hook for Pro to add additional field controls. * * @param \Elementor\Widget_Base $widget The widget instance. * @since 2.7.0 */ do_action( 'srfm_elementor_field_controls', $this ); $this->end_controls_section(); /** * Hook for Pro to add additional style sections. * * @param \Elementor\Widget_Base $widget The widget instance. * @since 2.7.0 */ do_action( 'srfm_elementor_after_styling_section', $this ); } /** * Render form widget output on the frontend. * * @since 0.0.5 * @return void|string */ protected function render() { $settings = $this->get_settings_for_display(); if ( ! is_array( $settings ) ) { return; } $is_editor = Plugin::instance()->editor->is_edit_mode(); $form_id = intval( $settings['srfm_form_block'] ?? 0 ); // Show placeholder in editor when no form selected. if ( $is_editor && empty( $form_id ) ) { ?> <div style="background: #D9DEE1; color: #9DA5AE; padding: 10px; font-family: Roboto, sans-serif"> <?php echo esc_html__( 'Select the form that you wish to add here.', 'sureforms' ); ?> </div> <?php return; } // Validation: Same as shortcode for backward compatibility. $form = get_post( $form_id ); if ( empty( $form_id ) || ! $form || ! in_array( $form->post_status, [ 'publish', 'protected' ], true ) ) { echo esc_html__( 'This form has been deleted or is unavailable.', 'sureforms' ); return; } $show_title = 'true' === ( $settings['srfm_show_form_title'] ?? '' ); // Build block_attrs from widget settings. $block_attrs = $this->get_block_attrs( $settings ); // Bypass shortcode - call get_form_markup() directly. // $do_blocks = true to match current shortcode behavior. // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped in Generate_Form_Markup. echo Generate_Form_Markup::get_form_markup( $form_id, ! $show_title, '', 'post', true, $block_attrs ); // Get spectra blocks and add css and js. $blocks = parse_blocks( get_post_field( 'post_content', $form_id ) ); $styles = Spec_Gb_Helper::get_instance()->get_assets( $blocks ); ?> <style><?php echo $styles['css']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></style> <script><?php echo $styles['js']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></script> <?php } /** * Convert widget settings to block_attrs array. * Uses same camelCase keys as Gutenberg for code reuse. * * @param array<string, mixed> $settings Widget settings. * @return array<string, mixed> Block attributes. * @since 2.7.0 */ protected function get_block_attrs( $settings ) { $block_attrs = [ 'blockId' => 'elementor-' . $this->get_id(), ]; // Check form theme — if inheriting, don't pass any custom styling attributes. $form_theme = $settings['formTheme'] ?? 'inherit'; $block_attrs['formTheme'] = $form_theme; if ( 'inherit' === $form_theme ) { return $block_attrs; } // Color controls that support Elementor Global Colors. $color_keys = [ 'primaryColor', 'textColor', 'textOnPrimaryColor', 'bgColor', ]; foreach ( $color_keys as $key ) { $color_value = self::get_resolved_color( $settings, $key ); if ( $color_value ) { $block_attrs[ $key ] = $color_value; } } // Non-color styling keys to pass through (camelCase). $styling_keys = [ 'fieldSpacing', 'buttonAlignment', // Background (non-color). 'bgType', 'bgImageSize', 'bgImagePosition', 'bgImageRepeat', 'bgImageAttachment', ]; foreach ( $styling_keys as $key ) { if ( isset( $settings[ $key ] ) && '' !== $settings[ $key ] && 'default' !== $settings[ $key ] ) { $block_attrs[ $key ] = $settings[ $key ]; } } // Build gradient CSS string from Group_Control_Background settings. // Use get_settings() (raw) instead of get_settings_for_display() because Elementor // nullifies group control child fields when the parent 'background' type field // is not explicitly saved (it uses our default 'gradient' but doesn't persist it). if ( 'gradient' === ( $settings['bgType'] ?? '' ) ) { /** Raw widget settings. * * @var array<string, mixed> $raw_settings */ $raw_settings = $this->get_settings(); $gradient_css = self::build_gradient_css( $raw_settings ); if ( $gradient_css ) { $block_attrs['bgGradient'] = $gradient_css; } } // Handle DIMENSIONS controls - map to individual camelCase keys for Gutenberg compatibility. $block_attrs = self::map_elementor_dimensions( $block_attrs, $settings, 'formPadding' ); $block_attrs = self::map_elementor_dimensions( $block_attrs, $settings, 'formBorderRadius' ); // Handle bgImage separately as it returns an object from Elementor. $bg_image = isset( $settings['bgImage'] ) && is_array( $settings['bgImage'] ) ? $settings['bgImage'] : []; if ( ! empty( $bg_image['url'] ) ) { $raw_url = esc_url_raw( $bg_image['url'] ); // Encode parentheses to prevent CSS injection in url() context. $block_attrs['bgImage'] = str_replace( [ '(', ')' ], [ '%28', '%29' ], $raw_url ); } if ( ! empty( $bg_image['id'] ) ) { $block_attrs['bgImageId'] = $bg_image['id']; } /** * Filters the Elementor block attributes after sanitization. * * Third-party code hooking this filter is responsible for sanitizing * any values it adds or modifies. Unsanitized values may be output * directly into CSS custom properties. * * Uses get_settings() (raw) instead of get_settings_for_display() because Elementor * nullifies Group_Control_Background child fields when the parent 'background' type * field is not explicitly saved (defaults aren't persisted to the database). * * @param array<string, mixed> $block_attrs Block attributes. * @param array<string, mixed> $settings Raw widget settings. * @since 2.7.0 */ /** Raw widget settings for filter. * * @var array<string, mixed> $raw_settings_for_filter */ $raw_settings_for_filter = $this->get_settings(); return apply_filters( 'srfm_elementor_block_attrs', $block_attrs, $raw_settings_for_filter ); } /** * Map Elementor dimensions control to individual camelCase block attributes. * * Elementor returns dimensions as an array with top/right/bottom/left/unit keys. * This maps them to individual keys like formPaddingTop, formPaddingRight, etc. * * @param array<string, mixed> $block_attrs Block attributes. * @param array<string, mixed> $settings Widget settings. * @param string $control_key The Elementor dimensions control key (e.g., 'formPadding'). * @return array<string, mixed> Updated block attributes. * @since 2.7.0 */ private static function map_elementor_dimensions( $block_attrs, $settings, $control_key ) { if ( empty( $settings[ $control_key ] ) || ! is_array( $settings[ $control_key ] ) ) { return $block_attrs; } $dimensions = $settings[ $control_key ]; $allowed_units = [ 'px', '%', 'em' ]; $raw_unit = $dimensions['unit'] ?? 'px'; $unit = in_array( $raw_unit, $allowed_units, true ) ? $raw_unit : 'px'; $sides = [ 'top', 'right', 'bottom', 'left' ]; foreach ( $sides as $side ) { if ( ! isset( $dimensions[ $side ] ) ) { continue; } if ( ! empty( $dimensions[ $side ] ) || '0' === $dimensions[ $side ] ) { $block_attrs[ $control_key . ucfirst( $side ) ] = $dimensions[ $side ]; } } $block_attrs[ $control_key . 'Unit' ] = $unit; return $block_attrs; } }
Save
Back