'ImportStringSource' => __DIR__ . '/includes/import/ImportStringSource.php',
'ImportTextFiles' => __DIR__ . '/maintenance/importTextFiles.php',
'ImportTitleFactory' => __DIR__ . '/includes/title/ImportTitleFactory.php',
+ 'ImportableUploadRevision' => __DIR__ . '/includes/import/ImportableUploadRevision.php',
+ 'ImportableUploadRevisionImporter' => __DIR__ . '/includes/import/ImportableUploadRevisionImporter.php',
'IncludableSpecialPage' => __DIR__ . '/includes/specialpage/IncludableSpecialPage.php',
'IndexPager' => __DIR__ . '/includes/pager/IndexPager.php',
'InfoAction' => __DIR__ . '/includes/actions/InfoAction.php',
'UploadFromStash' => __DIR__ . '/includes/upload/UploadFromStash.php',
'UploadFromUrl' => __DIR__ . '/includes/upload/UploadFromUrl.php',
'UploadLogFormatter' => __DIR__ . '/includes/logging/UploadLogFormatter.php',
+ 'UploadRevisionImporter' => __DIR__ . '/includes/import/UploadRevisionImporter.php',
'UploadSourceAdapter' => __DIR__ . '/includes/import/UploadSourceAdapter.php',
'UploadSourceField' => __DIR__ . '/includes/specials/formfields/UploadSourceField.php',
'UploadStash' => __DIR__ . '/includes/upload/UploadStash.php',
return $this->getService( 'ReadOnlyMode' );
}
+ /**
+ * @since 1.31
+ * @return \UploadRevisionImporter
+ */
+ public function getWikiRevisionUploadImporter() {
+ return $this->getService( 'UploadRevisionImporter' );
+ }
+
/**
* @since 1.30
* @return CommandFactory
);
},
+ 'UploadRevisionImporter' => function ( MediaWikiServices $services ) {
+ return new ImportableUploadRevisionImporter(
+ $services->getMainConfig()->get( 'EnableUploads' ),
+ LoggerFactory::getInstance( 'UploadRevisionImporter' )
+ );
+ },
+
'ShellCommandFactory' => function ( MediaWikiServices $services ) {
$config = $services->getMainConfig();
--- /dev/null
+<?php
+
+/**
+ * @since 1.31
+ */
+interface ImportableUploadRevision {
+
+ /**
+ * @since 1.31
+ * @return string Archive name of a revision if archived.
+ */
+ public function getArchiveName();
+
+ /**
+ * @since 1.31
+ * @return Title
+ */
+ public function getTitle();
+
+ /**
+ * @since 1.31
+ * @return string
+ */
+ public function getTimestamp();
+
+ /**
+ * @since 1.31
+ * @return string|null HTTP source of revision to be used for downloading.
+ */
+ public function getSrc();
+
+ /**
+ * @since 1.31
+ * @return string Local file source of the revision.
+ */
+ public function getFileSrc();
+
+ /**
+ * @since 1.31
+ * @return bool Is the return of getFileSrc only temporary?
+ */
+ public function isTempSrc();
+
+ /**
+ * @since 1.31
+ * @return string|bool sha1 of the revision, false if not set or errors occour.
+ */
+ public function getSha1();
+
+ /**
+ * @since 1.31
+ * @return User
+ */
+ public function getUserObj();
+
+ /**
+ * @since 1.31
+ * @return string The username of the user that created this revision
+ */
+ public function getUser();
+
+ /**
+ * @since 1.31
+ * @return string
+ */
+ public function getComment();
+
+}
--- /dev/null
+<?php
+
+use Psr\Log\LoggerInterface;
+
+/**
+ * @since 1.31
+ */
+class ImportableUploadRevisionImporter implements UploadRevisionImporter {
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @var bool
+ */
+ private $enableUploads;
+
+ /**
+ * @param bool $enableUploads
+ * @param LoggerInterface $logger
+ */
+ public function __construct(
+ $enableUploads,
+ LoggerInterface $logger
+ ) {
+ $this->enableUploads = $enableUploads;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @return StatusValue
+ */
+ private function newNotOkStatus() {
+ $statusValue = new StatusValue();
+ $statusValue->setOK( false );
+ return $statusValue;
+ }
+
+ public function import( ImportableUploadRevision $importableRevision ) {
+ # Construct a file
+ $archiveName = $importableRevision->getArchiveName();
+ if ( $archiveName ) {
+ $this->logger->debug( __METHOD__ . "Importing archived file as $archiveName\n" );
+ $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
+ RepoGroup::singleton()->getLocalRepo(), $archiveName );
+ } else {
+ $file = wfLocalFile( $importableRevision->getTitle() );
+ $file->load( File::READ_LATEST );
+ $this->logger->debug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
+ if ( $file->exists() && $file->getTimestamp() > $importableRevision->getTimestamp() ) {
+ $archiveName = $file->getTimestamp() . '!' . $file->getName();
+ $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
+ RepoGroup::singleton()->getLocalRepo(), $archiveName );
+ $this->logger->debug( __METHOD__ . "File already exists; importing as $archiveName\n" );
+ }
+ }
+ if ( !$file ) {
+ $this->logger->debug( __METHOD__ . ': Bad file for ' . $importableRevision->getTitle() . "\n" );
+ return $this->newNotOkStatus();
+ }
+
+ # Get the file source or download if necessary
+ $source = $importableRevision->getFileSrc();
+ $autoDeleteSource = $importableRevision->isTempSrc();
+ if ( !strlen( $source ) ) {
+ $source = $this->downloadSource( $importableRevision );
+ $autoDeleteSource = true;
+ }
+ if ( !strlen( $source ) ) {
+ $this->logger->debug( __METHOD__ . ": Could not fetch remote file.\n" );
+ return $this->newNotOkStatus();
+ }
+
+ $tmpFile = new TempFSFile( $source );
+ if ( $autoDeleteSource ) {
+ $tmpFile->autocollect();
+ }
+
+ $sha1File = ltrim( sha1_file( $source ), '0' );
+ $sha1 = $importableRevision->getSha1();
+ if ( $sha1 && ( $sha1 !== $sha1File ) ) {
+ $this->logger->debug( __METHOD__ . ": Corrupt file $source.\n" );
+ return $this->newNotOkStatus();
+ }
+
+ $user = $importableRevision->getUserObj() ?: User::newFromName( $importableRevision->getUser() );
+
+ # Do the actual upload
+ if ( $archiveName ) {
+ $status = $file->uploadOld( $source, $archiveName,
+ $importableRevision->getTimestamp(), $importableRevision->getComment(), $user );
+ } else {
+ $flags = 0;
+ $status = $file->upload(
+ $source,
+ $importableRevision->getComment(),
+ $importableRevision->getComment(),
+ $flags,
+ false,
+ $importableRevision->getTimestamp(),
+ $user
+ );
+ }
+
+ if ( $status->isGood() ) {
+ $this->logger->debug( __METHOD__ . ": Successful\n" );
+ } else {
+ $this->logger->debug( __METHOD__ . ': failed: ' . $status->getHTML() . "\n" );
+ }
+
+ return $status;
+ }
+
+ /**
+ * @deprecated DO NOT CALL ME.
+ * This method was introduced when factoring UploadImporter out of WikiRevision.
+ * It only has 1 use by the deprecated downloadSource method in WikiRevision.
+ * Do not use this in new code.
+ *
+ * @param ImportableUploadRevision $wikiRevision
+ *
+ * @return bool|string
+ */
+ public function downloadSource( ImportableUploadRevision $wikiRevision ) {
+ if ( !$this->enableUploads ) {
+ return false;
+ }
+
+ $tempo = tempnam( wfTempDir(), 'download' );
+ $f = fopen( $tempo, 'wb' );
+ if ( !$f ) {
+ $this->logger->debug( "IMPORT: couldn't write to temp file $tempo\n" );
+ return false;
+ }
+
+ // @todo FIXME!
+ $src = $wikiRevision->getSrc();
+ $data = Http::get( $src, [], __METHOD__ );
+ if ( !$data ) {
+ $this->logger->debug( "IMPORT: couldn't fetch source $src\n" );
+ fclose( $f );
+ unlink( $tempo );
+ return false;
+ }
+
+ fwrite( $f, $data );
+ fclose( $f );
+
+ return $tempo;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * @since 1.31
+ */
+interface UploadRevisionImporter {
+
+ /**
+ * @since 1.31
+ *
+ * @param ImportableUploadRevision $importableUploadRevision
+ *
+ * @return StatusValue On success, the value member contains the
+ * archive name, or an empty string if it was a new file.
+ */
+ public function import( ImportableUploadRevision $importableUploadRevision );
+
+}
* @file
* @ingroup SpecialPage
*/
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
/**
* Represents a revision, log entry or upload during the import process.
*
* @ingroup SpecialPage
*/
-class WikiRevision {
+class WikiRevision implements ImportableUploadRevision {
/**
* @since 1.17
/**
* @since 1.12.2
- * @var mixed
+ * @var string|null
*/
- protected $src;
+ protected $src = null;
/**
* @since 1.18
/**
* @since 1.12.2
- * @param mixed $src
+ * @param string|null $src
*/
public function setSrc( $src ) {
$this->src = $src;
/**
* @since 1.12.2
- * @return mixed
+ * @return string|null
*/
public function getSrc() {
return $this->src;
/**
* @since 1.12.2
+ * @deprecated in 1.31. Use UploadImporter::import
* @return bool
*/
public function importUpload() {
- # Construct a file
- $archiveName = $this->getArchiveName();
- if ( $archiveName ) {
- wfDebug( __METHOD__ . "Importing archived file as $archiveName\n" );
- $file = OldLocalFile::newFromArchiveName( $this->getTitle(),
- RepoGroup::singleton()->getLocalRepo(), $archiveName );
- } else {
- $file = wfLocalFile( $this->getTitle() );
- $file->load( File::READ_LATEST );
- wfDebug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
- if ( $file->exists() && $file->getTimestamp() > $this->getTimestamp() ) {
- $archiveName = $file->getTimestamp() . '!' . $file->getName();
- $file = OldLocalFile::newFromArchiveName( $this->getTitle(),
- RepoGroup::singleton()->getLocalRepo(), $archiveName );
- wfDebug( __METHOD__ . "File already exists; importing as $archiveName\n" );
- }
- }
- if ( !$file ) {
- wfDebug( __METHOD__ . ': Bad file for ' . $this->getTitle() . "\n" );
- return false;
- }
-
- # Get the file source or download if necessary
- $source = $this->getFileSrc();
- $autoDeleteSource = $this->isTempSrc();
- if ( !strlen( $source ) ) {
- $source = $this->downloadSource();
- $autoDeleteSource = true;
- }
- if ( !strlen( $source ) ) {
- wfDebug( __METHOD__ . ": Could not fetch remote file.\n" );
- return false;
- }
-
- $tmpFile = new TempFSFile( $source );
- if ( $autoDeleteSource ) {
- $tmpFile->autocollect();
- }
-
- $sha1File = ltrim( sha1_file( $source ), '0' );
- $sha1 = $this->getSha1();
- if ( $sha1 && ( $sha1 !== $sha1File ) ) {
- wfDebug( __METHOD__ . ": Corrupt file $source.\n" );
- return false;
- }
-
- $user = $this->getUserObj() ?: User::newFromName( $this->getUser() );
-
- # Do the actual upload
- if ( $archiveName ) {
- $status = $file->uploadOld( $source, $archiveName,
- $this->getTimestamp(), $this->getComment(), $user );
- } else {
- $flags = 0;
- $status = $file->upload( $source, $this->getComment(), $this->getComment(),
- $flags, false, $this->getTimestamp(), $user );
- }
-
- if ( $status->isGood() ) {
- wfDebug( __METHOD__ . ": Successful\n" );
- return true;
- } else {
- wfDebug( __METHOD__ . ': failed: ' . $status->getHTML() . "\n" );
- return false;
- }
+ $importer = MediaWikiServices::getInstance()->getWikiRevisionUploadImporter();
+ $statusValue = $importer->import( $this );
+ return $statusValue->isGood();
}
/**
* @since 1.12.2
+ * @deprecated in 1.31. Use UploadImporter::downloadSource
* @return bool|string
*/
public function downloadSource() {
- if ( !$this->config->get( 'EnableUploads' ) ) {
- return false;
- }
-
- $tempo = tempnam( wfTempDir(), 'download' );
- $f = fopen( $tempo, 'wb' );
- if ( !$f ) {
- wfDebug( "IMPORT: couldn't write to temp file $tempo\n" );
- return false;
- }
-
- // @todo FIXME!
- $src = $this->getSrc();
- $data = Http::get( $src, [], __METHOD__ );
- if ( !$data ) {
- wfDebug( "IMPORT: couldn't fetch source $src\n" );
- fclose( $f );
- unlink( $tempo );
- return false;
- }
-
- fwrite( $f, $data );
- fclose( $f );
-
- return $tempo;
+ $importer = new ImportableUploadRevisionImporter(
+ $this->config->get( 'EnableUploads' ),
+ LoggerFactory::getInstance( 'UploadRevisionImporter' )
+ );
+ return $importer->downloadSource( $this );
}
}