Add middleware

@param callable $callable Any callable that accepts two arguments:
1. A Request object
2. A Response object
@return static

@throws \RuntimeException If middleware is added while the stack is dequeuing
422212
private function addMiddleware(callable $callable, $stackName, $whenStackName)
    {
        // 禁止中间件执行过程中又添加中间件到栈中
        if ($this->middlewareLock) {
            throw new \RuntimeException(
                'Middleware can’t be added once the stack is dequeuing'
            );
        }

        if (!$this->tip) {
            $this->seedMiddlewareStack();
        }

        // 对callable做封装，以执行自动遍历
        $this->{$stackName}->enqueue(
            function ($request, $response) use (
                $callable, 
                $stackName, 
                $whenStackName
            ) {
                // return [Request, Response] or WhenCallable
                $result = call_user_func($callable, $request, $response);

                // callable返回WhenCallable，表示是有条件决断的中间件
                if ($result instanceof WhenCallable) {
                    // 返回条件满足时要执行的callable
                    $callable = $result->resolve($request, $response);
                    // 入栈继续等待
                    if ($callable===false) {
                        $this->{$whenStackName}->attach($result);
                    }
                    else {
                        // return [Request, Response]
                        $result = call_user_func($callable, $request, $response);
                    }
                }

                // 不是WhenCallable条件未达到的情况
                if ($callable!==false) {
                    
                    $this->checkReturn($result);

                    list ($request, $response) = $result;
                    // 执行处于等待中的决断
                    $this->{$whenStackName}->rewind();

                    while ($this->{$whenStackName}->valid()) {

                        $callable = $this->{$whenStackName}->current();
                        
                        $callable = $callable->resolve($request, $response);
                        // 条件决断再次失败
                        if ($callable===false) {
                            // null
                        }
                        else {
                            // return [req,res]
                            $result = call_user_func($callable, $request, $response);

                            $this->checkReturn($result);

                            list ($request, $response) = $result;

                            $this->{$whenStackName}->detach($callable);
                        }

                        $this->{$whenStackName}->next();
                    }
                }

                // 执行下个中间件
                if (!$this->{$stackName}->isEmpty()) {
                    $next = $this->{$stackName}->dequeue();
                    $result = $next($request, $response);
                }

                // [Request, Response]
                return $result;
            }
        );

        return $this;
    }
228913
protected function callableOptions($callable)
    {
        // resolve closure
        if (is_callable($callable)) {
            return $callable;
        }

        // resolve callable "Class@method" style
        if (is_string($callable) && list($class, $method) = explode('@', $callable)) {
            return [app()->make($class), $method];
        }

        // resolve callable [$object, "method"]
        if (2 === count($callable) && array_key_exists(0, $callable) && array_key_exists(1, $callable)) {
            if (is_object($class = $callable[0]) && is_string($method = $callable[1]) && method_exists($class, $method)) {
                return [$class, $method];
            }
        }

        return false;
    }
525625
public function register(callable $callable)
    {
        $this->groups[$this->group] = $this->options;

        $callable($this);

        array_pop($this->groups);

        return $this;
    }
539535
public function addMiddleware($callback)
    {
        $this->middlewares[] = function (Callable $next, Request $request, Response $response) use ($callback) {
            $container = Container::getInstance();
            $parameters = array_merge([
                "request"   => $request,
                "response"  => $response,
                "next"      => $next
            ], $request->getData());

            $container->call($callback, $parameters);
        };
    }
701459
public static function call($callable, $args)
    {
        if (is_scalar($callable) && mb_orig_strpos($callable, '::') === false) {
            return self::callFunction('', $callable, $args);
        }

        if (is_scalar($callable)) {
            $parts = explode('::', $callable);
            if (count($parts) != 2) {
                throw new \RuntimeException("Invalid callable format for '$callable', expected single '::'");
            }
            list($obj, $method) = $parts;
        } else if (is_array($callable)) {
            if (count($callable) != 2) {
                throw new \RuntimeException("Invalid callable format, expected array of exactly 2 elements");
            }
            list($obj, $method) = $callable;
        } else {
            return call_user_func_array($callable, $args);
        }

        if (is_object($obj)) {
            return self::callMethod($obj, null, $method, $args, true);
        } else if (is_scalar($obj)) {
            return self::callStaticMethod($obj, $method, $args, true);
        }

        throw new \RuntimeException("Invalid callable format, expected first array element to be object or scalar, " . gettype($obj) . " given");
    }
560344
public function add(callable $newTopMiddleware)
    {
        if ($this->isGuarded) {
            if ($newTopMiddleware instanceof GuardInterface) {
                throw new \RuntimeException('Invalid state: already guarded');
            }
        } else {
            if (!($newTopMiddleware instanceof GuardInterface)) {
                throw new \RuntimeException('Invalid state: not guarded');
            }
        }

        $clone = clone $this;
        $clone->isGuarded = true;

        return $clone->push($newTopMiddleware);
    }
307878
public function setHandler($handlerName, $handlerCallback)
    {
        $this->checkHandlerName($handlerName);

        if (!is_callable($handlerCallback))
        {
            throw new RuntimeException("Handler callback must be callable");
        }

        $this->handlers[$handlerName] = $handlerCallback;

        return $this;
    }
944371
public function map(callable $callable)
    {
        $keys = $this->keys();
        $items = array_map($callable, $this->attributes, $keys);

        return new static(array_combine($keys, $items));
    }
352354
public function push($callable, $args = [], $options = [])
    {
        $queue = $this->engine->setting($options, 'queue');
        $item = [
            'queue' => $queue,
            'class' => $callable,
            'args'  => [$args],
            'id'    => md5(uniqid('', true)),
            'queue_time' => microtime(true),
        ];
        $success = $this->engine->push($item, $options);

        unset($item['id']);
        if ($success) {
            $item['id'] = $this->engine->lastJobId();
        }

        $item['args'] = $args;
        $this->dispatchEvent('Queue.afterEnqueue', [
            'item' => $item,
            'success' => $success,
        ]);

        return $success;
    }
1225499
public function _and(callable $callable = null)
    {
        $history = $this->opIsAnd;
        $this->opIsAnd = true;

        if (is_callable($callable)) {
            $this->lBrackets();
            $callable();
            $this->rBrackets();
            $this->opIsAnd = $history;
        }

        return $this;
    }
164671
public function insert($table, callable $callable = null)
    {

        $this->connect($table);
        $insert = new Insert($this);

        return $callable($insert);
    }
489335
public function dynamic($callable)
    {
        return $this->attributes[$this->attribute] = new self::$classMap['dynamic']($this->attribute, $this->entity, $callable);
    }
957258
public function execute($callable = null)
    {
        if ($callable && !is_callable($callable)) {
            throw new \InvalidArgumentException('The argument must be a callable object.');
        }

        $exception = null;
        $this->setRunning(true);

        try {
            if ($callable) {
                call_user_func($callable, $this);
            }

            $this->flushPipeline();
        } catch (\Exception $exception) {
            // NOOP
        }

        $this->setRunning(false);

        if ($exception) {
            throw $exception;
        }

        return $this->responses;
    }
624027
public static function callFast(callable $callable, $args=null)
    {

        if (!is_array($args)) {
            return call_user_func($callable, $args === null ? [] : [$args]);
        }

        switch (count($args)) {
            case 0:
                return call_user_func($callable);
            case 1:
                return call_user_func($callable, $args[0]);
            case 2:
                return call_user_func($callable, $args[0], $args[1]);
            case 3:
                return call_user_func($callable, $args[0], $args[1], $args[2]);
            case 4:
                return call_user_func($callable, $args[0], $args[1], $args[2], $args[3]);
        }

        return call_user_func_array($callable, $args);
    }
1098887
public function extend($name, callable $callable)
    {
        $name = $name == '*' ? '*.*.*' : $name;
        $this->checkSegmentCount($name);
        $this->_extensions[$name] = $callable;

        return $this;
    }
252242
public function insert(
        callable $callable,
        /*# int */ $priority,
        /*# bool */ $sort = true
    ) {
        static $MAX = 9999999;

        if ($priority > 100 || $priority < 0) {
            throw new Exception\InvalidArgumentException(
                Message::get(Message::INVALID_EVENT_PRIORITY, $priority),
                Message::INVALID_EVENT_PRIORITY
            );
        }

        // key
        $key  = $priority * 10000000 + $MAX--;
        $this->queue[$key] = ['data' => $callable, 'priority' => $priority ];

        // sort by priority
        if ($sort) {
            $this->sort();
        }
    }
1110286
public static function fork($callable)
    {
        if (!is_callable($callable)) {
            throw new \RuntimeException('Callable is not callable.');
        }
        $pid = pcntl_fork();
        if ($pid < 0) {
            throw new \RuntimeException('Unable to fork');
        }

        if ($pid == 0) {
            call_user_func($callable);
            exit;
        }

        $tracker = new PidTracker($pid);

        return $tracker;
    }