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.999',
'<=' ) ||
117 !version_compare( $moduleDef[
'mwapi'],
'1.0.0',
'>=' )
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 = [
196 if ( isset( $opSpec[
'redirect'] ) ) {
198 $opSpec[
'handler'] = [
199 'class' => RedirectHandler::class,
200 'redirect' => $opSpec[
'redirect'],
202 unset( $opSpec[
'redirect'] );
205 $handlerSpec = $opSpec[
'handler'] ??
null;
206 if ( !$handlerSpec ) {
207 throw new RouteDefinitionException(
'Missing handler spec' );
211 'spec' => array_intersect_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
212 'config' => array_diff_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
213 'OAS' => array_intersect_key( $opSpec, array_flip( $oasKeys ) ),
221 $def = $this->getModuleDefinition();
222 return $def[
'info'] ?? [];