PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/dzakiafif/cokelatklasik
PHP | 411 lines | 183 code | 52 blank | 176 comment | 22 complexity | 48cb5bcdff99d671650f1180dd293ce3 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 marshaled 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,
  132. ReflectionParameter $parameter, array $extras = [])
  133. {
  134. if (array_key_exists($parameter->name, $extras)) {
  135. return $extras[$parameter->name];
  136. }
  137. if (isset($source[$parameter->name])) {
  138. return $source[$parameter->name];
  139. }
  140. if ($parameter->isDefaultValueAvailable()) {
  141. return $parameter->getDefaultValue();
  142. }
  143. MarshalException::whileMapping($command, $parameter);
  144. }
  145. /**
  146. * Dispatch a command to its appropriate handler.
  147. *
  148. * @param mixed $command
  149. * @param \Closure|null $afterResolving
  150. * @return mixed
  151. */
  152. public function dispatch($command, Closure $afterResolving = null)
  153. {
  154. if ($this->queueResolver && $this->commandShouldBeQueued($command)) {
  155. return $this->dispatchToQueue($command);
  156. } else {
  157. return $this->dispatchNow($command, $afterResolving);
  158. }
  159. }
  160. /**
  161. * Dispatch a command to its appropriate handler in the current process.
  162. *
  163. * @param mixed $command
  164. * @param \Closure|null $afterResolving
  165. * @return mixed
  166. */
  167. public function dispatchNow($command, Closure $afterResolving = null)
  168. {
  169. return $this->pipeline->send($command)->through($this->pipes)->then(function ($command) use ($afterResolving) {
  170. if ($command instanceof SelfHandling) {
  171. return $this->container->call([$command, 'handle']);
  172. }
  173. $handler = $this->resolveHandler($command);
  174. if ($afterResolving) {
  175. call_user_func($afterResolving, $handler);
  176. }
  177. return call_user_func(
  178. [$handler, $this->getHandlerMethod($command)], $command
  179. );
  180. });
  181. }
  182. /**
  183. * Determine if the given command should be queued.
  184. *
  185. * @param mixed $command
  186. * @return bool
  187. */
  188. protected function commandShouldBeQueued($command)
  189. {
  190. if ($command instanceof ShouldQueue) {
  191. return true;
  192. }
  193. return (new ReflectionClass($this->getHandlerClass($command)))->implementsInterface(
  194. 'Illuminate\Contracts\Queue\ShouldQueue'
  195. );
  196. }
  197. /**
  198. * Dispatch a command to its appropriate handler behind a queue.
  199. *
  200. * @param mixed $command
  201. * @return mixed
  202. *
  203. * @throws \RuntimeException
  204. */
  205. public function dispatchToQueue($command)
  206. {
  207. $queue = call_user_func($this->queueResolver);
  208. if (!$queue instanceof Queue) {
  209. throw new RuntimeException('Queue resolver did not return a Queue implementation.');
  210. }
  211. if (method_exists($command, 'queue')) {
  212. $command->queue($queue, $command);
  213. } else {
  214. $this->pushCommandToQueue($queue, $command);
  215. }
  216. }
  217. /**
  218. * Push the command onto the given queue instance.
  219. *
  220. * @param \Illuminate\Contracts\Queue\Queue $queue
  221. * @param mixed $command
  222. * @return void
  223. */
  224. protected function pushCommandToQueue($queue, $command)
  225. {
  226. if (isset($command->queue) && isset($command->delay)) {
  227. return $queue->laterOn($command->queue, $command->delay, $command);
  228. }
  229. if (isset($command->queue)) {
  230. return $queue->pushOn($command->queue, $command);
  231. }
  232. if (isset($command->delay)) {
  233. return $queue->later($command->delay, $command);
  234. }
  235. $queue->push($command);
  236. }
  237. /**
  238. * Get the handler instance for the given command.
  239. *
  240. * @param mixed $command
  241. * @return mixed
  242. */
  243. public function resolveHandler($command)
  244. {
  245. if ($command instanceof SelfHandling) {
  246. return $command;
  247. }
  248. return $this->container->make($this->getHandlerClass($command));
  249. }
  250. /**
  251. * Get the handler class for the given command.
  252. *
  253. * @param mixed $command
  254. * @return string
  255. */
  256. public function getHandlerClass($command)
  257. {
  258. if ($command instanceof SelfHandling) {
  259. return get_class($command);
  260. }
  261. return $this->inflectSegment($command, 0);
  262. }
  263. /**
  264. * Get the handler method for the given command.
  265. *
  266. * @param mixed $command
  267. * @return string
  268. */
  269. public function getHandlerMethod($command)
  270. {
  271. if ($command instanceof SelfHandling) {
  272. return 'handle';
  273. }
  274. return $this->inflectSegment($command, 1);
  275. }
  276. /**
  277. * Get the given handler segment for the given command.
  278. *
  279. * @param mixed $command
  280. * @param int $segment
  281. * @return string
  282. */
  283. protected function inflectSegment($command, $segment)
  284. {
  285. $className = get_class($command);
  286. if (isset($this->mappings[$className])) {
  287. return $this->getMappingSegment($className, $segment);
  288. } elseif ($this->mapper) {
  289. return $this->getMapperSegment($command, $segment);
  290. }
  291. throw new InvalidArgumentException("No handler registered for command [{$className}]");
  292. }
  293. /**
  294. * Get the given segment from a given class handler.
  295. *
  296. * @param string $className
  297. * @param int $segment
  298. * @return string
  299. */
  300. protected function getMappingSegment($className, $segment)
  301. {
  302. return explode('@', $this->mappings[$className])[$segment];
  303. }
  304. /**
  305. * Get the given segment from a given class handler using the custom mapper.
  306. *
  307. * @param mixed $command
  308. * @param int $segment
  309. * @return string
  310. */
  311. protected function getMapperSegment($command, $segment)
  312. {
  313. return explode('@', call_user_func($this->mapper, $command))[$segment];
  314. }
  315. /**
  316. * Register command-to-handler mappings.
  317. *
  318. * @param array $commands
  319. * @return void
  320. */
  321. public function maps(array $commands)
  322. {
  323. $this->mappings = array_merge($this->mappings, $commands);
  324. }
  325. /**
  326. * Register a fallback mapper callback.
  327. *
  328. * @param \Closure $mapper
  329. * @return void
  330. */
  331. public function mapUsing(Closure $mapper)
  332. {
  333. $this->mapper = $mapper;
  334. }
  335. /**
  336. * Map the command to a handler within a given root namespace.
  337. *
  338. * @param mixed $command
  339. * @param string $commandNamespace
  340. * @param string $handlerNamespace
  341. * @return string
  342. */
  343. public static function simpleMapping($command, $commandNamespace, $handlerNamespace)
  344. {
  345. $command = str_replace($commandNamespace, '', get_class($command));
  346. return $handlerNamespace.'\\'.trim($command, '\\').'Handler@handle';
  347. }
  348. /**
  349. * Set the pipes through which commands should be piped before dispatching.
  350. *
  351. * @param array $pipes
  352. * @return $this
  353. */
  354. public function pipeThrough(array $pipes)
  355. {
  356. $this->pipes = $pipes;
  357. return $this;
  358. }
  359. }