MediaWiki master
MatcherBasedModule.php
Go to the documentation of this file.
1<?php
2
4
5use InvalidArgumentException;
7
16abstract class MatcherBasedModule extends Module {
17
19 private ?array $matchers = [];
20
21 private bool $matchersInitialized = false;
22
23 public function getCacheData(): array {
24 $cacheData = [];
25
26 foreach ( $this->getMatchers() as $method => $matcher ) {
27 $cacheData[$method] = $matcher->getCacheData();
28 }
29
30 $cacheData[self::CACHE_CONFIG_HASH_KEY] = $this->getConfigHash();
31 return $cacheData;
32 }
33
34 public function initFromCacheData( array $cacheData ): bool {
35 if ( $cacheData[self::CACHE_CONFIG_HASH_KEY] !== $this->getConfigHash() ) {
36 return false;
37 }
38
39 unset( $cacheData[self::CACHE_CONFIG_HASH_KEY] );
40 $this->matchers = [];
41
42 foreach ( $cacheData as $method => $data ) {
43 $this->matchers[$method] = PathMatcher::newFromCache( $data );
44 }
45
46 $this->matchersInitialized = true;
47 return true;
48 }
49
55 abstract protected function getConfigHash(): string;
56
62 protected function getMatchers() {
63 if ( !$this->matchersInitialized ) {
64 $this->initRoutes();
65 $this->matchersInitialized = true;
66 }
67
68 return $this->matchers;
69 }
70
74 abstract protected function initRoutes(): void;
75
83 protected function addRoute( $method, string $path, array $info ) {
84 $methods = (array)$method;
85
86 // Make sure the matched path is known.
87 if ( !isset( $info['spec'] ) ) {
88 throw new InvalidArgumentException( 'Missing key in $info: "spec"' );
89 }
90
91 $info['path'] = $path;
92
93 foreach ( $methods as $method ) {
94 $method = strtoupper( $method );
95
96 if ( !isset( $this->matchers[$method] ) ) {
97 $this->matchers[$method] = new PathMatcher;
98 }
99
100 $this->matchers[$method]->add( $path, $info );
101 }
102 }
103
107 public function findHandlerMatch(
108 string $path,
109 string $requestMethod
110 ): array {
111 $requestMethod = strtoupper( $requestMethod );
112
113 $matchers = $this->getMatchers();
114 $matcher = $matchers[$requestMethod] ?? null;
115 $match = $matcher ? $matcher->match( $path ) : null;
116
117 if ( !$match ) {
118 // Return allowed methods, to support CORS and 405 responses.
119 return [
120 'found' => false,
121 'methods' => $this->getAllowedMethods( $path ),
122 ];
123 } else {
124 $info = $match['userData'];
125 $info['found'] = true;
126 $info['method'] = $requestMethod;
127 $info['params'] = $match['params'] ?? [];
128
129 return $info;
130 }
131 }
132
140 public function getAllowedMethods( string $relPath ): array {
141 $allowed = [];
142 foreach ( $this->getMatchers() as $allowedMethod => $allowedMatcher ) {
143 if ( $allowedMatcher->match( $relPath ) ) {
144 $allowed[] = $allowedMethod;
145 }
146 }
147
148 return array_unique(
149 in_array( 'GET', $allowed ) ? array_merge( [ 'HEAD' ], $allowed ) : $allowed
150 );
151 }
152
153}
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
MatcherBasedModules respond to requests by matching the requested path against a list of known routes...
addRoute( $method, string $path, array $info)
getConfigHash()
Get a config version hash for cache invalidation.
getMatchers()
Get an array of PathMatcher objects indexed by HTTP method.
initFromCacheData(array $cacheData)
Initialize from the given cache data if possible.
findHandlerMatch(string $path, string $requestMethod)
Determines which handler to use for the given path and returns an array describing the handler and in...
getAllowedMethods(string $relPath)
Get the allowed methods for a path.
getCacheData()
Return data that can later be used to initialize a new instance of this module in a fast and efficien...
initRoutes()
Initialize matchers by calling addRoute() for each known route.
A REST module represents a collection of endpoints.
Definition Module.php:33
A tree-based path routing algorithm.
add( $template, $userData)
Add a template to the matcher.
static newFromCache( $data)
Create a PathMatcher from cache data.