Skip to content

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:

ParameterTypeDescription
$flow_idintThe flow post ID
$flow_dataarrayComplete flow data being executed

Flow Data Structure:

php
$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:

php
/**
 * 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:

  1. Logging:
php
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);
  1. Notifications:
php
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);
  1. Prepare Environment:
php
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);
  1. Integration with Other Plugins:
php
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:

ParameterTypeDescription
$flow_idintThe flow post ID
$last_runarrayExecution results

Last Run Structure:

php
$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:

php
/**
 * 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:

  1. Email Notifications for Failures:
php
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);
  1. Track Statistics:
php
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);
  1. Slack Integration:
php
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);
  1. Trigger Remediation:
php
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);
  1. Update External Monitoring:
php
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:

php
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:

php
// 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:

php
remove_action('flowguard_before_flow_run', 'your_function', $priority);

Example:

php
// 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:

php
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:

php
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:

php
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:

php
/**
 * 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
<?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();

Future Actions

Additional actions planned for future versions:

  • flowguard_flow_created - When a flow is created
  • flowguard_flow_updated - When a flow is updated
  • flowguard_flow_deleted - When a flow is deleted
  • flowguard_step_executed - After each step executes
  • flowguard_flow_scheduled - When a flow is scheduled

Support

For questions about actions:

  1. Review WordPress Plugin API documentation
  2. Check the Flowguard source code
  3. Contact support for assistance