MediaWiki 1.40.4
ApiDelete.php
Go to the documentation of this file.
1<?php
31
38class ApiDelete extends ApiBase {
39
41
43 private $repoGroup;
44
46 private $deletePageFactory;
47
56 public function __construct(
57 ApiMain $mainModule,
58 $moduleName,
59 RepoGroup $repoGroup,
60 WatchlistManager $watchlistManager,
61 UserOptionsLookup $userOptionsLookup,
62 DeletePageFactory $deletePageFactory
63 ) {
64 parent::__construct( $mainModule, $moduleName );
65 $this->repoGroup = $repoGroup;
66 $this->deletePageFactory = $deletePageFactory;
67
68 // Variables needed in ApiWatchlistTrait trait
69 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
70 $this->watchlistMaxDuration =
71 $this->getConfig()->get( MainConfigNames::WatchlistExpiryMaxDuration );
72 $this->watchlistManager = $watchlistManager;
73 $this->userOptionsLookup = $userOptionsLookup;
74 }
75
83 public function execute() {
85
86 $params = $this->extractRequestParams();
87
88 $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
89 $titleObj = $pageObj->getTitle();
90 $this->getErrorFormatter()->setContextTitle( $titleObj );
91 if ( !$pageObj->exists() &&
92 // @phan-suppress-next-line PhanUndeclaredMethod
93 !( $titleObj->getNamespace() === NS_FILE && self::canDeleteFile( $pageObj->getFile() ) )
94 ) {
95 $this->dieWithError( 'apierror-missingtitle' );
96 }
97
98 $reason = $params['reason'];
99 $user = $this->getUser();
100
101 $tags = $params['tags'] ?: [];
102
103 if ( $titleObj->getNamespace() === NS_FILE ) {
104 $status = $this->deleteFile(
105 $pageObj,
106 $params['oldimage'],
107 $reason,
108 false,
109 $tags,
110 $params['deletetalk']
111 );
112 // TODO What kind of non-fatal errors should we expect here?
113 $wasScheduled = $status->isOK() && $status->getValue() === false;
114 } else {
115 $status = $this->delete( $pageObj, $reason, $tags, $params['deletetalk'] );
116 $wasScheduled = $status->isGood() && $status->getValue() === false;
117 }
118
119 if ( !$status->isOK() ) {
120 $this->dieStatus( $status );
121 }
122
123 if ( $wasScheduled ) {
124 $this->addWarning( [ 'delete-scheduled', $titleObj->getPrefixedText() ] );
125 }
126
127 // Deprecated parameters
128 if ( $params['watch'] ) {
129 $watch = 'watch';
130 } elseif ( $params['unwatch'] ) {
131 $watch = 'unwatch';
132 } else {
133 $watch = $params['watchlist'];
134 }
135
136 $watchlistExpiry = $this->getExpiryFromParams( $params );
137 $this->setWatch( $watch, $titleObj, $user, 'watchdeletion', $watchlistExpiry );
138
139 $r = [
140 'title' => $titleObj->getPrefixedText(),
141 'reason' => $reason,
142 ];
143
144 // TODO: We could expose additional information (scheduled and log ID) about the status of the talk page
145 // deletion.
146 if ( $wasScheduled ) {
147 $r['scheduled'] = true;
148 } else {
149 // Scheduled deletions don't currently have a log entry available at this point
150 $r['logid'] = $status->value;
151 }
152 $this->getResult()->addValue( null, $this->getModuleName(), $r );
153 }
154
167 private function delete( WikiPage $page, &$reason, array $tags, bool $deleteTalk ): StatusValue {
168 $title = $page->getTitle();
169
170 // Auto-generate a summary, if necessary
171 if ( $reason === null ) {
172 $reason = $page->getAutoDeleteReason();
173 if ( $reason === false ) {
174 // Should be reachable only if the page has no revisions
175 return Status::newFatal( 'cannotdelete', $title->getPrefixedText() ); // @codeCoverageIgnore
176 }
177 }
178
179 $deletePage = $this->deletePageFactory->newDeletePage( $page, $this->getAuthority() );
180 if ( $deleteTalk ) {
181 $checkStatus = $deletePage->canProbablyDeleteAssociatedTalk();
182 if ( !$checkStatus->isGood() ) {
183 foreach ( $checkStatus->getErrors() as $error ) {
184 $this->addWarning( $error );
185 }
186 } else {
187 $deletePage->setDeleteAssociatedTalk( true );
188 }
189 }
190 $deletionStatus = $deletePage->setTags( $tags )->deleteIfAllowed( $reason );
191 if ( $deletionStatus->isGood() ) {
192 $deletionStatus->value = $deletePage->deletionsWereScheduled()[DeletePage::PAGE_BASE]
193 ? false
194 : $deletePage->getSuccessfulDeletionsIDs()[DeletePage::PAGE_BASE];
195 }
196 return $deletionStatus;
197 }
198
203 protected static function canDeleteFile( File $file ) {
204 return $file->exists() && $file->isLocal() && !$file->getRedirected();
205 }
206
216 private function deleteFile(
217 WikiPage $page,
218 $oldimage,
219 &$reason,
220 bool $suppress,
221 array $tags,
222 bool $deleteTalk
223 ) {
224 $title = $page->getTitle();
225
226 // @phan-suppress-next-line PhanUndeclaredMethod There's no right typehint for it
227 $file = $page->getFile();
228 if ( !self::canDeleteFile( $file ) ) {
229 return $this->delete( $page, $reason, $tags, $deleteTalk );
230 }
231
232 // Check that the user is allowed to carry out the deletion
233 $this->checkTitleUserPermissions( $page->getTitle(), 'delete' );
234 if ( $tags ) {
235 // If change tagging was requested, check that the user is allowed to tag,
236 // and the tags are valid
237 $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $tags, $this->getAuthority() );
238 if ( !$tagStatus->isOK() ) {
239 $this->dieStatus( $tagStatus );
240 }
241 }
242
243 if ( $oldimage ) {
244 if ( !FileDeleteForm::isValidOldSpec( $oldimage ) ) {
245 return Status::newFatal( 'invalidoldimage' );
246 }
247 $oldfile = $this->repoGroup->getLocalRepo()->newFromArchiveName( $title, $oldimage );
248 if ( !$oldfile->exists() || !$oldfile->isLocal() || $oldfile->getRedirected() ) {
249 return Status::newFatal( 'nodeleteablefile' );
250 }
251 }
252
253 if ( $reason === null ) { // Log and RC don't like null reasons
254 $reason = '';
255 }
256
257 return FileDeleteForm::doDelete(
258 $title,
259 $file,
260 $oldimage,
261 $reason,
262 $suppress,
263 $this->getUser(),
264 $tags,
265 $deleteTalk
266 );
267 }
268
269 public function mustBePosted() {
270 return true;
271 }
272
273 public function isWriteMode() {
274 return true;
275 }
276
277 public function getAllowedParams() {
278 $params = [
279 'title' => null,
280 'pageid' => [
281 ParamValidator::PARAM_TYPE => 'integer'
282 ],
283 'reason' => null,
284 'tags' => [
285 ParamValidator::PARAM_TYPE => 'tags',
286 ParamValidator::PARAM_ISMULTI => true,
287 ],
288 'deletetalk' => false,
289 'watch' => [
290 ParamValidator::PARAM_DEFAULT => false,
291 ParamValidator::PARAM_DEPRECATED => true,
292 ],
293 ];
294
295 // Params appear in the docs in the order they are defined,
296 // which is why this is here and not at the bottom.
297 $params += $this->getWatchlistParams();
298
299 return $params + [
300 'unwatch' => [
301 ParamValidator::PARAM_DEFAULT => false,
302 ParamValidator::PARAM_DEPRECATED => true,
303 ],
304 'oldimage' => null,
305 ];
306 }
307
308 public function needsToken() {
309 return 'csrf';
310 }
311
312 protected function getExamplesMessages() {
313 $title = Title::newMainPage()->getPrefixedText();
314 $mp = rawurlencode( $title );
315
316 return [
317 "action=delete&title={$mp}&token=123ABC"
318 => 'apihelp-delete-example-simple',
319 "action=delete&title={$mp}&token=123ABC&reason=Preparing%20for%20move"
320 => 'apihelp-delete-example-reason',
321 ];
322 }
323
324 public function getHelpUrls() {
325 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Delete';
326 }
327}
getUser()
getAuthority()
getExpiryFromParams(array $params)
Get formatted expiry from the given parameters, or null if no expiry was provided.
setWatch(string $watch, Title $title, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
getWatchlistParams(array $watchOptions=[])
Get additional allow params specific to watchlisting.
const NS_FILE
Definition Defines.php:70
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:59
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1460
getErrorFormatter()
Definition ApiBase.php:648
getResult()
Get the result object.
Definition ApiBase.php:637
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:773
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition ApiBase.php:1378
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:506
getTitleOrPageId( $params, $load=false)
Get a WikiPage object from a title or pageid param, if possible.
Definition ApiBase.php:1044
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition ApiBase.php:1521
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition ApiBase.php:1305
API module that facilitates deleting pages.
Definition ApiDelete.php:38
__construct(ApiMain $mainModule, $moduleName, RepoGroup $repoGroup, WatchlistManager $watchlistManager, UserOptionsLookup $userOptionsLookup, DeletePageFactory $deletePageFactory)
Definition ApiDelete.php:56
execute()
Extracts the title and reason from the request parameters and invokes the local delete() function wit...
Definition ApiDelete.php:83
needsToken()
Returns the token type this module requires in order to execute.
getExamplesMessages()
Returns usage examples for this module.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getHelpUrls()
Return links to more detailed help pages about the module.
static canDeleteFile(File $file)
isWriteMode()
Indicates whether this module requires write mode.
mustBePosted()
Indicates whether this module must be called with a POST request.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:58
static canAddTagsAccompanyingChange(array $tags, Authority $performer=null, $checkBlock=true)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:68
A class containing constants representing the names of configuration variables.
Backend logic for performing a page delete action.
File deletion user interface.
Represents a title within MediaWiki.
Definition Title.php:82
Provides access to user options.
Prioritized list of file repositories.
Definition RepoGroup.php:30
Generic operation result class Has warning/error list, boolean status and arbitrary value.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Base representation for an editable wiki page.
Definition WikiPage.php:75
getAutoDeleteReason(&$hasHistory=false)
Auto-generates a deletion reason.
getTitle()
Get the title object of the article.
Definition WikiPage.php:318
Service for formatting and validating API parameters.
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Service for page delete actions.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42