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 $moduleDef = $this->loadJsonFile( $this->definitionFile );
104 throw new ModuleConfigurationException(
105 'Malformed module definition file: ' . $this->definitionFile
109 if ( !isset( $moduleDef[
'mwapi'] ) ) {
110 throw new ModuleConfigurationException(
111 'Missing mwapi version field in ' . $this->definitionFile
116 if ( version_compare( $moduleDef[
'mwapi'],
'1.0.0',
'<' ) ||
117 version_compare( $moduleDef[
'mwapi'],
'1.1.999',
'>' )
119 throw new ModuleConfigurationException(
120 "Unsupported openapi version {$moduleDef['mwapi']} in "
121 . $this->definitionFile
125 $localizer =
new JsonLocalizer( $this->responseFactory );
126 $moduleDef = $localizer->localizeJson( $moduleDef );
128 $this->moduleDef = $moduleDef;
129 return $this->moduleDef;
135 private function getRouteFileTimestamp(): int {
136 if ( $this->routeFileTimestamp === null ) {
137 $this->routeFileTimestamp = filemtime( $this->definitionFile );
139 return $this->routeFileTimestamp;
149 $moduleDef = $this->getModuleDefinition();
151 foreach ( $moduleDef[
'paths'] as
$path => $pSpec ) {
153 foreach ( $pSpec as $method => $opSpec ) {
154 $paths[
$path][] = strtoupper( $method );
162 $moduleDef = $this->getModuleDefinition();
165 foreach ( $moduleDef[
'paths'] as
$path => $pathSpec ) {
166 foreach ( $pathSpec as $method => $opSpec ) {
167 $info = $this->makeRouteInfo(
$path, $opSpec );
168 $this->addRoute( $method,
$path, $info );
178 private function makeRouteInfo(
string $path, array $opSpec ): array {
179 static $objectSpecKeys = [
194 'deprecationSettings'
197 if ( isset( $opSpec[
'redirect'] ) ) {
199 $opSpec[
'handler'] = [
200 'class' => RedirectHandler::class,
201 'redirect' => $opSpec[
'redirect'],
203 unset( $opSpec[
'redirect'] );
206 $handlerSpec = $opSpec[
'handler'] ??
null;
207 if ( !$handlerSpec ) {
208 throw new RouteDefinitionException(
'Missing handler spec' );
212 'spec' => array_intersect_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
213 'config' => array_diff_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
214 'openApiSpec' => array_intersect_key( $opSpec, array_flip( $oasKeys ) ),
223 $def = $this->getModuleDefinition();
224 return $def[
'info'] ?? [];