MediaWiki  master
ApiDelete.php
Go to the documentation of this file.
1 <?php
27 
34 class ApiDelete extends ApiBase {
35 
37 
39  private $repoGroup;
40 
43 
52  public function __construct(
53  ApiMain $mainModule,
54  $moduleName,
59  ) {
60  parent::__construct( $mainModule, $moduleName );
61  $this->repoGroup = $repoGroup;
62  $this->deletePageFactory = $deletePageFactory;
63 
64  // Variables needed in ApiWatchlistTrait trait
65  $this->watchlistExpiryEnabled = $this->getConfig()->get( 'WatchlistExpiry' );
66  $this->watchlistMaxDuration = $this->getConfig()->get( 'WatchlistExpiryMaxDuration' );
67  $this->watchlistManager = $watchlistManager;
68  $this->userOptionsLookup = $userOptionsLookup;
69  }
70 
78  public function execute() {
80 
81  $params = $this->extractRequestParams();
82 
83  $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
84  $titleObj = $pageObj->getTitle();
85  $this->getErrorFormatter()->setContextTitle( $titleObj );
86  if ( !$pageObj->exists() &&
87  // @phan-suppress-next-line PhanUndeclaredMethod
88  !( $titleObj->getNamespace() === NS_FILE && self::canDeleteFile( $pageObj->getFile() ) )
89  ) {
90  $this->dieWithError( 'apierror-missingtitle' );
91  }
92 
93  $reason = $params['reason'];
94  $user = $this->getUser();
95 
96  $tags = $params['tags'] ?: [];
97 
98  if ( $titleObj->getNamespace() === NS_FILE ) {
99  $status = $this->deleteFile(
100  $pageObj,
101  $params['oldimage'],
102  $reason,
103  false,
104  $tags
105  );
106  // TODO What kind of non-fatal errors should we expect here?
107  $wasScheduled = $status->isOK() && $status->getValue() === false;
108  } else {
109  $status = $this->delete( $pageObj, $reason, $tags );
110  $wasScheduled = $status->isGood() && $status->getValue() === false;
111  }
112 
113  if ( !$status->isOK() ) {
114  $this->dieStatus( $status );
115  }
116 
117  if ( $wasScheduled ) {
118  $this->addWarning( [ 'delete-scheduled', $titleObj->getPrefixedText() ] );
119  }
120 
121  // Deprecated parameters
122  if ( $params['watch'] ) {
123  $watch = 'watch';
124  } elseif ( $params['unwatch'] ) {
125  $watch = 'unwatch';
126  } else {
127  $watch = $params['watchlist'];
128  }
129 
130  $watchlistExpiry = $this->getExpiryFromParams( $params );
131  $this->setWatch( $watch, $titleObj, $user, 'watchdeletion', $watchlistExpiry );
132 
133  $r = [
134  'title' => $titleObj->getPrefixedText(),
135  'reason' => $reason,
136  ];
137 
138  if ( $wasScheduled ) {
139  $r['scheduled'] = true;
140  } else {
141  // Scheduled deletions don't currently have a log entry available at this point
142  $r['logid'] = $status->value;
143  }
144  $this->getResult()->addValue( null, $this->getModuleName(), $r );
145  }
146 
157  private function delete( WikiPage $page, &$reason = null, array $tags = [] ): StatusValue {
158  $title = $page->getTitle();
159 
160  // Auto-generate a summary, if necessary
161  if ( $reason === null ) {
162  $reason = $page->getAutoDeleteReason();
163  if ( $reason === false ) {
164  // Should be reachable only if the page has no revisions
165  return Status::newFatal( 'cannotdelete', $title->getPrefixedText() ); // @codeCoverageIgnore
166  }
167  }
168 
169  $deletePage = $this->deletePageFactory->newDeletePage( $page, $this->getAuthority() );
170  $deletionStatus = $deletePage->setTags( $tags )->deleteIfAllowed( $reason );
171  $deletionStatus->value = $deletePage->deletionsWereScheduled()[DeletePage::PAGE_BASE]
172  ? false
173  : $deletePage->getSuccessfulDeletionsIDs()[DeletePage::PAGE_BASE];
174  return $deletionStatus;
175  }
176 
181  protected static function canDeleteFile( File $file ) {
182  return $file->exists() && $file->isLocal() && !$file->getRedirected();
183  }
184 
193  private function deleteFile( WikiPage $page, $oldimage,
194  &$reason = null, bool $suppress = false, array $tags = []
195  ) {
196  $title = $page->getTitle();
197 
198  // @phan-suppress-next-line PhanUndeclaredMethod There's no right typehint for it
199  $file = $page->getFile();
200  if ( !self::canDeleteFile( $file ) ) {
201  return $this->delete( $page, $reason, $tags );
202  }
203 
204  // Check that the user is allowed to carry out the deletion
205  $this->checkTitleUserPermissions( $page->getTitle(), 'delete' );
206  if ( $tags ) {
207  // If change tagging was requested, check that the user is allowed to tag,
208  // and the tags are valid
209  $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $tags, $this->getAuthority() );
210  if ( !$tagStatus->isOK() ) {
211  $this->dieStatus( $tagStatus );
212  }
213  }
214 
215  if ( $oldimage ) {
216  if ( !FileDeleteForm::isValidOldSpec( $oldimage ) ) {
217  return Status::newFatal( 'invalidoldimage' );
218  }
219  $oldfile = $this->repoGroup->getLocalRepo()->newFromArchiveName( $title, $oldimage );
220  if ( !$oldfile->exists() || !$oldfile->isLocal() || $oldfile->getRedirected() ) {
221  return Status::newFatal( 'nodeleteablefile' );
222  }
223  }
224 
225  if ( $reason === null ) { // Log and RC don't like null reasons
226  $reason = '';
227  }
228 
229  return FileDeleteForm::doDelete( $title, $file, $oldimage, $reason, $suppress, $this->getUser(), $tags );
230  }
231 
232  public function mustBePosted() {
233  return true;
234  }
235 
236  public function isWriteMode() {
237  return true;
238  }
239 
240  public function getAllowedParams() {
241  $params = [
242  'title' => null,
243  'pageid' => [
244  ApiBase::PARAM_TYPE => 'integer'
245  ],
246  'reason' => null,
247  'tags' => [
248  ApiBase::PARAM_TYPE => 'tags',
249  ApiBase::PARAM_ISMULTI => true,
250  ],
251  'watch' => [
252  ApiBase::PARAM_DFLT => false,
254  ],
255  ];
256 
257  // Params appear in the docs in the order they are defined,
258  // which is why this is here and not at the bottom.
259  $params += $this->getWatchlistParams();
260 
261  return $params + [
262  'unwatch' => [
263  ApiBase::PARAM_DFLT => false,
265  ],
266  'oldimage' => null,
267  ];
268  }
269 
270  public function needsToken() {
271  return 'csrf';
272  }
273 
274  protected function getExamplesMessages() {
275  return [
276  'action=delete&title=Main%20Page&token=123ABC'
277  => 'apihelp-delete-example-simple',
278  'action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move'
279  => 'apihelp-delete-example-reason',
280  ];
281  }
282 
283  public function getHelpUrls() {
284  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Delete';
285  }
286 }
ApiBase\checkTitleUserPermissions
checkTitleUserPermissions( $pageIdentity, $actions, array $options=[])
Helper function for permission-denied errors.
Definition: ApiBase.php:1571
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:49
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:72
StatusValue
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: StatusValue.php:43
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1354
getExpiryFromParams
getExpiryFromParams(array $params)
Get formatted expiry from the given parameters, or null if no expiry was provided.
Definition: ApiWatchlistTrait.php:164
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1436
ApiBase\getTitleOrPageId
getTitleOrPageId( $params, $load=false)
Get a WikiPage object from a title or pageid param, if possible.
Definition: ApiBase.php:1033
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:81
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:628
WikiPage
Class representing a MediaWiki article and history.
Definition: WikiPage.php:63
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
ApiDelete\canDeleteFile
static canDeleteFile(File $file)
Definition: ApiDelete.php:181
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
ApiDelete\__construct
__construct(ApiMain $mainModule, $moduleName, RepoGroup $repoGroup, WatchlistManager $watchlistManager, UserOptionsLookup $userOptionsLookup, DeletePageFactory $deletePageFactory)
Definition: ApiDelete.php:52
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:55
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
Definition: ApiBase.php:101
ApiDelete\needsToken
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiDelete.php:270
File
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:67
ApiDelete\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiDelete.php:240
MediaWiki\Watchlist\WatchlistManager
WatchlistManager service.
Definition: WatchlistManager.php:52
ApiDelete
API module that facilitates deleting pages.
Definition: ApiDelete.php:34
ApiDelete\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiDelete.php:232
ApiDelete\execute
execute()
Extracts the title and reason from the request parameters and invokes the local delete() function wit...
Definition: ApiDelete.php:78
setWatch
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.
Definition: ApiWatchlistTrait.php:96
WikiPage\getTitle
getTitle()
Get the title object of the article.
Definition: WikiPage.php:314
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:764
$title
$title
Definition: testCompression.php:38
Page\DeletePageFactory
Definition: DeletePageFactory.php:10
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:630
ApiDelete\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiDelete.php:274
ApiDelete\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiDelete.php:283
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:144
ApiDelete\$deletePageFactory
DeletePageFactory $deletePageFactory
Definition: ApiDelete.php:42
ApiBase\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: ApiBase.php:1293
MediaWiki\User\UserOptionsLookup
Provides access to user options.
Definition: UserOptionsLookup.php:29
ApiWatchlistTrait
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Definition: ApiWatchlistTrait.php:21
$watchlistManager
WatchlistManager $watchlistManager
Definition: ApiWatchlistTrait.php:30
$userOptionsLookup
UserOptionsLookup $userOptionsLookup
Definition: ApiWatchlistTrait.php:33
getWatchlistParams
getWatchlistParams(array $watchOptions=[])
Get additional allow params specific to watchlisting.
Definition: ApiWatchlistTrait.php:59
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:73
ApiBase\dieStatus
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:1499
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:497
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:77
RepoGroup
Prioritized list of file repositories.
Definition: RepoGroup.php:32
ApiDelete\$repoGroup
RepoGroup $repoGroup
Definition: ApiDelete.php:39
ApiDelete\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiDelete.php:236
Page\DeletePage
Definition: DeletePage.php:49
NS_FILE
const NS_FILE
Definition: Defines.php:70
ApiBase\getErrorFormatter
getErrorFormatter()
Definition: ApiBase.php:639
ApiDelete\deleteFile
deleteFile(WikiPage $page, $oldimage, &$reason=null, bool $suppress=false, array $tags=[])
Definition: ApiDelete.php:193
FileDeleteForm\doDelete
static doDelete(Title $title, LocalFile $file, ?string $oldimage, $reason, $suppress, UserIdentity $user, $tags=[], bool $deleteTalk=false)
Really delete the file.
Definition: FileDeleteForm.php:50
FileDeleteForm\isValidOldSpec
static isValidOldSpec( $oldimage)
Is the provided oldimage value valid?
Definition: FileDeleteForm.php:156
WikiPage\getAutoDeleteReason
getAutoDeleteReason(&$hasHistory=false)
Auto-generates a deletion reason.
Definition: WikiPage.php:3065