'OR', 'groups' => [], ]; } $sanitized = [ 'logic' => in_array( $meta_value['logic'] ?? 'OR', [ 'AND', 'OR' ], true ) ? $meta_value['logic'] : 'OR', 'groups' => [], ]; if ( isset( $meta_value['groups'] ) && is_array( $meta_value['groups'] ) ) { foreach ( $meta_value['groups'] as $group ) { if ( ! is_array( $group ) ) { continue; } $sanitized_group = [ 'logic' => in_array( $group['logic'] ?? 'AND', [ 'AND', 'OR' ], true ) ? $group['logic'] : 'AND', 'conditions' => [], ]; if ( isset( $group['conditions'] ) && is_array( $group['conditions'] ) ) { foreach ( $group['conditions'] as $condition ) { if ( ! is_array( $condition ) ) { continue; } $sanitized_condition = [ 'type' => sanitize_text_field( $condition['type'] ?? '' ), 'rule' => sanitize_text_field( $condition['rule'] ?? '' ), 'operator' => sanitize_text_field( $condition['operator'] ?? '' ), 'value' => $this->sanitize_condition_value( $condition ), ]; $sanitized_group['conditions'][] = $sanitized_condition; } } $sanitized['groups'][] = $sanitized_group; } } return $sanitized; } /** * Sanitize condition value - handles custom field two-part values and arrays * * @param array $condition The condition array. * @return string|array */ private function sanitize_condition_value( $condition ) { $value = $condition['value'] ?? ''; if ( empty( $value ) ) { return ''; } // Handle array values for multi-select operators. if ( is_array( $value ) ) { // Filter out empty values to improve data quality. return array_filter( array_map( 'sanitize_text_field', $value ) ); } // Try to decode JSON array. $decoded = json_decode( $value, true ); if ( is_array( $decoded ) ) { // Filter out empty values to improve data quality. return wp_json_encode( array_filter( array_map( 'sanitize_text_field', $decoded ) ) ); } // Extended condition types support. $is_custom_field = ( 'custom' === ( $condition['rule'] ?? '' ) ) && in_array( $condition['type'] ?? '', [ 'post_meta', 'user_meta', 'query_arg', 'referrer', 'cookie', 'options' ], true ); if ( $is_custom_field && false !== strpos( $value, '|' ) ) { $parts = explode( '|', $value, 2 ); $field_name = sanitize_text_field( $parts[0] ); $comparison_value = sanitize_text_field( $parts[1] ?? '' ); // Rebuild the value with sanitized parts. return $field_name . '|' . $comparison_value; } return sanitize_text_field( $value ); } /** * Get all available condition types. * * @return array */ public static function get_condition_types() { // Ensure conditions are registered if called early. if ( empty( GenerateBlocks_Pro_Conditions_Registry::get_all() ) && did_action( 'init' ) ) { self::get_instance()->register_core_conditions(); } $types = GenerateBlocks_Pro_Conditions_Registry::get_all(); // Format for backward compatibility. $formatted = []; foreach ( $types as $key => $type ) { $formatted[ $key ] = [ 'label' => $type['label'], 'class' => $type['class'], 'operators' => $type['operators'], ]; } return apply_filters( 'generateblocks_condition_types', $formatted ); } /** * Get rules for a specific condition type. * * @param string $type The condition type. * @return array */ public static function get_condition_rules( $type = '' ) { // Ensure conditions are registered if called early. if ( empty( GenerateBlocks_Pro_Conditions_Registry::get_all() ) && did_action( 'init' ) ) { self::get_instance()->register_core_conditions(); } $instance = GenerateBlocks_Pro_Conditions_Registry::get_instance( $type ); if ( ! $instance ) { return []; } $rules = $instance->get_rules(); return apply_filters( 'generateblocks_condition_rules', $rules, $type ); } /** * Get location rules (from your existing system). * * @return array */ private static function get_location_rules() { $rules = [ 'general:site' => __( 'Entire Site', 'generateblocks-pro' ), 'general:front_page' => __( 'Front Page', 'generateblocks-pro' ), 'general:blog' => __( 'Blog', 'generateblocks-pro' ), 'general:singular' => __( 'All Singular', 'generateblocks-pro' ), 'general:archive' => __( 'All Archives', 'generateblocks-pro' ), 'general:author' => __( 'Author Archives', 'generateblocks-pro' ), 'general:date' => __( 'Date Archives', 'generateblocks-pro' ), 'general:search' => __( 'Search Results', 'generateblocks-pro' ), 'general:404' => __( '404 Template', 'generateblocks-pro' ), ]; // Add post types. $post_types = get_post_types( [ 'public' => true ], 'objects' ); foreach ( $post_types as $post_type_slug => $post_type ) { $rules[ 'post:' . $post_type_slug ] = $post_type->labels->singular_name; if ( $post_type->has_archive ) { // translators: %s is the singular name of the post type. $rules[ 'archive:' . $post_type_slug ] = sprintf( __( '%s Archive', 'generateblocks-pro' ), $post_type->labels->singular_name ); } } return $rules; } /** * Get user role rules. * * @return array */ private static function get_user_role_rules() { $rules = [ 'general:all' => __( 'All Users', 'generateblocks-pro' ), 'general:logged_in' => __( 'Logged In', 'generateblocks-pro' ), 'general:logged_out' => __( 'Logged Out', 'generateblocks-pro' ), ]; if ( function_exists( 'get_editable_roles' ) ) { $roles = get_editable_roles(); foreach ( $roles as $slug => $data ) { $rules[ $slug ] = $data['name']; } } return $rules; } /** * Get metadata for a specific rule. * * @param string $type The condition type. * @param string $rule The rule key. * @return array */ public static function get_rule_metadata( $type, $rule ) { // Ensure conditions are registered if called early. if ( empty( GenerateBlocks_Pro_Conditions_Registry::get_all() ) && did_action( 'init' ) ) { self::get_instance()->register_core_conditions(); } $instance = GenerateBlocks_Pro_Conditions_Registry::get_instance( $type ); if ( ! $instance ) { return [ 'needs_value' => true, 'value_type' => 'text', 'supports_multi' => false, ]; } $metadata = $instance->get_rule_metadata( $rule ); return apply_filters( 'generateblocks_rule_metadata', $metadata, $type, $rule ); } /** * Main function to determine if conditions are met. * * @param array $conditions The conditions array. * @param array $context Optional context data (e.g., post_id for loop context). * @return bool */ public static function show( $conditions, $context = [] ) { if ( empty( $conditions ) || empty( $conditions['groups'] ) ) { return true; } $group_results = []; foreach ( $conditions['groups'] as $group ) { if ( empty( $group['conditions'] ) ) { $group_results[] = true; continue; } $condition_results = []; foreach ( $group['conditions'] as $condition ) { $condition_results[] = self::evaluate_single_condition( $condition, $context ); } // Apply group logic (AND/OR within group). if ( 'OR' === $group['logic'] ) { $group_results[] = in_array( true, $condition_results, true ); } else { $group_results[] = ! in_array( false, $condition_results, true ); } } // Apply top-level logic to combine group results. $top_logic = $conditions['logic'] ?? 'OR'; if ( 'AND' === $top_logic ) { return ! in_array( false, $group_results, true ); } else { return in_array( true, $group_results, true ); } } /** * Evaluate a single condition. * * @param array $condition The condition to evaluate. * @param array $context Optional context data (e.g., post_id for loop context). * @return bool */ private static function evaluate_single_condition( $condition, $context = [] ) { // Ensure conditions are registered. if ( empty( GenerateBlocks_Pro_Conditions_Registry::get_all() ) && did_action( 'init' ) ) { self::get_instance()->register_core_conditions(); } if ( empty( $condition['type'] ) || empty( $condition['rule'] ) || empty( $condition['operator'] ) ) { return false; } return GenerateBlocks_Pro_Conditions_Registry::evaluate( $condition['type'], $condition['rule'], $condition['operator'], $condition['value'] ?? '', $context // Pass context through to conditions. ); } } // Initialize the singleton instance. GenerateBlocks_Pro_Conditions::get_instance()->init();