Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslationStashActionApi
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 7
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
110
 formatTranslation
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 isWriteMode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 needsToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TranslatorSandbox;
5
6use MediaWiki\Api\ApiBase;
7use MediaWiki\Api\ApiMain;
8use MediaWiki\Extension\Translate\MessageGroupProcessing\MessageGroups;
9use MediaWiki\Extension\Translate\MessageLoading\MessageHandle;
10use MediaWiki\Extension\Translate\MessageLoading\MessageIndex;
11use MediaWiki\Json\FormatJson;
12use MediaWiki\Title\Title;
13use MediaWiki\User\UserFactory;
14use Wikimedia\ParamValidator\ParamValidator;
15use Wikimedia\Rdbms\IConnectionProvider;
16
17/**
18 * WebAPI module for storing translations for users who are in a sandbox.
19 * Access is controlled by hooks in TranslateSandbox class.
20 * @author Niklas Laxström
21 * @license GPL-2.0-or-later
22 * @since 2013.06
23 */
24class TranslationStashActionApi extends ApiBase {
25    private IConnectionProvider $dbProvider;
26    private UserFactory $userFactory;
27    private MessageIndex $messageIndex;
28
29    public function __construct(
30        ApiMain $mainModule,
31        string $moduleName,
32        IConnectionProvider $dbProvider,
33        UserFactory $userFactory,
34        MessageIndex $messageIndex
35    ) {
36        parent::__construct( $mainModule, $moduleName );
37        $this->dbProvider = $dbProvider;
38        $this->userFactory = $userFactory;
39        $this->messageIndex = $messageIndex;
40    }
41
42    public function execute(): void {
43        $params = $this->extractRequestParams();
44
45        // The user we are operating on, not necessarily the user making the request
46        $user = $this->getUser();
47
48        if ( isset( $params['username'] ) ) {
49            if ( $user->isAllowed( 'translate-sandboxmanage' ) ) {
50                $user = $this->userFactory->newFromName( $params['username'] );
51                if ( !$user ) {
52                    $this->dieWithError( [ 'apierror-badparameter', 'username' ], 'invalidparam' );
53                }
54            } else {
55                $this->dieWithError( [ 'apierror-badparameter', 'username' ], 'invalidparam' );
56            }
57        }
58
59        $stash = new TranslationStashStorage( $this->dbProvider->getPrimaryDatabase() );
60        $action = $params['subaction'];
61
62        if ( $action === 'add' ) {
63            if ( !isset( $params['title'] ) ) {
64                $this->dieWithError( [ 'apierror-missingparam', 'title' ] );
65            }
66            if ( !isset( $params['translation'] ) ) {
67                $this->dieWithError( [ 'apierror-missingparam', 'translation' ] );
68            }
69
70            $metadata = $params['metadata'] ? FormatJson::decode( $params['metadata'], true ) : null;
71            // @todo: Return value of Title::newFromText not checked
72            $translation = new StashedTranslation(
73                $user,
74                Title::newFromText( $params['title'] ),
75                $params['translation'],
76                $metadata
77            );
78            $stash->addTranslation( $translation );
79        }
80
81        $output = [];
82        if ( $action === 'query' ) {
83            $output['translations'] = [];
84
85            $translations = $stash->getTranslations( $user );
86            foreach ( $translations as $translation ) {
87                $output['translations'][] = $this->formatTranslation( $translation );
88            }
89        }
90
91        // If we got this far, nothing has failed
92        $output['result'] = 'ok';
93        $this->getResult()->addValue( null, $this->getModuleName(), $output );
94    }
95
96    private function formatTranslation( StashedTranslation $translation ): array {
97        $title = $translation->getTitle();
98        $handle = new MessageHandle( $title );
99
100        // Prepare for the worst
101        $definition = '';
102        $comparison = '';
103        if ( $handle->isValid() ) {
104            $groupId = $this->messageIndex->getPrimaryGroupId( $handle );
105            $group = MessageGroups::getGroup( $groupId );
106
107            $key = $handle->getKey();
108
109            $definition = $group->getMessage( $key, $group->getSourceLanguage() );
110            $comparison = $group->getMessage( $key, $handle->getCode() );
111        }
112
113        return [
114            'title' => $title->getPrefixedText(),
115            'definition' => $definition,
116            'translation' => $translation->getValue(),
117            'comparison' => $comparison,
118            'metadata' => $translation->getMetadata(),
119        ];
120    }
121
122    public function isWriteMode(): bool {
123        return true;
124    }
125
126    public function needsToken(): string {
127        return 'csrf';
128    }
129
130    protected function getAllowedParams(): array {
131        return [
132            'subaction' => [
133                ParamValidator::PARAM_TYPE => [ 'add', 'query' ],
134                ParamValidator::PARAM_REQUIRED => true,
135            ],
136            'title' => [
137                ParamValidator::PARAM_TYPE => 'string',
138            ],
139            'translation' => [
140                ParamValidator::PARAM_TYPE => 'string',
141            ],
142            'metadata' => [
143                ParamValidator::PARAM_TYPE => 'string',
144            ],
145            'username' => [
146                ParamValidator::PARAM_TYPE => 'string',
147            ],
148        ];
149    }
150
151    protected function getExamplesMessages(): array {
152        return [
153            'action=translationstash&subaction=add&title=MediaWiki:Jan/fi&translation=tammikuu&metadata={}'
154                => 'apihelp-translationstash-example-1',
155            'action=translationstash&subaction=query'
156                => 'apihelp-translationstash-example-2',
157        ];
158    }
159}