<?php

/*
The Cascade Isolation Pattern is designed to manage a chain of dependent operations where the execution of each step in the chain is isolated from the others unless explicitly passed a “success state.” This pattern ensures that downstream operations in a chain won’t execute unless the preceding steps complete successfully.

This is particularly useful in applications requiring tightly controlled workflows, like multi-step transaction processing, data pipelines, or sequential validations.
*/

class CascadeStep {
    private $callback;
    private $isolation = true; // Default to isolation unless overridden

    public function __construct(callable $callback, bool $isolation = true) {
        $this->callback = $callback;
        $this->isolation = $isolation;
    }

    public function execute($input) {
        if (!$this->isolation) {
            return ($this->callback)($input); // Execute without checking input validity
        }

        // For isolated steps, execute only if input is valid
        if ($input['status'] === 'success') {
            return ($this->callback)($input);
        } else {
            return [
                'status' => 'failure',
                'message' => 'Previous step failed. Cascade halted.'
            ];
        }
    }
}

class Cascade {
    private $steps = [];

    public function addStep(CascadeStep $step) {
        $this->steps[] = $step;
    }

    public function execute($initialInput) {
        $result = $initialInput;

        foreach ($this->steps as $step) {
            $result = $step->execute($result);
            if ($result['status'] !== 'success') {
                break; // Stop the cascade if a step fails
            }
        }

        return $result;
    }
}

// Example Usage:

// Define a multi-step process
$step1 = new CascadeStep(function($input) {
    echo "Step 1: Validating data...\n";
    if ($input['data'] === 'valid') {
        return ['status' => 'success', 'message' => 'Step 1 successful'];
    }
    return ['status' => 'failure', 'message' => 'Invalid data in Step 1'];
});

$step2 = new CascadeStep(function($input) {
    echo "Step 2: Processing data...\n";
    return ['status' => 'success', 'message' => 'Step 2 successful'];
});

$step3 = new CascadeStep(function($input) {
    echo "Step 3: Finalizing...\n";
    return ['status' => 'success', 'message' => 'All steps completed'];
});

// Create a cascade
$cascade = new Cascade();
$cascade->addStep($step1);
$cascade->addStep($step2);
$cascade->addStep($step3);

// Run the cascade
$input = ['status' => 'success', 'data' => 'valid'];
$result = $cascade->execute($input);
print_r($result); // Should output the success message of Step 3

// Run with invalid input
$invalidInput = ['status' => 'success', 'data' => 'invalid'];
$result = $cascade->execute($invalidInput);
print_r($result); // Should halt at Step 1 with failure message