Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/routing/RouteCompiler.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | 1fec387a4317 |
children |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
44 * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as | 44 * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as |
45 * a PCRE subpattern | 45 * a PCRE subpattern |
46 */ | 46 */ |
47 public static function compile(Route $route) | 47 public static function compile(Route $route) |
48 { | 48 { |
49 $hostVariables = array(); | 49 $hostVariables = []; |
50 $variables = array(); | 50 $variables = []; |
51 $hostRegex = null; | 51 $hostRegex = null; |
52 $hostTokens = array(); | 52 $hostTokens = []; |
53 | 53 |
54 if ('' !== $host = $route->getHost()) { | 54 if ('' !== $host = $route->getHost()) { |
55 $result = self::compilePattern($route, $host, true); | 55 $result = self::compilePattern($route, $host, true); |
56 | 56 |
57 $hostVariables = $result['variables']; | 57 $hostVariables = $result['variables']; |
92 ); | 92 ); |
93 } | 93 } |
94 | 94 |
95 private static function compilePattern(Route $route, $pattern, $isHost) | 95 private static function compilePattern(Route $route, $pattern, $isHost) |
96 { | 96 { |
97 $tokens = array(); | 97 $tokens = []; |
98 $variables = array(); | 98 $variables = []; |
99 $matches = array(); | 99 $matches = []; |
100 $pos = 0; | 100 $pos = 0; |
101 $defaultSeparator = $isHost ? '.' : '/'; | 101 $defaultSeparator = $isHost ? '.' : '/'; |
102 $useUtf8 = preg_match('//u', $pattern); | 102 $useUtf8 = preg_match('//u', $pattern); |
103 $needsUtf8 = $route->getOption('utf8'); | 103 $needsUtf8 = $route->getOption('utf8'); |
104 | 104 |
115 preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); | 115 preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); |
116 foreach ($matches as $match) { | 116 foreach ($matches as $match) { |
117 $varName = substr($match[0][0], 1, -1); | 117 $varName = substr($match[0][0], 1, -1); |
118 // get all static text preceding the current variable | 118 // get all static text preceding the current variable |
119 $precedingText = substr($pattern, $pos, $match[0][1] - $pos); | 119 $precedingText = substr($pattern, $pos, $match[0][1] - $pos); |
120 $pos = $match[0][1] + strlen($match[0][0]); | 120 $pos = $match[0][1] + \strlen($match[0][0]); |
121 | 121 |
122 if (!strlen($precedingText)) { | 122 if (!\strlen($precedingText)) { |
123 $precedingChar = ''; | 123 $precedingChar = ''; |
124 } elseif ($useUtf8) { | 124 } elseif ($useUtf8) { |
125 preg_match('/.$/u', $precedingText, $precedingChar); | 125 preg_match('/.$/u', $precedingText, $precedingChar); |
126 $precedingChar = $precedingChar[0]; | 126 $precedingChar = $precedingChar[0]; |
127 } else { | 127 } else { |
132 // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the | 132 // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the |
133 // variable would not be usable as a Controller action argument. | 133 // variable would not be usable as a Controller action argument. |
134 if (preg_match('/^\d/', $varName)) { | 134 if (preg_match('/^\d/', $varName)) { |
135 throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); | 135 throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); |
136 } | 136 } |
137 if (in_array($varName, $variables)) { | 137 if (\in_array($varName, $variables)) { |
138 throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); | 138 throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); |
139 } | 139 } |
140 | 140 |
141 if (strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { | 141 if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { |
142 throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); | 142 throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); |
143 } | 143 } |
144 | 144 |
145 if ($isSeparator && $precedingText !== $precedingChar) { | 145 if ($isSeparator && $precedingText !== $precedingChar) { |
146 $tokens[] = array('text', substr($precedingText, 0, -strlen($precedingChar))); | 146 $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; |
147 } elseif (!$isSeparator && strlen($precedingText) > 0) { | 147 } elseif (!$isSeparator && \strlen($precedingText) > 0) { |
148 $tokens[] = array('text', $precedingText); | 148 $tokens[] = ['text', $precedingText]; |
149 } | 149 } |
150 | 150 |
151 $regexp = $route->getRequirement($varName); | 151 $regexp = $route->getRequirement($varName); |
152 if (null === $regexp) { | 152 if (null === $regexp) { |
153 $followingPattern = (string) substr($pattern, $pos); | 153 $followingPattern = (string) substr($pattern, $pos); |
154 // Find the next static character after the variable that functions as a separator. By default, this separator and '/' | 154 // Find the next static character after the variable that functions as a separator. By default, this separator and '/' |
155 // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all | 155 // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all |
156 // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are | 156 // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are |
157 // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html')) | 157 // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) |
158 // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. | 158 // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. |
159 // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally | 159 // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally |
160 // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. | 160 // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. |
161 $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); | 161 $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); |
162 $regexp = sprintf( | 162 $regexp = sprintf( |
182 if (!$useUtf8 && $needsUtf8) { | 182 if (!$useUtf8 && $needsUtf8) { |
183 throw new \LogicException(sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern)); | 183 throw new \LogicException(sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern)); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName); | 187 $tokens[] = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName]; |
188 $variables[] = $varName; | 188 $variables[] = $varName; |
189 } | 189 } |
190 | 190 |
191 if ($pos < strlen($pattern)) { | 191 if ($pos < \strlen($pattern)) { |
192 $tokens[] = array('text', substr($pattern, $pos)); | 192 $tokens[] = ['text', substr($pattern, $pos)]; |
193 } | 193 } |
194 | 194 |
195 // find the first optional token | 195 // find the first optional token |
196 $firstOptional = PHP_INT_MAX; | 196 $firstOptional = PHP_INT_MAX; |
197 if (!$isHost) { | 197 if (!$isHost) { |
198 for ($i = count($tokens) - 1; $i >= 0; --$i) { | 198 for ($i = \count($tokens) - 1; $i >= 0; --$i) { |
199 $token = $tokens[$i]; | 199 $token = $tokens[$i]; |
200 if ('variable' === $token[0] && $route->hasDefault($token[3])) { | 200 if ('variable' === $token[0] && $route->hasDefault($token[3])) { |
201 $firstOptional = $i; | 201 $firstOptional = $i; |
202 } else { | 202 } else { |
203 break; | 203 break; |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 // compute the matching regexp | 208 // compute the matching regexp |
209 $regexp = ''; | 209 $regexp = ''; |
210 for ($i = 0, $nbToken = count($tokens); $i < $nbToken; ++$i) { | 210 for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { |
211 $regexp .= self::computeRegexp($tokens, $i, $firstOptional); | 211 $regexp .= self::computeRegexp($tokens, $i, $firstOptional); |
212 } | 212 } |
213 $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''); | 213 $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''); |
214 | 214 |
215 // enable Utf8 matching if really required | 215 // enable Utf8 matching if really required |
216 if ($needsUtf8) { | 216 if ($needsUtf8) { |
217 $regexp .= 'u'; | 217 $regexp .= 'u'; |
218 for ($i = 0, $nbToken = count($tokens); $i < $nbToken; ++$i) { | 218 for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { |
219 if ('variable' === $tokens[$i][0]) { | 219 if ('variable' === $tokens[$i][0]) { |
220 $tokens[$i][] = true; | 220 $tokens[$i][] = true; |
221 } | 221 } |
222 } | 222 } |
223 } | 223 } |
224 | 224 |
225 return array( | 225 return [ |
226 'staticPrefix' => self::determineStaticPrefix($route, $tokens), | 226 'staticPrefix' => self::determineStaticPrefix($route, $tokens), |
227 'regex' => $regexp, | 227 'regex' => $regexp, |
228 'tokens' => array_reverse($tokens), | 228 'tokens' => array_reverse($tokens), |
229 'variables' => $variables, | 229 'variables' => $variables, |
230 ); | 230 ]; |
231 } | 231 } |
232 | 232 |
233 /** | 233 /** |
234 * Determines the longest static prefix possible for a route. | 234 * Determines the longest static prefix possible for a route. |
235 * | 235 * |
300 if ($index >= $firstOptional) { | 300 if ($index >= $firstOptional) { |
301 // Enclose each optional token in a subpattern to make it optional. | 301 // Enclose each optional token in a subpattern to make it optional. |
302 // "?:" means it is non-capturing, i.e. the portion of the subject string that | 302 // "?:" means it is non-capturing, i.e. the portion of the subject string that |
303 // matched the optional subpattern is not passed back. | 303 // matched the optional subpattern is not passed back. |
304 $regexp = "(?:$regexp"; | 304 $regexp = "(?:$regexp"; |
305 $nbTokens = count($tokens); | 305 $nbTokens = \count($tokens); |
306 if ($nbTokens - 1 == $index) { | 306 if ($nbTokens - 1 == $index) { |
307 // Close the optional subpatterns | 307 // Close the optional subpatterns |
308 $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); | 308 $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); |
309 } | 309 } |
310 } | 310 } |