Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
CreateLexemeRouteHandler
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 7
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 factory
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 run
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 runUseCase
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 newSuccessHttpResponse
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 getBodyParamSettings
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
2
1<?php declare( strict_types = 1 );
2
3namespace Wikibase\Lexeme\MediaWiki\RestApi;
4
5use MediaWiki\HookContainer\HookRunner;
6use MediaWiki\MediaWikiServices;
7use MediaWiki\Rest\Handler;
8use MediaWiki\Rest\Response;
9use MediaWiki\Rest\SimpleHandler;
10use MediaWiki\Rest\Validator\Validator;
11use Wikibase\Lexeme\Interactors\CreateLexeme\CreateLexeme;
12use Wikibase\Lexeme\Interactors\CreateLexeme\CreateLexemeRequest;
13use Wikibase\Lexeme\Interactors\CreateLexeme\CreateLexemeResponse;
14use Wikibase\Lexeme\Interactors\UseCaseError;
15use Wikibase\Lexeme\Presentation\RestSerialization\LexemeSerializer;
16use Wikibase\Lexeme\WikibaseLexemeServices;
17use Wikibase\Repo\Domains\Crud\RouteHandlers\Middleware\TempUserCreationResponseHeaderMiddleware;
18use Wikibase\Repo\RestApi\Middleware\AuthenticationMiddleware;
19use Wikibase\Repo\RestApi\Middleware\MiddlewareHandler;
20use Wikibase\Repo\RestApi\Middleware\UserAgentCheckMiddleware;
21use Wikimedia\ParamValidator\ParamValidator;
22
23/**
24 * @license GPL-2.0-or-later
25 */
26class CreateLexemeRouteHandler extends SimpleHandler {
27
28    use AssertValidTopLevelFields;
29
30    public const LEXEME_BODY_PARAM = 'lexeme';
31    public const TAGS_BODY_PARAM = 'tags';
32    public const BOT_BODY_PARAM = 'bot';
33    public const COMMENT_BODY_PARAM = 'comment';
34
35    public function __construct(
36        private CreateLexeme $createLexeme,
37        private MiddlewareHandler $middlewareHandler,
38        private LexemeSerializer $lexemeSerializer,
39        private ResponseFactory $responseFactory,
40    ) {
41    }
42
43    public static function factory(): Handler {
44        return new self(
45            WikibaseLexemeServices::getCreateLexeme(),
46            new MiddlewareHandler( [
47                    WikibaseLexemeServices::getUnexpectedErrorHandlerMiddleware(),
48                    new UserAgentCheckMiddleware(),
49                    new AuthenticationMiddleware( MediaWikiServices::getInstance()->getUserIdentityUtils() ),
50                    new TempUserCreationResponseHeaderMiddleware(
51                        new HookRunner( MediaWikiServices::getInstance()->getHookContainer() )
52                    ),
53                ]
54            ),
55            WikibaseLexemeServices::getLexemeSerializer(),
56            new ResponseFactory(),
57        );
58    }
59
60    public function validate( Validator $restValidator ): void {
61        $this->assertValidTopLevelTypes( $this->getRequest()->getParsedBody(), $this->getBodyParamSettings() );
62        parent::validate( $restValidator );
63    }
64
65    public function run(): Response {
66        return $this->middlewareHandler->run( $this, fn () => $this->runUseCase() );
67    }
68
69    public function runUseCase(): Response {
70        $jsonBody = $this->getValidatedBody();
71        '@phan-var array $jsonBody'; // guaranteed to be an array per getBodyParamSettings()
72        $mwUser = $this->getAuthority()->getUser();
73
74        try {
75            return $this->newSuccessHttpResponse(
76                $this->createLexeme->execute(
77                    new CreateLexemeRequest(
78                        $jsonBody[self::LEXEME_BODY_PARAM],
79                        $jsonBody[self::TAGS_BODY_PARAM] ?? [],
80                        $jsonBody[self::BOT_BODY_PARAM] ?? false,
81                        $jsonBody[self::COMMENT_BODY_PARAM] ?? null,
82                        $mwUser->isRegistered() ? $mwUser->getName() : null,
83                    )
84                )
85            );
86        } catch ( UseCaseError $e ) {
87            return $this->responseFactory->newErrorResponseFromException( $e );
88        }
89    }
90
91    private function newSuccessHttpResponse( CreateLexemeResponse $useCaseResponse ): Response {
92        $httpResponse = $this->responseFactory->newSuccessResponse(
93            json_encode(
94                $this->lexemeSerializer->serialize( $useCaseResponse->lexeme ),
95                JSON_UNESCAPED_SLASHES
96            ),
97            $useCaseResponse->revisionId,
98            $useCaseResponse->lastModified,
99            statusCode: 201,
100        );
101        $httpResponse->setHeader(
102            'Location',
103            $this->getRouter()->getRouteUrl(
104                GetLexemeRouteHandler::ROUTE,
105                [ GetLexemeRouteHandler::LEXEME_ID_PATH_PARAM => $useCaseResponse->lexeme->id->getSerialization() ]
106            )
107        );
108
109        return $httpResponse;
110    }
111
112    public function getBodyParamSettings(): array {
113        return [
114            self::LEXEME_BODY_PARAM => [
115                self::PARAM_SOURCE => 'body',
116                ParamValidator::PARAM_TYPE => 'array',
117                ParamValidator::PARAM_REQUIRED => true,
118            ],
119            self::TAGS_BODY_PARAM => [
120                self::PARAM_SOURCE => 'body',
121                ParamValidator::PARAM_TYPE => 'array',
122                ParamValidator::PARAM_REQUIRED => false,
123                ParamValidator::PARAM_DEFAULT => [],
124            ],
125            self::BOT_BODY_PARAM => [
126                self::PARAM_SOURCE => 'body',
127                ParamValidator::PARAM_TYPE => 'boolean',
128                ParamValidator::PARAM_REQUIRED => false,
129                ParamValidator::PARAM_DEFAULT => false,
130            ],
131            self::COMMENT_BODY_PARAM => [
132                self::PARAM_SOURCE => 'body',
133                ParamValidator::PARAM_TYPE => 'string',
134                ParamValidator::PARAM_REQUIRED => false,
135            ],
136        ];
137    }
138
139}