Merge "Convert Special:DeletedContributions to use OOUI."
[lhc/web/wiklou.git] / includes / api / ApiTag.php
1 <?php
2
3 /**
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 *
19 * @file
20 */
21
22 /**
23 * @ingroup API
24 * @since 1.25
25 */
26 class ApiTag extends ApiBase {
27
28 public function execute() {
29 $params = $this->extractRequestParams();
30 $user = $this->getUser();
31
32 // make sure the user is allowed
33 if ( !$user->isAllowed( 'changetags' ) ) {
34 $this->dieUsage( "You don't have permission to add or remove change tags from individual edits",
35 'permissiondenied' );
36 }
37
38 if ( $user->isBlocked() ) {
39 $this->dieBlocked( $user->getBlock() );
40 }
41
42 // validate and process each revid, rcid and logid
43 $this->requireAtLeastOneParameter( $params, 'revid', 'rcid', 'logid' );
44 $ret = [];
45 if ( $params['revid'] ) {
46 foreach ( $params['revid'] as $id ) {
47 $ret[] = $this->processIndividual( 'revid', $params, $id );
48 }
49 }
50 if ( $params['rcid'] ) {
51 foreach ( $params['rcid'] as $id ) {
52 $ret[] = $this->processIndividual( 'rcid', $params, $id );
53 }
54 }
55 if ( $params['logid'] ) {
56 foreach ( $params['logid'] as $id ) {
57 $ret[] = $this->processIndividual( 'logid', $params, $id );
58 }
59 }
60
61 ApiResult::setIndexedTagName( $ret, 'result' );
62 $this->getResult()->addValue( null, $this->getModuleName(), $ret );
63 }
64
65 protected static function validateLogId( $logid ) {
66 $dbr = wfGetDB( DB_REPLICA );
67 $result = $dbr->selectField( 'logging', 'log_id', [ 'log_id' => $logid ],
68 __METHOD__ );
69 return (bool)$result;
70 }
71
72 protected function processIndividual( $type, $params, $id ) {
73 $idResult = [ $type => $id ];
74
75 // validate the ID
76 $valid = false;
77 switch ( $type ) {
78 case 'rcid':
79 $valid = RecentChange::newFromId( $id );
80 break;
81 case 'revid':
82 $valid = Revision::newFromId( $id );
83 break;
84 case 'logid':
85 $valid = self::validateLogId( $id );
86 break;
87 }
88
89 if ( !$valid ) {
90 $idResult['status'] = 'error';
91 $idResult += $this->parseMsg( [ "nosuch$type", $id ] );
92 return $idResult;
93 }
94
95 $status = ChangeTags::updateTagsWithChecks( $params['add'],
96 $params['remove'],
97 ( $type === 'rcid' ? $id : null ),
98 ( $type === 'revid' ? $id : null ),
99 ( $type === 'logid' ? $id : null ),
100 null,
101 $params['reason'],
102 $this->getUser() );
103
104 if ( !$status->isOK() ) {
105 if ( $status->hasMessage( 'actionthrottledtext' ) ) {
106 $idResult['status'] = 'skipped';
107 } else {
108 $idResult['status'] = 'failure';
109 $idResult['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
110 }
111 } else {
112 $idResult['status'] = 'success';
113 if ( is_null( $status->value->logId ) ) {
114 $idResult['noop'] = '';
115 } else {
116 $idResult['actionlogid'] = $status->value->logId;
117 $idResult['added'] = $status->value->addedTags;
118 ApiResult::setIndexedTagName( $idResult['added'], 't' );
119 $idResult['removed'] = $status->value->removedTags;
120 ApiResult::setIndexedTagName( $idResult['removed'], 't' );
121 }
122 }
123 return $idResult;
124 }
125
126 public function mustBePosted() {
127 return true;
128 }
129
130 public function isWriteMode() {
131 return true;
132 }
133
134 public function getAllowedParams() {
135 return [
136 'rcid' => [
137 ApiBase::PARAM_TYPE => 'integer',
138 ApiBase::PARAM_ISMULTI => true,
139 ],
140 'revid' => [
141 ApiBase::PARAM_TYPE => 'integer',
142 ApiBase::PARAM_ISMULTI => true,
143 ],
144 'logid' => [
145 ApiBase::PARAM_TYPE => 'integer',
146 ApiBase::PARAM_ISMULTI => true,
147 ],
148 'add' => [
149 ApiBase::PARAM_TYPE => 'tags',
150 ApiBase::PARAM_ISMULTI => true,
151 ],
152 'remove' => [
153 ApiBase::PARAM_TYPE => 'string',
154 ApiBase::PARAM_ISMULTI => true,
155 ],
156 'reason' => [
157 ApiBase::PARAM_DFLT => '',
158 ],
159 ];
160 }
161
162 public function needsToken() {
163 return 'csrf';
164 }
165
166 protected function getExamplesMessages() {
167 return [
168 'action=tag&revid=123&add=vandalism&token=123ABC'
169 => 'apihelp-tag-example-rev',
170 'action=tag&logid=123&remove=spam&reason=Wrongly+applied&token=123ABC'
171 => 'apihelp-tag-example-log',
172 ];
173 }
174
175 public function getHelpUrls() {
176 return 'https://www.mediawiki.org/wiki/API:Tag';
177 }
178 }