Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
ReviewTranslationActionApi.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TranslatorInterface;
5
6use MediaWiki\Api\ApiBase;
7use MediaWiki\Api\ApiMain;
10use MediaWiki\Logging\ManualLogEntry;
11use MediaWiki\Revision\RevisionLookup;
12use MediaWiki\Revision\RevisionRecord;
13use MediaWiki\Status\Status;
14use MediaWiki\Title\TitleFormatter;
15use MediaWiki\User\User;
16use Wikimedia\ParamValidator\ParamValidator;
17use Wikimedia\Rdbms\IConnectionProvider;
18
25class ReviewTranslationActionApi extends ApiBase {
27 protected static $right = 'translate-messagereview';
28
29 public function __construct(
30 ApiMain $main,
31 string $moduleName,
32 private readonly RevisionLookup $revisionLookup,
33 private readonly TitleFormatter $titleFormatter,
34 private readonly IConnectionProvider $dbProvider,
35 private readonly HookRunner $hookRunner,
36 ) {
37 parent::__construct( $main, $moduleName );
38 }
39
40 public function execute() {
41 $this->checkUserRightsAny( self::$right );
42
43 $params = $this->extractRequestParams();
44
45 $revRecord = $this->revisionLookup->getRevisionById( $params['revision'] );
46 if ( !$revRecord ) {
47 $this->dieWithError( [ 'apierror-nosuchrevid', $params['revision'] ], 'invalidrevision' );
48 }
49
50 $status = $this->getReviewBlockers( $this->getUser(), $revRecord );
51 if ( !$status->isGood() ) {
52 if ( $status->hasMessage( 'blocked' ) ) {
53 $this->dieBlocked( $this->getUser()->getBlock() );
54 } else {
55 $this->dieStatus( $status );
56 }
57 }
58
59 $ok = $this->doReview( $this->getUser(), $revRecord );
60 if ( !$ok ) {
61 $this->addWarning( 'apiwarn-translate-alreadyreviewedbyyou' );
62 }
63
64 $prefixedText = $this->titleFormatter->getPrefixedText( $revRecord->getPageAsLinkTarget() );
65 $output = [ 'review' => [
66 'title' => $prefixedText,
67 'pageid' => $revRecord->getPageId(),
68 'revision' => $revRecord->getId()
69 ] ];
70
71 $this->getResult()->addValue( null, $this->getModuleName(), $output );
72 }
73
78 private function doReview( User $user, RevisionRecord $revRecord ): bool {
79 $dbw = $this->dbProvider->getPrimaryDatabase();
80 $dbw->newInsertQueryBuilder()
81 ->insertInto( 'translate_reviews' )
82 ->ignore()
83 ->row( [
84 'trr_user' => $user->getId(),
85 'trr_page' => $revRecord->getPageId(),
86 'trr_revision' => $revRecord->getId(),
87 ] )
88 ->caller( __METHOD__ )
89 ->execute();
90
91 if ( !$dbw->affectedRows() ) {
92 return false;
93 }
94
95 $title = $revRecord->getPageAsLinkTarget();
96
97 $entry = new ManualLogEntry( 'translationreview', 'message' );
98 $entry->setPerformer( $user );
99 $entry->setTarget( $title );
100 $entry->setParameters( [
101 '4::revision' => $revRecord->getId(),
102 ] );
103
104 $logid = $entry->insert();
105 $entry->publish( $logid );
106
107 $handle = new MessageHandle( $title );
108 $this->hookRunner->onTranslateEventTranslationReview( $handle );
109
110 return true;
111 }
112
117 private function getReviewBlockers( User $user, RevisionRecord $revRecord ): Status {
118 if ( !$user->isAllowed( self::$right ) ) {
119 return Status::newFatal( 'apierror-permissiondenied-generic' );
120 }
121
122 if ( $user->getBlock() ) {
123 return Status::newFatal( 'blocked' );
124 }
125
126 $title = $revRecord->getPageAsLinkTarget();
127 $handle = new MessageHandle( $title );
128 if ( !$handle->isValid() ) {
129 return Status::newFatal( 'apierror-translate-unknownmessage' );
130 }
131
132 if ( $user->equals( $revRecord->getUser() ) ) {
133 return Status::newFatal( 'apierror-translate-owntranslation' );
134 }
135
136 if ( $handle->isFuzzy() ) {
137 return Status::newFatal( 'apierror-translate-fuzzymessage' );
138 }
139
140 return Status::newGood();
141 }
142
143 public function isWriteMode(): bool {
144 return true;
145 }
146
147 public function needsToken(): string {
148 return 'csrf';
149 }
150
151 protected function getAllowedParams(): array {
152 return [
153 'revision' => [
154 ParamValidator::PARAM_TYPE => 'integer',
155 ParamValidator::PARAM_REQUIRED => true,
156 ],
157 ];
158 }
159
160 protected function getExamplesMessages(): array {
161 return [
162 'action=translationreview&revision=1&token=foo'
163 => 'apihelp-translationreview-example-1',
164 ];
165 }
166}
Hook runner for the Translate extension.
Class for pointing to messages, like Title class is for titles.