PageRenderTime 52ms CodeModel.GetById 7ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/techniconline/kmc
PHP | 388 lines | 169 code | 50 blank | 169 comment | 18 complexity | 0e13efd5aafadd78df63d3a8fd6d1024 MD5 | raw file
  1. <?php namespace Illuminate\Bus;
  2. use Closure;
  3. use ArrayAccess;
  4. use ReflectionClass;
  5. use RuntimeException;
  6. use ReflectionParameter;
  7. use InvalidArgumentException;
  8. use Illuminate\Pipeline\Pipeline;
  9. use Illuminate\Support\Collection;
  10. use Illuminate\Contracts\Queue\Queue;
  11. use Illuminate\Contracts\Bus\SelfHandling;
  12. use Illuminate\Contracts\Container\Container;
  13. use Illuminate\Contracts\Bus\HandlerResolver;
  14. use Illuminate\Contracts\Queue\ShouldBeQueued;
  15. use Illuminate\Contracts\Bus\QueueingDispatcher;
  16. use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
  17. class Dispatcher implements DispatcherContract, QueueingDispatcher, HandlerResolver
  18. {
  19. /**
  20. * The container implementation.
  21. *
  22. * @var \Illuminate\Contracts\Container\Container
  23. */
  24. protected $container;
  25. /**
  26. * The pipeline instance for the bus.
  27. *
  28. * @var \Illuminate\Pipeline\Pipeline
  29. */
  30. protected $pipeline;
  31. /**
  32. * The pipes to send commands through before dispatching.
  33. *
  34. * @var array
  35. */
  36. protected $pipes = [];
  37. /**
  38. * The queue resolver callback.
  39. *
  40. * @var \Closure|null
  41. */
  42. protected $queueResolver;
  43. /**
  44. * All of the command-to-handler mappings.
  45. *
  46. * @var array
  47. */
  48. protected $mappings = [];
  49. /**
  50. * The fallback mapping Closure.
  51. *
  52. * @var \Closure
  53. */
  54. protected $mapper;
  55. /**
  56. * Create a new command dispatcher instance.
  57. *
  58. * @param \Illuminate\Contracts\Container\Container $container
  59. * @param \Closure|null $queueResolver
  60. * @return void
  61. */
  62. public function __construct(Container $container, Closure $queueResolver = null)
  63. {
  64. $this->container = $container;
  65. $this->queueResolver = $queueResolver;
  66. $this->pipeline = new Pipeline($container);
  67. }
  68. /**
  69. * Marshal a command and dispatch it to its appropriate handler.
  70. *
  71. * @param mixed $command
  72. * @param array $array
  73. * @return mixed
  74. */
  75. public function dispatchFromArray($command, array $array)
  76. {
  77. return $this->dispatch($this->marshalFromArray($command, $array));
  78. }
  79. /**
  80. * Marshal a command and dispatch it to its appropriate handler.
  81. *
  82. * @param mixed $command
  83. * @param \ArrayAccess $source
  84. * @param array $extras
  85. * @return mixed
  86. */
  87. public function dispatchFrom($command, ArrayAccess $source, array $extras = [])
  88. {
  89. return $this->dispatch($this->marshal($command, $source, $extras));
  90. }
  91. /**
  92. * Marshal a command from the given array.
  93. *
  94. * @param string $command
  95. * @param array $array
  96. * @return mixed
  97. */
  98. protected function marshalFromArray($command, array $array)
  99. {
  100. return $this->marshal($command, new Collection, $array);
  101. }
  102. /**
  103. * Marshal a command from the given array accessible object.
  104. *
  105. * @param string $command
  106. * @param \ArrayAccess $source
  107. * @param array $extras
  108. * @return mixed
  109. */
  110. protected function marshal($command, ArrayAccess $source, array $extras = [])
  111. {
  112. $injected = [];
  113. $reflection = new ReflectionClass($command);
  114. if ($constructor = $reflection->getConstructor()) {
  115. $injected = array_map(function ($parameter) use ($command, $source, $extras) {
  116. return $this->getParameterValueForCommand($command, $source, $parameter, $extras);
  117. }, $constructor->getParameters());
  118. }
  119. return $reflection->newInstanceArgs($injected);
  120. }
  121. /**
  122. * Get a parameter value for a marshaled command.
  123. *
  124. * @param string $command
  125. * @param \ArrayAccess $source
  126. * @param \ReflectionParameter $parameter
  127. * @param array $extras
  128. * @return mixed
  129. */
  130. protected function getParameterValueForCommand($command, ArrayAccess $source,
  131. ReflectionParameter $parameter, array $extras = array())
  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 ShouldBeQueued) {
  190. return true;
  191. }
  192. return (new ReflectionClass($this->getHandlerClass($command)))->implementsInterface(
  193. 'Illuminate\Contracts\Queue\ShouldBeQueued'
  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. $command->queue($queue, $command);
  212. } else {
  213. $queue->push($command);
  214. }
  215. }
  216. /**
  217. * Get the handler instance for the given command.
  218. *
  219. * @param mixed $command
  220. * @return mixed
  221. */
  222. public function resolveHandler($command)
  223. {
  224. if ($command instanceof SelfHandling) {
  225. return $command;
  226. }
  227. return $this->container->make($this->getHandlerClass($command));
  228. }
  229. /**
  230. * Get the handler class for the given command.
  231. *
  232. * @param mixed $command
  233. * @return string
  234. */
  235. public function getHandlerClass($command)
  236. {
  237. if ($command instanceof SelfHandling) {
  238. return get_class($command);
  239. }
  240. return $this->inflectSegment($command, 0);
  241. }
  242. /**
  243. * Get the handler method for the given command.
  244. *
  245. * @param mixed $command
  246. * @return string
  247. */
  248. public function getHandlerMethod($command)
  249. {
  250. if ($command instanceof SelfHandling) {
  251. return 'handle';
  252. }
  253. return $this->inflectSegment($command, 1);
  254. }
  255. /**
  256. * Get the given handler segment for the given command.
  257. *
  258. * @param mixed $command
  259. * @param int $segment
  260. * @return string
  261. */
  262. protected function inflectSegment($command, $segment)
  263. {
  264. $className = get_class($command);
  265. if (isset($this->mappings[$className])) {
  266. return $this->getMappingSegment($className, $segment);
  267. } elseif ($this->mapper) {
  268. return $this->getMapperSegment($command, $segment);
  269. }
  270. throw new InvalidArgumentException("No handler registered for command [{$className}]");
  271. }
  272. /**
  273. * Get the given segment from a given class handler.
  274. *
  275. * @param string $className
  276. * @param int $segment
  277. * @return string
  278. */
  279. protected function getMappingSegment($className, $segment)
  280. {
  281. return explode('@', $this->mappings[$className])[$segment];
  282. }
  283. /**
  284. * Get the given segment from a given class handler using the custom mapper.
  285. *
  286. * @param mixed $command
  287. * @param int $segment
  288. * @return string
  289. */
  290. protected function getMapperSegment($command, $segment)
  291. {
  292. return explode('@', call_user_func($this->mapper, $command))[$segment];
  293. }
  294. /**
  295. * Register command-to-handler mappings.
  296. *
  297. * @param array $commands
  298. * @return void
  299. */
  300. public function maps(array $commands)
  301. {
  302. $this->mappings = array_merge($this->mappings, $commands);
  303. }
  304. /**
  305. * Register a fallback mapper callback.
  306. *
  307. * @param \Closure $mapper
  308. * @return void
  309. */
  310. public function mapUsing(Closure $mapper)
  311. {
  312. $this->mapper = $mapper;
  313. }
  314. /**
  315. * Map the command to a handler within a given root namespace.
  316. *
  317. * @param mixed $command
  318. * @param string $commandNamespace
  319. * @param string $handlerNamespace
  320. * @return string
  321. */
  322. public static function simpleMapping($command, $commandNamespace, $handlerNamespace)
  323. {
  324. $command = str_replace($commandNamespace, '', get_class($command));
  325. return $handlerNamespace . '\\' . trim($command, '\\') . 'Handler@handle';
  326. }
  327. /**
  328. * Set the pipes through which commands should be piped before dispatching.
  329. *
  330. * @param array $pipes
  331. * @return $this
  332. */
  333. public function pipeThrough(array $pipes)
  334. {
  335. $this->pipes = $pipes;
  336. return $this;
  337. }
  338. }