# Event Reference

PteroCA uses a domain event system built on Symfony's EventDispatcher component. Events are dispatched throughout the application lifecycle, allowing plugins and custom code to react to actions such as user registration, server creation, payments, and more. The system contains **266+ events** across 26 categories, covering virtually every operation in PteroCA.

All domain events extend `AbstractDomainEvent` with automatic UUID generation, timestamps, and schema versioning. Events follow consistent patterns:

* **Pre-Events** — Before an operation (can be vetoed/stopped)
* **Post-Events** — After an operation (for side effects)
* **Mutable Events** — Allow modifying data in transit
* **CLI Events** — Background process events

## How to Subscribe to Events

Create a class that implements `EventSubscriberInterface` and define which events it listens to:

```php
<?php
namespace Plugins\MyPlugin\EventSubscriber;

use App\Core\Event\User\UserRegisteredEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            UserRegisteredEvent::class => 'onUserRegistered',
        ];
    }

    public function onUserRegistered(UserRegisteredEvent $event): void
    {
        $userId = $event->getUserId();
        // Your plugin logic here
    }
}
```

> **Plugin developers:** For a complete guide to subscribing to events in plugins, including correct service configuration and a full list of available events organized by category, see the [Plugin Event System](/for-developers/plugins/event-system.md) documentation.

> **Important:** Plugin event subscribers must **NOT** use the `kernel.event_subscriber` service tag. The plugin registry discovers event subscribers automatically when the plugin is enabled. Use the plugin service registration method described in [Plugin Event System](/for-developers/plugins/event-system.md) instead. Tagging with `kernel.event_subscriber` would cause the subscriber to load even when the plugin is disabled.

Correct service registration for plugins:

```yaml
services:
    # CORRECT - No kernel.event_subscriber tag
    Plugins\MyPlugin\EventSubscriber\MyEventSubscriber:
        public: true

    # WRONG - Would load even when plugin disabled
    # Plugins\MyPlugin\EventSubscriber\MyEventSubscriber:
    #     tags: ['kernel.event_subscriber']
```

## Event Categories

Events are organized into the following categories, each corresponding to a namespace under `App\Core\Event\`:

| Category              | Namespace                          | Description                                                                |
| --------------------- | ---------------------------------- | -------------------------------------------------------------------------- |
| **Admin**             | `App\Core\Event\Admin\`            | Admin overview and panel events                                            |
| **Balance**           | `App\Core\Event\Balance\`          | Balance recharge and payment events                                        |
| **Cart**              | `App\Core\Event\Cart\`             | Shopping cart operations                                                   |
| **CLI**               | `App\Core\Event\Cli\`              | Background CLI command events (suspend, delete, sync)                      |
| **CRUD**              | `App\Core\Event\Crud\`             | EasyAdmin CRUD configuration and operation events                          |
| **Dashboard**         | `App\Core\Event\Dashboard\`        | Dashboard access and data loading                                          |
| **Email**             | `App\Core\Event\Email\`            | Email before/after send events                                             |
| **Form**              | `App\Core\Event\Form\`             | Form build and submit events                                               |
| **Landing**           | `App\Core\Event\Landing\`          | Landing page and navigation events                                         |
| **Menu**              | `App\Core\Event\Menu\`             | Menu item collection events                                                |
| **Page**              | `App\Core\Event\Page\`             | Static page events                                                         |
| **Password Recovery** | `App\Core\Event\PasswordRecovery\` | Password reset flow events                                                 |
| **Payment**           | `App\Core\Event\Payment\`          | Payment gateway collection and processing                                  |
| **Plugin**            | `App\Core\Event\Plugin\`           | Plugin lifecycle events (enable, disable, discovery)                       |
| **Product**           | `App\Core\Event\Product\`          | Product copy and management events                                         |
| **Security**          | `App\Core\Event\Security\`         | Permission registration events                                             |
| **Server**            | `App\Core\Event\Server\`           | Server purchase, renewal, backups, databases, schedules, subusers, network |
| **SSO**               | `App\Core\Event\SSO\`              | Single sign-on redirect and token events                                   |
| **Store**             | `App\Core\Event\Store\`            | Store and product browsing events                                          |
| **Theme**             | `App\Core\Event\Theme\`            | Theme upload, copy, export, delete, default change                         |
| **User**              | `App\Core\Event\User\`             | User registration, authentication, and account events                      |
| **View**              | `App\Core\Event\View\`             | View data manipulation before rendering                                    |
| **Voucher**           | `App\Core\Event\Voucher\`          | Voucher CRUD and redemption events                                         |
| **Widget**            | `App\Core\Event\Widget\`           | Dashboard widget collection events                                         |

For the full list of available events with detailed descriptions, types, and usage examples, refer to the [Plugin Event System](/for-developers/plugins/event-system.md) documentation.

## Core Event Patterns

### Stoppable Events (Pre-Events)

Pre-events allow plugins to validate or block operations before they happen:

```php
use App\Core\Event\User\Registration\UserRegistrationRequestedEvent;

public function onRegistrationRequested(UserRegistrationRequestedEvent $event): void
{
    if ($this->isBlacklisted($event->getEmail())) {
        $event->stopPropagation();
        $event->setRejected(true, 'Email domain is blacklisted');
    }
}
```

### Mutable Events

Some events allow modifying data in transit, such as adjusting a balance amount before it is applied:

```php
use App\Core\Event\Balance\BalanceAboutToBeAddedEvent;

public function onBalanceAboutToBeAdded(BalanceAboutToBeAddedEvent $event): void
{
    if ($this->isFirstRecharge($event->getUserId())) {
        $bonus = $event->getAmount() * 0.10;
        $event->setAmount($event->getAmount() + $bonus);
    }
}
```

### Collection Events

Collection events allow plugins to add items to menus, widgets, tabs, and payment gateways:

```php
use App\Core\Event\Menu\MenuItemsCollectedEvent;

public function onMenuItemsCollected(MenuItemsCollectedEvent $event): void
{
    $event->addMenuItem('main',
        MenuItem::linkToRoute('My Plugin', 'fa fa-puzzle-piece', 'plugin_my_plugin_index')
    );
}
```

### Event Priority

Control execution order when multiple listeners exist (higher priority runs first):

```php
public static function getSubscribedEvents(): array
{
    return [
        UserRegisteredEvent::class => ['onUserRegistered', 10],  // Higher = runs first
    ];
}
```

## Creating Custom Events

Plugins can define and dispatch their own events:

```php
<?php
namespace Plugins\MyPlugin\Event;

use Symfony\Contracts\EventDispatcher\Event;

class CustomActionEvent extends Event
{
    public function __construct(
        private readonly string $actionName,
        private readonly array $data,
    ) {}

    public function getActionName(): string { return $this->actionName; }
    public function getData(): array { return $this->data; }
}
```

Dispatch the event via Symfony's `EventDispatcherInterface`:

```php
$this->eventDispatcher->dispatch(new CustomActionEvent('my_action', $data));
```

## Related Guides

* [Plugin Event System](/for-developers/plugins/event-system.md) - Full event list with examples and service configuration
* [Bootstrap & Lifecycle](/for-developers/plugins/bootstrap-and-lifecycle.md) - Plugin initialization
* [UI Components](/for-developers/plugins/ui-components.md) - Register widgets and tabs via events
* [Best Practices](/for-developers/plugins/best-practices.md) - Plugin development guidelines


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pteroca.com/for-developers/event-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
