# Хуки та події

Хуки — спосіб для плагінів втручатися в роботу ядра та інших плагінів, не змінюючи їхній код. Реалізовані в стилі WordPress класом `Celena\Core\Plugin\Hook`. Є два види: **actions** (побічні ефекти) та **filters** (перетворення значення).

Контракт імені: `<область>.<подія>` у нижньому регістрі, наприклад `news.published`.

## Actions — дії

Ефект без повернення значення. Підписників може бути кілька, порядок не важливий.

```php
use Celena\Core\Plugin\Hook;

// Підписатися:
Hook::on('news.published', function (array $news): void {
    // наприклад, надіслати сповіщення
});

// Викликати (це робить ядро/модуль):
Hook::action('news.published', $news);
```

## Filters — фільтри

Перетворюють значення, передаючи його ланцюжком підписників.

```php
// Підписатися (можна вказати пріоритет, менше = раніше):
Hook::addFilter('news.title', fn (string $t) => trim($t), 10);

// Застосувати:
$title = Hook::filter('news.title', $news['title'], $news);
```

## Вбудовані хуки ядра

| Хук | Тип | Аргументи |
|-----|-----|-----------|
| `kernel.boot` | action | `Container $c` |
| `request.before` | action | `Request $req` |
| `response.before_send` | filter | `Response $res, Request $req` |
| `user.registered` | action | `array $user` |
| `user.login.success` | action | `array $user` |
| `user.login.failed` | action | `string $email, string $ip` |
| `news.published` | action | `array $news` |
| `news.title` | filter | `string $title, array $news` |
| `template.render.before` | action | `string $template, array $vars` |
| `template.globals` | filter | `array $vars` |
| `admin.sidebar` | filter | `array $items` |
| `admin.notifications` | filter | `array $items` |
| `cache.cleared` | action | `string $type` |

Список розширюється в міру зростання ядра.

## Часті сценарії

### Додати пункт у меню адмінки

```php
Hook::addFilter('admin.sidebar', function (array $items): array {
    $icon = new \Celena\Core\Template\Tags\IconTag();
    $items[] = [
        'svg'          => $icon(['name' => 'mail', 'size' => 22, 'class' => 'sb-ico']),
        'label'        => 'Заявки',
        'url'          => '/admin/forms',
        'slug'         => 'forms',
        'active_slugs' => ['forms', 'leads'],
        'children'     => [
            ['label' => 'Форми',     'url' => '/admin/forms', 'slug' => 'forms'],
            ['label' => 'Усі заявки', 'url' => '/admin/leads', 'slug' => 'leads'],
        ],
    ];
    return $items;
});
```

### Прокинути змінну в усі шаблони

```php
Hook::addFilter('template.globals', function (array $vars): array {
    $vars['my_flag'] = '1';   // доступно як {my_flag} у будь-якому шаблоні
    return $vars;
}, 0);
```

### Додати сповіщення в «дзвіночок»

```php
Hook::addFilter('admin.notifications', function (array $items): array {
    $items[] = ['title' => 'Нові заявки', 'text' => '3 шт.', 'url' => '/admin/forms', 'time' => ''];
    return $items;
});
```

## Власні хуки в плагіні

Плагін може випускати власні події, щоб інші розширення могли на них підписатися:

```php
Hook::action('shop.order.created', $order);
$price = Hook::filter('shop.price', $price, $product);
```

Документуйте такі хуки в `docs/hooks.md` свого плагіна — це контракт для інтеграцій.
