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