15use Wikimedia\ObjectFactory\ObjectFactory;
43 private string $definitionFile;
45 private ?array $moduleDef =
null;
47 private ?
int $routeFileTimestamp =
null;
49 private ?
string $configHash =
null;
55 string $definitionFile,
60 ObjectFactory $objectFactory,
75 $this->definitionFile = $definitionFile;
82 if ( $this->configHash === null ) {
83 $this->configHash = md5( json_encode( [
86 'fileTimestamps' => $this->getRouteFileTimestamp()
89 return $this->configHash;
95 private function getModuleDefinition(): array {
96 if ( $this->moduleDef !== null ) {
97 return $this->moduleDef;
100 $this->routeFileTimestamp = filemtime( $this->definitionFile );
101 $this->moduleDef = static::loadModuleDefinition( $this->definitionFile, $this->responseFactory );
103 return $this->moduleDef;
115 $moduleDef = static::loadJsonFile( $file );
122 if ( array_is_list( $moduleDef ) ) {
124 $file .
' appears to be a flat route file, not a module definition file.'
130 $mwapi = $moduleDef[
'mwapi'] ??
null;
131 '@phan-var ?string $mwapi';
133 if ( !is_string( $mwapi ) ) {
135 'Missing or malformed mwapi version field in ' . $file
140 if ( version_compare( $mwapi,
'1.0.0',
'<' ) ||
141 version_compare( $mwapi,
'1.1.999',
'>' )
144 "Unsupported mwapi version {$mwapi} in "
149 $localizer =
new JsonLocalizer( $responseFactory );
150 return $localizer->localizeJson( $moduleDef );
156 private function getRouteFileTimestamp(): int {
157 if ( $this->routeFileTimestamp === null ) {
158 $this->routeFileTimestamp = filemtime( $this->definitionFile );
160 return $this->routeFileTimestamp;
170 $moduleDef = $this->getModuleDefinition();
172 foreach ( $moduleDef[
'paths'] as
$path => $pSpec ) {
174 foreach ( $pSpec as $method => $opSpec ) {
175 $paths[
$path][] = strtoupper( $method );
183 $moduleDef = $this->getModuleDefinition();
186 foreach ( $moduleDef[
'paths'] as
$path => $pathSpec ) {
187 foreach ( $pathSpec as $method => $opSpec ) {
188 $info = $this->makeRouteInfo(
$path, $opSpec );
189 $this->addRoute( $method,
$path, $info );
199 private function makeRouteInfo(
string $path, array $opSpec ): array {
200 static $objectSpecKeys = [
215 'deprecationSettings',
219 if ( isset( $opSpec[
'redirect'] ) ) {
221 $opSpec[
'handler'] = [
222 'class' => RedirectHandler::class,
223 'redirect' => $opSpec[
'redirect'],
225 unset( $opSpec[
'redirect'] );
228 $handlerSpec = $opSpec[
'handler'] ??
null;
229 if ( !$handlerSpec ) {
230 throw new RouteDefinitionException(
'Missing handler spec' );
234 'spec' => array_intersect_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
235 'config' => array_diff_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
236 'openApiSpec' => array_intersect_key( $opSpec, array_flip( $oasKeys ) ),
245 $def = $this->getModuleDefinition();
246 return $def[
'info'] ?? [];
251 $def = $this->getModuleDefinition();
252 return $def[
'externalDocs'] ?? [];
if(!defined('MW_SETUP_CALLBACK'))