Merge "Factor OldRevisionImporter & ImportableOldRevision out of WikiRevision"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 21 Feb 2018 10:31:32 +0000 (10:31 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 21 Feb 2018 10:31:32 +0000 (10:31 +0000)
autoload.php
includes/MediaWikiServices.php
includes/ServiceWiring.php
includes/import/ImportableOldRevision.php [new file with mode: 0644]
includes/import/ImportableOldRevisionImporter.php [new file with mode: 0644]
includes/import/OldRevisionImporter.php [new file with mode: 0644]
includes/import/WikiRevision.php

index 88a6425..7f90d47 100644 (file)
@@ -647,6 +647,8 @@ $wgAutoloadLocalClasses = [
        'ImportStringSource' => __DIR__ . '/includes/import/ImportStringSource.php',
        'ImportTextFiles' => __DIR__ . '/maintenance/importTextFiles.php',
        'ImportTitleFactory' => __DIR__ . '/includes/title/ImportTitleFactory.php',
+       'ImportableOldRevision' => __DIR__ . '/includes/import/ImportableOldRevision.php',
+       'ImportableOldRevisionImporter' => __DIR__ . '/includes/import/ImportableOldRevisionImporter.php',
        'ImportableUploadRevision' => __DIR__ . '/includes/import/ImportableUploadRevision.php',
        'ImportableUploadRevisionImporter' => __DIR__ . '/includes/import/ImportableUploadRevisionImporter.php',
        'IncludableSpecialPage' => __DIR__ . '/includes/specialpage/IncludableSpecialPage.php',
@@ -1077,6 +1079,7 @@ $wgAutoloadLocalClasses = [
        'ObjectFactory' => __DIR__ . '/includes/compat/ObjectFactory.php',
        'OldChangesList' => __DIR__ . '/includes/changes/OldChangesList.php',
        'OldLocalFile' => __DIR__ . '/includes/filerepo/file/OldLocalFile.php',
+       'OldRevisionImporter' => __DIR__ . '/includes/import/OldRevisionImporter.php',
        'OracleInstaller' => __DIR__ . '/includes/installer/OracleInstaller.php',
        'OracleUpdater' => __DIR__ . '/includes/installer/OracleUpdater.php',
        'OrderedStreamingForkController' => __DIR__ . '/includes/OrderedStreamingForkController.php',
index 6f2d72c..59f194d 100644 (file)
@@ -698,6 +698,22 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'UploadRevisionImporter' );
        }
 
+       /**
+        * @since 1.31
+        * @return \OldRevisionImporter
+        */
+       public function getWikiRevisionOldRevisionImporter() {
+               return $this->getService( 'OldRevisionImporter' );
+       }
+
+       /**
+        * @since 1.31
+        * @return \OldRevisionImporter
+        */
+       public function getWikiRevisionOldRevisionImporterNoUpdates() {
+               return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
+       }
+
        /**
         * @since 1.30
         * @return CommandFactory
index 672734d..dab9fb9 100644 (file)
@@ -449,6 +449,22 @@ return [
                );
        },
 
+       'OldRevisionImporter' => function ( MediaWikiServices $services ) {
+               return new ImportableOldRevisionImporter(
+                       true,
+                       LoggerFactory::getInstance( 'OldRevisionImporter' ),
+                       $services->getDBLoadBalancer()
+               );
+       },
+
+       'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) {
+               return new ImportableOldRevisionImporter(
+                       false,
+                       LoggerFactory::getInstance( 'OldRevisionImporter' ),
+                       $services->getDBLoadBalancer()
+               );
+       },
+
        'ShellCommandFactory' => function ( MediaWikiServices $services ) {
                $config = $services->getMainConfig();
 
diff --git a/includes/import/ImportableOldRevision.php b/includes/import/ImportableOldRevision.php
new file mode 100644 (file)
index 0000000..6d1e242
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface ImportableOldRevision {
+
+       /**
+        * @since 1.31
+        * @return User
+        */
+       public function getUserObj();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getUser();
+
+       /**
+        * @since 1.31
+        * @return Title
+        */
+       public function getTitle();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getTimestamp();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getComment();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getModel();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getFormat();
+
+       /**
+        * @since 1.31
+        * @return Content
+        */
+       public function getContent();
+
+       /**
+        * @since 1.31
+        * @return bool
+        */
+       public function getMinor();
+
+       /**
+        * @since 1.31
+        * @return bool|string
+        */
+       public function getSha1Base36();
+
+}
diff --git a/includes/import/ImportableOldRevisionImporter.php b/includes/import/ImportableOldRevisionImporter.php
new file mode 100644 (file)
index 0000000..33fad3e
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+
+use Psr\Log\LoggerInterface;
+use Wikimedia\Rdbms\LoadBalancer;
+
+/**
+ * @since 1.31
+ */
+class ImportableOldRevisionImporter implements OldRevisionImporter {
+
+       /**
+        * @var LoggerInterface
+        */
+       private $logger;
+
+       /**
+        * @var bool
+        */
+       private $doUpdates;
+
+       /**
+        * @var LoadBalancer
+        */
+       private $loadBalancer;
+
+       /**
+        * @param bool $doUpdates
+        * @param LoggerInterface $logger
+        * @param LoadBalancer $loadBalancer
+        */
+       public function __construct(
+               $doUpdates,
+               LoggerInterface $logger,
+               LoadBalancer $loadBalancer
+       ) {
+               $this->doUpdates = $doUpdates;
+               $this->logger = $logger;
+               $this->loadBalancer = $loadBalancer;
+       }
+
+       public function import( ImportableOldRevision $importableRevision, $doUpdates = true ) {
+               $dbw = $this->loadBalancer->getConnectionRef( DB_MASTER );
+
+               # Sneak a single revision into place
+               $user = $importableRevision->getUserObj() ?: User::newFromName( $importableRevision->getUser() );
+               if ( $user ) {
+                       $userId = intval( $user->getId() );
+                       $userText = $user->getName();
+               } else {
+                       $userId = 0;
+                       $userText = $importableRevision->getUser();
+                       $user = new User;
+               }
+
+               // avoid memory leak...?
+               Title::clearCaches();
+
+               $page = WikiPage::factory( $importableRevision->getTitle() );
+               $page->loadPageData( 'fromdbmaster' );
+               if ( !$page->exists() ) {
+                       // must create the page...
+                       $pageId = $page->insertOn( $dbw );
+                       $created = true;
+                       $oldcountable = null;
+               } else {
+                       $pageId = $page->getId();
+                       $created = false;
+
+                       // Note: sha1 has been in XML dumps since 2012. If you have an
+                       // older dump, the duplicate detection here won't work.
+                       $prior = $dbw->selectField( 'revision', '1',
+                               [ 'rev_page' => $pageId,
+                                       'rev_timestamp' => $dbw->timestamp( $importableRevision->getTimestamp() ),
+                                       'rev_sha1' => $importableRevision->getSha1Base36() ],
+                               __METHOD__
+                       );
+                       if ( $prior ) {
+                               // @todo FIXME: This could fail slightly for multiple matches :P
+                               $this->logger->debug( __METHOD__ . ": skipping existing revision for [[" .
+                                       $importableRevision->getTitle()->getPrefixedText() . "]], timestamp " .
+                                       $importableRevision->getTimestamp() . "\n" );
+                               return false;
+                       }
+               }
+
+               if ( !$pageId ) {
+                       // This seems to happen if two clients simultaneously try to import the
+                       // same page
+                       $this->logger->debug( __METHOD__ . ': got invalid $pageId when importing revision of [[' .
+                               $importableRevision->getTitle()->getPrefixedText() . ']], timestamp ' .
+                               $importableRevision->getTimestamp() . "\n" );
+                       return false;
+               }
+
+               // Select previous version to make size diffs correct
+               // @todo This assumes that multiple revisions of the same page are imported
+               // in order from oldest to newest.
+               $prevId = $dbw->selectField( 'revision', 'rev_id',
+                       [
+                               'rev_page' => $pageId,
+                               'rev_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $importableRevision->getTimestamp() ) ),
+                       ],
+                       __METHOD__,
+                       [ 'ORDER BY' => [
+                               'rev_timestamp DESC',
+                               'rev_id DESC', // timestamp is not unique per page
+                       ]
+                       ]
+               );
+
+               # @todo FIXME: Use original rev_id optionally (better for backups)
+               # Insert the row
+               $revision = new Revision( [
+                       'title' => $importableRevision->getTitle(),
+                       'page' => $pageId,
+                       'content_model' => $importableRevision->getModel(),
+                       'content_format' => $importableRevision->getFormat(),
+                       // XXX: just set 'content' => $wikiRevision->getContent()?
+                       'text' => $importableRevision->getContent()->serialize( $importableRevision->getFormat() ),
+                       'comment' => $importableRevision->getComment(),
+                       'user' => $userId,
+                       'user_text' => $userText,
+                       'timestamp' => $importableRevision->getTimestamp(),
+                       'minor_edit' => $importableRevision->getMinor(),
+                       'parent_id' => $prevId,
+               ] );
+               $revision->insertOn( $dbw );
+               $changed = $page->updateIfNewerOn( $dbw, $revision );
+
+               if ( $changed !== false && $this->doUpdates ) {
+                       $this->logger->debug( __METHOD__ . ": running updates\n" );
+                       // countable/oldcountable stuff is handled in WikiImporter::finishImportPage
+                       $page->doEditUpdates(
+                               $revision,
+                               $user,
+                               [ 'created' => $created, 'oldcountable' => 'no-change' ]
+                       );
+               }
+
+               return true;
+       }
+
+}
diff --git a/includes/import/OldRevisionImporter.php b/includes/import/OldRevisionImporter.php
new file mode 100644 (file)
index 0000000..72af43b
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface OldRevisionImporter {
+
+       /**
+        * @since 1.31
+        *
+        * @param ImportableOldRevision $importableRevision
+        *
+        * @return bool Success
+        */
+       public function import( ImportableOldRevision $importableRevision );
+
+}
index 1aba862..4325a1a 100644 (file)
@@ -34,7 +34,7 @@ use MediaWiki\MediaWikiServices;
  *
  * @ingroup SpecialPage
  */
-class WikiRevision implements ImportableUploadRevision {
+class WikiRevision implements ImportableUploadRevision, ImportableOldRevision {
 
        /**
         * @since 1.17
@@ -513,6 +513,17 @@ class WikiRevision implements ImportableUploadRevision {
                return false;
        }
 
+       /**
+        * @since 1.31
+        * @return bool|string
+        */
+       public function getSha1Base36() {
+               if ( $this->sha1base36 ) {
+                       return $this->sha1base36;
+               }
+               return false;
+       }
+
        /**
         * @since 1.17
         * @return string
@@ -579,106 +590,16 @@ class WikiRevision implements ImportableUploadRevision {
 
        /**
         * @since 1.4.1
+        * @deprecated in 1.31. Use OldRevisionImporter::import
         * @return bool
         */
        public function importOldRevision() {
-               $dbw = wfGetDB( DB_MASTER );
-
-               # Sneak a single revision into place
-               $user = $this->getUserObj() ?: User::newFromName( $this->getUser() );
-               if ( $user ) {
-                       $userId = intval( $user->getId() );
-                       $userText = $user->getName();
+               if ( $this->mNoUpdates ) {
+                       $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporterNoUpdates();
                } else {
-                       $userId = 0;
-                       $userText = $this->getUser();
-                       $user = new User;
-               }
-
-               // avoid memory leak...?
-               Title::clearCaches();
-
-               $page = WikiPage::factory( $this->title );
-               $page->loadPageData( 'fromdbmaster' );
-               if ( !$page->exists() ) {
-                       // must create the page...
-                       $pageId = $page->insertOn( $dbw );
-                       $created = true;
-                       $oldcountable = null;
-               } else {
-                       $pageId = $page->getId();
-                       $created = false;
-
-                       // Note: sha1 has been in XML dumps since 2012. If you have an
-                       // older dump, the duplicate detection here won't work.
-                       $prior = $dbw->selectField( 'revision', '1',
-                               [ 'rev_page' => $pageId,
-                                       'rev_timestamp' => $dbw->timestamp( $this->timestamp ),
-                                       'rev_sha1' => $this->sha1base36 ],
-                               __METHOD__
-                       );
-                       if ( $prior ) {
-                               // @todo FIXME: This could fail slightly for multiple matches :P
-                               wfDebug( __METHOD__ . ": skipping existing revision for [[" .
-                                       $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n" );
-                               return false;
-                       }
-               }
-
-               if ( !$pageId ) {
-                       // This seems to happen if two clients simultaneously try to import the
-                       // same page
-                       wfDebug( __METHOD__ . ': got invalid $pageId when importing revision of [[' .
-                               $this->title->getPrefixedText() . ']], timestamp ' . $this->timestamp . "\n" );
-                       return false;
+                       $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporter();
                }
-
-               // Select previous version to make size diffs correct
-               // @todo This assumes that multiple revisions of the same page are imported
-               // in order from oldest to newest.
-               $prevId = $dbw->selectField( 'revision', 'rev_id',
-                       [
-                               'rev_page' => $pageId,
-                               'rev_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $this->timestamp ) ),
-                       ],
-                       __METHOD__,
-                       [ 'ORDER BY' => [
-                                       'rev_timestamp DESC',
-                                       'rev_id DESC', // timestamp is not unique per page
-                               ]
-                       ]
-               );
-
-               # @todo FIXME: Use original rev_id optionally (better for backups)
-               # Insert the row
-               $revision = new Revision( [
-                       'title' => $this->title,
-                       'page' => $pageId,
-                       'content_model' => $this->getModel(),
-                       'content_format' => $this->getFormat(),
-                       // XXX: just set 'content' => $this->getContent()?
-                       'text' => $this->getContent()->serialize( $this->getFormat() ),
-                       'comment' => $this->getComment(),
-                       'user' => $userId,
-                       'user_text' => $userText,
-                       'timestamp' => $this->timestamp,
-                       'minor_edit' => $this->minor,
-                       'parent_id' => $prevId,
-                       ] );
-               $revision->insertOn( $dbw );
-               $changed = $page->updateIfNewerOn( $dbw, $revision );
-
-               if ( $changed !== false && !$this->mNoUpdates ) {
-                       wfDebug( __METHOD__ . ": running updates\n" );
-                       // countable/oldcountable stuff is handled in WikiImporter::finishImportPage
-                       $page->doEditUpdates(
-                               $revision,
-                               $user,
-                               [ 'created' => $created, 'oldcountable' => 'no-change' ]
-                       );
-               }
-
-               return true;
+               return $importer->import( $this );
        }
 
        /**