MediaWiki  master
ApiTag.php
Go to the documentation of this file.
1 <?php
2 
23 
28 class ApiTag extends ApiBase {
29 
31 
33  private $revisionStore;
34 
35  public function execute() {
36  $this->revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
37 
38  $params = $this->extractRequestParams();
39  $user = $this->getUser();
40 
41  // make sure the user is allowed
42  $this->checkUserRightsAny( 'changetags' );
43 
44  // Fail early if the user is sitewide blocked.
45  $block = $user->getBlock();
46  if ( $block && $block->isSitewide() ) {
47  $this->dieBlocked( $block );
48  }
49 
50  // Check if user can add tags
51  if ( $params['tags'] ) {
52  $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
53  if ( !$ableToTag->isOK() ) {
54  $this->dieStatus( $ableToTag );
55  }
56  }
57 
58  // validate and process each revid, rcid and logid
59  $this->requireAtLeastOneParameter( $params, 'revid', 'rcid', 'logid' );
60  $ret = [];
61  if ( $params['revid'] ) {
62  foreach ( $params['revid'] as $id ) {
63  $ret[] = $this->processIndividual( 'revid', $params, $id );
64  }
65  }
66  if ( $params['rcid'] ) {
67  foreach ( $params['rcid'] as $id ) {
68  $ret[] = $this->processIndividual( 'rcid', $params, $id );
69  }
70  }
71  if ( $params['logid'] ) {
72  foreach ( $params['logid'] as $id ) {
73  $ret[] = $this->processIndividual( 'logid', $params, $id );
74  }
75  }
76 
77  ApiResult::setIndexedTagName( $ret, 'result' );
78  $this->getResult()->addValue( null, $this->getModuleName(), $ret );
79  }
80 
81  protected static function validateLogId( $logid ) {
82  $dbr = wfGetDB( DB_REPLICA );
83  $result = $dbr->selectField( 'logging', 'log_id', [ 'log_id' => $logid ],
84  __METHOD__ );
85  return (bool)$result;
86  }
87 
88  protected function processIndividual( $type, $params, $id ) {
89  $user = $this->getUser();
90  $idResult = [ $type => $id ];
91 
92  // validate the ID
93  $valid = false;
94  switch ( $type ) {
95  case 'rcid':
96  $valid = RecentChange::newFromId( $id );
97  if ( $valid && $this->getPermissionManager()->isBlockedFrom( $user, $valid->getTitle() ) ) {
98  $idResult['status'] = 'error';
99  // @phan-suppress-next-line PhanTypeMismatchArgument
100  $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
101  'apierror-blocked',
102  'blocked',
103  [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
104  ) );
105  return $idResult;
106  }
107  break;
108  case 'revid':
109  $valid = $this->revisionStore->getRevisionById( $id );
110  if (
111  $valid &&
112  $this->getPermissionManager()->isBlockedFrom( $user, $valid->getPageAsLinkTarget() )
113  ) {
114  $idResult['status'] = 'error';
115  // @phan-suppress-next-line PhanTypeMismatchArgument
116  $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
117  'apierror-blocked',
118  'blocked',
119  [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
120  ) );
121  return $idResult;
122  }
123  break;
124  case 'logid':
125  $valid = self::validateLogId( $id );
126  break;
127  }
128 
129  if ( !$valid ) {
130  $idResult['status'] = 'error';
131  // Messages: apierror-nosuchrcid apierror-nosuchrevid apierror-nosuchlogid
132  $idResult += $this->getErrorFormatter()->formatMessage( [ "apierror-nosuch$type", $id ] );
133  return $idResult;
134  }
135 
136  $status = ChangeTags::updateTagsWithChecks( $params['add'],
137  $params['remove'],
138  ( $type === 'rcid' ? $id : null ),
139  ( $type === 'revid' ? $id : null ),
140  ( $type === 'logid' ? $id : null ),
141  null,
142  $params['reason'],
143  $this->getUser() );
144 
145  if ( !$status->isOK() ) {
146  if ( $status->hasMessage( 'actionthrottledtext' ) ) {
147  $idResult['status'] = 'skipped';
148  } else {
149  $idResult['status'] = 'failure';
150  $idResult['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
151  }
152  } else {
153  $idResult['status'] = 'success';
154  if ( is_null( $status->value->logId ) ) {
155  $idResult['noop'] = true;
156  } else {
157  $idResult['actionlogid'] = $status->value->logId;
158  $idResult['added'] = $status->value->addedTags;
159  ApiResult::setIndexedTagName( $idResult['added'], 't' );
160  $idResult['removed'] = $status->value->removedTags;
161  ApiResult::setIndexedTagName( $idResult['removed'], 't' );
162 
163  if ( $params['tags'] ) {
164  ChangeTags::addTags( $params['tags'], null, null, $status->value->logId );
165  }
166  }
167  }
168  return $idResult;
169  }
170 
171  public function mustBePosted() {
172  return true;
173  }
174 
175  public function isWriteMode() {
176  return true;
177  }
178 
179  public function getAllowedParams() {
180  return [
181  'rcid' => [
182  ApiBase::PARAM_TYPE => 'integer',
183  ApiBase::PARAM_ISMULTI => true,
184  ],
185  'revid' => [
186  ApiBase::PARAM_TYPE => 'integer',
187  ApiBase::PARAM_ISMULTI => true,
188  ],
189  'logid' => [
190  ApiBase::PARAM_TYPE => 'integer',
191  ApiBase::PARAM_ISMULTI => true,
192  ],
193  'add' => [
194  ApiBase::PARAM_TYPE => 'tags',
195  ApiBase::PARAM_ISMULTI => true,
196  ],
197  'remove' => [
198  ApiBase::PARAM_TYPE => 'string',
199  ApiBase::PARAM_ISMULTI => true,
200  ],
201  'reason' => [
202  ApiBase::PARAM_DFLT => '',
203  ],
204  'tags' => [
205  ApiBase::PARAM_TYPE => 'tags',
206  ApiBase::PARAM_ISMULTI => true,
207  ],
208  ];
209  }
210 
211  public function needsToken() {
212  return 'csrf';
213  }
214 
215  protected function getExamplesMessages() {
216  return [
217  'action=tag&revid=123&add=vandalism&token=123ABC'
218  => 'apihelp-tag-example-rev',
219  'action=tag&logid=123&remove=spam&reason=Wrongly+applied&token=123ABC'
220  => 'apihelp-tag-example-log',
221  ];
222  }
223 
224  public function getHelpUrls() {
225  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Tag';
226  }
227 }
requireAtLeastOneParameter( $params,... $required)
Die if none of a certain set of parameters is set and not false.
Definition: ApiBase.php:953
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
isWriteMode()
Definition: ApiTag.php:175
getErrorFormatter()
Get the error formatter.
Definition: ApiBase.php:654
getResult()
Get the result object.
Definition: ApiBase.php:640
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:2078
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition: ApiBase.php:55
execute()
Definition: ApiTag.php:35
dieBlocked(AbstractBlock $block)
Throw an ApiUsageException, which will (if uncaught) call the main module&#39;s error handler and die wit...
Definition: ApiBase.php:2047
static newFromId( $rcid)
Obtain the recent change with a given rc_id value.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
trait ApiBlockInfoTrait
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
needsToken()
Definition: ApiTag.php:211
processIndividual( $type, $params, $id)
Definition: ApiTag.php:88
MediaWiki Revision RevisionStore $revisionStore
Definition: ApiTag.php:33
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
getAllowedParams()
Definition: ApiTag.php:179
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks...
Definition: ApiBase.php:710
getHelpUrls()
Definition: ApiTag.php:224
This abstract class implements many basic API functions, and is the base of all API classes...
Definition: ApiBase.php:42
static updateTagsWithChecks( $tagsToAdd, $tagsToRemove, $rc_id, $rev_id, $log_id, $params, $reason, User $user)
Adds and/or removes tags to/from a given change, checking whether it is allowed first, and adding a log entry afterwards.
Definition: ChangeTags.php:668
const DB_REPLICA
Definition: defines.php:25
static canAddTagsAccompanyingChange(array $tags, User $user=null)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Definition: ChangeTags.php:526
getExamplesMessages()
Definition: ApiTag.php:215
static addTags( $tags, $rc_id=null, $rev_id=null, $log_id=null, $params=null, RecentChange $rc=null)
Add tags to a change given its rc_id, rev_id and/or log_id.
Definition: ChangeTags.php:256
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:2122
mustBePosted()
Definition: ApiTag.php:171
static validateLogId( $logid)
Definition: ApiTag.php:81
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
Definition: ApiMessage.php:40