MediaWiki master
ExtraRoutesModule.php
Go to the documentation of this file.
1<?php
2
4
5use AppendIterator;
6use ArrayIterator;
7use Iterator;
18use Wikimedia\ObjectFactory\ObjectFactory;
19
65
67 private array $routeFiles;
68
72 private array $extraRoutes;
73
74 private JsonLocalizer $jsonLocalizer;
75
80 private ?array $routesFromFiles = null;
81
83 private ?array $routeFileTimestamps = null;
84
85 private ?string $configHash = null;
86
95 public function __construct(
96 array $routeFiles,
97 array $extraRoutes,
98 Router $router,
100 BasicAuthorizerInterface $basicAuth,
101 ObjectFactory $objectFactory,
102 Validator $restValidator,
103 ErrorReporter $errorReporter,
104 HookContainer $hookContainer
105 ) {
106 parent::__construct(
107 $router,
108 '',
110 $basicAuth,
111 $objectFactory,
112 $restValidator,
113 $errorReporter,
114 $hookContainer
115 );
116 $this->routeFiles = $routeFiles;
117 $this->extraRoutes = $extraRoutes;
118 $this->jsonLocalizer = new JsonLocalizer( $responseFactory );
119 }
120
124 protected function getConfigHash(): string {
125 if ( $this->configHash === null ) {
126 $this->configHash = md5( json_encode( [
127 'class' => __CLASS__,
128 'version' => 1,
129 'extraRoutes' => $this->extraRoutes,
130 'fileTimestamps' => $this->getRouteFileTimestamps()
131 ] ) );
132 }
133 return $this->configHash;
134 }
135
143 private function getRoutesFromFiles(): array {
144 if ( $this->routesFromFiles !== null ) {
145 return $this->routesFromFiles;
146 }
147
148 $this->routesFromFiles = [];
149 $this->routeFileTimestamps = [];
150 foreach ( $this->routeFiles as $fileName ) {
151 $this->routeFileTimestamps[$fileName] = filemtime( $fileName );
152
153 $routes = $this->loadJsonFile( $fileName );
154
155 $this->routesFromFiles = array_merge( $this->routesFromFiles, $routes );
156 }
157
158 return $this->routesFromFiles;
159 }
160
166 private function getRouteFileTimestamps(): array {
167 if ( $this->routeFileTimestamps === null ) {
168 $this->routeFileTimestamps = [];
169 foreach ( $this->routeFiles as $fileName ) {
170 $this->routeFileTimestamps[$fileName] = filemtime( $fileName );
171 }
172 }
173 return $this->routeFileTimestamps;
174 }
175
179 public function getDefinedPaths(): array {
180 $paths = [];
181 foreach ( $this->getAllRoutes() as $spec ) {
182 $key = $spec['path'];
183
184 $methods = isset( $spec['method'] ) ? (array)$spec['method'] : [ 'GET' ];
185
186 $paths[$key] = array_merge( $paths[$key] ?? [], $methods );
187 }
188
189 return $paths;
190 }
191
195 private function getAllRoutes() {
196 $iterator = new AppendIterator;
197 $iterator->append( new ArrayIterator( $this->getRoutesFromFiles() ) );
198 $iterator->append( new ArrayIterator( $this->extraRoutes ) );
199 return $iterator;
200 }
201
202 protected function initRoutes(): void {
203 $routeDefs = $this->getAllRoutes();
204
205 foreach ( $routeDefs as $route ) {
206 if ( !isset( $route['path'] ) ) {
207 throw new RouteDefinitionException( 'Missing path' );
208 }
209
210 $path = $route['path'];
211 $method = $route['method'] ?? 'GET';
212 $info = $this->makeRouteInfo( $route );
213
214 $this->addRoute( $method, $path, $info );
215 }
216 }
217
223 private function makeRouteInfo( array $route ): array {
224 static $objectSpecKeys = [
225 'class',
226 'factory',
227 'services',
228 'optional_services',
229 'args',
230 ];
231
232 if ( isset( $route['redirect'] ) ) {
233 // Redirect shorthand
234 $info = [
235 'spec' => [ 'class' => RedirectHandler::class ],
236 'config' => $route,
237 ];
238 } else {
239 // Object spec at the top level
240 $info = [
241 'spec' => array_intersect_key( $route, array_flip( $objectSpecKeys ) ),
242 'config' => array_diff_key( $route, array_flip( $objectSpecKeys ) ),
243 ];
244 }
245 if ( isset( $route['openApiSpec'] ) ) {
246 $info['openApiSpec'] = $this->jsonLocalizer->localizeJson( $route['openApiSpec'] );
247 }
248
249 $info['path'] = $route['path'];
250 return $info;
251 }
252
253 public function getOpenApiInfo() {
254 // Note that mwapi-1.0 is based on OAS 3.0, so it doesn't support the
255 // "summary" property introduced in 3.1.
256 return [
257 'title' => $this->jsonLocalizer->getFormattedMessage( 'rest-module-extra-routes-title' ),
258 'description' => $this->jsonLocalizer->getFormattedMessage( 'rest-module-extra-routes-desc' ),
259 'version' => 'undefined',
260 ];
261 }
262}
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:82
Utility class for json localization needs in the REST API.
A Module that is based on flat route definitions in the form originally introduced in MW 1....
getOpenApiInfo()
Return an array with data to be included in an OpenAPI "info" object describing this module.
__construct(array $routeFiles, array $extraRoutes, Router $router, ResponseFactory $responseFactory, BasicAuthorizerInterface $basicAuth, ObjectFactory $objectFactory, Validator $restValidator, ErrorReporter $errorReporter, HookContainer $hookContainer)
initRoutes()
Initialize matchers by calling addRoute() for each known route.
getConfigHash()
Get a config version hash for cache invalidation.
MatcherBasedModules respond to requests by matching the requested path against a list of known routes...
ResponseFactory $responseFactory
Definition Module.php:45
Exception indicating incorrect REST module configuration.
Generates standardized response objects.
The REST router is responsible for gathering module configuration, matching an input path against the...
Definition Router.php:30
Wrapper for ParamValidator.
Definition Validator.php:37
An interface used by Router to ensure that the client has "basic" access, i.e.
An ErrorReporter internally reports an error that happened during the handling of a request.