14use Wikimedia\ObjectFactory\ObjectFactory;
42 private ?array $moduleDef =
null;
44 private ?
int $routeFileTimestamp =
null;
46 private ?
string $configHash =
null;
52 private readonly
string $definitionFile,
57 ObjectFactory $objectFactory,
78 if ( $this->configHash === null ) {
79 $this->configHash = md5( json_encode( [
82 'fileTimestamps' => $this->getRouteFileTimestamp()
85 return $this->configHash;
91 private function getModuleDefinition(): array {
92 if ( $this->moduleDef !== null ) {
93 return $this->moduleDef;
96 $this->routeFileTimestamp = filemtime( $this->definitionFile );
97 $this->moduleDef = static::loadModuleDefinition(
98 $this->definitionFile,
99 $this->getJsonLocalizer()
102 return $this->moduleDef;
114 $moduleDef = static::loadJsonFile( $file );
121 if ( array_is_list( $moduleDef ) ) {
123 $file .
' appears to be a flat route file, not a module definition file.'
129 $mwapi = $moduleDef[
'mwapi'] ??
null;
130 '@phan-var ?string $mwapi';
132 if ( !is_string( $mwapi ) ) {
134 'Missing or malformed mwapi version field in ' . $file
139 if ( version_compare( $mwapi,
'1.0.0',
'<' ) ||
140 version_compare( $mwapi,
'1.2.999',
'>' )
143 "Unsupported mwapi version {$mwapi} in "
154 private function getRouteFileTimestamp(): int {
155 if ( $this->routeFileTimestamp === null ) {
156 $this->routeFileTimestamp = filemtime( $this->definitionFile );
158 return $this->routeFileTimestamp;
168 $moduleDef = $this->getModuleDefinition();
170 foreach ( $moduleDef[
'paths'] as
$path => $pSpec ) {
172 foreach ( $pSpec as $method => $opSpec ) {
173 $paths[
$path][] = strtoupper( $method );
181 $moduleDef = $this->getModuleDefinition();
184 foreach ( $moduleDef[
'paths'] as
$path => $pathSpec ) {
185 foreach ( $pathSpec as $method => $opSpec ) {
186 $info = $this->makeRouteInfo(
$path, $opSpec );
187 $this->addRoute( $method,
$path, $info );
197 private function makeRouteInfo(
string $path, array $opSpec ): array {
198 static $objectSpecKeys = [
214 'deprecationSettings',
218 if ( isset( $opSpec[
'redirect'] ) ) {
220 $opSpec[
'handler'] = [
221 'class' => RedirectHandler::class,
222 'redirect' => $opSpec[
'redirect'],
224 unset( $opSpec[
'redirect'] );
227 $handlerSpec = $opSpec[
'handler'] ??
null;
228 if ( !$handlerSpec ) {
229 throw new RouteDefinitionException(
'Missing handler spec' );
233 'spec' => array_intersect_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
234 'config' => array_diff_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
235 'openApiSpec' => array_intersect_key( $opSpec, array_flip( $oasKeys ) ),
244 $def = $this->getModuleDefinition();
245 return $def[
'info'] ?? [];
250 $def = $this->getModuleDefinition();
251 return $def[
'externalDocs'] ?? [];
256 $def = $this->getModuleDefinition();
257 return $def[
'tags'] ?? [];
if(!defined('MW_SETUP_CALLBACK'))