MediaWiki  master
ApiTag.php
Go to the documentation of this file.
1 <?php
2 
25 
30 class ApiTag extends ApiBase {
31 
33 
35  private $dbr;
36 
38  private $revisionStore;
39 
46  public function __construct(
47  ApiMain $main,
48  $action,
49  ILoadBalancer $loadBalancer,
51  ) {
52  parent::__construct( $main, $action );
53  $this->dbr = $loadBalancer->getConnectionRef( DB_REPLICA );
54  $this->revisionStore = $revisionStore;
55  }
56 
57  public function execute() {
58  $params = $this->extractRequestParams();
59  $user = $this->getUser();
60 
61  // make sure the user is allowed
62  $this->checkUserRightsAny( 'changetags' );
63 
64  // Fail early if the user is sitewide blocked.
65  $block = $user->getBlock();
66  if ( $block && $block->isSitewide() ) {
67  $this->dieBlocked( $block );
68  }
69 
70  // Check if user can add tags
71  if ( $params['tags'] ) {
72  $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getAuthority() );
73  if ( !$ableToTag->isOK() ) {
74  $this->dieStatus( $ableToTag );
75  }
76  }
77 
78  // validate and process each revid, rcid and logid
79  $this->requireAtLeastOneParameter( $params, 'revid', 'rcid', 'logid' );
80  $ret = [];
81  if ( $params['revid'] ) {
82  foreach ( $params['revid'] as $id ) {
83  $ret[] = $this->processIndividual( 'revid', $params, $id );
84  }
85  }
86  if ( $params['rcid'] ) {
87  foreach ( $params['rcid'] as $id ) {
88  $ret[] = $this->processIndividual( 'rcid', $params, $id );
89  }
90  }
91  if ( $params['logid'] ) {
92  foreach ( $params['logid'] as $id ) {
93  $ret[] = $this->processIndividual( 'logid', $params, $id );
94  }
95  }
96 
97  ApiResult::setIndexedTagName( $ret, 'result' );
98  $this->getResult()->addValue( null, $this->getModuleName(), $ret );
99  }
100 
101  protected function validateLogId( $logid ) {
102  $result = $this->dbr->selectField( 'logging', 'log_id', [ 'log_id' => $logid ],
103  __METHOD__ );
104  return (bool)$result;
105  }
106 
107  protected function processIndividual( $type, $params, $id ) {
108  $user = $this->getUser();
109  $idResult = [ $type => $id ];
110 
111  // validate the ID
112  $valid = false;
113  switch ( $type ) {
114  case 'rcid':
115  $valid = RecentChange::newFromId( $id );
116  // TODO: replace use of PermissionManager
117  if ( $valid && $this->getPermissionManager()->isBlockedFrom( $user, $valid->getTitle() ) ) {
118  $idResult['status'] = 'error';
119  // @phan-suppress-next-line PhanTypeMismatchArgument
120  $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
121  'apierror-blocked',
122  'blocked',
123  [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
124  ) );
125  return $idResult;
126  }
127  break;
128  case 'revid':
129  $valid = $this->revisionStore->getRevisionById( $id );
130  // TODO: replace use of PermissionManager
131  if (
132  $valid &&
133  $this->getPermissionManager()->isBlockedFrom( $user, $valid->getPageAsLinkTarget() )
134  ) {
135  $idResult['status'] = 'error';
136  // @phan-suppress-next-line PhanTypeMismatchArgument
137  $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
138  'apierror-blocked',
139  'blocked',
140  [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
141  ) );
142  return $idResult;
143  }
144  break;
145  case 'logid':
146  $valid = $this->validateLogId( $id );
147  break;
148  }
149 
150  if ( !$valid ) {
151  $idResult['status'] = 'error';
152  // Messages: apierror-nosuchrcid apierror-nosuchrevid apierror-nosuchlogid
153  $idResult += $this->getErrorFormatter()->formatMessage( [ "apierror-nosuch$type", $id ] );
154  return $idResult;
155  }
156 
157  $status = ChangeTags::updateTagsWithChecks( $params['add'],
158  $params['remove'],
159  ( $type === 'rcid' ? $id : null ),
160  ( $type === 'revid' ? $id : null ),
161  ( $type === 'logid' ? $id : null ),
162  null,
163  $params['reason'],
164  $this->getAuthority()
165  );
166 
167  if ( !$status->isOK() ) {
168  if ( $status->hasMessage( 'actionthrottledtext' ) ) {
169  $idResult['status'] = 'skipped';
170  } else {
171  $idResult['status'] = 'failure';
172  $idResult['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
173  }
174  } else {
175  $idResult['status'] = 'success';
176  if ( $status->value->logId === null ) {
177  $idResult['noop'] = true;
178  } else {
179  $idResult['actionlogid'] = $status->value->logId;
180  $idResult['added'] = $status->value->addedTags;
181  ApiResult::setIndexedTagName( $idResult['added'], 't' );
182  $idResult['removed'] = $status->value->removedTags;
183  ApiResult::setIndexedTagName( $idResult['removed'], 't' );
184 
185  if ( $params['tags'] ) {
186  ChangeTags::addTags( $params['tags'], null, null, $status->value->logId );
187  }
188  }
189  }
190  return $idResult;
191  }
192 
193  public function mustBePosted() {
194  return true;
195  }
196 
197  public function isWriteMode() {
198  return true;
199  }
200 
201  public function getAllowedParams() {
202  return [
203  'rcid' => [
204  ApiBase::PARAM_TYPE => 'integer',
205  ApiBase::PARAM_ISMULTI => true,
206  ],
207  'revid' => [
208  ApiBase::PARAM_TYPE => 'integer',
209  ApiBase::PARAM_ISMULTI => true,
210  ],
211  'logid' => [
212  ApiBase::PARAM_TYPE => 'integer',
213  ApiBase::PARAM_ISMULTI => true,
214  ],
215  'add' => [
216  ApiBase::PARAM_TYPE => 'tags',
217  ApiBase::PARAM_ISMULTI => true,
218  ],
219  'remove' => [
220  ApiBase::PARAM_TYPE => 'string',
221  ApiBase::PARAM_ISMULTI => true,
222  ],
223  'reason' => [
224  ApiBase::PARAM_DFLT => '',
225  ],
226  'tags' => [
227  ApiBase::PARAM_TYPE => 'tags',
228  ApiBase::PARAM_ISMULTI => true,
229  ],
230  ];
231  }
232 
233  public function needsToken() {
234  return 'csrf';
235  }
236 
237  protected function getExamplesMessages() {
238  return [
239  'action=tag&revid=123&add=vandalism&token=123ABC'
240  => 'apihelp-tag-example-rev',
241  'action=tag&logid=123&remove=spam&reason=Wrongly+applied&token=123ABC'
242  => 'apihelp-tag-example-log',
243  ];
244  }
245 
246  public function getHelpUrls() {
247  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Tag';
248  }
249 }
ApiTag
Definition: ApiTag.php:30
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:49
MediaWiki\Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:88
ChangeTags\updateTagsWithChecks
static updateTagsWithChecks( $tagsToAdd, $tagsToRemove, $rc_id, $rev_id, $log_id, $params, $reason, Authority $performer)
Adds and/or removes tags to/from a given change, checking whether it is allowed first,...
Definition: ChangeTags.php:779
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:72
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:571
ApiTag\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiTag.php:197
ApiBase\checkUserRightsAny
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:1488
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
Wikimedia\Rdbms\ILoadBalancer\getConnectionRef
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)
Get a live database handle reference for a server index.
ApiTag\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiTag.php:57
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:55
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
ApiBase\dieBlocked
dieBlocked(Block $block)
Throw an ApiUsageException, which will (if uncaught) call the main module's error handler and die wit...
Definition: ApiBase.php:1409
ApiTag\$dbr
IDatabase $dbr
Definition: ApiTag.php:35
ApiTag\processIndividual
processIndividual( $type, $params, $id)
Definition: ApiTag.php:107
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:707
ApiTag\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiTag.php:201
ApiTag\needsToken
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiTag.php:233
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
ApiBase\requireAtLeastOneParameter
requireAtLeastOneParameter( $params,... $required)
Die if none of a certain set of parameters is set and not false.
Definition: ApiBase.php:904
ApiMessage\create
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
Definition: ApiMessage.php:43
ApiBlockInfoTrait
trait ApiBlockInfoTrait
Definition: ApiBlockInfoTrait.php:27
RecentChange\newFromId
static newFromId( $rcid)
Obtain the recent change with a given rc_id value.
Definition: RecentChange.php:213
ApiTag\validateLogId
validateLogId( $logid)
Definition: ApiTag.php:101
ChangeTags\canAddTagsAccompanyingChange
static canAddTagsAccompanyingChange(array $tags, Authority $performer=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:625
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:603
ApiTag\$revisionStore
RevisionStore $revisionStore
Definition: ApiTag.php:38
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:144
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:628
ApiTag\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiTag.php:237
ApiTag\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiTag.php:193
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:70
ApiBase\dieStatus
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:1442
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:440
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:71
ApiTag\__construct
__construct(ApiMain $main, $action, ILoadBalancer $loadBalancer, RevisionStore $revisionStore)
Definition: ApiTag.php:46
ApiBase\getErrorFormatter
getErrorFormatter()
Definition: ApiBase.php:582
ApiTag\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiTag.php:246
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
ChangeTags\addTags
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:328
$type
$type
Definition: testCompression.php:52