vendor/mpociot/pipeline/src/Pipeline.php line 102

Open in your IDE?
  1. <?php
  2. namespace Mpociot\Pipeline;
  3. use Closure;
  4. class Pipeline
  5. {
  6. /**
  7. * The object being passed through the pipeline.
  8. *
  9. * @var mixed
  10. */
  11. protected $passable;
  12. /**
  13. * The array of class pipes.
  14. *
  15. * @var array
  16. */
  17. protected $pipes = [];
  18. /**
  19. * The additional parameters.
  20. *
  21. * @var array
  22. */
  23. protected $parameters = [];
  24. /**
  25. * The method to call on each pipe.
  26. *
  27. * @var string
  28. */
  29. protected $method = 'handle';
  30. /**
  31. * Set the object being sent through the pipeline.
  32. *
  33. * @param mixed $passable
  34. * @return $this
  35. */
  36. public function send(...$passable)
  37. {
  38. $this->passable = $passable;
  39. return $this;
  40. }
  41. /**
  42. * Set the array of pipes.
  43. *
  44. * @param array|mixed $pipes
  45. * @return $this
  46. */
  47. public function through($pipes)
  48. {
  49. $this->pipes = is_array($pipes) ? $pipes : func_get_args();
  50. return $this;
  51. }
  52. /**
  53. * Set the method to call on the pipes.
  54. *
  55. * @param string $method
  56. * @return $this
  57. */
  58. public function via($method)
  59. {
  60. $this->method = $method;
  61. return $this;
  62. }
  63. /**
  64. * Set the additional parameters to send
  65. *
  66. * @param mixed $parameters
  67. * @return $this
  68. */
  69. public function with(...$parameters)
  70. {
  71. $this->parameters = $parameters;
  72. return $this;
  73. }
  74. /**
  75. * Run the pipeline with a final destination callback.
  76. *
  77. * @param \Closure $destination
  78. * @return mixed
  79. */
  80. public function then(Closure $destination)
  81. {
  82. $pipeline = array_reduce(
  83. array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
  84. );
  85. return call_user_func_array($pipeline, $this->passable);
  86. }
  87. /**
  88. * Get the final piece of the Closure onion.
  89. *
  90. * @param \Closure $destination
  91. * @return \Closure
  92. */
  93. protected function prepareDestination(Closure $destination)
  94. {
  95. return function () use ($destination) {
  96. return call_user_func_array($destination, func_get_args());
  97. };
  98. }
  99. /**
  100. * Get a Closure that represents a slice of the application onion.
  101. *
  102. * @return \Closure
  103. */
  104. protected function carry()
  105. {
  106. return function ($stack, $pipe) {
  107. return function () use ($stack, $pipe) {
  108. $passable = func_get_args();
  109. $passable[] = $stack;
  110. $passable = array_merge($passable, $this->parameters);
  111. if (is_callable($pipe)) {
  112. // If the pipe is an instance of a Closure, we will just call it directly but
  113. // otherwise we'll resolve the pipes out of the container and call it with
  114. // the appropriate method and arguments, returning the results back out.
  115. return call_user_func_array($pipe, $passable);
  116. } elseif (! is_object($pipe)) {
  117. list($name, $parameters) = $this->parsePipeString($pipe);
  118. // If the pipe is a string we will parse the string and resolve the class out
  119. // of the dependency injection container. We can then build a callable and
  120. // execute the pipe function giving in the parameters that are required.
  121. $pipe = new $name();
  122. $parameters = array_merge($passable, $parameters);
  123. } else {
  124. // If the pipe is already an object we'll just make a callable and pass it to
  125. // the pipe as-is. There is no need to do any extra parsing and formatting
  126. // since the object we're given was already a fully instantiated object.
  127. $parameters = $passable;
  128. }
  129. return method_exists($pipe, $this->method)
  130. ? call_user_func_array([$pipe, $this->method], $parameters)
  131. : $pipe(...$parameters);
  132. };
  133. };
  134. }
  135. /**
  136. * Parse full pipe string to get name and parameters.
  137. *
  138. * @param string $pipe
  139. * @return array
  140. */
  141. protected function parsePipeString($pipe)
  142. {
  143. list($name, $parameters) = array_pad(explode(':', $pipe, 2), 2, []);
  144. if (is_string($parameters)) {
  145. $parameters = explode(',', $parameters);
  146. }
  147. return [$name, $parameters];
  148. }
  149. }