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