Prepare regex for resolving route a extract variables from route.

@param string $route     Route
@param array  $variables Variables

@return string Transformed route
430590
private function transformRouteVariables(string $route, array $variables) : string
    {
        list($valueToReplace, , $parametersVariables) = array_pad(
            $variables,
            3,
            null
        );

        if (isset($parametersVariables)) {
            return str_replace(
                $valueToReplace,
                '('.reset($parametersVariables).')',
                $route
            );
        }

        return str_replace($valueToReplace, '([^/]+)', $route);
    }
1060843
protected function mergeTemplate(array $variables)
    {
        $prepared_variables = [];
        foreach ($variables as $name => $value) {
            $prepared_variables[sprintf("{:%s:}", $name)] = $value;
        }

        return strtr(
            $this->getCodeTemplate(),
            $prepared_variables
        );
    }
184353
private function prepareRouteRegexp(string $route): string
    {
        if (!array_key_exists($route, self::$parsed_regexp)) {
            self::$parsed_regexp[$route] = preg_replace(array_keys($this->regexp_map), array_values($this->regexp_map), $route);
        }
        return self::$parsed_regexp[$route];
    }
580264
public function convertRouteParam($route)
    {
        $patterns = array(
            ':any?' => ':[a-zA-Z0-9\.\-_%=]?+',
            ':num?' => ':[0-9]?+',
            ':all?' => ':.?*',
            ':num' => ':[0-9]+',
            ':any' => ':[a-zA-Z0-9\.\-_%=]+',
            ':all' => ':.*',
        );

        $route = str_replace(array_keys($patterns), array_values($patterns), $route);

        return $route;
    }
1203749
private function getHypertextString($routes = [])
    {
        // Check if we have routes
        if (!$routes) {
            return '';
        }

        // Loop through the routes and add them to the string
        $str = "links: \n";
        foreach ($routes as $name => $route) {
            $str .= "\trel: {$name}. href: {$route}.\n";
        }
        return $str;
    }
487136
protected function extractParameter(string $parameter, array $variables): array
    {
        $result = preg_match(
            '/^\s*' . self::REGEX_VARIABLE . '(\s*,\s*(?<next>.+))?\s*$/is',
            $parameter,
            $matches
        );

        if ($result === 0) {
            throw new SyntaxErrorException("Invalid parameter list $parameter");
        }

        return empty($matches['next'])
            ? [$this->getValue($matches, $variables)]
            : array_merge(
                [$this->getValue($matches, $variables)],
                $this->extractParameter($matches['next'], $variables)
            );
    }
149254
public static function expand($template, array $variables)
    {
        if (strpos($template, '{') === false) {
            return $template;
        }

        self::$variables = $variables;

        return preg_replace_callback('/\{([^\}]+)\}/', [UriTemplate::class, 'expandMatch'], $template);
    }
1273038
static function substituteUrlArgTokens($route)
	{	
		$orig = $route;
		$tokens = [];
		// look for things like this {id} and like this {id?},
		// optionally preceeded by a forward slash
		while(preg_match('#/?({([\w\_]+)\??})#i', $route, $matches)) {
			// get the argument name:
			$arg = $matches[2];
			$tokens[] = $arg;
			// capture what we're going to replace 
			$subject = $matches[0];
			// make the replacement, e.g., (?P<id>[a-z\-\_]+)
			$replacement = '(?P<'.$arg.'>[^/]+)';
			// if the original arg was preceeded by a forward slash, we need to put it back
			if (stripos($subject, '/') === 0) {
				$replacement = '/' . $replacement;
			}
			// if the original arg has a ?, then we need to wrap our new token in the same
			if (stripos($subject, '?') !== false) {
				$replacement = '('.$replacement.')?';
			}
			// make the substitution
			$route = str_replace($subject, $replacement, $route);
		}
		
		return [ $route, $tokens ];
	}
504982
public static function uriTemplate($template, array $variables)
    {
        if (function_exists('\\uri_template')) {
            return \uri_template($template, $variables);
        }

        static $uriTemplate;
        if (!$uriTemplate) {
            $uriTemplate = new UriTemplate();
        }

        return $uriTemplate->expand($template, $variables);
    }
23195
private function getDomainRegex($route)
    {
        ReflectionHelper::invokePrivateMethod($route, 'compileRoute');
        $compiledRoute = ReflectionHelper::readPrivateProperty($route, 'compiled');

        return $compiledRoute->getHostRegex();
    }
1256773
public function extractRoutePath(string $route)
    {
        $url = (strpos($route, '/') === false) ? url($route) : $route;
        $this->router->handle($url);

        return $this->router->getMatchedRoute()->getPaths();
    }
1014124
private static function compileRegex(&$route, $pos){
    $re_catch_vars = '/\:([a-zA-Z0-9_]+)/';
    $re_replace_with = "(?P<R{$pos}V$1>[^/\?]+)";
    $replacement = preg_replace($re_catch_vars, $re_replace_with, $route);
    return "(?P<R$pos>^$replacement\$)";
  }
188798
private List<String> getVariables(String routePath) {
		List<String> variables = new ArrayList<String>();

		Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath);
		while (matcher.find()) {
			// group(0) always stands for the entire expression and we only want what is inside the {}
			variables.add(matcher.group(1));
		}

		return variables;
	}
874762
private function parseRoutes(Collection $routes) : array
    {
        $parsedRoutes = [];
        foreach ($routes as $route) {
            $routeUrl = strtr($route->getUrl(), $this->regexShortcuts);

            list($routeRegex, $parameters) = $this->transformRoute($routeUrl);

            $parsedRoute = new Parsed($route);
            $parsedRoute->setPlaceholders($parameters);

            $parsedRoutes[] = [$routeRegex, $parsedRoute];
        }

        return $parsedRoutes;
    }
1330254
private function replaceVariables($template, array $variables): string
    {
        foreach ($variables as $key => $value) {
            $key = '%'.$key.'%';

            $template = \str_replace($key, $value, $template);
        }

        return $template;
    }
590109
private function getVarRegex(ParsedRoute $parsedRoute, string $segment) : string
    {
        if (preg_match(self::$variableMatchingRegex, $segment, $matches) !== 1) {
            throw new RouteException("Variable name can't be empty");
        }

        $variableName = $matches[1];
        $defaultValue = $matches[2] ?? '';

        if (strlen($variableName) > self::VARIABLE_MAXIMUM_LENGTH) {
            throw new RouteException(sprintf(
                'Variable name "%s" cannot be longer than %d characters. Please use a shorter name.',
                $variableName,
                self::VARIABLE_MAXIMUM_LENGTH)
            );
        }

        if (in_array($variableName, $this->variableNames)) {
            throw new RouteException("Route uses multiple references to \"$variableName\"");
        }

        $this->variableNames[] = $variableName;
        $parsedRoute->setDefaultValue($variableName, $defaultValue);
        $variableRegex = $parsedRoute->getVarRegex($variableName);

        if ($variableRegex === null) {
            // Add a default regex
            $variableRegex = "[^\/:]+";
        }

        $this->cursor += mb_strlen($matches[0]);

        return sprintf('(?P<%s>%s)', $variableName, $variableRegex);
    }
131634
protected function buildRegexp($pattern, array $matches)
    {
        $src = [];
        $trg = [];
        foreach ($matches as $match) {
            list($key, $regexp) = $this->splitSegment($match[3]);

            if (in_array(substr($regexp, -1), ['+', '*', '?'])) {
                throw new RouteException('Route must not end with quantification token');
            }

            $src[rtrim($match[0], '/')] = $key;

            $trg[$key] = '(?P<' . $key . '>' . $regexp . '+)';

            if ($match[1] == '(') {
                $trg[$key] = '(' . $trg[$key] . $this->buildConditionalSlash(preg_quote($match[4], '/')) . ')?';
            }
        }

        $pattern = strtr($pattern, $src);
        $pattern = preg_quote($pattern, '/');
        $pattern = strtr($pattern, $trg);
        $pattern = str_replace('\/((?P', '\/?((?P', $pattern);
        $pattern = $this->buildConditionalSlash($pattern);

        return '/^' . $pattern . '$/i';
    }