Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
AddLexemeStatementRouteHandler
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 8
132
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 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 checkPreconditions
0.00% covered (danger)
0.00%
0 / 1
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 / 24
0.00% covered (danger)
0.00%
0 / 1
20
 newSuccessHttpResponse
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 getParamSettings
0.00% covered (danger)
0.00%
0 / 7
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\RequestInterface;
9use MediaWiki\Rest\Response;
10use MediaWiki\Rest\ResponseInterface;
11use MediaWiki\Rest\SimpleHandler;
12use Wikibase\Lexeme\Interactors\AddLexemeStatement\AddLexemeStatement;
13use Wikibase\Lexeme\Interactors\AddLexemeStatement\AddLexemeStatementRequest;
14use Wikibase\Lexeme\Interactors\AddLexemeStatement\AddLexemeStatementResponse;
15use Wikibase\Lexeme\Interactors\GetLexeme\LexemeRedirect;
16use Wikibase\Lexeme\Interactors\UseCaseError;
17use Wikibase\Lexeme\WikibaseLexemeServices;
18use Wikibase\Repo\Domains\Crud\RouteHandlers\Middleware\TempUserCreationResponseHeaderMiddleware;
19use Wikibase\Repo\Domains\Crud\WbCrud;
20use Wikibase\Repo\Domains\Statements\Application\Serialization\StatementSerializer;
21use Wikibase\Repo\RestApi\Middleware\AuthenticationMiddleware;
22use Wikibase\Repo\RestApi\Middleware\MiddlewareHandler;
23use Wikibase\Repo\RestApi\Middleware\UserAgentCheckMiddleware;
24use Wikimedia\ParamValidator\ParamValidator;
25
26/**
27 * @license GPL-2.0-or-later
28 */
29class AddLexemeStatementRouteHandler extends SimpleHandler {
30
31    private const LEXEME_ID_PATH_PARAM = 'lexeme_id';
32    private const STATEMENT_BODY_PARAM = 'statement';
33    private const TAGS_BODY_PARAM = 'tags';
34    private const BOT_BODY_PARAM = 'bot';
35    private const COMMENT_BODY_PARAM = 'comment';
36
37    public function __construct(
38        private AddLexemeStatement $addLexemeStatement,
39        private MiddlewareHandler $middlewareHandler,
40        private StatementSerializer $statementSerializer,
41        private ResponseFactory $responseFactory,
42    ) {
43    }
44
45    public static function factory(): Handler {
46        return new self(
47            WikibaseLexemeServices::getAddLexemeStatement(),
48            new MiddlewareHandler( [
49                WikibaseLexemeServices::getUnexpectedErrorHandlerMiddleware(),
50                new UserAgentCheckMiddleware(),
51                new AuthenticationMiddleware( MediaWikiServices::getInstance()->getUserIdentityUtils() ),
52                WikibaseLexemeServices::getPreconditionMiddlewareFactory()->newPreconditionMiddleware(
53                    fn ( RequestInterface $request ): string => $request->getPathParam( self::LEXEME_ID_PATH_PARAM )
54                ),
55                new TempUserCreationResponseHeaderMiddleware(
56                    new HookRunner( MediaWikiServices::getInstance()->getHookContainer() )
57                ),
58            ] ),
59            WbCrud::getStatementSerializer(),
60            new ResponseFactory(),
61        );
62    }
63
64    /**
65     * Preconditions are checked via {@link PreconditionMiddleware}
66     */
67    public function checkPreconditions(): ?ResponseInterface {
68        return null;
69    }
70
71    public function run( string $lexemeId ): Response {
72        return $this->middlewareHandler->run( $this, fn () => $this->runUseCase( $lexemeId ) );
73    }
74
75    private function runUseCase( string $lexemeId ): Response {
76        $jsonBody = $this->getValidatedBody();
77        '@phan-var array $jsonBody'; // guaranteed to be an array per getBodyParamSettings()
78        $mwUser = $this->getAuthority()->getUser();
79
80        try {
81            return $this->newSuccessHttpResponse(
82                $this->addLexemeStatement->execute(
83                    new AddLexemeStatementRequest(
84                        $lexemeId,
85                        $jsonBody[self::STATEMENT_BODY_PARAM],
86                        $jsonBody[self::TAGS_BODY_PARAM] ?? [],
87                        $jsonBody[self::BOT_BODY_PARAM] ?? false,
88                        $jsonBody[self::COMMENT_BODY_PARAM] ?? null,
89                        $mwUser->isRegistered() ? $mwUser->getName() : null,
90                    )
91                )
92            );
93        } catch ( LexemeRedirect $e ) {
94            $redirectTarget = $e->redirectTarget->getSerialization();
95
96            return $this->responseFactory->newErrorResponseFromException(
97                UseCaseError::newLexemeRedirected(
98                    $lexemeId,
99                    $redirectTarget
100                )
101            );
102        } catch ( UseCaseError $e ) {
103            return $this->responseFactory->newErrorResponseFromException( $e );
104        }
105    }
106
107    private function newSuccessHttpResponse( AddLexemeStatementResponse $useCaseResponse ): Response {
108        return $this->responseFactory->newSuccessResponse(
109            json_encode(
110                $this->statementSerializer->serialize( $useCaseResponse->statement ),
111                JSON_UNESCAPED_SLASHES
112            ),
113            $useCaseResponse->revisionId,
114            $useCaseResponse->lastModified,
115            statusCode: 201,
116        );
117    }
118
119    public function getParamSettings(): array {
120        return [
121            self::LEXEME_ID_PATH_PARAM => [
122                self::PARAM_SOURCE => 'path',
123                ParamValidator::PARAM_TYPE => 'string',
124                ParamValidator::PARAM_REQUIRED => true,
125            ],
126        ];
127    }
128
129    public function getBodyParamSettings(): array {
130        return [
131            self::STATEMENT_BODY_PARAM => [
132                self::PARAM_SOURCE => 'body',
133                ParamValidator::PARAM_TYPE => 'array',
134                ParamValidator::PARAM_REQUIRED => true,
135            ],
136            self::TAGS_BODY_PARAM => [
137                self::PARAM_SOURCE => 'body',
138                ParamValidator::PARAM_TYPE => 'array',
139                ParamValidator::PARAM_REQUIRED => false,
140                ParamValidator::PARAM_DEFAULT => [],
141            ],
142            self::BOT_BODY_PARAM => [
143                self::PARAM_SOURCE => 'body',
144                ParamValidator::PARAM_TYPE => 'boolean',
145                ParamValidator::PARAM_REQUIRED => false,
146                ParamValidator::PARAM_DEFAULT => false,
147            ],
148            self::COMMENT_BODY_PARAM => [
149                self::PARAM_SOURCE => 'body',
150                ParamValidator::PARAM_TYPE => 'string',
151                ParamValidator::PARAM_REQUIRED => false,
152            ],
153        ];
154    }
155}