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