These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * |
||
4 | * |
||
5 | * Created on Jun 30, 2007 |
||
6 | * |
||
7 | * Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com" |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or modify |
||
10 | * it under the terms of the GNU General Public License as published by |
||
11 | * the Free Software Foundation; either version 2 of the License, or |
||
12 | * (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU General Public License along |
||
20 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
22 | * http://www.gnu.org/copyleft/gpl.html |
||
23 | * |
||
24 | * @file |
||
25 | */ |
||
26 | |||
27 | /** |
||
28 | * API module that facilitates deleting pages. The API equivalent of action=delete. |
||
29 | * Requires API write mode to be enabled. |
||
30 | * |
||
31 | * @ingroup API |
||
32 | */ |
||
33 | class ApiDelete extends ApiBase { |
||
34 | /** |
||
35 | * Extracts the title and reason from the request parameters and invokes |
||
36 | * the local delete() function with these as arguments. It does not make use of |
||
37 | * the delete function specified by Article.php. If the deletion succeeds, the |
||
38 | * details of the article deleted and the reason for deletion are added to the |
||
39 | * result object. |
||
40 | */ |
||
41 | public function execute() { |
||
42 | $this->useTransactionalTimeLimit(); |
||
43 | |||
44 | $params = $this->extractRequestParams(); |
||
45 | |||
46 | $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' ); |
||
47 | if ( !$pageObj->exists() ) { |
||
48 | $this->dieUsageMsg( 'notanarticle' ); |
||
49 | } |
||
50 | |||
51 | $titleObj = $pageObj->getTitle(); |
||
52 | $reason = $params['reason']; |
||
53 | $user = $this->getUser(); |
||
54 | |||
55 | // Check that the user is allowed to carry out the deletion |
||
56 | $errors = $titleObj->getUserPermissionsErrors( 'delete', $user ); |
||
57 | if ( count( $errors ) ) { |
||
58 | $this->dieUsageMsg( $errors[0] ); |
||
59 | } |
||
60 | |||
61 | // If change tagging was requested, check that the user is allowed to tag, |
||
62 | // and the tags are valid |
||
63 | View Code Duplication | if ( count( $params['tags'] ) ) { |
|
64 | $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user ); |
||
65 | if ( !$tagStatus->isOK() ) { |
||
66 | $this->dieStatus( $tagStatus ); |
||
67 | } |
||
68 | } |
||
69 | |||
70 | if ( $titleObj->getNamespace() == NS_FILE ) { |
||
71 | $status = self::deleteFile( |
||
72 | $pageObj, |
||
0 ignored issues
–
show
|
|||
73 | $user, |
||
74 | $params['oldimage'], |
||
75 | $reason, |
||
76 | false, |
||
77 | $params['tags'] |
||
78 | ); |
||
79 | } else { |
||
80 | $status = self::delete( $pageObj, $user, $reason, $params['tags'] ); |
||
81 | } |
||
82 | |||
83 | if ( is_array( $status ) ) { |
||
84 | $this->dieUsageMsg( $status[0] ); |
||
85 | } |
||
86 | if ( !$status->isGood() ) { |
||
87 | $this->dieStatus( $status ); |
||
88 | } |
||
89 | |||
90 | // Deprecated parameters |
||
91 | View Code Duplication | if ( $params['watch'] ) { |
|
92 | $watch = 'watch'; |
||
93 | } elseif ( $params['unwatch'] ) { |
||
94 | $watch = 'unwatch'; |
||
95 | } else { |
||
96 | $watch = $params['watchlist']; |
||
97 | } |
||
98 | $this->setWatch( $watch, $titleObj, 'watchdeletion' ); |
||
99 | |||
100 | $r = [ |
||
101 | 'title' => $titleObj->getPrefixedText(), |
||
102 | 'reason' => $reason, |
||
103 | 'logid' => $status->value |
||
104 | ]; |
||
105 | $this->getResult()->addValue( null, $this->getModuleName(), $r ); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * We have our own delete() function, since Article.php's implementation is split in two phases |
||
110 | * |
||
111 | * @param Page|WikiPage $page Page or WikiPage object to work on |
||
112 | * @param User $user User doing the action |
||
113 | * @param string|null $reason Reason for the deletion. Autogenerated if null |
||
114 | * @param array $tags Tags to tag the deletion with |
||
115 | * @return Status|array |
||
116 | */ |
||
117 | protected static function delete( Page $page, User $user, &$reason = null, $tags = [] ) { |
||
118 | $title = $page->getTitle(); |
||
119 | |||
120 | // Auto-generate a summary, if necessary |
||
121 | if ( is_null( $reason ) ) { |
||
122 | // Need to pass a throwaway variable because generateReason expects |
||
123 | // a reference |
||
124 | $hasHistory = false; |
||
125 | $reason = $page->getAutoDeleteReason( $hasHistory ); |
||
126 | if ( $reason === false ) { |
||
127 | return [ [ 'cannotdelete', $title->getPrefixedText() ] ]; |
||
128 | } |
||
129 | } |
||
130 | |||
131 | $error = ''; |
||
132 | |||
133 | // Luckily, Article.php provides a reusable delete function that does the hard work for us |
||
134 | return $page->doDeleteArticleReal( $reason, false, 0, true, $error, $user, $tags ); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @param Page $page Object to work on |
||
139 | * @param User $user User doing the action |
||
140 | * @param string $oldimage Archive name |
||
141 | * @param string $reason Reason for the deletion. Autogenerated if null. |
||
142 | * @param bool $suppress Whether to mark all deleted versions as restricted |
||
143 | * @param array $tags Tags to tag the deletion with |
||
144 | * @return Status|array |
||
145 | */ |
||
146 | protected static function deleteFile( Page $page, User $user, $oldimage, |
||
147 | &$reason = null, $suppress = false, $tags = [] |
||
148 | ) { |
||
149 | $title = $page->getTitle(); |
||
150 | |||
151 | $file = $page->getFile(); |
||
152 | if ( !$file->exists() || !$file->isLocal() || $file->getRedirected() ) { |
||
153 | return self::delete( $page, $user, $reason, $tags ); |
||
154 | } |
||
155 | |||
156 | if ( $oldimage ) { |
||
157 | if ( !FileDeleteForm::isValidOldSpec( $oldimage ) ) { |
||
158 | return [ [ 'invalidoldimage' ] ]; |
||
159 | } |
||
160 | $oldfile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $oldimage ); |
||
161 | if ( !$oldfile->exists() || !$oldfile->isLocal() || $oldfile->getRedirected() ) { |
||
162 | return [ [ 'nodeleteablefile' ] ]; |
||
163 | } |
||
164 | } |
||
165 | |||
166 | if ( is_null( $reason ) ) { // Log and RC don't like null reasons |
||
167 | $reason = ''; |
||
168 | } |
||
169 | |||
170 | return FileDeleteForm::doDelete( $title, $file, $oldimage, $reason, $suppress, $user, $tags ); |
||
171 | } |
||
172 | |||
173 | public function mustBePosted() { |
||
174 | return true; |
||
175 | } |
||
176 | |||
177 | public function isWriteMode() { |
||
178 | return true; |
||
179 | } |
||
180 | |||
181 | public function getAllowedParams() { |
||
182 | return [ |
||
183 | 'title' => null, |
||
184 | 'pageid' => [ |
||
185 | ApiBase::PARAM_TYPE => 'integer' |
||
186 | ], |
||
187 | 'reason' => null, |
||
188 | 'tags' => [ |
||
189 | ApiBase::PARAM_TYPE => 'tags', |
||
190 | ApiBase::PARAM_ISMULTI => true, |
||
191 | ], |
||
192 | 'watch' => [ |
||
193 | ApiBase::PARAM_DFLT => false, |
||
194 | ApiBase::PARAM_DEPRECATED => true, |
||
195 | ], |
||
196 | 'watchlist' => [ |
||
197 | ApiBase::PARAM_DFLT => 'preferences', |
||
198 | ApiBase::PARAM_TYPE => [ |
||
199 | 'watch', |
||
200 | 'unwatch', |
||
201 | 'preferences', |
||
202 | 'nochange' |
||
203 | ], |
||
204 | ], |
||
205 | 'unwatch' => [ |
||
206 | ApiBase::PARAM_DFLT => false, |
||
207 | ApiBase::PARAM_DEPRECATED => true, |
||
208 | ], |
||
209 | 'oldimage' => null, |
||
210 | ]; |
||
211 | } |
||
212 | |||
213 | public function needsToken() { |
||
214 | return 'csrf'; |
||
215 | } |
||
216 | |||
217 | protected function getExamplesMessages() { |
||
218 | return [ |
||
219 | 'action=delete&title=Main%20Page&token=123ABC' |
||
220 | => 'apihelp-delete-example-simple', |
||
221 | 'action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move' |
||
222 | => 'apihelp-delete-example-reason', |
||
223 | ]; |
||
224 | } |
||
225 | |||
226 | public function getHelpUrls() { |
||
227 | return 'https://www.mediawiki.org/wiki/API:Delete'; |
||
228 | } |
||
229 | } |
||
230 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: