Get the arity of a handler

@param string|callable|object $callable
@return int
517838
public static function getArity($callable)
    {
        if (is_object($callable)) {
            foreach (['__invoke', 'handle'] as $method) {
                if (! method_exists($callable, $method)) {
                    continue;
                }

                $r = new ReflectionMethod($callable, $method);
                return $r->getNumberOfRequiredParameters();
            }
            return 0;
        }

        if (! is_callable($callable)) {
            return 0;
        }

        $r = new ReflectionFunction($callable);
        return $r->getNumberOfRequiredParameters();
    }
1025773
private static function reg($callable)
    {
        $id = debug_backtrace()[2]['function'];
        if (! self::getInstance()->offsetExists($id)) {
            self::getInstance()->offsetSet($id, $callable);
        }
        return self::getInstance()->offsetGet($id);
    }
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;
    }
1073567
public function resolve($callable)
    {
        if (is_string($callable) && strpos($callable, '::') !== false) {
            $callable = explode('::', $callable, 2);
        }

        $callable = $this->resolveFromContainer($callable);

        if (! is_callable($callable)) {
            throw NotCallableException::fromInvalidCallable($callable, true);
        }

        return $callable;
    }
985369
public function compiled(callable $callable): string
    {
        if (! $this->compiler) {
            $this->compiler = new Compiler(
                new AstAnalyzerAdapter(
                    new AstAnalyzer
                )
            );
        }

        return ($this->compiler)($callable);
    }
819166
public function reduce($callable)
	{
		$ret = true;
		$carry = null;
		for( $this->rewind(); $this->valid(); $this->next() )
		{
			$model = $this->current();
			if( $carry !== null && !$callable($carry,$model) )
			{
				$ret = false;
				break;
			}
			$carry = $model;
		}
		return $ret;
	}
662743
public static function call(callable $callable, $args=null)
    {

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

        return static::callFast($callable, static::evaluateArgs($args));

    }
23656
public function setStrainerDateRange($callable = null, $attr = [])
    {

        // if callable is a string , it's a field
        if (is_string($callable) || $callable instanceof Expression) {
            $field = $callable;
            $callable = null;
        }

        // create the strainer
        $strainer = new DateRange($this, $callable, $attr);

        //if a fields is set, we configure the strainer
        if (isset($field)) {
            $strainer->setField($field);
        }

        return $this->setStrainer($strainer);
    }
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");
    }
127074
public static function invokeCallable($callable, $args = null)
    {
        if (null != $args) {
            if (is_array($args)) {
                $results = call_user_func_array($callable, $args);
            } else {
                $results = call_user_func($callable, $args);
            }
        } else {
            $results = call_user_func($callable);
        }

        return $results;
    }
827158
public function invoke(Callable $callable, array $args = [])
    {
        // object/class method
        if (is_string($callable) && false !== strpos($callable, '::')) {
            $callable = explode('::', $callable);
        }
        if (is_array($callable)) {
            $reflection = new \ReflectionMethod($callable[0], $callable[1]);
        }

        // closures, functions and any other callable
        if (!isset($reflection)) {
            $reflection = new \ReflectionFunction($callable);
        }

        // inject arguments
        $arguments = $this->inject($reflection, $args);
        return $callable(...$arguments);
    }
111967
public function map($callable)
    {
        if (!$this->isCallable($callable)) {
            throw new ArrayObjectException(ArrayObjectException::MSG_INVALID_PARAM, [
                '$callable',
                'a callable function or method'
            ]);
        }

        $this->val(array_map($callable, $this->val()));

        return $this;
    }
773217
private static function getCallToolArgs($callable, $tool, $operation)
    {
        $className = get_parent_class($callable[0]);
        $methodRef = new \ReflectionMethod($className, $callable[1]);
        $annotations = ToolParser::getInstance()->getData()['class'][$className]['Methods'][$methodRef->name]['Args'] ?? [];
        $args = [];
        foreach($methodRef->getParameters() as $param)
        {
            $annotation = $annotations[$param->name] ?? null;
            if(null === $annotation)
            {
                $value = $param->isOptional() ? $param->getDefaultValue() : null;
            }
            else if(Args::exists($annotation->name))
            {
                $value = static::parseArgValue(Args::get($annotation->name), $annotation);
            }
            else if($annotation->required)
            {
                throw new \InvalidArgumentException(sprintf('tool %s/%s param %s is required', $tool, $operation, $annotation->name));
            }
            else
            {
                $value = $annotation->default;
            }
            $args[] = $value;
        }
        return $args;
    }
381912
public function annotate(callable $callable) {
		$fn = null;
		$invoke = function () {};

		// TODO can this be *any* cleaner?
		if(is_array($callable)) {
			// support shorthand array callable form
			// callable arrays will always have 2 elements--otherwise they don't pass the typehint
			$cls = new ReflectionClass($callable[0]);
			$fn = $cls->getMethod($callable[1]);
			$invoke = function ($args) use($fn, $callable) {
				return function () use($fn, $callable, $args) {
					return $fn->invokeArgs($callable[0], $args);
				};
			};
		} else if(!($callable instanceof \Closure)) {
			// support magic __invoke method form
			$cls = new ReflectionClass($callable);
			$fn = $cls->getMethod('__invoke');
			$invoke = function ($args) use($fn, $callable) {
				return function () use($fn, $callable, $args) {
					return $fn->invokeArgs($callable, $args);
				};
			};
		} else {
			// support all other callables
			$fn = new ReflectionFunction($callable);
			$invoke = function ($args) use($fn) {
				return function () use($fn, $args) {
					return $fn->invokeArgs($args);
				};
			};
		}

		$cacheId = sha1($fn->__toString());
		if(array_key_exists($cacheId, $this->fnCache)) {
			return $this->fnCache[$cacheId];
		}

		$args = $this->getArgs($fn);
		$annotated = $invoke($args);
		$this->fnCache[$cacheId] = $annotated;
		return $annotated;
	}
102447
public function parseIdGenerator($callable)
    {
        if ($callable instanceof Closure) {
            return $callable;
        }

        $class    = null;
        $method   = null;
        $isMethod = false;
        $isModel  = false;
        $bail     = false;

        if (is_array($callable) && count($callable) === 2) {
            list($class, $func) = $callable;
            $isMethod = ($class && $func);
        } elseif (is_string($callable) && strpos($callable, '::') > 1) {
            list($class, $func) = explode('::', $callable);
            $isMethod = ($class && $func);
        }

        if ($isMethod) {
            $model   = $this->targetModel();
            $isModel = is_a($model, $class);

            $method = new ReflectionMethod($class, $func);
            if ($isModel && $method->isPublic()) {
                return $method->getClosure($model);
            } elseif ($method->isStatic() && $method->isPublic()) {
                return $callable;
            } else {
                $bail = true;
            }
        }

        if ($bail || !(is_string($callable) && function_exists($callable))) {
            throw new InvalidArgumentException(
                sprintf(
                    'The ID generator must be callable, received: %s',
                    is_object($callable)
                        ? get_class($callable)
                        : (is_string($callable)
                            ? $callable
                            : gettype($callable)
                        )
                )
            );
        }

        return $callable;
    }
1112081
protected function performStringCallable($callable)
    {
        if ( ! preg_match('#^(?<class>[\\a-z0-9_]+)@(?<method>[a-z0-9_]+)$#i', $callable, $matches)) {
            throw new \UnexpectedValueException("Unable to process callable string '{$callable}'");
        }

        $instance = app($matches['class']);

        $result = $instance->{$matches['method']}($this);

        return $result === null ? true : (bool) $result;
    }
127270
static function prototype(callable $callable) {
        /** @var \ReflectionMethod|\ReflectionFunction  $prototype */
        
        if(\is_array($callable)) {
            $prototype = new \ReflectionMethod($callable[0], $callable[1]);
        } else {
            $prototype = new \ReflectionFunction($callable);
        }
        
        $signature = '';
        
        /** @var \ReflectionParameter  $param */
        foreach($prototype->getParameters() as $param) {
            $type = $param->getType();
            $signature .= ($type->allowsNull() ? '?' : '').$type->getName().($param->isOptional() ? '?' : '').',';
        }
        
        $signature = \substr($signature, 0, -1);
        
        $return = $prototype->getReturnType();
        if($return !== null) {
            $signature .= '='.($return->allowsNull() ? '?' : '').$return->getName();
        }
        
        if(empty($signature)) {
            throw new \InvalidArgumentException('Given callable has no signature to build');
        }
        
        return $signature;
    }