wiki.techinc.nl/includes/page/WikiFilePage.php
Daimona Eaytoy 0ef73ec13e Move some methods from FileDeleteForm to a subclass of DeleteAction
This is where the UI logic is supposed to live. The remaining methods in
FileDeleteForm will later be deprecated in favour of a dedicated command
object.

This patch tries to move the code to the new class with minimal changes,
with cleanup left to do for later.

Also change return typehints and docs for getFile(): WikiFilePage::loadFile()
is guaranteed to load a file. The "|bool" would confuse PHPStorm and
phan.

Note that FileDeleteForm is unused everywhere, except for some static
methods not touched by this patch.

Bug: T288282
Change-Id: I4fa1dfa096cd2ae7a58067764b12a275b1cce1d5
2021-09-17 22:13:19 +02:00

278 lines
6.5 KiB
PHP

<?php
/**
* Special handling for file pages.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
use MediaWiki\Actions\FileDeleteAction;
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\FakeResultWrapper;
/**
* Special handling for file pages
*
* @ingroup Media
*/
class WikiFilePage extends WikiPage {
/** @var File|false */
protected $mFile = false;
/** @var LocalRepo|null */
protected $mRepo = null;
/** @var bool */
protected $mFileLoaded = false;
/** @var array|null */
protected $mDupes = null;
public function __construct( $title ) {
parent::__construct( $title );
$this->mDupes = null;
$this->mRepo = null;
}
/**
* @param File $file
*/
public function setFile( File $file ) {
$this->mFile = $file;
$this->mFileLoaded = true;
}
/**
* @return bool
*/
protected function loadFile() {
$services = MediaWikiServices::getInstance();
if ( $this->mFileLoaded ) {
return true;
}
$this->mFile = $services->getRepoGroup()->findFile( $this->mTitle );
if ( !$this->mFile ) {
$this->mFile = $services->getRepoGroup()->getLocalRepo()
->newFile( $this->mTitle );
}
if ( !$this->mFile instanceof File ) {
throw new RuntimeException( 'Expected to find file. See T250767' );
}
$this->mRepo = $this->mFile->getRepo();
$this->mFileLoaded = true;
return true;
}
/**
* @return mixed|null|Title
*/
public function getRedirectTarget() {
$this->loadFile();
if ( $this->mFile->isLocal() ) {
return parent::getRedirectTarget();
}
// Foreign image page
$from = $this->mFile->getRedirected();
$to = $this->mFile->getName();
if ( $from == $to ) {
return null;
}
$this->mRedirectTarget = Title::makeTitle( NS_FILE, $to );
return $this->mRedirectTarget;
}
/**
* @return bool|mixed|Title
*/
public function followRedirect() {
$this->loadFile();
if ( $this->mFile->isLocal() ) {
return parent::followRedirect();
}
$from = $this->mFile->getRedirected();
$to = $this->mFile->getName();
if ( $from == $to ) {
return false;
}
return Title::makeTitle( NS_FILE, $to );
}
/**
* @return bool
*/
public function isRedirect() {
$this->loadFile();
if ( $this->mFile->isLocal() ) {
return parent::isRedirect();
}
return (bool)$this->mFile->getRedirected();
}
/**
* @return bool
*/
public function isLocal() {
$this->loadFile();
return $this->mFile->isLocal();
}
/**
* @return File
*/
public function getFile(): File {
$this->loadFile();
return $this->mFile;
}
/**
* @return File[]|null
*/
public function getDuplicates() {
$this->loadFile();
if ( $this->mDupes !== null ) {
return $this->mDupes;
}
$hash = $this->mFile->getSha1();
if ( !( $hash ) ) {
$this->mDupes = [];
return $this->mDupes;
}
$dupes = MediaWikiServices::getInstance()->getRepoGroup()->findBySha1( $hash );
// Remove duplicates with self and non matching file sizes
$self = $this->mFile->getRepoName() . ':' . $this->mFile->getName();
$size = $this->mFile->getSize();
/**
* @var File $file
*/
foreach ( $dupes as $index => $file ) {
$key = $file->getRepoName() . ':' . $file->getName();
if ( $key == $self ) {
unset( $dupes[$index] );
}
if ( $file->getSize() != $size ) {
unset( $dupes[$index] );
}
}
$this->mDupes = $dupes;
return $this->mDupes;
}
/**
* Override handling of action=purge
* @return bool
*/
public function doPurge() {
$this->loadFile();
if ( $this->mFile->exists() ) {
wfDebug( 'ImagePage::doPurge purging ' . $this->mFile->getName() );
$job = HTMLCacheUpdateJob::newForBacklinks(
$this->mTitle,
'imagelinks',
[ 'causeAction' => 'file-purge' ]
);
JobQueueGroup::singleton()->lazyPush( $job );
} else {
wfDebug( 'ImagePage::doPurge no image for '
. $this->mFile->getName() . "; limiting purge to cache only" );
}
// even if the file supposedly doesn't exist, force any cached information
// to be updated (in case the cached information is wrong)
// Purge current version and its thumbnails
$this->mFile->purgeCache( [ 'forThumbRefresh' => true ] );
// Purge the old versions and their thumbnails
foreach ( $this->mFile->getHistory() as $oldFile ) {
$oldFile->purgeCache( [ 'forThumbRefresh' => true ] );
}
if ( $this->mRepo ) {
// Purge redirect cache
$this->mRepo->invalidateImageRedirect( $this->mTitle );
}
return parent::doPurge();
}
/**
* Get the categories this file is a member of on the wiki where it was uploaded.
* For local files, this is the same as getCategories().
* For foreign API files (InstantCommons), this is not supported currently.
* Results will include hidden categories.
*
* @return TitleArray|Title[]
* @since 1.23
*/
public function getForeignCategories() {
$this->loadFile();
$title = $this->mTitle;
$file = $this->mFile;
if ( !$file instanceof LocalFile ) {
wfDebug( __METHOD__ . " is not supported for this file" );
return TitleArray::newFromResult( new FakeResultWrapper( [] ) );
}
/** @var LocalRepo $repo */
$repo = $file->getRepo();
$dbr = $repo->getReplicaDB();
$res = $dbr->select(
[ 'page', 'categorylinks' ],
[
'page_title' => 'cl_to',
'page_namespace' => NS_CATEGORY,
],
[
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey(),
],
__METHOD__,
[],
[ 'categorylinks' => [ 'JOIN', 'page_id = cl_from' ] ]
);
return TitleArray::newFromResult( $res );
}
/**
* @since 1.28
* @return string
*/
public function getWikiDisplayName() {
return $this->getFile()->getRepo()->getDisplayName();
}
/**
* @since 1.28
* @return string
*/
public function getSourceURL() {
return $this->getFile()->getDescriptionUrl();
}
/**
* @inheritDoc
*/
public function getActionOverrides() {
return [ 'delete' => FileDeleteAction::class ] + parent::getActionOverrides();
}
}