WordPress Actions
Flowguard provides action hooks that allow developers to execute custom code at specific points during flow execution.
Overview
Actions are WordPress hooks that let you run custom functions when certain events occur. Flowguard fires actions before and after flow execution, enabling you to:
- Log execution events
- Send notifications
- Trigger external systems
- Update custom data
- Integrate with other plugins
Available Actions
flowguard_before_flow_run
Fires immediately before a flow begins execution.
Hook Name: flowguard_before_flow_run
Parameters:
| Parameter | Type | Description |
|---|---|---|
$flow_id | int | The flow post ID |
$flow_data | array | Complete flow data being executed |
Flow Data Structure:
$flow_data = [
'id' => 123, // Flow post ID
'title' => 'Login Test Flow', // Flow title
'steps' => [...], // Array of step objects
'settings' => [ // Flow settings
'timeout' => 30000,
'retries' => 0,
'screenshot' => true,
],
'siteUrl' => 'https://yoursite.com',
];Example Usage:
/**
* Log flow execution start
*/
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
error_log(sprintf(
'Flowguard: Starting flow #%d "%s" with %d steps',
$flow_id,
$flow_data['title'],
count($flow_data['steps'])
));
}, 10, 2);Use Cases:
- Logging:
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
// Log to custom table
global $wpdb;
$wpdb->insert('flow_execution_log', [
'flow_id' => $flow_id,
'started_at' => current_time('mysql'),
'status' => 'started',
]);
}, 10, 2);- Notifications:
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
// Send Slack notification
wp_remote_post('https://hooks.slack.com/services/YOUR/WEBHOOK/URL', [
'body' => json_encode([
'text' => "Flow '{$flow_data['title']}' started execution",
]),
]);
}, 10, 2);- Prepare Environment:
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
// Clear caches before testing
wp_cache_flush();
// Set up test data
if (strpos($flow_data['title'], 'Cart Test') !== false) {
// Ensure cart is empty
WC()->cart->empty_cart();
}
}, 10, 2);- Integration with Other Plugins:
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
// Pause maintenance mode during tests
if (function_exists('wp_maintenance_mode')) {
update_option('wp_maintenance_mode', false);
}
}, 10, 2);flowguard_after_flow_run
Fires after a flow completes execution (whether successful or failed).
Hook Name: flowguard_after_flow_run
Parameters:
| Parameter | Type | Description |
|---|---|---|
$flow_id | int | The flow post ID |
$last_run | array | Execution results |
Last Run Structure:
$last_run = [
'timestamp' => '2024-12-06T15:30:00', // ISO 8601 format
'status' => 'passed', // passed, failed, or running
'duration' => 3450, // Execution time in milliseconds
'error' => '', // Error message (if failed)
'results' => [ // Step-by-step results
[
'step' => 1,
'type' => 'navigate',
'status' => 'passed',
'duration' => 1200,
'error' => '',
],
// ... more step results
],
];Example Usage:
/**
* Log flow execution completion
*/
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
error_log(sprintf(
'Flowguard: Flow #%d completed with status "%s" in %dms',
$flow_id,
$last_run['status'],
$last_run['duration']
));
}, 10, 2);Use Cases:
- Email Notifications for Failures:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
if ($last_run['status'] === 'failed') {
$flow = get_post($flow_id);
wp_mail(
'admin@yoursite.com',
'Flowguard: Flow Failed',
sprintf(
"Flow '%s' failed:\n\n%s",
$flow->post_title,
$last_run['error']
)
);
}
}, 10, 2);- Track Statistics:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
// Store execution history
$history = get_option('flowguard_execution_history', []);
$history[] = [
'flow_id' => $flow_id,
'timestamp' => $last_run['timestamp'],
'status' => $last_run['status'],
'duration' => $last_run['duration'],
];
// Keep last 100 executions
if (count($history) > 100) {
$history = array_slice($history, -100);
}
update_option('flowguard_execution_history', $history);
}, 10, 2);- Slack Integration:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
$flow = get_post($flow_id);
$emoji = $last_run['status'] === 'passed' ? ':white_check_mark:' : ':x:';
wp_remote_post('https://hooks.slack.com/services/YOUR/WEBHOOK/URL', [
'body' => json_encode([
'text' => sprintf(
"%s Flow '%s' %s in %.2fs",
$emoji,
$flow->post_title,
$last_run['status'],
$last_run['duration'] / 1000
),
]),
]);
}, 10, 2);- Trigger Remediation:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
if ($last_run['status'] === 'failed') {
// Attempt automatic fix
$flow = get_post($flow_id);
if (strpos($flow->post_title, 'Cache') !== false) {
// Clear all caches if cache-related test failed
wp_cache_flush();
// Optionally re-run the flow
do_action('flowguard_rerun_flow', $flow_id);
}
}
}, 10, 2);- Update External Monitoring:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
// Send to monitoring service (e.g., Datadog, New Relic)
wp_remote_post('https://monitoring-service.com/api/events', [
'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'],
'body' => json_encode([
'event_type' => 'flowguard.execution',
'flow_id' => $flow_id,
'status' => $last_run['status'],
'duration' => $last_run['duration'],
'timestamp' => strtotime($last_run['timestamp']),
]),
]);
}, 10, 2);Action Priority
All Flowguard actions accept priority and argument count parameters:
add_action('flowguard_before_flow_run', 'your_function', $priority, $accepted_args);Default priority: 10
Lower numbers = Earlier execution Higher numbers = Later execution
Example with priority:
// Run this first (priority 5)
add_action('flowguard_before_flow_run', 'setup_test_environment', 5, 2);
// Run this second (priority 10, default)
add_action('flowguard_before_flow_run', 'log_execution', 10, 2);
// Run this last (priority 20)
add_action('flowguard_before_flow_run', 'notify_team', 20, 2);Removing Actions
To remove a previously added action:
remove_action('flowguard_before_flow_run', 'your_function', $priority);Example:
// Add action
add_action('flowguard_after_flow_run', 'send_notification', 10, 2);
// Remove action later
remove_action('flowguard_after_flow_run', 'send_notification', 10);Best Practices
1. Check Flow Context
Filter actions based on flow properties:
add_action('flowguard_before_flow_run', function($flow_id, $flow_data) {
// Only run for production flows
if (strpos($flow_data['title'], '[Production]') !== false) {
// Special handling for production tests
}
}, 10, 2);2. Handle Errors Gracefully
Don't let your action callbacks break flow execution:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
try {
// Your code here
send_notification($flow_id, $last_run);
} catch (Exception $e) {
error_log('Flowguard notification failed: ' . $e->getMessage());
// Don't re-throw - let flow complete
}
}, 10, 2);3. Use Appropriate Priority
Order your actions logically:
- Low priority (5-9): Setup and preparation
- Default priority (10): Main operations
- High priority (11-20): Cleanup and notifications
4. Avoid Heavy Operations
Keep action callbacks fast to not delay execution:
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
// Good: Queue notification for async processing
wp_schedule_single_event(time(), 'send_flow_notification', [$flow_id, $last_run]);
// Bad: Send email synchronously (slow)
// wp_mail('admin@example.com', 'Flow Complete', '...');
}, 10, 2);5. Document Your Hooks
Comment your action callbacks:
/**
* Send Slack notification when critical flows fail
*
* @param int $flow_id Flow post ID
* @param array $last_run Execution results
*/
add_action('flowguard_after_flow_run', function($flow_id, $last_run) {
// Implementation
}, 10, 2);Complete Example: Flow Monitoring System
Here's a complete example that implements comprehensive flow monitoring:
<?php
/**
* Flowguard Custom Monitoring
*/
class Flowguard_Monitor {
public function __construct() {
add_action('flowguard_before_flow_run', [$this, 'before_run'], 10, 2);
add_action('flowguard_after_flow_run', [$this, 'after_run'], 10, 2);
}
/**
* Log flow start
*/
public function before_run($flow_id, $flow_data) {
// Log to database
global $wpdb;
$wpdb->insert('flow_executions', [
'flow_id' => $flow_id,
'flow_title' => $flow_data['title'],
'started_at' => current_time('mysql'),
'status' => 'running',
]);
// Store execution ID for later use
$execution_id = $wpdb->insert_id;
update_post_meta($flow_id, '_current_execution_id', $execution_id);
// Notify team for critical flows
if ($this->is_critical_flow($flow_data)) {
$this->notify_slack("🔄 Critical flow '{$flow_data['title']}' started");
}
}
/**
* Log flow completion
*/
public function after_run($flow_id, $last_run) {
global $wpdb;
// Get execution ID
$execution_id = get_post_meta($flow_id, '_current_execution_id', true);
// Update database
$wpdb->update(
'flow_executions',
[
'status' => $last_run['status'],
'duration' => $last_run['duration'],
'error' => $last_run['error'],
'completed_at' => current_time('mysql'),
],
['id' => $execution_id]
);
// Handle failures
if ($last_run['status'] === 'failed') {
$this->handle_failure($flow_id, $last_run);
}
// Send statistics
$this->update_statistics($flow_id, $last_run);
// Clean up
delete_post_meta($flow_id, '_current_execution_id');
}
/**
* Handle flow failures
*/
private function handle_failure($flow_id, $last_run) {
$flow = get_post($flow_id);
// Email admin
wp_mail(
get_option('admin_email'),
'Flowguard: Flow Failed',
$this->format_failure_email($flow, $last_run)
);
// Notify Slack
$this->notify_slack("❌ Flow '{$flow->post_title}' failed: {$last_run['error']}");
// Increment failure count
$failures = (int) get_post_meta($flow_id, '_failure_count', true);
update_post_meta($flow_id, '_failure_count', $failures + 1);
}
/**
* Update statistics
*/
private function update_statistics($flow_id, $last_run) {
$stats = get_option('flowguard_statistics', [
'total_executions' => 0,
'total_passed' => 0,
'total_failed' => 0,
'total_duration' => 0,
]);
$stats['total_executions']++;
$stats['total_' . $last_run['status']]++;
$stats['total_duration'] += $last_run['duration'];
update_option('flowguard_statistics', $stats);
}
/**
* Check if flow is critical
*/
private function is_critical_flow($flow_data) {
$critical_keywords = ['checkout', 'payment', 'login', 'critical'];
$title_lower = strtolower($flow_data['title']);
foreach ($critical_keywords as $keyword) {
if (strpos($title_lower, $keyword) !== false) {
return true;
}
}
return false;
}
/**
* Send Slack notification
*/
private function notify_slack($message) {
$webhook_url = get_option('flowguard_slack_webhook');
if (!$webhook_url) {
return;
}
wp_remote_post($webhook_url, [
'body' => json_encode(['text' => $message]),
'headers' => ['Content-Type' => 'application/json'],
]);
}
/**
* Format failure email
*/
private function format_failure_email($flow, $last_run) {
return sprintf(
"Flow: %s\n" .
"Status: Failed\n" .
"Duration: %dms\n" .
"Error: %s\n\n" .
"View flow: %s",
$flow->post_title,
$last_run['duration'],
$last_run['error'],
admin_url('admin.php?page=flowguard#/flows/' . $flow->ID)
);
}
}
// Initialize
new Flowguard_Monitor();Related Documentation
- WordPress Filters - Modify flow data
- REST API - API endpoints
- Running Flows - User guide
Future Actions
Additional actions planned for future versions:
flowguard_flow_created- When a flow is createdflowguard_flow_updated- When a flow is updatedflowguard_flow_deleted- When a flow is deletedflowguard_step_executed- After each step executesflowguard_flow_scheduled- When a flow is scheduled
Support
For questions about actions:
- Review WordPress Plugin API documentation
- Check the Flowguard source code
- Contact support for assistance