Dispatcher.php 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace Illuminate\Bus;
  3. use Closure;
  4. use RuntimeException;
  5. use Illuminate\Pipeline\Pipeline;
  6. use Illuminate\Contracts\Queue\Queue;
  7. use Illuminate\Contracts\Queue\ShouldQueue;
  8. use Illuminate\Contracts\Container\Container;
  9. use Illuminate\Contracts\Bus\QueueingDispatcher;
  10. class Dispatcher implements QueueingDispatcher
  11. {
  12. /**
  13. * The container implementation.
  14. *
  15. * @var \Illuminate\Contracts\Container\Container
  16. */
  17. protected $container;
  18. /**
  19. * The pipeline instance for the bus.
  20. *
  21. * @var \Illuminate\Pipeline\Pipeline
  22. */
  23. protected $pipeline;
  24. /**
  25. * The pipes to send commands through before dispatching.
  26. *
  27. * @var array
  28. */
  29. protected $pipes = [];
  30. /**
  31. * The command to handler mapping for non-self-handling events.
  32. *
  33. * @var array
  34. */
  35. protected $handlers = [];
  36. /**
  37. * The queue resolver callback.
  38. *
  39. * @var \Closure|null
  40. */
  41. protected $queueResolver;
  42. /**
  43. * Create a new command dispatcher instance.
  44. *
  45. * @param \Illuminate\Contracts\Container\Container $container
  46. * @param \Closure|null $queueResolver
  47. * @return void
  48. */
  49. public function __construct(Container $container, Closure $queueResolver = null)
  50. {
  51. $this->container = $container;
  52. $this->queueResolver = $queueResolver;
  53. $this->pipeline = new Pipeline($container);
  54. }
  55. /**
  56. * Dispatch a command to its appropriate handler.
  57. *
  58. * @param mixed $command
  59. * @return mixed
  60. */
  61. public function dispatch($command)
  62. {
  63. if ($this->queueResolver && $this->commandShouldBeQueued($command)) {
  64. return $this->dispatchToQueue($command);
  65. }
  66. return $this->dispatchNow($command);
  67. }
  68. /**
  69. * Dispatch a command to its appropriate handler in the current process.
  70. *
  71. * @param mixed $command
  72. * @param mixed $handler
  73. * @return mixed
  74. */
  75. public function dispatchNow($command, $handler = null)
  76. {
  77. if ($handler || $handler = $this->getCommandHandler($command)) {
  78. $callback = function ($command) use ($handler) {
  79. return $handler->handle($command);
  80. };
  81. } else {
  82. $callback = function ($command) {
  83. return $this->container->call([$command, 'handle']);
  84. };
  85. }
  86. return $this->pipeline->send($command)->through($this->pipes)->then($callback);
  87. }
  88. /**
  89. * Determine if the given command has a handler.
  90. *
  91. * @param mixed $command
  92. * @return bool
  93. */
  94. public function hasCommandHandler($command)
  95. {
  96. return array_key_exists(get_class($command), $this->handlers);
  97. }
  98. /**
  99. * Retrieve the handler for a command.
  100. *
  101. * @param mixed $command
  102. * @return bool|mixed
  103. */
  104. public function getCommandHandler($command)
  105. {
  106. if ($this->hasCommandHandler($command)) {
  107. return $this->container->make($this->handlers[get_class($command)]);
  108. }
  109. return false;
  110. }
  111. /**
  112. * Determine if the given command should be queued.
  113. *
  114. * @param mixed $command
  115. * @return bool
  116. */
  117. protected function commandShouldBeQueued($command)
  118. {
  119. return $command instanceof ShouldQueue;
  120. }
  121. /**
  122. * Dispatch a command to its appropriate handler behind a queue.
  123. *
  124. * @param mixed $command
  125. * @return mixed
  126. *
  127. * @throws \RuntimeException
  128. */
  129. public function dispatchToQueue($command)
  130. {
  131. $connection = $command->connection ?? null;
  132. $queue = call_user_func($this->queueResolver, $connection);
  133. if (! $queue instanceof Queue) {
  134. throw new RuntimeException('Queue resolver did not return a Queue implementation.');
  135. }
  136. if (method_exists($command, 'queue')) {
  137. return $command->queue($queue, $command);
  138. }
  139. return $this->pushCommandToQueue($queue, $command);
  140. }
  141. /**
  142. * Push the command onto the given queue instance.
  143. *
  144. * @param \Illuminate\Contracts\Queue\Queue $queue
  145. * @param mixed $command
  146. * @return mixed
  147. */
  148. protected function pushCommandToQueue($queue, $command)
  149. {
  150. if (isset($command->queue, $command->delay)) {
  151. return $queue->laterOn($command->queue, $command->delay, $command);
  152. }
  153. if (isset($command->queue)) {
  154. return $queue->pushOn($command->queue, $command);
  155. }
  156. if (isset($command->delay)) {
  157. return $queue->later($command->delay, $command);
  158. }
  159. return $queue->push($command);
  160. }
  161. /**
  162. * Set the pipes through which commands should be piped before dispatching.
  163. *
  164. * @param array $pipes
  165. * @return $this
  166. */
  167. public function pipeThrough(array $pipes)
  168. {
  169. $this->pipes = $pipes;
  170. return $this;
  171. }
  172. /**
  173. * Map a command to a handler.
  174. *
  175. * @param array $map
  176. * @return $this
  177. */
  178. public function map(array $map)
  179. {
  180. $this->handlers = array_merge($this->handlers, $map);
  181. return $this;
  182. }
  183. }