Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 100
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslationStashSpecialPage
0.00% covered (danger)
0.00%
0 / 100
0.00% covered (danger)
0.00%
0 / 10
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 doesWrites
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 hasPermissionToUse
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 showPage
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
6
 getMessageTable
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 tuxLanguageSelector
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
2
 getSourceLanguage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTargetLanguage
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TranslatorSandbox;
5
6use FormatJson;
7use Language;
8use MediaWiki\Config\ServiceOptions;
9use MediaWiki\Extension\Translate\Utilities\Utilities;
10use MediaWiki\Html\Html;
11use MediaWiki\Languages\LanguageFactory;
12use MediaWiki\Languages\LanguageNameUtils;
13use MediaWiki\Title\Title;
14use MediaWiki\User\UserOptionsLookup;
15use SpecialPage;
16
17/**
18 * Special page for new users to translate example messages.
19 *
20 * @author Santhosh Thottingal
21 * @license GPL-2.0-or-later
22 * @ingroup SpecialPage TranslateSpecialPage
23 */
24class TranslationStashSpecialPage extends SpecialPage {
25    /** @var TranslationStashReader */
26    private $stash;
27    /** @var ServiceOptions */
28    private $options;
29    /** @var LanguageNameUtils */
30    private $languageNameUtils;
31    /** @var UserOptionsLookup */
32    private $userOptionsLookup;
33    /** @var LanguageFactory */
34    private $languageFactory;
35
36    public const CONSTRUCTOR_OPTIONS = [
37        'TranslateSandboxLimit',
38    ];
39
40    public function __construct(
41        LanguageNameUtils $languageNameUtils,
42        TranslationStashReader $stash,
43        UserOptionsLookup $userOptionsLookup,
44        LanguageFactory $languageFactory,
45        ServiceOptions $options
46    ) {
47        parent::__construct( 'TranslationStash' );
48        $this->languageNameUtils = $languageNameUtils;
49        $this->stash = $stash;
50        $this->userOptionsLookup = $userOptionsLookup;
51        $this->languageFactory = $languageFactory;
52        $this->options = $options;
53    }
54
55    public function doesWrites() {
56        return true;
57    }
58
59    protected function getGroupName() {
60        return 'translation';
61    }
62
63    public function execute( $params ) {
64        $limit = $this->options->get( 'TranslateSandboxLimit' );
65
66        $this->setHeaders();
67        $out = $this->getOutput();
68
69        if ( !$this->hasPermissionToUse() ) {
70            $out->redirect( Title::newMainPage()->getLocalURL() );
71
72            return;
73        }
74
75        $out->addJsConfigVars( 'wgTranslateSandboxLimit', $limit );
76        $out->addModules( 'ext.translate.specialTranslationStash' );
77        $out->addModuleStyles( 'mediawiki.ui.button' );
78        $this->showPage();
79    }
80
81    /** Checks that the user is in the sandbox. */
82    private function hasPermissionToUse(): bool {
83        return TranslateSandbox::isSandboxed( $this->getUser() );
84    }
85
86    /** Generates the whole page html and appends it to output */
87    private function showPage(): void {
88        $out = $this->getOutput();
89        $user = $this->getUser();
90
91        $count = count( $this->stash->getTranslations( $user ) );
92        if ( $count === 0 ) {
93            $progress = $this->msg( 'translate-translationstash-initialtranslation' )->parse();
94        } else {
95            $progress = $this->msg( 'translate-translationstash-translations' )
96                ->numParams( $count )
97                ->parse();
98        }
99
100        $out->addHTML(
101            <<<HTML
102            <div class="grid">
103                <div class="row translate-welcome-header">
104                    <h1>
105                        {$this->msg( 'translate-translationstash-welcome', $user->getName() )->parse()}
106                    </h1>
107                    <p>
108                        {$this->msg( 'translate-translationstash-welcome-note' )->parse()}
109                    </p>
110                </div>
111                <div class="row translate-stash-control">
112                    <div class="six columns stash-stats">
113                        {$progress}
114                    </div>
115                    <div class="six columns ext-translate-language-selector">
116                        {$this->tuxLanguageSelector()}
117                    </div>
118                </div>
119                {$this->getMessageTable()}
120                <div class="row limit-reached hide"></div>
121            </div>
122            HTML
123        );
124    }
125
126    private function getMessageTable(): string {
127        $sourceLang = $this->getSourceLanguage();
128        $targetLang = $this->getTargetLanguage();
129
130        return Html::element(
131            'div',
132            [
133                'class' => 'row tux-messagelist',
134                'data-sourcelangcode' => $sourceLang->getCode(),
135                'data-sourcelangdir' => $sourceLang->getDir(),
136                'data-targetlangcode' => $targetLang->getCode(),
137                'data-targetlangdir' => $targetLang->getDir(),
138            ]
139        );
140    }
141
142    private function tuxLanguageSelector(): string {
143        // The name will be displayed in the UI language,
144        // so use for lang and dir
145        $language = $this->getTargetLanguage();
146        $targetLangName = $this->languageNameUtils->getLanguageName( $language->getCode() );
147
148        $label = Html::element( 'span', [], $this->msg( 'tux-languageselector' )->text() );
149
150        $languageIcon = Html::element(
151            'span',
152            [ 'class' => 'ext-translate-language-icon' ]
153        );
154
155        $targetLanguageName = Html::element(
156            'span',
157            [
158                'class' => 'ext-translate-target-language',
159                'dir' => $language->getDir(),
160                'lang' => $language->getHtmlCode()
161            ],
162            $targetLangName
163        );
164
165        $expandIcon = Html::element(
166            'span',
167            [ 'class' => 'ext-translate-language-selector-expand' ]
168        );
169
170        $value = Html::rawElement(
171            'span',
172            [
173                'class' => 'uls mw-ui-button',
174                'tabindex' => 0,
175                'title' => $this->msg( 'tux-select-target-language' )->text()
176            ],
177            $languageIcon . $targetLanguageName . $expandIcon
178        );
179
180        return Html::rawElement(
181            'div',
182            [ 'class' => 'columns ext-translate-language-selector' ],
183            "$label $value"
184        );
185    }
186
187    /** Returns the source language for messages. */
188    protected function getSourceLanguage(): Language {
189        // Bad
190        return $this->languageFactory->getLanguage( 'en' );
191    }
192
193    /** Returns the default target language for messages. */
194    private function getTargetLanguage(): Language {
195        $ui = $this->getLanguage();
196        $source = $this->getSourceLanguage();
197        if ( !$ui->equals( $source ) ) {
198            return $ui;
199        }
200
201        $options = FormatJson::decode(
202            $this->userOptionsLookup->getOption( $this->getUser(), 'translate-sandbox' ),
203            true
204        );
205        $supported = Utilities::getLanguageNames( 'en' );
206
207        if ( isset( $options['languages'] ) ) {
208            foreach ( $options['languages'] as $code ) {
209                if ( !isset( $supported[$code] ) ) {
210                    continue;
211                }
212
213                if ( $code !== $source->getCode() ) {
214                    return $this->languageFactory->getLanguage( $code );
215                }
216            }
217        }
218
219        // User has not chosen any valid language. Pick the source.
220        return $this->languageFactory->getLanguage( $source->getCode() );
221    }
222}