PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php

https://gitlab.com/Pasantias/pasantiasASLG
PHP | 409 lines | 182 code | 51 blank | 176 comment | 21 complexity | 5e7de027199e5dd9fb0eef3b099d67fa MD5 | raw file
  1. <?php
  2. namespace Illuminate\Bus;
  3. use Closure;
  4. use ArrayAccess;
  5. use ReflectionClass;
  6. use RuntimeException;
  7. use ReflectionParameter;
  8. use InvalidArgumentException;
  9. use Illuminate\Pipeline\Pipeline;
  10. use Illuminate\Support\Collection;
  11. use Illuminate\Contracts\Queue\Queue;
  12. use Illuminate\Contracts\Bus\SelfHandling;
  13. use Illuminate\Contracts\Queue\ShouldQueue;
  14. use Illuminate\Contracts\Container\Container;
  15. use Illuminate\Contracts\Bus\HandlerResolver;
  16. use Illuminate\Contracts\Bus\QueueingDispatcher;
  17. use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
  18. class Dispatcher implements DispatcherContract, QueueingDispatcher, HandlerResolver
  19. {
  20. /**
  21. * The container implementation.
  22. *
  23. * @var \Illuminate\Contracts\Container\Container
  24. */
  25. protected $container;
  26. /**
  27. * The pipeline instance for the bus.
  28. *
  29. * @var \Illuminate\Pipeline\Pipeline
  30. */
  31. protected $pipeline;
  32. /**
  33. * The pipes to send commands through before dispatching.
  34. *
  35. * @var array
  36. */
  37. protected $pipes = [];
  38. /**
  39. * The queue resolver callback.
  40. *
  41. * @var \Closure|null
  42. */
  43. protected $queueResolver;
  44. /**
  45. * All of the command-to-handler mappings.
  46. *
  47. * @var array
  48. */
  49. protected $mappings = [];
  50. /**
  51. * The fallback mapping Closure.
  52. *
  53. * @var \Closure
  54. */
  55. protected $mapper;
  56. /**
  57. * Create a new command dispatcher instance.
  58. *
  59. * @param \Illuminate\Contracts\Container\Container $container
  60. * @param \Closure|null $queueResolver
  61. * @return void
  62. */
  63. public function __construct(Container $container, Closure $queueResolver = null)
  64. {
  65. $this->container = $container;
  66. $this->queueResolver = $queueResolver;
  67. $this->pipeline = new Pipeline($container);
  68. }
  69. /**
  70. * Marshal a command and dispatch it to its appropriate handler.
  71. *
  72. * @param mixed $command
  73. * @param array $array
  74. * @return mixed
  75. */
  76. public function dispatchFromArray($command, array $array)
  77. {
  78. return $this->dispatch($this->marshalFromArray($command, $array));
  79. }
  80. /**
  81. * Marshal a command and dispatch it to its appropriate handler.
  82. *
  83. * @param mixed $command
  84. * @param \ArrayAccess $source
  85. * @param array $extras
  86. * @return mixed
  87. */
  88. public function dispatchFrom($command, ArrayAccess $source, array $extras = [])
  89. {
  90. return $this->dispatch($this->marshal($command, $source, $extras));
  91. }
  92. /**
  93. * Marshal a command from the given array.
  94. *
  95. * @param string $command
  96. * @param array $array
  97. * @return mixed
  98. */
  99. protected function marshalFromArray($command, array $array)
  100. {
  101. return $this->marshal($command, new Collection, $array);
  102. }
  103. /**
  104. * Marshal a command from the given array accessible object.
  105. *
  106. * @param string $command
  107. * @param \ArrayAccess $source
  108. * @param array $extras
  109. * @return mixed
  110. */
  111. protected function marshal($command, ArrayAccess $source, array $extras = [])
  112. {
  113. $injected = [];
  114. $reflection = new ReflectionClass($command);
  115. if ($constructor = $reflection->getConstructor()) {
  116. $injected = array_map(function ($parameter) use ($command, $source, $extras) {
  117. return $this->getParameterValueForCommand($command, $source, $parameter, $extras);
  118. }, $constructor->getParameters());
  119. }
  120. return $reflection->newInstanceArgs($injected);
  121. }
  122. /**
  123. * Get a parameter value for a marshalled command.
  124. *
  125. * @param string $command
  126. * @param \ArrayAccess $source
  127. * @param \ReflectionParameter $parameter
  128. * @param array $extras
  129. * @return mixed
  130. */
  131. protected function getParameterValueForCommand($command, ArrayAccess $source, ReflectionParameter $parameter, array $extras = [])
  132. {
  133. if (array_key_exists($parameter->name, $extras)) {
  134. return $extras[$parameter->name];
  135. }
  136. if (isset($source[$parameter->name])) {
  137. return $source[$parameter->name];
  138. }
  139. if ($parameter->isDefaultValueAvailable()) {
  140. return $parameter->getDefaultValue();
  141. }
  142. MarshalException::whileMapping($command, $parameter);
  143. }
  144. /**
  145. * Dispatch a command to its appropriate handler.
  146. *
  147. * @param mixed $command
  148. * @param \Closure|null $afterResolving
  149. * @return mixed
  150. */
  151. public function dispatch($command, Closure $afterResolving = null)
  152. {
  153. if ($this->queueResolver && $this->commandShouldBeQueued($command)) {
  154. return $this->dispatchToQueue($command);
  155. } else {
  156. return $this->dispatchNow($command, $afterResolving);
  157. }
  158. }
  159. /**
  160. * Dispatch a command to its appropriate handler in the current process.
  161. *
  162. * @param mixed $command
  163. * @param \Closure|null $afterResolving
  164. * @return mixed
  165. */
  166. public function dispatchNow($command, Closure $afterResolving = null)
  167. {
  168. return $this->pipeline->send($command)->through($this->pipes)->then(function ($command) use ($afterResolving) {
  169. if ($command instanceof SelfHandling) {
  170. return $this->container->call([$command, 'handle']);
  171. }
  172. $handler = $this->resolveHandler($command);
  173. if ($afterResolving) {
  174. call_user_func($afterResolving, $handler);
  175. }
  176. return call_user_func(
  177. [$handler, $this->getHandlerMethod($command)], $command
  178. );
  179. });
  180. }
  181. /**
  182. * Determine if the given command should be queued.
  183. *
  184. * @param mixed $command
  185. * @return bool
  186. */
  187. protected function commandShouldBeQueued($command)
  188. {
  189. if ($command instanceof ShouldQueue) {
  190. return true;
  191. }
  192. return (new ReflectionClass($this->getHandlerClass($command)))->implementsInterface(
  193. 'Illuminate\Contracts\Queue\ShouldQueue'
  194. );
  195. }
  196. /**
  197. * Dispatch a command to its appropriate handler behind a queue.
  198. *
  199. * @param mixed $command
  200. * @return mixed
  201. *
  202. * @throws \RuntimeException
  203. */
  204. public function dispatchToQueue($command)
  205. {
  206. $queue = call_user_func($this->queueResolver);
  207. if (! $queue instanceof Queue) {
  208. throw new RuntimeException('Queue resolver did not return a Queue implementation.');
  209. }
  210. if (method_exists($command, 'queue')) {
  211. return $command->queue($queue, $command);
  212. } else {
  213. return $this->pushCommandToQueue($queue, $command);
  214. }
  215. }
  216. /**
  217. * Push the command onto the given queue instance.
  218. *
  219. * @param \Illuminate\Contracts\Queue\Queue $queue
  220. * @param mixed $command
  221. * @return mixed
  222. */
  223. protected function pushCommandToQueue($queue, $command)
  224. {
  225. if (isset($command->queue, $command->delay)) {
  226. return $queue->laterOn($command->queue, $command->delay, $command);
  227. }
  228. if (isset($command->queue)) {
  229. return $queue->pushOn($command->queue, $command);
  230. }
  231. if (isset($command->delay)) {
  232. return $queue->later($command->delay, $command);
  233. }
  234. return $queue->push($command);
  235. }
  236. /**
  237. * Get the handler instance for the given command.
  238. *
  239. * @param mixed $command
  240. * @return mixed
  241. */
  242. public function resolveHandler($command)
  243. {
  244. if ($command instanceof SelfHandling) {
  245. return $command;
  246. }
  247. return $this->container->make($this->getHandlerClass($command));
  248. }
  249. /**
  250. * Get the handler class for the given command.
  251. *
  252. * @param mixed $command
  253. * @return string
  254. */
  255. public function getHandlerClass($command)
  256. {
  257. if ($command instanceof SelfHandling) {
  258. return get_class($command);
  259. }
  260. return $this->inflectSegment($command, 0);
  261. }
  262. /**
  263. * Get the handler method for the given command.
  264. *
  265. * @param mixed $command
  266. * @return string
  267. */
  268. public function getHandlerMethod($command)
  269. {
  270. if ($command instanceof SelfHandling) {
  271. return 'handle';
  272. }
  273. return $this->inflectSegment($command, 1);
  274. }
  275. /**
  276. * Get the given handler segment for the given command.
  277. *
  278. * @param mixed $command
  279. * @param int $segment
  280. * @return string
  281. */
  282. protected function inflectSegment($command, $segment)
  283. {
  284. $className = get_class($command);
  285. if (isset($this->mappings[$className])) {
  286. return $this->getMappingSegment($className, $segment);
  287. } elseif ($this->mapper) {
  288. return $this->getMapperSegment($command, $segment);
  289. }
  290. throw new InvalidArgumentException("No handler registered for command [{$className}]");
  291. }
  292. /**
  293. * Get the given segment from a given class handler.
  294. *
  295. * @param string $className
  296. * @param int $segment
  297. * @return string
  298. */
  299. protected function getMappingSegment($className, $segment)
  300. {
  301. return explode('@', $this->mappings[$className])[$segment];
  302. }
  303. /**
  304. * Get the given segment from a given class handler using the custom mapper.
  305. *
  306. * @param mixed $command
  307. * @param int $segment
  308. * @return string
  309. */
  310. protected function getMapperSegment($command, $segment)
  311. {
  312. return explode('@', call_user_func($this->mapper, $command))[$segment];
  313. }
  314. /**
  315. * Register command-to-handler mappings.
  316. *
  317. * @param array $commands
  318. * @return void
  319. */
  320. public function maps(array $commands)
  321. {
  322. $this->mappings = array_merge($this->mappings, $commands);
  323. }
  324. /**
  325. * Register a fallback mapper callback.
  326. *
  327. * @param \Closure $mapper
  328. * @return void
  329. */
  330. public function mapUsing(Closure $mapper)
  331. {
  332. $this->mapper = $mapper;
  333. }
  334. /**
  335. * Map the command to a handler within a given root namespace.
  336. *
  337. * @param mixed $command
  338. * @param string $commandNamespace
  339. * @param string $handlerNamespace
  340. * @return string
  341. */
  342. public static function simpleMapping($command, $commandNamespace, $handlerNamespace)
  343. {
  344. $command = str_replace($commandNamespace, '', get_class($command));
  345. return $handlerNamespace.'\\'.trim($command, '\\').'Handler@handle';
  346. }
  347. /**
  348. * Set the pipes through which commands should be piped before dispatching.
  349. *
  350. * @param array $pipes
  351. * @return $this
  352. */
  353. public function pipeThrough(array $pipes)
  354. {
  355. $this->pipes = $pipes;
  356. return $this;
  357. }
  358. }