PHP code example of cmatosbc / clotho

1. Go to this page and download the library: Download cmatosbc/clotho library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

cmatosbc / clotho example snippets


use Clotho\Attribute\EventBefore;
use Clotho\Attribute\EventAfter;

class UserService
{
    #[EventBefore('user.create')]
    #[EventAfter('user.create')]
    public function createUser(string $name, string $email): array
    {
        return [
            'id' => 1,
            'name' => $name,
            'email' => $email,
        ];
    }
}

// Set up the event system
$dispatcher = new EventDispatcher();
$handler = new EventAttributeHandler($dispatcher);

// Add event listeners
$dispatcher->addEventListener('user.create', function (array $payload) {
    echo "User creation started with email: " . $payload['arguments'][1];
});

// Wrap and use the method
$service = new UserService();
$createUser = $handler->wrapMethod($service, 'createUser');
$result = $createUser('John Doe', '[email protected]');

use Clotho\Event\BeforeMethodEvent;
use Clotho\Event\AfterMethodEvent;

class OrderService
{
    #[EventBefore]
    public function submitOrder(array $items): array
    {
        return ['order_id' => 123, 'items' => $items];
    }
}

// Higher priority listeners execute first
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Validate stock levels
    if (!$this->checkStock($event->getArguments()[0])) {
        $event->stopPropagation();
    }
}, 20);

$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Check user credit
}, 10);

$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Log order attempt
}, 0);

// After events with priority
$dispatcher->addEventListener(AfterMethodEvent::class, function (AfterMethodEvent $event) {
    // High priority post-processing
    $result = $event->getResult();
    // Process order result
}, 20);

// Listen to all user events
$dispatcher->addEventListener('user.*', function ($payload) {
    echo "User operation detected: " . $payload['event'];
});

// Listen to all create operations
$dispatcher->addEventListener('*.create', function ($payload) {
    echo "Create operation detected in module: " . $payload['module'];
});

class UserService
{
    #[EventBefore('user.profile.update')]
    #[EventBefore('user.settings.update')]
    public function updateUserData(string $section, array $data): array
    {
        return ['section' => $section, 'data' => $data];
    }
}

class GroupService
{
    #[EventBefore('admin.group:create')]
    #[EventBefore('user.group:update')]
    public function manageGroup(string $operation, array $data): array
    {
        return ['operation' => $operation, 'data' => $data];
    }
}

// Listen to all group creation events
$dispatcher->addEventListener('*.group:create', function ($payload) {
    echo "Group creation in progress...";
});

use Clotho\Event\BeforeMethodEvent;

class UserService
{
    #[EventBefore]
    public function deleteUser(int $userId): bool
    {
        // Delete user logic
        return true;
    }
}

$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    if (!$this->hasPermission('delete_users')) {
        echo "Permission denied";
        $event->stopPropagation();
        return;
    }
}, 20);

$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // This won't execute if the previous listener stops propagation
    echo "Deleting user...";
}, 10);

use Clotho\Event\BeforeMethodEvent;
use Clotho\Event\AfterMethodEvent;
use Clotho\Attribute\EventBefore;
use Clotho\Attribute\EventAfter;

class UserService
{
    #[EventBefore('user.create')]
    #[EventAfter('user.create')]
    public function createUser(string $name, string $email): array
    {
        return [
            'id' => 1,
            'name' => $name,
            'email' => $email,
        ];
    }
}

// Listen for event objects (useful for priority-based handling)
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    $arguments = $event->getArguments();
    echo "Creating user: " . $arguments[0];
}, 20);

// Listen for named events (useful for domain-specific handling)
$dispatcher->addEventListener('user.create', function (array $payload) {
    $event = $payload['event']; // BeforeMethodEvent or AfterMethodEvent
    $arguments = $payload['arguments'];
    echo "User creation event: " . $arguments[0];
});

use Clotho\Event\BeforeMethodEvent;
use Clotho\Event\AfterMethodEvent;
use Clotho\Event\BeforeFunctionEvent;
use Clotho\Event\AfterFunctionEvent;

// Listen for method events
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    $methodName = $event->getMethodName();
    $arguments = $event->getArguments();
    
    if (!$this->isValid($arguments)) {
        $event->stopPropagation();
    }
}, 10);

// Listen for after events with results
$dispatcher->addEventListener(AfterMethodEvent::class, function (AfterMethodEvent $event) {
    if ($event->hasException()) {
        $this->handleError($event->getException());
        return;
    }
    
    $result = $event->getResult();
    $this->processResult($result);
});

use Clotho\Event\BeforeMethodEvent;

// High priority validation
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Runs first (priority 20)
    if (!$this->hasPermission()) {
        $event->stopPropagation();
    }
}, 20);

// Normal priority logging
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Runs second (priority 10)
    $this->logAccess($event->getMethodName());
}, 10);

// Low priority operations
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    // Runs last (priority 0)
    $this->notify($event->getMethodName());
}, 0);

use Clotho\Event\BeforeMethodEvent;

class UserService
{
    #[EventBefore]
    public function deleteUser(int $userId): void
    {
        // Delete user logic
    }
}

// High priority security check
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    if (!$this->hasPermission('delete_users')) {
        $event->stopPropagation(); // Prevents further listeners from executing
        throw new SecurityException('Permission denied');
    }
}, 20);

// This won't execute if permission check fails
$dispatcher->addEventListener(BeforeMethodEvent::class, function (BeforeMethodEvent $event) {
    $this->logDeletion($event->getArguments()[0]);
}, 10);

use Clotho\Exception\EventDispatchException;
use Clotho\Exception\EventListenerException;
use Clotho\Exception\EventPropagationException;

// Invalid event name
try {
    $dispatcher->dispatch(''); // Empty event name
} catch (EventDispatchException $e) {
    // Handles dispatch-related errors:
    // - Empty or invalid event names
    // - Errors thrown by event listeners
}

// Invalid listener priority
try {
    // Priority must be between -100 and 100
    $dispatcher->addEventListener('user.create', $listener, 150);
} catch (EventListenerException $e) {
    // Handles listener-related errors:
    // - Invalid priority values
    // - Invalid listener types
}

// 1. Events with no listeners - perfectly valid
$dispatcher->dispatch('user.created', ['id' => 123]);

// 2. Stopping event propagation - normal control flow
$dispatcher->addEventListener('user.delete', function (BeforeMethodEvent $event) {
    if (!$this->hasPermission()) {
        $event->stopPropagation(); // Stops further listeners, no exception
        return;
    }
    // Process the event
}, 20);

// 3. Wildcard events with no matches - also valid
$dispatcher->dispatch('custom.event');

[
    'event' => BeforeMethodEvent,    // The actual event object
    'object' => object,              // The object instance the method belongs to
    'method' => string,              // Name of the method being called
    'arguments' => array,            // Array of arguments passed to the method
]

[
    'event' => AfterMethodEvent,     // The actual event object
    'object' => object,              // The object instance the method belongs to
    'method' => string,              // Name of the method being called
    'arguments' => array,            // Array of arguments passed to the method
    'result' => mixed,               // The return value from the method (if successful)
    'exception' => Throwable|null    // Exception object if method threw an exception
]

[
    'event' => BeforeFunctionEvent,  // The actual event object
    'function' => string,            // Name of the function being called
    'arguments' => array,            // Array of arguments passed to the function
]

[
    'event' => AfterFunctionEvent,   // The actual event object
    'function' => string,            // Name of the function being called
    'arguments' => array,            // Array of arguments passed to the function
    'result' => mixed,               // The return value from the function (if successful)
    'exception' => Throwable|null    // Exception object if function threw an exception
]

use Clotho\Attribute\EventBefore;
use Clotho\Attribute\EventAfter;

class UserService
{
    #[EventBefore('user.create')]
    #[EventAfter('user.create')]
    public function createUser(string $name, string $email): array
    {
        return [
            'id' => 1,
            'name' => $name,
            'email' => $email,
        ];
    }
}

// Access payload in before event
$dispatcher->addEventListener('user.create', function (array $payload) {
    $event = $payload['event'];           // BeforeMethodEvent instance
    $object = $payload['object'];         // UserService instance
    $method = $payload['method'];         // "createUser"
    $arguments = $payload['arguments'];   // [$name, $email]
    
    echo "Creating user {$arguments[0]} with email {$arguments[1]}";
});

// Access payload in after event
$dispatcher->addEventListener('user.create', function (array $payload) {
    if (isset($payload['exception'])) {
        echo "Error creating user: " . $payload['exception']->getMessage();
        return;
    }
    
    $result = $payload['result'];  // The returned user array
    echo "Created user with ID: {$result['id']}";
});