start_controls_section( 'eppro_conditions_section', [ 'label' => EPPRO_Elementor_Helper::panel_label( __( 'Visibility Conditions', 'admore-widgets-suite' ) ), 'tab' => \Elementor\Controls_Manager::TAB_ADVANCED, ] ); $element->add_control( 'eppro_conditions_enable', [ 'label' => __( 'Enable Conditions', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', ] ); // ── Login Status ────────────────────────────────────────────────────── $element->add_control( 'eppro_cond_login_heading', [ 'label' => __( 'Login Status', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_login', [ 'label' => __( 'Show If', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'always', 'options' => [ 'always' => __( 'Always', 'admore-widgets-suite' ), 'logged_in' => __( 'Logged In', 'admore-widgets-suite' ), 'logged_out' => __( 'Logged Out', 'admore-widgets-suite' ), ], 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); // ── User Role ───────────────────────────────────────────────────────── $element->add_control( 'eppro_cond_role', [ 'label' => __( 'Required Role (leave blank = any)', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::SELECT2, 'multiple' => true, 'options' => self::get_roles(), 'condition' => [ 'eppro_conditions_enable' => 'yes', 'eppro_cond_login' => 'logged_in' ], ] ); // ── Date Range ──────────────────────────────────────────────────────── $element->add_control( 'eppro_cond_date_heading', [ 'label' => __( 'Date / Time Range', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_date_start', [ 'label' => __( 'Start (YYYY-MM-DD HH:MM)', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::DATE_TIME, 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_date_end', [ 'label' => __( 'End (YYYY-MM-DD HH:MM)', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::DATE_TIME, 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); // ── Device ──────────────────────────────────────────────────────────── $element->add_control( 'eppro_cond_device_heading', [ 'label' => __( 'Device', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_devices', [ 'label' => __( 'Show On', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::SELECT2, 'multiple' => true, 'default' => [ 'desktop', 'tablet', 'mobile' ], 'options' => [ 'desktop' => __( 'Desktop', 'admore-widgets-suite' ), 'tablet' => __( 'Tablet', 'admore-widgets-suite' ), 'mobile' => __( 'Mobile', 'admore-widgets-suite' ), ], 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); // ── URL Parameter ───────────────────────────────────────────────────── $element->add_control( 'eppro_cond_url_heading', [ 'label' => __( 'URL Parameter', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_url_param_key', [ 'label' => __( 'Parameter Name', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => 'utm_source', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_url_param_value', [ 'label' => __( 'Parameter Value (blank = just exists)', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::TEXT, 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); // ── Referrer ────────────────────────────────────────────────────────── $element->add_control( 'eppro_cond_referrer_heading', [ 'label' => __( 'Referrer', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->add_control( 'eppro_cond_referrer', [ 'label' => __( 'Referrer Contains', 'admore-widgets-suite' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => 'google.com', 'condition' => [ 'eppro_conditions_enable' => 'yes' ], ] ); $element->end_controls_section(); } // ========================================================================= // Evaluate & Hide // ========================================================================= /** * @param bool $should_render Current decision. * @param mixed $element The Elementor element being rendered. */ public static function should_render( $should_render, $element ) { if ( ! $should_render || ! $element instanceof \Elementor\Controls_Stack ) { return $should_render; } // Cheap raw check first; most elements do not use conditions. if ( 'yes' !== $element->get_settings( 'eppro_conditions_enable' ) ) { return $should_render; } // Keep every element visible (and selectable) while editing. if ( self::is_editing() ) { return $should_render; } return self::passes_all( $element->get_settings_for_display() ); } private static function is_editing(): bool { if ( ! class_exists( '\Elementor\Plugin' ) ) return false; $elementor = \Elementor\Plugin::$instance; if ( isset( $elementor->editor ) && $elementor->editor->is_edit_mode() ) return true; if ( isset( $elementor->preview ) && $elementor->preview->is_preview_mode() ) return true; return false; } /** Parse an Elementor DATE_TIME value in the site's timezone. */ private static function to_timestamp( string $value ): int { $value = trim( $value ); if ( '' === $value ) return 0; try { return ( new \DateTimeImmutable( $value, wp_timezone() ) )->getTimestamp(); } catch ( \Exception $e ) { return 0; } } // ========================================================================= // Condition Evaluators // ========================================================================= private static function passes_all( array $s ): bool { // Login status $login_rule = $s['eppro_cond_login'] ?? 'always'; if ( 'logged_in' === $login_rule && ! is_user_logged_in() ) return false; if ( 'logged_out' === $login_rule && is_user_logged_in() ) return false; // User role $roles = $s['eppro_cond_role'] ?? []; if ( 'logged_in' === $login_rule && ! empty( $roles ) ) { $user = wp_get_current_user(); if ( empty( array_intersect( (array) $user->roles, (array) $roles ) ) ) return false; } // Date range — the editor stores local site time, so parse it in the site timezone. $now = time(); $start = self::to_timestamp( (string) ( $s['eppro_cond_date_start'] ?? '' ) ); if ( $start && $now < $start ) return false; $end = self::to_timestamp( (string) ( $s['eppro_cond_date_end'] ?? '' ) ); if ( $end && $now > $end ) return false; // Device (based on UA) $devices = $s['eppro_cond_devices'] ?? [ 'desktop', 'tablet', 'mobile' ]; if ( ! empty( $devices ) && ! in_array( self::detect_device(), (array) $devices, true ) ) return false; // URL parameter (read-only visibility check on a public page view — no nonce by design). $param_key = sanitize_key( $s['eppro_cond_url_param_key'] ?? '' ); if ( ! empty( $param_key ) ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_GET[ $param_key ] ) ) return false; $param_val = $s['eppro_cond_url_param_value'] ?? ''; if ( '' !== $param_val && sanitize_text_field( wp_unslash( $_GET[ $param_key ] ) ) !== $param_val ) return false; // phpcs:enable WordPress.Security.NonceVerification.Recommended } // Referrer $ref_match = sanitize_text_field( $s['eppro_cond_referrer'] ?? '' ); if ( ! empty( $ref_match ) ) { $referrer = sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ?? '' ) ); if ( strpos( $referrer, $ref_match ) === false ) return false; } return true; } // ========================================================================= // Helpers // ========================================================================= private static function detect_device(): string { $ua = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ); if ( preg_match( '/Mobile|Android.*Mobile|iPhone|iPod|Windows Phone/i', $ua ) ) return 'mobile'; if ( preg_match( '/iPad|Android|Tablet/i', $ua ) ) return 'tablet'; return 'desktop'; } private static function get_roles(): array { $options = []; foreach ( wp_roles()->roles as $slug => $role ) { $options[ $slug ] = translate_user_role( $role['name'] ); } return $options; } }