Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.54% covered (warning)
81.54%
53 / 65
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
CreationHandler
81.54% covered (warning)
81.54%
53 / 65
50.00% covered (danger)
50.00%
3 / 6
11.76
0.00% covered (danger)
0.00%
0 / 1
 getTitleParameter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getBodyParamSettings
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
1
 getActionModuleParameters
84.21% covered (warning)
84.21%
16 / 19
0.00% covered (danger)
0.00%
0 / 1
6.14
 mapActionModuleResponse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 getResponseBodySchemaFileName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResponseHeaderSettings
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Rest\Handler;
4
5use MediaWiki\Request\WebResponse;
6use MediaWiki\Rest\Handler;
7use MediaWiki\Rest\LocalizedHttpException;
8use MediaWiki\Rest\Response;
9use MediaWiki\Rest\ResponseHeaders;
10use Wikimedia\Message\MessageValue;
11use Wikimedia\ParamValidator\ParamValidator;
12
13/**
14 * Core REST API endpoint that handles page creation (main slot only)
15 */
16class CreationHandler extends EditHandler {
17
18    /**
19     * @inheritDoc
20     */
21    protected function getTitleParameter() {
22        $body = $this->getValidatedBody();
23        '@phan-var array $body';
24        return $body['title'];
25    }
26
27    /**
28     * @inheritDoc
29     * @return array
30     */
31    public function getBodyParamSettings(): array {
32        return [
33            'source' => [
34                self::PARAM_SOURCE => 'body',
35                ParamValidator::PARAM_TYPE => 'string',
36                ParamValidator::PARAM_REQUIRED => true,
37                Handler::PARAM_DESCRIPTION => new MessageValue( 'rest-param-desc-source' )
38            ],
39            'title' => [
40                self::PARAM_SOURCE => 'body',
41                ParamValidator::PARAM_TYPE => 'string',
42                ParamValidator::PARAM_REQUIRED => true,
43                Handler::PARAM_DESCRIPTION => new MessageValue( 'rest-param-desc-create-title' )
44            ],
45            'comment' => [
46                self::PARAM_SOURCE => 'body',
47                ParamValidator::PARAM_TYPE => 'string',
48                ParamValidator::PARAM_REQUIRED => true,
49                Handler::PARAM_DESCRIPTION => new MessageValue( 'rest-param-desc-comment' )
50            ],
51            'content_model' => [
52                self::PARAM_SOURCE => 'body',
53                ParamValidator::PARAM_TYPE => 'string',
54                ParamValidator::PARAM_REQUIRED => false,
55                Handler::PARAM_DESCRIPTION => new MessageValue( 'rest-param-desc-contentmodel' )
56            ],
57        ]
58        + $this->getTokenParamDefinition();
59    }
60
61    /**
62     * @inheritDoc
63     */
64    protected function getActionModuleParameters() {
65        $body = $this->getValidatedBody();
66        '@phan-var array $body';
67
68        $title = $this->getTitleParameter();
69
70        $contentmodel = $body['content_model'] ?: null;
71
72        if ( $contentmodel !== null && !$this->contentHandlerFactory->isDefinedModel( $contentmodel ) ) {
73            throw new LocalizedHttpException(
74                new MessageValue( 'rest-bad-content-model', [ $body['content_model'] ] ), 400
75            );
76        }
77
78        // Use a known good CSRF token if a token is not needed because we are
79        // using a method of authentication that protects against CSRF, like OAuth.
80        $token = $this->needsToken() ? $this->getToken() : $this->getUser()->getEditToken();
81
82        $params = [
83            'action' => 'edit',
84            'title' => $title,
85            'text' => $body['source'],
86            'summary' => $body['comment'],
87            'token' => $token,
88            'createonly' => true,
89        ];
90
91        if ( $contentmodel !== null ) {
92            $params['contentmodel'] = $contentmodel;
93        }
94
95        return $params;
96    }
97
98    protected function mapActionModuleResponse(
99        WebResponse $actionModuleResponse,
100        array $actionModuleResult,
101        Response $response
102    ) {
103        parent::mapActionModuleResponse(
104            $actionModuleResponse,
105            $actionModuleResult,
106            $response
107        );
108
109        $title = $this->urlEncodeTitle( $actionModuleResult['edit']['title'] );
110
111        $url = $this->getRouter()->getRouteUrl( '/v1/page/' . $title );
112        $response->setHeader( ResponseHeaders::LOCATION, $url );
113    }
114
115    /**
116     * This method specifies the JSON schema file for the response
117     * body when creating a new page.
118     *
119     * @return ?string The file path to the NewPage JSON schema.
120     */
121    public function getResponseBodySchemaFileName( string $method ): ?string {
122        return __DIR__ . '/Schema/NewPage.json';
123    }
124
125    /** @inheritDoc */
126    public function getResponseHeaderSettings(): array {
127        return array_merge(
128            parent::getResponseHeaderSettings(),
129            [
130                ResponseHeaders::LOCATION => ResponseHeaders::RESPONSE_HEADER_DEFINITIONS[
131                    ResponseHeaders::LOCATION
132                ]
133            ]
134        );
135    }
136}