
# مشغلات الإجراءات

يتيح لك `Queuety::on_action()` تحويل إجراء عادي في WordPress إلى إرسال لسير عمل دائم.

يوفر ذلك جسرًا واضحًا:

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

يفيد هذا عندما يكون الحدث المهم موجودًا بالفعل في WordPress، وينبغي أن تتم الاستجابة المكلفة أو طويلة التشغيل بشكل غير متزامن.

## مثال: راجع المحتوى عند حفظ منشور

```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}",
);
```

في هذا المثال:

- يظل `save_post` حدث WordPress الأصلي
- يحول `map` وسائط الخطاف الأولية إلى حالة سير عمل عادية
- يتخطى `when` الأحداث غير المرغوب فيها قبل وضع أي شيء في قائمة الانتظار
- يمنع `idempotency_key` تكرار عمليات تشغيل الخطاف من إرسال عمليات تشغيل مكررة

## ما الذي يعمل بشكل متزامن

يظل رد نداء الإجراء نفسه يعمل ضمن طلب WordPress الحالي.

وهذا يعني أن الأجزاء التالية تعمل بشكل متزامن:

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

تعمل خطوات سير العمل فقط بشكل غير متزامن بعد الإرسال.

## قواعد الحمولة

ينبغي أن تحتوي الحمولات المعينة على مصفوفات عادية وقيم مفردة و`null`.

لا تمرر كائنات WordPress الأولية مثل `WP_Post` مباشرةً إلى حالة سير العمل. طَبّعها داخل `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,
    ],
);
```

تُرفض المفاتيح التي تبدأ بـ`_`، لأن هذه الأسماء محجوزة لحالة سير العمل الداخلية.

## الوسائط المقبولة

يتطلب WordPress عدد `accepted_args` عند تسجيل رد نداء إجراء.

يستنتج Queuety العدد افتراضيًا من عمليات رد النداء `map` و`when` و`idempotency_key`، لذا لا تحتاج الحالة الشائعة إلى إعدادات إضافية:

```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,
    ],
);
```

إذا احتجت إلى تجاوز يدوي، فمرر `accepted_args` صراحةً:

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

## منشئات سير العمل المضمنة

يمكنك إرسال اسم سير عمل مسجل أو `WorkflowBuilder` مضمن.

تفيد المنشئات المضمنة عندما يكون سير العمل الخاص بالخطاف معرّفًا في ملف التهيئة نفسه:

```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}",
);
```

## متى يكون هذا مناسبًا

استخدم مشغلات الإجراءات عندما:

- يصدر WordPress الحدث الذي تريده بالفعل
- ينبغي أن تصمد الاستجابة أمام انتهاء مهلة الطلب أو إعادة تشغيل العامل
- قد تتفرع أعمال المتابعة أو تنتظر أو تتطلب موافقة
- تحتاج عمليات تشغيل الخطاف المكررة إلى منع تكرار دائم

استخدم استدعاء `Queuety::dispatch()` أو `Queuety::workflow()` مباشرًا بدلًا من ذلك عندما لا يرتبط العمل بحدّ حدث WordPress.

## ليست مخصصة للمرشحات

صُمم `Queuety::on_action()` للإجراءات فقط.

المرشحات تحويلات متزامنة وقت الطلب. وينبغي عادةً أن تظل متزامنة، لأن WordPress يتوقع إرجاع قيمة تمت تصفيتها فورًا.
