GeneratePress AI is here - Read the release post

Learn GeneratePress

Developers

Conditions

This documentation provides a comprehensive guide for both users creating conditions and developers extending the system. The modular architecture makes it easy to add new condition types while maintaining consistency and performance.

For a shorter walk-through of building a condition type, see Registering conditions. For the hooks and the rule filters of the built-in types, see Conditions: registering types and rules and Conditions: built-in rule filters.

Architecture Overview

The Conditions system uses a modular, interface-based architecture:

// Core Interface
interface GenerateBlocks_Pro_Condition_Interface {
    public function evaluate($rule, $operator, $value, $context = []);
    public function get_rules();
    public function get_rule_metadata($rule);
    public function get_operators_for_rule($rule);
    public function sanitize_value($value, $rule);
}

// Registry Pattern
GenerateBlocks_Pro_Conditions_Registry::register($type, $args, $classname);

// Evaluation
$result = GenerateBlocks_Pro_Conditions::show($conditions);

Data Structure

Conditions are stored as post meta in JSON format:

{
  "logic": "OR",
  "groups": [
    {
      "logic": "AND",
      "conditions": [
        {
          "type": "location",
          "rule": "post:page",
          "operator": "is",
          "value": "123"
        }
      ]
    }
  ]
}

Creating Custom Condition Types

Step 1: Create the Condition Class

class My_Custom_Condition extends GenerateBlocks_Pro_Condition_Abstract {
    
    public function evaluate($rule, $operator, $value, $context = []) {
        // Your evaluation logic here
        switch ($rule) {
            case 'my_rule':
                return $this->check_my_condition($operator, $value);
            default:
                return false;
        }
    }
    
    public function get_rules() {
        return [
            'my_rule' => __('My Custom Rule', 'textdomain'),
        ];
    }
    
    public function get_rule_metadata($rule) {
        return [
            'needs_value' => true,
            'value_type' => 'text',
            'supports_multi' => false,
        ];
    }
    
    private function check_my_condition($operator, $value) {
        // Implement your condition logic
        // get_current_value() is your own helper that returns the value to compare.
        $current_value = $this->get_current_value();
        
        switch ($operator) {
            case 'equals':
                return $current_value === $value;
            case 'contains':
                return false !== strpos($current_value, $value);
            default:
                return false;
        }
    }
}

Step 2: Register the Condition Type

add_action('generateblocks_register_conditions', function() {
    GenerateBlocks_Pro_Conditions_Registry::register(
        'my_custom_type',
        [
            'label' => __('My Custom Type', 'textdomain'),
            'operators' => ['equals', 'contains', 'is', 'is_not'],
            'priority' => 100,
        ],
        'My_Custom_Condition'
    );
});

Rule metadata options

Control how your condition appears in the UI:

public function get_rule_metadata($rule) {
    return [
        'needs_value' => true,                    // Show value field
        'value_type' => 'text',                   // Input type
        'supports_multi' => false,                // Multi-select support
    ];
}

Value Types

  • text : simple text input
  • number : numeric input
  • datetime : date/time picker
  • time : time picker
  • object_selector : post/term search
  • hierarchical_object_selector : parent/child posts
  • day_selector : day of the week picker
  • custom_field : field name + comparison value
  • none : no value required

Advanced Features

Multi-Value Support

Enable multi-select for your conditions:

public function get_rule_metadata($rule) {
    return [
        'needs_value' => true,
        'value_type' => 'object_selector',
        'supports_multi' => true, // Enables multi-select
    ];
}

public function get_operators_for_rule($rule) {
    if ($this->rule_supports_multi_select($rule)) {
        return ['includes_any', 'includes_all', 'excludes_any', 'excludes_all'];
    }
    return ['is', 'is_not'];
}

Context-Aware Evaluation

Pass context data to evaluations:

$context = [
    'post_id' => get_the_ID(),
    'user_id' => get_current_user_id(),
    'custom_data' => $my_data,
];

$result = GenerateBlocks_Pro_Conditions_Registry::evaluate(
    $type, $rule, $operator, $value, $context
);

REST API Integrations

Custom Endpoints

add_action('rest_api_init', function() {
    register_rest_route('generateblocks-pro/advanced-conditions/v1', 
        '/search_my_objects/', [
        'methods' => 'GET',
        'callback' => 'my_search_callback',
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        },
        'args' => [
            'search' => [
                'required' => false,
                'type' => 'string',
                'sanitize_callback' => 'sanitize_text_field',
            ],
        ],
    ]);
});

function my_search_callback($request) {
    $search = $request->get_param('search');
    
    // Your search logic here
    $results = [];
    
    return new WP_REST_Response([
        'success' => true,
        'response' => $results,
    ], 200);
}

Performance Optimization

Caching

The system automatically caches evaluation results:

// Cached automatically for current request
$result = GenerateBlocks_Pro_Conditions_Registry::evaluate(
    $type, $rule, $operator, $value, $context
);

Efficient Queries

Use efficient database queries in your conditions:

// Avoid: Multiple database calls in loops
foreach ($posts as $post) {
    $meta = get_post_meta($post->ID, $meta_key, true); // Bad
}

Testing

Unit Testing

class Test_My_Condition extends WP_UnitTestCase {
    
    public function test_condition_evaluation() {
        $condition = new My_Custom_Condition();
        
        $result = $condition->evaluate('my_rule', 'equals', 'test_value');
        
        $this->assertTrue($result);
    }
    
    public function test_rule_metadata() {
        $condition = new My_Custom_Condition();
        
        $metadata = $condition->get_rule_metadata('my_rule');
        
        $this->assertEquals('text', $metadata['value_type']);
    }
}

Registry Testing

public function test_condition_registration() {
    // Reset for testing
    GenerateBlocks_Pro_Conditions_Registry::reset_for_testing();
    
    // Register condition
    GenerateBlocks_Pro_Conditions_Registry::register(
        'test_type',
        ['label' => 'Test'],
        'My_Custom_Condition'
    );
    
    // Test registration
    $types = GenerateBlocks_Pro_Conditions_Registry::get_all();
    $this->assertArrayHasKey('test_type', $types);
}

Security Considerations

Input Sanitization

Always sanitize user input:

public function sanitize_value($value, $rule) {
    if ('custom' === $rule) {
        return $this->sanitize_custom_value($value);
    }
    
    if (is_array($value)) {
        return array_map('sanitize_text_field', $value);
    }
    
    return sanitize_text_field($value);
}

Permission Checks

Verify user capabilities:

public function edit_posts_permission() {
    return current_user_can('edit_posts');
}

Nonce Verification

REST API automatically handles nonces, but for custom forms:

if (!wp_verify_nonce($_POST['nonce'], 'my_condition_action')) {
    wp_die('Security check failed');
}

Hooks and Filters

Available Filters

// Modify condition types
add_filter('generateblocks_condition_types', function($types) {
    // Modify $types array
    return $types;
});

// Modify condition rules
add_filter('generateblocks_condition_rules', function($rules, $type) {
    // Modify $rules array
    return $rules;
}, 10, 2);

// Modify rule metadata
add_filter('generateblocks_rule_metadata', function($metadata, $type, $rule) {
    // Modify $metadata array
    return $metadata;
}, 10, 3);

Available Actions

// Register custom conditions
add_action('generateblocks_register_conditions', function() {
    // Register your conditions here
});

Debugging

Logging

Add logging to your conditions:

if (defined('WP_DEBUG') && WP_DEBUG) {
    error_log('Condition evaluation: ' . print_r($result, true));
}