/** * Build RouteRegex from Route. * * @param Route $route * * @return RouteRegex */ public static function create(Route $route) { $matches = array(); $tokens = array(); $variables = array(); $pattern = $route->getPath(); $pos = 0; // match all variables between variable prefix and suffix. preg_match_all(self::getVariablePattern(), $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach ((array) $matches as $i => $match) { $variable = substr($match[0][0], 1, -1); $preceding = substr($pattern, $pos, $match[0][1] - $pos); $pos = $match[0][1] + strlen($match[0][0]); $precedingChar = strlen($preceding) > 0 ? substr($preceding, -1) : ''; $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); if (is_numeric($variable)) { throw new InvalidArgumentException(sprintf('Variable name "%s" must be string.', $variable)); } if (in_array($variable, $variables)) { throw new InvalidArgumentException(sprintf('Variable name "%s" can\'t define more than once.', $variable)); } if ($isSeparator && strlen($preceding) > 1) { $tokens[] = array('type' => 'text', 'path' => substr($preceding, 0, -1)); } elseif (!$isSeparator && strlen($preceding) > 0) { $tokens[] = array('type' => 'text', 'path' => $preceding); } $regex = $route->getRequirementBag()->get($variable); if (null === $regex) { $regex = '[^/]++'; } $tokens[] = array('type' => 'variable', 'preceding' => $isSeparator ? $precedingChar : '', 'regex' => $regex, 'variable' => $variable); $variables[] = $variable; } if ($pos < strlen($pattern)) { $tokens[] = array('type' => 'text', 'path' => substr($pattern, $pos)); } $numberOfToken = count($tokens); $lastToken = $tokens[$numberOfToken - 1]; $optionalIndex = -1; if ('variable' === $lastToken['type'] && $route->getDefaultBag()->has($lastToken['variable'])) { $optionalIndex = $numberOfToken - 1; } $regex = ''; foreach ($tokens as $i => $token) { $regex .= self::buildRegex($token, $i, $optionalIndex); } return new RouteRegex(sprintf('%s^%s$%ss', static::$regexDelimiter, $regex, static::$regexDelimiter), $variables, $tokens); }
/** * Add new route and append the prefix. * * @param string $name * @param Route $route * * @return Route */ public function add($name, Route $route) { // replacing route will not place the new route at end of collection // so we need to remove it first unset($this->routes[$name]); $path = '/' !== $route->getPath() ? trim($route->getPath(), '/') : ltrim($route->getPath(), '/'); $this->routes[$name] = $route; $this->routes[$name]->setPath(sprintf('%s/%s', $this->prefix, $path)); if (null !== $this->domain && !empty($this->domain)) { $this->routes[$name]->setDomain($this->domain); } if (count($this->schemas) > 0) { $this->routes[$name]->getSchema()->replace($this->schemas); } return $route->setParent($this); }