
# Trigger delle azioni

`Queuety::on_action()` permette di trasformare una normale azione WordPress nell’avvio di un workflow duraturo.

Questo crea un collegamento diretto:

`WordPress action -> mapped payload -> durable workflow`

È utile quando l’evento di interesse esiste già in WordPress e la risposta costosa o di lunga durata deve avvenire in modo asincrono.

## Esempio: revisionare i contenuti quando si salva un articolo

```php
use Queuety\Queuety;

Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'post_type' => $post->post_type,
        'update' => $update,
    ],
    when: static fn ( int $post_id, object $post ): bool => 'post' === $post->post_type,
    idempotency_key: static fn ( int $post_id ): string => "save_post:{$post_id}",
);
```

In questo esempio:

- `save_post` è ancora l’evento WordPress originale
- `map` trasforma gli argomenti grezzi dell’hook in uno stato del workflow semplice
- `when` esclude gli eventi indesiderati prima che venga messo qualcosa in coda
- `idempotency_key` evita che le attivazioni ripetute dell’hook avviino esecuzioni duplicate

## Cosa viene eseguito in modo sincrono

La callback dell’azione viene comunque eseguita all’interno della richiesta WordPress corrente.

Ciò significa che queste parti sono sincrone:

- `when`
- `map`
- `idempotency_key`

Solo i passaggi del workflow vengono eseguiti in modo asincrono dopo l’avvio.

## Regole per il payload

I payload mappati devono contenere array semplici, valori scalari e `null`.

Non passate oggetti WordPress grezzi come `WP_Post` direttamente allo stato del workflow. Prima normalizzateli all’interno di `map()`:

```php
Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'post_type' => $post->post_type,
        'post_status' => $post->post_status,
        'update' => $update,
    ],
);
```

Le chiavi che iniziano con `_` vengono rifiutate, perché questi nomi sono riservati allo stato interno del workflow.

## Argomenti accettati

WordPress richiede un conteggio `accepted_args` quando si registra una callback di azione.

Per impostazione predefinita, Queuety lo deduce dalle callback `map`, `when` e `idempotency_key`, quindi nel caso comune non serve alcuna configurazione aggiuntiva:

```php
Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'update' => $update,
    ],
);
```

Se serve un override manuale, passate esplicitamente `accepted_args`:

```php
Queuety::on_action(
    'comment_post',
    workflow: 'comment_review',
    accepted_args: 2,
);
```

## Builder inline dei workflow

Potete avviare un workflow registrato per nome o tramite un builder inline `WorkflowBuilder`.

I builder inline sono utili quando il workflow specifico dell’hook è definito nello stesso file di bootstrap:

```php
$review = Queuety::workflow( 'comment_review' )
    ->then( ModerateCommentStep::class )
    ->then( NotifyModeratorStep::class );

Queuety::on_action(
    'comment_post',
    workflow: $review,
    map: static fn ( int $comment_id ): array => [
        'comment_id' => $comment_id,
    ],
    idempotency_key: static fn ( int $comment_id ): string => "comment:{$comment_id}",
);
```

## Quando è una scelta adatta

Usate i trigger delle azioni quando:

- WordPress emette già l’evento che vi interessa
- la risposta deve resistere ai timeout delle richieste o ai riavvii dei worker
- il lavoro successivo può diramarsi, attendere o richiedere un’approvazione
- le attivazioni duplicate dell’hook richiedono un’idempotenza duratura

Usate invece una chiamata diretta a `Queuety::dispatch()` o `Queuety::workflow()` quando il lavoro non è legato a un confine di evento WordPress.

## Non per i filtri

`Queuety::on_action()` è intenzionalmente riservato alle azioni.

I filtri sono trasformazioni sincrone eseguite durante la richiesta. Di solito devono restare sincroni, perché WordPress si aspetta di ricevere immediatamente il valore filtrato.
