Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiContentTranslationUnreviewedCheck
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 4
56
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
 validateRequest
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 execute
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
12
 isInternal
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types=1 );
3
4namespace ContentTranslation\ActionApi;
5
6use ContentTranslation\DTO\PublishedTranslationDTO;
7use ContentTranslation\Service\UserService;
8use ContentTranslation\Store\TranslationCorporaStore;
9use ContentTranslation\Store\TranslationStore;
10use MediaWiki\Api\ApiBase;
11use MediaWiki\Api\ApiMain;
12
13/**
14 * Action API module that is used to check if any "unreviewed" translation
15 * has just been published by the current user. A translation is considered
16 * "unreviewed" if the user has spent fewer minutes to complete it, than the
17 * number of the translated paragraphs, with a maximum limit to 10 minutes.
18 * That is, if the user has spent 10 or more minutes to complete a translation,
19 * the translation is considered "reviewed", even if it contains hundreds
20 * of paragraphs.
21 *
22 * @author Nik Gkountas
23 * @license GPL-2.0-or-later
24 * @since 2024.03
25 */
26class ApiContentTranslationUnreviewedCheck extends ApiBase {
27    private UserService $userService;
28    private TranslationStore $translationStore;
29    private TranslationCorporaStore $corporaStore;
30
31    public function __construct(
32        ApiMain $mainModule,
33        string $action,
34        TranslationStore $translationStore,
35        TranslationCorporaStore $corporaStore,
36        UserService $userService
37    ) {
38        parent::__construct( $mainModule, $action );
39        $this->translationStore = $translationStore;
40        $this->userService = $userService;
41        $this->corporaStore = $corporaStore;
42    }
43
44    private function validateRequest(): void {
45        $user = $this->getUser();
46
47        if ( !$user->isNamed() ) {
48            $this->dieWithError( 'apierror-cxcheckunreviewed-anon-user' );
49        }
50    }
51
52    public function execute() {
53        $this->validateRequest();
54
55        // This method returns the last published translation, in the last 10 minutes.
56        // Checking the most recent translation is enough here. Previous translations
57        // have already been checked before the most recent translation was published.
58        $recentTranslation = $this->translationStore->findRecentTranslationByUser(
59            $this->userService->getGlobalUserId( $this->getUser() )
60        );
61        $result = [ 'result' => 'success' ];
62
63        if ( !$recentTranslation ) {
64            $this->getResult()->addValue( null, $this->getModuleName(), $result );
65            return;
66        }
67
68        $translatedSubSectionsCount = $this->corporaStore->countTranslatedSubSectionsByTranslationId(
69            $recentTranslation->getTranslationId()
70        );
71
72        $startUnixTimestamp = (int)wfTimestamp( TS_UNIX, $recentTranslation->translation['startTimestamp'] );
73        $minutesPassed = ( time() - $startUnixTimestamp ) / 60;
74        if ( $translatedSubSectionsCount > $minutesPassed ) {
75            $result['result'] = 'failure';
76            $translationDTO = new PublishedTranslationDTO(
77                $recentTranslation->getTranslationId(),
78                $recentTranslation->translation['sourceTitle'],
79                $recentTranslation->translation['sourceLanguage'],
80                $recentTranslation->translation['targetLanguage'],
81                $recentTranslation->translation['startTimestamp'],
82                $recentTranslation->translation['lastUpdateTimestamp'],
83                $recentTranslation->translation['sourceRevisionId'],
84                $recentTranslation->translation['targetTitle'],
85                $recentTranslation->translation['targetURL'],
86                []
87            );
88            $result['translation'] = $translationDTO->toArray();
89        }
90
91        $this->getResult()->addValue( null, $this->getModuleName(), $result );
92    }
93
94    public function isInternal() {
95        return true;
96    }
97}