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 inputnumber: numeric inputdatetime: date/time pickertime: time pickerobject_selector: post/term searchhierarchical_object_selector: parent/child postsday_selector: day of the week pickercustom_field: field name + comparison valuenone: 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));
}