|
15 | 15 | use Closure; |
16 | 16 | use CloudCreativity\Modules\Contracts\Infrastructure\Queue\EnqueuerContainer as IEnqueuerContainer; |
17 | 17 | use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; |
| 18 | +use CloudCreativity\Modules\Infrastructure\InfrastructureException; |
| 19 | +use Psr\Container\ContainerInterface; |
18 | 20 |
|
19 | 21 | final class EnqueuerContainer implements IEnqueuerContainer |
20 | 22 | { |
21 | 23 | /** |
22 | | - * @var array<class-string<Command>, Closure> |
| 24 | + * @var array<class-string<Command>, Closure|string> |
23 | 25 | */ |
24 | 26 | private array $bindings = []; |
25 | 27 |
|
26 | 28 | /** |
27 | | - * @param Closure(): object $default |
| 29 | + * @param (Closure(): object)|string|null $default |
28 | 30 | */ |
29 | | - public function __construct(private readonly Closure $default) |
30 | | - { |
| 31 | + public function __construct( |
| 32 | + private Closure|string|null $default = null, |
| 33 | + private readonly ?ContainerInterface $container = null, |
| 34 | + ) { |
| 35 | + if (is_string($this->default) && $this->container === null) { |
| 36 | + throw new InfrastructureException( |
| 37 | + 'Cannot bind default enqueuer as a string without a PSR container.', |
| 38 | + ); |
| 39 | + } |
31 | 40 | } |
32 | 41 |
|
33 | 42 | /** |
34 | 43 | * Bind an enqueuer factory into the container. |
35 | 44 | * |
36 | 45 | * @param class-string<Command> $queueableName |
37 | | - * @param Closure(): object $binding |
| 46 | + * @param (Closure(): object)|string $binding |
38 | 47 | */ |
39 | | - public function bind(string $queueableName, Closure $binding): void |
| 48 | + public function bind(string $queueableName, Closure|string $binding): void |
40 | 49 | { |
41 | 50 | $this->bindings[$queueableName] = $binding; |
42 | 51 | } |
43 | 52 |
|
| 53 | + public function withDefault(Closure|string $binding): void |
| 54 | + { |
| 55 | + if ($this->default !== null) { |
| 56 | + throw new InfrastructureException('Default enqueuer is already set.'); |
| 57 | + } |
| 58 | + |
| 59 | + if (is_string($binding) && $this->container === null) { |
| 60 | + throw new InfrastructureException( |
| 61 | + 'Cannot bind default enqueuer as a string without a PSR container.', |
| 62 | + ); |
| 63 | + } |
| 64 | + |
| 65 | + $this->default = $binding; |
| 66 | + } |
| 67 | + |
44 | 68 | public function get(string $command): Enqueuer |
45 | 69 | { |
46 | | - $factory = $this->bindings[$command] ?? $this->default; |
| 70 | + $binding = $this->bindings[$command] ?? $this->default; |
47 | 71 |
|
48 | | - $enqueuer = $factory(); |
| 72 | + if ($binding instanceof Closure) { |
| 73 | + $instance = $binding(); |
| 74 | + assert(is_object($instance), "Enqueuer binding for command {$command} must return an object."); |
| 75 | + return new Enqueuer($instance); |
| 76 | + } |
49 | 77 |
|
50 | | - assert(is_object($enqueuer), "Enqueuer binding for {$command} must return an object."); |
| 78 | + if (is_string($binding)) { |
| 79 | + $instance = $this->container?->get($binding); |
| 80 | + assert(is_object($instance), "PSR container enqueuer binding {$binding} is not an object."); |
| 81 | + return new Enqueuer($instance); |
| 82 | + } |
51 | 83 |
|
52 | | - return new Enqueuer($enqueuer); |
| 84 | + throw new InfrastructureException('No enqueuer bound for command: ' . $command); |
53 | 85 | } |
54 | 86 | } |
0 commit comments