WordPress Filters
Flowguard provides filter hooks that allow developers to modify data and behavior before it's processed.
Overview
Filters are WordPress hooks that let you modify data as it passes through Flowguard. Unlike actions (which execute code), filters transform data and return modified values.
Use filters to:
- Modify flow data before execution
- Customize default settings
- Transform step configurations
- Add custom validation
- Integrate with other systems
Available Filters
flowguard_flow_data
Modifies flow data before it's sent for execution.
Hook Name: flowguard_flow_data
Parameters:
| Parameter | Type | Description |
|---|---|---|
$flow_data | array | Complete flow data |
$flow_id | int | The flow post ID |
Flow Data Structure:
$flow_data = [
'id' => 123,
'title' => 'Login Test Flow',
'steps' => [
[
'id' => 'step_1',
'type' => 'navigate',
'config' => [
'url' => 'https://yoursite.com/login'
]
],
// ... more steps
],
'settings' => [
'timeout' => 30000,
'retries' => 0,
'screenshot' => true,
],
'siteUrl' => 'https://yoursite.com',
];Return Value: Modified $flow_data array
Example Usage:
/**
* Add custom headers to all flows
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['headers'] = [
'X-Flow-ID' => $flow_id,
'X-Site-ID' => get_current_blog_id(),
];
return $flow_data;
}, 10, 2);Use Cases:
1. Add Authentication Tokens
/**
* Add auth token to flows that need it
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Only for flows with "API" in the title
if (strpos($flow_data['title'], 'API') !== false) {
$flow_data['authToken'] = get_option('my_api_token');
}
return $flow_data;
}, 10, 2);2. Modify Timeouts Dynamically
/**
* Increase timeout for slow pages
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'navigate') {
// Double timeout for navigation steps
if (!isset($step['timeout'])) {
$step['timeout'] = $flow_data['settings']['timeout'] * 2;
}
}
}
return $flow_data;
}, 10, 2);3. Add Custom Step Data
/**
* Add metadata to steps
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
foreach ($flow_data['steps'] as &$step) {
$step['metadata'] = [
'flow_id' => $flow_id,
'timestamp' => current_time('c'),
'user_id' => get_current_user_id(),
];
}
return $flow_data;
}, 10, 2);4. Replace URLs for Staging
/**
* Replace production URLs with staging URLs
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$is_staging = defined('WP_ENVIRONMENT_TYPE') && WP_ENVIRONMENT_TYPE === 'staging';
if ($is_staging) {
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'navigate' && isset($step['config']['url'])) {
$step['config']['url'] = str_replace(
'https://production.com',
'https://staging.com',
$step['config']['url']
);
}
}
}
return $flow_data;
}, 10, 2);5. Add Performance Monitoring
/**
* Add performance markers
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['performance'] = [
'enabled' => true,
'track_steps' => true,
'report_url' => 'https://monitor.example.com/api/report',
];
return $flow_data;
}, 10, 2);6. Inject Test Data
/**
* Add test user credentials dynamically
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Find fill steps for username/password
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'fill') {
// Replace placeholder with actual test credentials
if (isset($step['config']['text'])) {
$step['config']['text'] = str_replace(
'{{TEST_USER}}',
get_option('flowguard_test_username'),
$step['config']['text']
);
$step['config']['text'] = str_replace(
'{{TEST_PASS}}',
get_option('flowguard_test_password'),
$step['config']['text']
);
}
}
}
return $flow_data;
}, 10, 2);7. Add Conditional Logic
/**
* Skip certain steps based on conditions
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Skip login steps if already logged in
$is_logged_in = is_user_logged_in();
if ($is_logged_in) {
$flow_data['steps'] = array_filter($flow_data['steps'], function($step) {
return !isset($step['tags']) || !in_array('login', $step['tags']);
});
// Re-index array
$flow_data['steps'] = array_values($flow_data['steps']);
}
return $flow_data;
}, 10, 2);8. Add Custom Validation
/**
* Validate flow data before execution
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Ensure all navigate steps have valid URLs
foreach ($flow_data['steps'] as $step) {
if ($step['type'] === 'navigate') {
$url = $step['config']['url'] ?? '';
if (!filter_var($url, FILTER_VALIDATE_URL)) {
// Log error
error_log("Flowguard: Invalid URL in flow {$flow_id}: {$url}");
// Fix it
$step['config']['url'] = home_url();
}
}
}
return $flow_data;
}, 10, 2);9. Add Environment Variables
/**
* Inject environment-specific configuration
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['environment'] = [
'name' => wp_get_environment_type(),
'debug' => WP_DEBUG,
'multisite' => is_multisite(),
'locale' => get_locale(),
];
return $flow_data;
}, 10, 2);10. Modify Settings Based on Flow Type
/**
* Adjust settings for different flow types
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Critical flows get more retries
if (strpos(strtolower($flow_data['title']), 'critical') !== false) {
$flow_data['settings']['retries'] = 3;
$flow_data['settings']['timeout'] = 60000;
}
// Quick smoke tests run fast
if (strpos(strtolower($flow_data['title']), 'smoke') !== false) {
$flow_data['settings']['timeout'] = 10000;
$flow_data['settings']['screenshot'] = false;
}
return $flow_data;
}, 10, 2);Filter Priority
Filters accept priority and argument count parameters:
add_filter('flowguard_flow_data', 'your_function', $priority, $accepted_args);Default priority: 10
Lower numbers = Earlier execution Higher numbers = Later execution
Example with priority:
// Run first (priority 5) - Set defaults
add_filter('flowguard_flow_data', 'set_flow_defaults', 5, 2);
// Run second (priority 10) - Modify URLs
add_filter('flowguard_flow_data', 'replace_urls', 10, 2);
// Run last (priority 20) - Final validation
add_filter('flowguard_flow_data', 'validate_flow_data', 20, 2);Removing Filters
To remove a previously added filter:
remove_filter('flowguard_flow_data', 'your_function', $priority);Example:
// Add filter
add_filter('flowguard_flow_data', 'modify_data', 10, 2);
// Remove filter later
remove_filter('flowguard_flow_data', 'modify_data', 10);Best Practices
1. Always Return the Data
Filters must return the modified data:
// ✅ Good - Returns modified data
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['custom'] = 'value';
return $flow_data;
}, 10, 2);
// ❌ Bad - Doesn't return anything
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['custom'] = 'value';
// Missing return statement!
}, 10, 2);2. Preserve Data Structure
Don't break the expected data structure:
// ✅ Good - Adds new fields, keeps structure
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
$flow_data['custom_field'] = 'value';
return $flow_data;
}, 10, 2);
// ❌ Bad - Replaces entire array
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
return ['completely' => 'different'];
}, 10, 2);3. Check Existence Before Modifying
Verify data exists before accessing it:
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Check if steps array exists
if (isset($flow_data['steps']) && is_array($flow_data['steps'])) {
foreach ($flow_data['steps'] as &$step) {
// Modify steps safely
}
}
return $flow_data;
}, 10, 2);4. Use Type Checking
Ensure data types are correct:
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Ensure timeout is an integer
if (isset($flow_data['settings']['timeout'])) {
$flow_data['settings']['timeout'] = absint($flow_data['settings']['timeout']);
}
return $flow_data;
}, 10, 2);5. Handle Errors Gracefully
Don't let filters break execution:
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
try {
// Your modifications
$flow_data = apply_custom_logic($flow_data);
} catch (Exception $e) {
error_log('Flowguard filter error: ' . $e->getMessage());
// Return original data on error
}
return $flow_data;
}, 10, 2);6. Document Your Filters
Comment complex filter logic:
/**
* Inject environment-specific URLs into flow navigation steps
*
* Replaces placeholder URLs like {{BASE_URL}} with the actual
* WordPress site URL based on the current environment.
*
* @param array $flow_data Complete flow data
* @param int $flow_id Flow post ID
* @return array Modified flow data
*/
add_filter('flowguard_flow_data', function($flow_data, $flow_id) {
// Implementation
return $flow_data;
}, 10, 2);7. Use Appropriate Priority
Order filters logically based on dependencies:
// Priority 5: Set base configuration
add_filter('flowguard_flow_data', 'set_defaults', 5, 2);
// Priority 10: Apply modifications
add_filter('flowguard_flow_data', 'apply_customizations', 10, 2);
// Priority 15: Final adjustments
add_filter('flowguard_flow_data', 'finalize_data', 15, 2);Complete Example: Dynamic Flow Configuration
Here's a complete example that implements dynamic flow configuration:
<?php
/**
* Flowguard Dynamic Configuration
*/
class Flowguard_Config {
private $config;
public function __construct() {
// Load configuration
$this->config = $this->load_config();
// Add filter
add_filter('flowguard_flow_data', [$this, 'modify_flow_data'], 10, 2);
}
/**
* Load configuration from options
*/
private function load_config() {
return [
'environments' => [
'production' => [
'base_url' => 'https://production.com',
'timeout' => 30000,
],
'staging' => [
'base_url' => 'https://staging.com',
'timeout' => 60000,
],
],
'test_users' => [
'admin' => [
'username' => 'test_admin',
'password' => 'test_pass_123',
],
'customer' => [
'username' => 'test_customer',
'password' => 'test_pass_456',
],
],
];
}
/**
* Modify flow data based on configuration
*/
public function modify_flow_data($flow_data, $flow_id) {
// 1. Replace environment placeholders
$flow_data = $this->replace_placeholders($flow_data);
// 2. Inject test credentials
$flow_data = $this->inject_credentials($flow_data);
// 3. Adjust timeouts
$flow_data = $this->adjust_timeouts($flow_data);
// 4. Add tracking
$flow_data = $this->add_tracking($flow_data, $flow_id);
// 5. Validate
$flow_data = $this->validate($flow_data);
return $flow_data;
}
/**
* Replace environment placeholders
*/
private function replace_placeholders($flow_data) {
$environment = wp_get_environment_type();
$base_url = $this->config['environments'][$environment]['base_url'] ?? home_url();
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'navigate' && isset($step['config']['url'])) {
$step['config']['url'] = str_replace(
'{{BASE_URL}}',
$base_url,
$step['config']['url']
);
}
}
return $flow_data;
}
/**
* Inject test user credentials
*/
private function inject_credentials($flow_data) {
// Detect which user type based on flow title
$user_type = 'customer'; // default
if (stripos($flow_data['title'], 'admin') !== false) {
$user_type = 'admin';
}
$credentials = $this->config['test_users'][$user_type] ?? null;
if (!$credentials) {
return $flow_data;
}
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'fill' && isset($step['config']['text'])) {
$text = $step['config']['text'];
if (strpos($text, '{{USERNAME}}') !== false) {
$step['config']['text'] = $credentials['username'];
}
if (strpos($text, '{{PASSWORD}}') !== false) {
$step['config']['text'] = $credentials['password'];
}
}
}
return $flow_data;
}
/**
* Adjust timeouts based on environment
*/
private function adjust_timeouts($flow_data) {
$environment = wp_get_environment_type();
$timeout = $this->config['environments'][$environment]['timeout'] ?? 30000;
$flow_data['settings']['timeout'] = $timeout;
return $flow_data;
}
/**
* Add tracking information
*/
private function add_tracking($flow_data, $flow_id) {
$flow_data['tracking'] = [
'flow_id' => $flow_id,
'environment' => wp_get_environment_type(),
'timestamp' => current_time('c'),
'user_id' => get_current_user_id(),
'site_id' => get_current_blog_id(),
];
return $flow_data;
}
/**
* Validate flow data
*/
private function validate($flow_data) {
// Ensure all URLs are absolute
foreach ($flow_data['steps'] as &$step) {
if ($step['type'] === 'navigate') {
$url = $step['config']['url'] ?? '';
if ($url && !filter_var($url, FILTER_VALIDATE_URL)) {
error_log("Flowguard: Invalid URL detected: {$url}");
$step['config']['url'] = home_url();
}
}
}
// Ensure timeout is reasonable
$timeout = $flow_data['settings']['timeout'] ?? 30000;
if ($timeout < 1000 || $timeout > 300000) {
error_log('Flowguard: Timeout out of range, using default');
$flow_data['settings']['timeout'] = 30000;
}
return $flow_data;
}
}
// Initialize
new Flowguard_Config();Related Documentation
- WordPress Actions - Execute code at specific points
- REST API - API endpoints
- Flow Editor - Building flows
Future Filters
Additional filters planned for future versions:
flowguard_step_config- Modify individual step configurationflowguard_flow_results- Transform results before savingflowguard_settings_defaults- Change default settingsflowguard_validation_rules- Add custom validationflowguard_timeout_value- Dynamic timeout calculation
Support
For questions about filters:
- Review WordPress Plugin API documentation
- Check the Flowguard source code
- Contact support for assistance