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;
9use MediaWiki\Revision\RevisionLookup;
10use MediaWiki\Revision\RevisionRecord;
12use Status;
13use TitleFormatter;
14use User;
15use Wikimedia\ParamValidator\ParamValidator;
16use Wikimedia\Rdbms\ILoadBalancer;
17
24class ReviewTranslationActionApi extends ApiBase {
25 protected static $right = 'translate-messagereview';
27 private $revisionLookup;
29 private $titleFormatter;
31 private $loadBalancer;
32
33 public function __construct(
34 ApiMain $main,
35 string $moduleName,
36 RevisionLookup $revisionLookup,
37 TitleFormatter $titleFormatter,
38 ILoadBalancer $loadBalancer
39 ) {
40 parent::__construct( $main, $moduleName );
41 $this->revisionLookup = $revisionLookup;
42 $this->titleFormatter = $titleFormatter;
43 $this->loadBalancer = $loadBalancer;
44 }
45
46 public function execute() {
47 $this->checkUserRightsAny( self::$right );
48
49 $params = $this->extractRequestParams();
50
51 $revRecord = $this->revisionLookup->getRevisionById( $params['revision'] );
52 if ( !$revRecord ) {
53 $this->dieWithError( [ 'apierror-nosuchrevid', $params['revision'] ], 'invalidrevision' );
54 }
55
56 $status = $this->getReviewBlockers( $this->getUser(), $revRecord );
57 if ( !$status->isGood() ) {
58 if ( $status->hasMessage( 'blocked' ) ) {
59 $this->dieBlocked( $this->getUser()->getBlock() );
60 } else {
61 $this->dieStatus( $status );
62 }
63 }
64
65 $ok = $this->doReview( $this->getUser(), $revRecord );
66 if ( !$ok ) {
67 $this->addWarning( 'apiwarn-translate-alreadyreviewedbyyou' );
68 }
69
70 $prefixedText = $this->titleFormatter->getPrefixedText( $revRecord->getPageAsLinkTarget() );
71 $output = [ 'review' => [
72 'title' => $prefixedText,
73 'pageid' => $revRecord->getPageId(),
74 'revision' => $revRecord->getId()
75 ] ];
76
77 $this->getResult()->addValue( null, $this->getModuleName(), $output );
78 }
79
84 private function doReview( User $user, RevisionRecord $revRecord ): bool {
85 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
86 $table = 'translate_reviews';
87 $row = [
88 'trr_user' => $user->getId(),
89 'trr_page' => $revRecord->getPageId(),
90 'trr_revision' => $revRecord->getId(),
91 ];
92 $options = [ 'IGNORE' ];
93 $dbw->insert( $table, $row, __METHOD__, $options );
94
95 if ( !$dbw->affectedRows() ) {
96 return false;
97 }
98
99 $title = $revRecord->getPageAsLinkTarget();
100
101 $entry = new ManualLogEntry( 'translationreview', 'message' );
102 $entry->setPerformer( $user );
103 $entry->setTarget( $title );
104 $entry->setParameters( [
105 '4::revision' => $revRecord->getId(),
106 ] );
107
108 $logid = $entry->insert();
109 $entry->publish( $logid );
110
111 $handle = new MessageHandle( $title );
112 $this->getHookContainer()->run( 'TranslateEventTranslationReview', [ $handle ] );
113
114 return true;
115 }
116
121 private function getReviewBlockers( User $user, RevisionRecord $revRecord ): Status {
122 if ( !$user->isAllowed( self::$right ) ) {
123 return Status::newFatal( 'apierror-permissiondenied-generic' );
124 }
125
126 if ( $user->getBlock() ) {
127 return Status::newFatal( 'blocked' );
128 }
129
130 $title = $revRecord->getPageAsLinkTarget();
131 $handle = new MessageHandle( $title );
132 if ( !$handle->isValid() ) {
133 return Status::newFatal( 'apierror-translate-unknownmessage' );
134 }
135
136 if ( $user->equals( $revRecord->getUser() ) ) {
137 return Status::newFatal( 'apierror-translate-owntranslation' );
138 }
139
140 if ( $handle->isFuzzy() ) {
141 return Status::newFatal( 'apierror-translate-fuzzymessage' );
142 }
143
144 return Status::newGood();
145 }
146
147 public function isWriteMode(): bool {
148 return true;
149 }
150
151 public function needsToken(): string {
152 return 'csrf';
153 }
154
155 protected function getAllowedParams(): array {
156 return [
157 'revision' => [
158 ParamValidator::PARAM_TYPE => 'integer',
159 ParamValidator::PARAM_REQUIRED => true,
160 ],
161 'token' => [
162 ParamValidator::PARAM_TYPE => 'string',
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}
Class for pointing to messages, like Title class is for titles.