* @ingroup Media */ use MediaWiki\MediaWikiServices; use MediaWiki\User\UserIdentity; /** * File deletion user interface * * @ingroup Media */ class FileDeleteForm { /** * Really delete the file * * @param Title $title * @param LocalFile $file * @param string|null $oldimage Archive name * @param string $reason Reason of the deletion * @param bool $suppress Whether to mark all deleted versions as restricted * @param UserIdentity $user * @param string[] $tags Tags to apply to the deletion action * @throws MWException * @return Status */ public static function doDelete( Title $title, LocalFile $file, ?string $oldimage, $reason, $suppress, UserIdentity $user, $tags = [] ): Status { if ( $oldimage ) { $page = null; $status = $file->deleteOldFile( $oldimage, $reason, $user, $suppress ); if ( $status->isOK() ) { // Need to do a log item $logComment = wfMessage( 'deletedrevision', $oldimage )->inContentLanguage()->text(); if ( trim( $reason ) != '' ) { $logComment .= wfMessage( 'colon-separator' ) ->inContentLanguage()->text() . $reason; } $logtype = $suppress ? 'suppress' : 'delete'; $logEntry = new ManualLogEntry( $logtype, 'delete' ); $logEntry->setPerformer( $user ); $logEntry->setTarget( $title ); $logEntry->setComment( $logComment ); $logEntry->addTags( $tags ); $logid = $logEntry->insert(); $logEntry->publish( $logid ); $status->value = $logid; } } else { $status = Status::newFatal( 'cannotdelete', wfEscapeWikiText( $title->getPrefixedText() ) ); $page = MediaWikiServices::getInstance()->getWikiPageFactory()->newFromTitle( $title ); '@phan-var WikiFilePage $page'; $dbw = wfGetDB( DB_PRIMARY ); $dbw->startAtomic( __METHOD__ ); // delete the associated article first $error = ''; $deleteStatus = $page->doDeleteArticleReal( $reason, $user, $suppress, null, $error, null, $tags ); // doDeleteArticleReal() returns a non-fatal error status if the page // or revision is missing, so check for isOK() rather than isGood() if ( $deleteStatus->isOK() ) { $status = $file->deleteFile( $reason, $user, $suppress ); if ( $status->isOK() ) { if ( $deleteStatus->value === null ) { // No log ID from doDeleteArticleReal(), probably // because the page/revision didn't exist, so create // one here. $logtype = $suppress ? 'suppress' : 'delete'; $logEntry = new ManualLogEntry( $logtype, 'delete' ); $logEntry->setPerformer( $user ); $logEntry->setTarget( $title ); $logEntry->setComment( $reason ); $logEntry->addTags( $tags ); $logid = $logEntry->insert(); $dbw->onTransactionPreCommitOrIdle( static function () use ( $logEntry, $logid ) { $logEntry->publish( $logid ); }, __METHOD__ ); $status->value = $logid; } else { $status->value = $deleteStatus->value; // log id } $dbw->endAtomic( __METHOD__ ); } else { // Page deleted but file still there? rollback page delete $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); $lbFactory->rollbackPrimaryChanges( __METHOD__ ); } } else { $dbw->endAtomic( __METHOD__ ); } } if ( $status->isOK() ) { $legacyUser = MediaWikiServices::getInstance() ->getUserFactory() ->newFromUserIdentity( $user ); Hooks::runner()->onFileDeleteComplete( $file, $oldimage, $page, $legacyUser, $reason ); } return $status; } /** * Is the provided `oldimage` value valid? * * @param string $oldimage * @return bool */ public static function isValidOldSpec( $oldimage ) { return strlen( $oldimage ) >= 16 && strpos( $oldimage, '/' ) === false && strpos( $oldimage, '\\' ) === false; } }