Movatterモバイル変換


[0]ホーム

URL:


MediaWiki master
PathRouter.php
Go to the documentation of this file.
1<?php
9namespaceMediaWiki\Request;
10
11useMediaWiki\Exception\FatalError;
12useMediaWiki\Utils\UrlUtils;
13use stdClass;
14
65classPathRouter {
66
70private $patterns = [];
71
82protectedfunctiondoAdd($path, $params, $options, $key =null ) {
83// Make sure all paths start with a /
84if ($path[0] !=='/' ) {
85$path ='/' .$path;
86 }
87
88if ( !isset( $options['strict'] ) || !$options['strict'] ) {
89// Unless this is a strict path make sure that the path has a $1
90if ( !str_contains($path,'$1' ) ) {
91if ($path[-1] !=='/' ) {
92$path .='/';
93 }
94$path .='$1';
95 }
96 }
97
98// If 'title' is not specified and our path pattern contains a $1
99// Add a default 'title' => '$1' rule to the parameters.
100if ( !isset( $params['title'] ) && str_contains($path,'$1' ) ) {
101 $params['title'] ='$1';
102 }
103// If the user explicitly marked 'title' as false then omit it from the matches
104if ( isset( $params['title'] ) && $params['title'] ===false ) {
105 unset( $params['title'] );
106 }
107
108// Loop over our parameters and convert basic key => string
109// patterns into fully descriptive array form
110foreach ( $params as $paramName => $paramData ) {
111if ( is_string( $paramData ) ) {
112if ( preg_match('/\$(\d+|key)/u', $paramData ) ) {
113 $paramArrKey ='pattern';
114 }else {
115// If there's no replacement use a value instead
116// of a pattern for a little more efficiency
117 $paramArrKey ='value';
118 }
119 $params[$paramName] = [
120 $paramArrKey => $paramData
121 ];
122 }
123 }
124
125// Loop over our options and convert any single value $# restrictions
126// into an array so we only have to do in_array tests.
127foreach ( $options as $optionName => $optionData ) {
128if ( preg_match('/^\$\d+$/u', $optionName ) && !is_array( $optionData ) ) {
129 $options[$optionName] = [ $optionData ];
130 }
131 }
132
133 $pattern = (object)[
134'path' =>$path,
135'params' => $params,
136'options' => $options,
137'key' => $key,
138 ];
139 $pattern->weight =self::makeWeight( $pattern );
140 $this->patterns[] = $pattern;
141 }
142
150publicfunctionadd($path, $params = [], $options = [] ) {
151if ( is_array($path ) ) {
152foreach ($path as $key => $onePath ) {
153 $this->doAdd( $onePath, $params, $options, $key );
154 }
155 }else {
156 $this->doAdd($path, $params, $options );
157 }
158 }
159
167publicfunctionvalidateRoute($path, $varName ) {
168if ($path && !preg_match('/^(https?:\/\/|\/)/',$path ) ) {
169// T48998: Bail out early if path is non-absolute
170thrownewFatalError(
171"If you use a relative URL for \$$varName, it must start " .
172'with a slash (<code>/</code>).<br><br>See ' .
173"<a href=\"https://www.mediawiki.org/wiki/Manual:\$$varName\">" .
174"https://www.mediawiki.org/wiki/Manual:\$$varName</a>."
175 );
176 }
177 }
178
186publicfunctionaddStrict($path, $params = [], $options = [] ) {
187 $options['strict'] =true;
188 $this->add($path, $params, $options );
189 }
190
195protectedfunctionsortByWeight() {
196 $weights = [];
197foreach ( $this->patterns as $key => $pattern ) {
198 $weights[$key] = $pattern->weight;
199 }
200 array_multisort( $weights, SORT_DESC, SORT_NUMERIC, $this->patterns );
201 }
202
207protectedstaticfunctionmakeWeight( $pattern ) {
208 # Start with a weight of 0
209 $weight = 0;
210
211// Explode the path to work with
212$path = explode('/', $pattern->path );
213
214 # For each level of the path
215foreach ($path as $piece ) {
216if ( preg_match('/^\$(\d+|key)$/u', $piece ) ) {
217 # For a piece that is only a $1 variable add 1 points of weight
218 $weight++;
219 } elseif ( preg_match('/\$(\d+|key)/u', $piece ) ) {
220 # For a piece that simply contains a $1 variable add 2 points of weight
221 $weight += 2;
222 }else {
223 # For a solid piece add a full 3 points of weight
224 $weight += 3;
225 }
226 }
227
228foreach ( $pattern->options as $key => $option ) {
229if ( preg_match('/^\$\d+$/u', $key ) ) {
230 # Add 0.5 for restrictions to values
231 # This way given two separate "/$2/$1" patterns the
232 # one with a limited set of $2 values will dominate
233 # the one that'll match more loosely
234 $weight += 0.5;
235 }
236 }
237
238return $weight;
239 }
240
247publicfunctionparse($path ) {
248// Make sure our patterns are sorted by weight so the most specific
249// matches are tested first
250 $this->sortByWeight();
251
252$matches = $this->internalParse($path );
253if ($matches ===null ) {
254// Try with the normalized path (T100782)
255$path = UrlUtils::removeDotSegments($path );
256$path = preg_replace('#/+#','/',$path );
257$matches = $this->internalParse($path );
258 }
259
260// We know the difference between null (no matches) and
261// [] (a match with no data) but our WebRequest caller
262// expects [] even when we have no matches so return
263// a [] when we have null
264return$matches ?? [];
265 }
266
273protectedfunctioninternalParse($path ) {
274$matches =null;
275
276foreach ( $this->patterns as $pattern ) {
278if ($matches !==null ) {
279break;
280 }
281 }
282return$matches;
283 }
284
290protectedstaticfunctionextractTitle($path, $pattern ) {
291// Convert the path pattern into a regexp we can match with
292 $regexp = preg_quote( $pattern->path,'#' );
293// .* for the $1
294 $regexp = preg_replace('#\\\\\$1#u','(?P<par1>.*)', $regexp );
295// .+ for the rest of the parameter numbers
296 $regexp = preg_replace('#\\\\\$(\d+)#u','(?P<par$1>.+?)', $regexp );
297 $regexp ="#^{$regexp}$#";
298
299$matches = [];
300 $data = [];
301
302// Try to match the path we were asked to parse with our regexp
303if ( preg_match( $regexp,$path, $m ) ) {
304// Ensure that any $# restriction we have set in our {$option}s
305// matches properly here.
306foreach ( $pattern->options as $key => $option ) {
307if ( preg_match('/^\$\d+$/u', $key ) ) {
308 $n = intval( substr( $key, 1 ) );
309 $value = rawurldecode( $m["par{$n}"] );
310if ( !in_array( $value, $option ) ) {
311// If any restriction does not match return null
312// to signify that this rule did not match.
313returnnull;
314 }
315 }
316 }
317
318// Give our $data array a copy of every $# that was matched
319foreach ( $m as $matchKey => $matchValue ) {
320if ( preg_match('/^par\d+$/u', $matchKey ) ) {
321 $n = intval( substr( $matchKey, 3 ) );
322 $data['$' . $n] = rawurldecode( $matchValue );
323 }
324 }
325// If present give our $data array a $key as well
326if ( isset( $pattern->key ) ) {
327 $data['$key'] = $pattern->key;
328 }
329
330// Go through our parameters for this match and add data to our matches and data arrays
331foreach ( $pattern->params as $paramName => $paramData ) {
332 $value =null;
333// Differentiate data: from normal parameters and keep the correct
334// array key around (ie: foo for data:foo)
335if ( preg_match('/^data:/u', $paramName ) ) {
336 $isData =true;
337 $key = substr( $paramName, 5 );
338 }else {
339 $isData =false;
340 $key = $paramName;
341 }
342
343if ( isset( $paramData['value'] ) ) {
344// For basic values just set the raw data as the value
345 $value = $paramData['value'];
346 } elseif ( isset( $paramData['pattern'] ) ) {
347// For patterns we have to make value replacements on the string
348 $value =self::expandParamValue( $m, $pattern->key ??null,
349 $paramData['pattern'] );
350if ( $value ===false ) {
351// Pattern required data that wasn't available, abort
352returnnull;
353 }
354 }
355
356// Send things that start with data: to $data, the rest to $matches
357if ( $isData ) {
358 $data[$key] = $value;
359 }else {
360$matches[$key] = $value;
361 }
362 }
363
364// If this match includes a callback, execute it
365if ( isset( $pattern->options['callback'] ) ) {
366 $pattern->options['callback']($matches, $data );
367 }
368 }else {
369// Our regexp didn't match, return null to signify no match.
370returnnull;
371 }
372// Fall through, everything went ok, return our matches array
373return$matches;
374 }
375
384protectedstaticfunctionexpandParamValue( $pathMatches, $key, $value ) {
385 $error =false;
386
387 $replacer =staticfunction ( $m ) use ( $pathMatches, $key, &$error ) {
388if ( $m[1] =="key" ) {
389if ( $key ===null ) {
390 $error =true;
391
392return'';
393 }
394
395return $key;
396 }else {
397 $d = $m[1];
398if ( !isset( $pathMatches["par$d"] ) ) {
399 $error =true;
400
401return'';
402 }
403
404return rawurldecode( $pathMatches["par$d"] );
405 }
406 };
407
408 $value = preg_replace_callback('/\$(\d+|key)/u', $replacer, $value );
409if ( $error ) {
410returnfalse;
411 }
412
413return $value;
414 }
415
422publicstaticfunctiongetActionPaths( array $actionPaths, $articlePath ) {
423if ( !$actionPaths ) {
424returnfalse;
425 }
426// Processing of urls for this feature requires that 'view' is set.
427// By default, set it to the pretty article path.
428if ( !isset( $actionPaths['view'] ) ) {
429 $actionPaths['view'] = $articlePath;
430 }
431return $actionPaths;
432 }
433}
$path
$path
DefinitionNoLocalSettings.php:14
$matches
$matches
DefinitionNoLocalSettings.php:13
MediaWiki\Exception\FatalError
Abort the web request with a custom HTML string that will represent the entire response.
DefinitionFatalError.php:25
MediaWiki\Request\PathRouter
MediaWiki\Request\PathRouter class.
DefinitionPathRouter.php:65
MediaWiki\Request\PathRouter\getActionPaths
static getActionPaths(array $actionPaths, $articlePath)
DefinitionPathRouter.php:422
MediaWiki\Request\PathRouter\add
add( $path, $params=[], $options=[])
Add a new path pattern to the path router.
DefinitionPathRouter.php:150
MediaWiki\Request\PathRouter\expandParamValue
static expandParamValue( $pathMatches, $key, $value)
Replace $key etc.
DefinitionPathRouter.php:384
MediaWiki\Request\PathRouter\extractTitle
static extractTitle( $path, $pattern)
DefinitionPathRouter.php:290
MediaWiki\Request\PathRouter\validateRoute
validateRoute( $path, $varName)
DefinitionPathRouter.php:167
MediaWiki\Request\PathRouter\sortByWeight
sortByWeight()
Protected helper to re-sort our patterns so that the most specific (most heavily weighted) patterns a...
DefinitionPathRouter.php:195
MediaWiki\Request\PathRouter\doAdd
doAdd( $path, $params, $options, $key=null)
Protected helper to do the actual bulk work of adding a single pattern.
DefinitionPathRouter.php:82
MediaWiki\Request\PathRouter\makeWeight
static makeWeight( $pattern)
DefinitionPathRouter.php:207
MediaWiki\Request\PathRouter\internalParse
internalParse( $path)
Match a path against each defined pattern.
DefinitionPathRouter.php:273
MediaWiki\Request\PathRouter\addStrict
addStrict( $path, $params=[], $options=[])
Add a new path pattern to the path router with the strict option on.
DefinitionPathRouter.php:186
MediaWiki\Request\PathRouter\parse
parse( $path)
Parse a path and return the query matches for the path.
DefinitionPathRouter.php:247
MediaWiki\Utils\UrlUtils
A service to expand, parse, and otherwise manipulate URLs.
DefinitionUrlUtils.php:16
MediaWiki\Request
DefinitionContentSecurityPolicy.php:7

[8]ページ先頭

©2009-2025 Movatter.jp