MediaWiki REL1_37
ActionModuleBasedHandler.php
Go to the documentation of this file.
1<?php
2
4
5use ApiBase;
6use ApiMain;
7use ApiMessage;
10use IApiMessage;
17use WebResponse;
23
29abstract class ActionModuleBasedHandler extends Handler {
30
34 private $session = null;
35
39 private $apiMain = null;
40
41 protected function getUser() {
42 return $this->getApiMain()->getUser();
43 }
44
48 protected function getSession() {
49 if ( !$this->session ) {
50 $this->session = $this->getApiMain()->getRequest()->getSession();
51 }
52
53 return $this->session;
54 }
55
61 public function setApiMain( ApiMain $apiMain ) {
62 $this->apiMain = $apiMain;
63 }
64
68 public function getApiMain() {
69 if ( $this->apiMain ) {
70 return $this->apiMain;
71 }
72
73 $context = RequestContext::getMain();
74 $session = $context->getRequest()->getSession();
75
76 // NOTE: This being a FauxRequest instance triggers special case behavior
77 // in ApiMain, causing ApiMain::isInternalMode() to return true. Among other things,
78 // this causes ApiMain to throw errors rather than encode them in the result data.
79 $fauxRequest = new FauxRequest( [], true, $session );
80 $fauxRequest->setSessionId( $session->getSessionId() );
81
82 $fauxContext = new RequestContext();
83 $fauxContext->setRequest( $fauxRequest );
84 $fauxContext->setUser( $context->getUser() );
85 $fauxContext->setLanguage( $context->getLanguage() );
86
87 $this->apiMain = new ApiMain( $fauxContext, true );
88 return $this->apiMain;
89 }
90
98 public function overrideActionModule( string $name, string $group, ApiBase $module ) {
99 $this->getApiMain()->getModuleManager()->addModule(
100 $name,
101 $group,
102 [
103 'class' => get_class( $module ),
104 'factory' => static function () use ( $module ) {
105 return $module;
106 }
107 ]
108 );
109 }
110
120 public function execute() {
121 $apiMain = $this->getApiMain();
122
123 $params = $this->getActionModuleParameters();
125
126 foreach ( $params as $key => $value ) {
127 $request->setVal( $key, $value );
128 }
129
130 try {
131 // NOTE: ApiMain detects the this to be an internal call, so it will throw
132 // ApiUsageException rather than putting error messages into the result.
133 $apiMain->execute();
134 } catch ( ApiUsageException $ex ) {
135 // use a fake loop to throw the first error
136 foreach ( $ex->getStatusValue()->getErrorsByType( 'error' ) as $error ) {
137 $msg = ApiMessage::create( $error );
138 $this->throwHttpExceptionForActionModuleError( $msg, $ex->getCode() ?: 400 );
139 }
140
141 // This should never happen, since ApiUsageExceptions should always
142 // have errors in their Status object.
143 throw new HttpException(
144 'Unmapped action module error: ' . $ex->getMessage(),
145 $ex->getCode()
146 );
147 }
148
149 $actionModuleResult = $apiMain->getResult()->getResultData( null, [ 'Strip' => 'all' ] );
150
151 // construct result
152 $resultData = $this->mapActionModuleResult( $actionModuleResult );
153
154 $response = $this->getResponseFactory()->createFromReturnValue( $resultData );
155
157 $apiMain->getRequest()->response(),
158 $actionModuleResult,
159 $response
160 );
161
162 return $response;
163 }
164
174 abstract protected function getActionModuleParameters();
175
184 abstract protected function mapActionModuleResult( array $data );
185
202 protected function mapActionModuleResponse(
203 WebResponse $actionModuleResponse,
204 array $actionModuleResult,
205 Response $response
206 ) {
207 // TODO: map status, headers, cookies, etc
208 }
209
228 protected function throwHttpExceptionForActionModuleError( IApiMessage $msg, $statusCode = 400 ) {
229 // override to supply mappings
230
231 throw new LocalizedHttpException(
232 $this->makeMessageValue( $msg ),
233 $statusCode,
234 // Include the original error code in the response.
235 // This makes it easier to track down the original cause of the error,
236 // and allows more specific mappings to be added to
237 // implementations of throwHttpExceptionForActionModuleError() provided by
238 // subclasses
239 [ 'actionModuleErrorCode' => $msg->getApiCode() ]
240 );
241 }
242
250 protected function makeMessageValue( IApiMessage $msg ) {
251 $params = [];
252
253 // TODO: find a better home for the parameter mapping logic
254 foreach ( $msg->getParams() as $p ) {
255 $params[] = $this->makeMessageParam( $p );
256 }
257
258 return new MessageValue( $msg->getKey(), $params );
259 }
260
266 private function makeMessageParam( $param ) {
267 if ( is_array( $param ) ) {
268 foreach ( $param as $type => $value ) {
269 if ( $type === 'list' ) {
270 $paramList = [];
271
272 foreach ( $value as $v ) {
273 $paramList[] = $this->makeMessageParam( $v );
274 }
275
276 return new ListParam( ParamType::TEXT, $paramList );
277 } else {
278 return new ScalarParam( $type, $value );
279 }
280 }
281 } else {
282 return new ScalarParam( ParamType::TEXT, $param );
283 }
284 }
285
286}
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:55
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:49
getResult()
Get the ApiResult object associated with current request.
Definition ApiMain.php:622
execute()
Execute api request.
Definition ApiMain.php:820
Extension of Message implementing IApiMessage @newable.
Exception used to abort API execution with an error.
getStatusValue()
Fetch the error status.
WebRequest clone which takes values from a provided array.
Base class for REST handlers that are implemented by mapping to an existing ApiModule.
setApiMain(ApiMain $apiMain)
Set main action API entry point for testing.
overrideActionModule(string $name, string $group, ApiBase $module)
Overrides an action API module.
throwHttpExceptionForActionModuleError(IApiMessage $msg, $statusCode=400)
Throws a HttpException for a given IApiMessage that represents an error.
mapActionModuleResponse(WebResponse $actionModuleResponse, array $actionModuleResult, Response $response)
Transfers relevant information, such as header values, from the WebResponse constructed by the action...
execute()
Main execution method, implemented to delegate execution to ApiMain.
makeMessageValue(IApiMessage $msg)
Constructs a MessageValue from an IApiMessage.
mapActionModuleResult(array $data)
Maps an action API result to a REST API result.
getActionModuleParameters()
Maps a REST API request to an action API request.
Base class for REST route handlers.
Definition Handler.php:17
RequestInterface $request
Definition Handler.php:32
getResponseFactory()
Get the ResponseFactory which can be used to generate Response objects.
Definition Handler.php:170
This is the base exception class for non-fatal exceptions thrown from REST handlers.
Manages data for an authenticated session.
Definition Session.php:48
getRequest()
Returns the request associated with this session.
Definition Session.php:164
getSessionId()
Returns the SessionId object.
Definition Session.php:89
Group all the pieces relevant to the context of a request into one instance @newable.
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
Value object representing a message parameter that consists of a list of values.
Definition ListParam.php:12
Value object representing a message parameter that consists of a list of values.
Value object representing a message for i18n.
The constants used to specify parameter types.
Definition ParamType.php:11
Value object representing a message parameter holding a single value.
Interface for messages with machine-readable data for use by the API.
getApiCode()
Returns a machine-readable code for use by the API.
getParams()
Returns the message parameters.
getKey()
Returns the message key.