Get the arguments for a function from a route using reflection

@param \stdClass                   $route
@param \ReflectionFunctionAbstract $refl
@return array
16182
protected function getFunctionArgs(\stdClass $route, \ReflectionFunctionAbstract $refl)
    {
        $args = [];
        $params = $refl->getParameters();

        foreach ($params as $param) {
            $key = $param->name;

            if (property_exists($route, $key)) {
                $value = $route->$key;
            } else {
                if (!$param->isOptional()) {
                    $fn = $refl instanceof \ReflectionMethod ? $refl->class . '::' . $refl->name : $refl->name;
                    throw new \RuntimeException("Missing argument '$key' for {$fn}()");
                }
                
                $value = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
            }

            $args[$key] = $value;
        }
        
        return $args;
    }
150672
public function route($route, $prefix = null)
    {
        $this->route = substr($route, strlen($prefix));
        $parameters = [];

        // Go through predefined routes till a match is found
        foreach ($this->routeOrder as $routeName) {
            $routeDescription = $this->routes[$routeName];
            $parameters = $this->match($this->route, $routeDescription);
            if ($parameters !== false) {
                return [
                    'route' => $this->route,
                    'parameters' => $this->fillInDefaultParameters($routeDescription, $parameters),
                    'description' => $routeDescription
                ];
            }
        }
        return [
            'route' => $this->route,
            'parameters' => $parameters,
            'description' => $this->routes['default']
        ];
    }
666308
protected function buildCallbackFromControllerRoute($route)
    {
        list($controller, $methodName) = $this->determineClassAndMethod($route);
        $app      = & $this;
        $callable = function () use ($app, $controller, $methodName) {
            // Get action arguments
            $args = func_get_args();
            // Try to fetch the instance from Slim's container, otherwise lazy-instantiate it
            $instance = $app->container->has($controller) ? $app->container->get($controller) : new $controller($app);

            return call_user_func_array(array($instance, $methodName), $args);
        };

        return $callable;
    }
1148296
public function parseRoute (Route $route) {

		if (preg_match_all('#^' . $route->getRoute () . '$#', $this->getUrl (), $matches, PREG_OFFSET_CAPTURE)) {

			// Rework matches to only contain the matches, not the orig string
			$matches = array_slice($matches, 1);

			// Extract the matched URL parameters (and only the parameters)
			$params = array_map(function($match, $index) use ($matches) {

				// We have a following parameter: take the substring from the current param position until the next one's position (thank you PREG_OFFSET_CAPTURE)
				if (isset($matches[$index+1]) && isset($matches[$index+1][0]) && is_array($matches[$index+1][0])) {
					return trim(substr($match[0][0], 0, $matches[$index+1][0][1] - $match[0][1]), '/');
				}

				// We have no following paramete: return the whole lot
				else {
					return (isset($match[0][0]) ? trim($match[0][0], '/') : null);
				}

			}, $matches, array_keys($matches));

			if (empty ($params)) {
				return true;
			}
			else {
				return $params;
			}
		}

		return false;
	}
773422
private function extractFunctionFromRoute(Route $route)
    {
        $controller = explode('::', $this->extractControllerDefaultFromRoute($route));

        return isset($controller[1]) ? $controller[1] : null;
    }
520855
private function createRegexp($uri, Route $route)
    {
        $patterns = [];
        foreach ($route->getParameterPatterns() as $key => $pattern) {
            $patterns['\\{' . $key . '\\}'] = '(' . $pattern . ')';
        }
        $uri = preg_quote($uri, '#');

        return strtr($uri, $patterns);
    }
82544
protected function callback($route) {
		return function (&...$args) use ($route) {
			// Grab args using function because we don't know the number of args being passed.
			// https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
			// https://wiki.php.net/rfc/variadics
			$route = preg_replace('/[^a-zA-Z0-9_\/]/', '', (string)$route);

			// Keep the original trigger
			$trigger = $route;

			// Trigger the pre events
			$result = $this->registry->get('event')->trigger('model/' . $trigger . '/before', array(&$route, &$args));

			if ($result && !$result instanceof Exception) {
				$output = $result;
			} else {
				$class = 'Model' . preg_replace('/[^a-zA-Z0-9]/', '', substr($route, 0, strrpos($route, '/')));

				// Store the model object
				$key = substr($route, 0, strrpos($route, '/'));

				// Check if the model has already been initialised or not
				if (!$this->registry->has($key)) {
					$object = new $class($this->registry);

					$this->registry->set($key, $object);
				} else {
					$object = $this->registry->get($key);
				}

				$method = substr($route, strrpos($route, '/') + 1);

				$callable = array($object, $method);

				if (is_callable($callable)) {
					$output = call_user_func_array($callable, $args);
				} else {
					throw new \Exception('Error: Could not call model/' . $route . '!');
				}
			}

			// Trigger the post events
			$result = $this->registry->get('event')->trigger('model/' . $trigger . '/after', array(&$route, &$args, &$output));

			if ($result && !$result instanceof Exception) {
				$output = $result;
			}

			return $output;
		};
	}
509248
protected function getRouteInformation(Route $route)
    {
        if ($route->getName()) {
            return [
                'uri'    => $route->uri(),
                'name'   => $route->getName(),
                'before' => $this->getBeforeFilters($route),
            ];
        }

        return null;
    }
632639
private function getParams($currentPath, $route)
    {
        $path = substr($currentPath, strlen($route));
        $path = (substr($path, 0, 1) == "/") ? substr($path, 1) : $path;
        $path = (substr($path, -1) == "/") ? substr($path, 0, -1) : $path;

        $this->getFilterParams($path);
        $this->getDataParams();
        $this->parseParameterValues();
        $this->cleanReservedParams();
    }
352865
private function getPostInterceptors(CalledUri $calledUri, Route $route = null): array
    {
        $global = $this->getApplicable($calledUri, $this->postInterceptors);
        if (null === $route) {
            return $global;
        }

        return array_merge($route->postInterceptors(), $global);
    }
689379
private function getFunctionArguments(\ReflectionFunctionAbstract $reflection, $values)
    {
        $arguments = [];
        if (!empty($reflection->getParameters())) {
            foreach ($values as $value) {
                $arguments[] = $value;
            }
        }
        return $arguments;
    }
1077128
public function getRouteProperties($route, Request $request)
    {
        return [$route->uri(), $route->methods(), $route->getAction()];
    }
353386
protected function getRegExpRoute($route)
    {
        return preg_replace_callback(
            '#(/?)\{(\S+?)(:(\S+?))?\}#',
            function (array $matches) {
                $startMod = $matches[1];
                $name = $matches[2];
                $type = isset($matches[4]) ? $matches[4] : 'string';

                $type = $this->getTypeRegexp($type);

                $regexp = $startMod . "(?P<$name>$type)";
                if (!$this->isRequiredParam($name)) {
                    $regexp = "({$regexp})?";
                }

                return $regexp;
            },
            $route
        );
    }
1300368
protected function computeMissingRouteParameters(Route $route, array $parameters): array
    {
        $compiledRoute = $route->compile();
        $variables = array_flip($compiledRoute->getVariables());
        $mergedParams = array_replace($route->getDefaults(), $this->router->getContext()->getParameters(), $parameters);

        return array_flip(array_diff_key($variables, $mergedParams));
    }
1056695
public function dispatch($route, $request)
    {
        $request->setParam('Closure', $route[4]);

        if(isset($route[3]) && is_string($route[3])) {
            $view = $route[3];
            $data = $route[4];
            return ['view' => [$view, $data]];
        }
        elseif(isset($route[2]) && is_string($route[2])) {
            list($controller, $method) = explode('@', $route[2]);
            return ['controller' => [$controller, $method]];
        }
        elseif(isset($route[2]) && ($route[2] instanceof Closure || get_class($route[2]) === "Closure")) {
            $function = $route[2];
            $reflectionFunction = new ReflectionFunction($function);
            $numReqParam = $reflectionFunction->getNumberOfRequiredParameters();
            if($numReqParam > count($request->getParam('Closure'))) {
                throw new Exception('Invaliding number of required parameter passed in route\'s callable function: '.$route[1]);
            }
            ob_start();
            if($request->getParam('Closure') !== false && is_array($request->getParam('Closure')) ) {
                $return = call_user_func_array($route[2], $request->getParam('Closure'));
            }
            else {
                //$function();
                throw new Exception('Invaliding parameter passed in route\'s callable function: '.$route[1]);
            }
            $output = ob_get_clean();
            return ['output' => [$output, $return]];
        }
        else {
            throw new Exception('Invaliding route is registered for: '.$route[1]);
        }
    }
413373
private function getArguments(\ReflectionMethod $method)
    {
        $arguments = [];

        foreach ($method->getParameters() as $index => $parameter) {
            $argument = $this->getArgument($index, $parameter);

            if (null === $argument && false === $parameter->allowsNull()) {
                throw new Exception(
                    sprintf('Could not inject parameter #%d into "%s::__construct"', $index, $this->item)
                );
            }

            $arguments[] = $argument;
        }

        return $arguments;
    }
749322
public function dispatch(Route $route)
    {
        $callback = $route->getCallback();
        $params = array_values($route->getData());

        if ($callback instanceof Closure) {
            return $this->container->resolveClosure($callback, $params);
        }

        $class = $this->container->make($callback[0]);
        return $this->container->resolveMethod($class, $callback[1], $params);
    }