. namespace hoplite\http2; require_once HOPLITE_ROOT . '/http2/middleware.php'; require_once HOPLITE_ROOT . '/http2/request.php'; require_once HOPLITE_ROOT . '/http2/response.php'; class Pipeline { private $middleware = []; public function add($middleware) { /* if (!($middleware instanceof Middleware || $middleware instanceof \Closure || is_array($middleware))) { // TODO(php7): TypeError throw new \Exception(__FUNCTION__ . ' requires a Middleware or Closure'); } */ $this->middleware[] = $middleware; return $this; } public function build() { $chain = new Sentinel(new NotFoundResponse()); for ($i = count($this->middleware) - 1; $i >= 0; --$i) { $args = $this->middleware[$i]; if ($args instanceof \Closure) { $chain = new ClosureMiddleware($this, $chain, $args); } else if (is_array($args)) { $class = array_shift($args); array_unshift($args, $this, $chain); $chain = new $class(...$args); } else { $chain = new $args($this, $chain); } } return $chain; } public function run(Middleware $chain) { $response = $chain->execute(new Request()); $response->generate(); } public function buildAndRun() { $this->run($this->build()); } } class SubPipeline extends Middleware { public function __construct(Pipeline $subpipe) { // Skip calling super since this is a new pipeline and the // next middleware will be selected by building the subpipe. // It would be possible to build the middleware chain here, but // doing it lazily on execution is more efficient, since SubPipeline // should be used to partition applications. $this->subpipe = $subpipe; } public function execute(Request $request) { return $this->subpipe->build()->execute($request); } }