41 private string $definitionFile;
43 private ?array $moduleDef =
null;
45 private ?
int $routeFileTimestamp =
null;
47 private ?
string $configHash =
null;
53 string $definitionFile,
58 ObjectFactory $objectFactory,
71 $this->definitionFile = $definitionFile;
80 if ( $this->configHash === null ) {
81 $this->configHash = md5( json_encode( [
84 'fileTimestamps' => $this->getRouteFileTimestamp()
87 return $this->configHash;
95 private function loadDefinition(): 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 $this->moduleDef = $moduleDef;
126 return $this->moduleDef;
132 private function getRouteFileTimestamp(): int {
133 if ( $this->routeFileTimestamp === null ) {
134 $this->routeFileTimestamp = filemtime( $this->definitionFile );
136 return $this->routeFileTimestamp;
146 $moduleDef = $this->loadDefinition();
148 foreach ( $moduleDef[
'paths'] as
$path => $pSpec ) {
150 foreach ( $pSpec as $method => $opSpec ) {
151 $paths[
$path][] = strtoupper( $method );
159 $moduleDef = $this->loadDefinition();
162 foreach ( $moduleDef[
'paths'] as
$path => $pathSpec ) {
163 foreach ( $pathSpec as $method => $opSpec ) {
164 $info = $this->makeRouteInfo(
$path, $opSpec );
165 $this->addRoute( $method,
$path, $info );
175 private function makeRouteInfo(
string $path, array $opSpec ): array {
176 static $objectSpecKeys = [
193 if ( isset( $opSpec[
'redirect'] ) ) {
195 $opSpec[
'handler'] = [
196 'class' => RedirectHandler::class,
197 'redirect' => $opSpec[
'redirect'],
199 unset( $opSpec[
'redirect'] );
202 $handlerSpec = $opSpec[
'handler'] ??
null;
203 if ( !$handlerSpec ) {
204 throw new RouteDefinitionException(
'Missing handler spec' );
208 'spec' => array_intersect_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
209 'config' => array_diff_key( $handlerSpec, array_flip( $objectSpecKeys ) ),
210 'OAS' => array_intersect_key( $opSpec, array_flip( $oasKeys ) ),