MediaWiki  master
ImportableOldRevisionImporter.php
Go to the documentation of this file.
1 <?php
2 
6 use Psr\Log\LoggerInterface;
8 
13 
17  private $logger;
18 
22  private $doUpdates;
23 
27  private $loadBalancer;
28 
34  public function __construct(
35  $doUpdates,
36  LoggerInterface $logger,
38  ) {
39  $this->doUpdates = $doUpdates;
40  $this->logger = $logger;
41  $this->loadBalancer = $loadBalancer;
42  }
43 
44  public function import( ImportableOldRevision $importableRevision, $doUpdates = true ) {
45  $dbw = $this->loadBalancer->getConnectionRef( DB_MASTER );
46 
47  # Sneak a single revision into place
48  $user = $importableRevision->getUserObj() ?: User::newFromName( $importableRevision->getUser() );
49  if ( $user ) {
50  $userId = intval( $user->getId() );
51  $userText = $user->getName();
52  } else {
53  $userId = 0;
54  $userText = $importableRevision->getUser();
55  $user = new User;
56  }
57 
58  // avoid memory leak...?
60 
61  $page = WikiPage::factory( $importableRevision->getTitle() );
62  $page->loadPageData( 'fromdbmaster' );
63  if ( !$page->exists() ) {
64  // must create the page...
65  $pageId = $page->insertOn( $dbw );
66  $created = true;
67  $oldcountable = null;
68  } else {
69  $pageId = $page->getId();
70  $created = false;
71 
72  // Note: sha1 has been in XML dumps since 2012. If you have an
73  // older dump, the duplicate detection here won't work.
74  if ( $importableRevision->getSha1Base36() !== false ) {
75  $prior = $dbw->selectField( 'revision', '1',
76  [ 'rev_page' => $pageId,
77  'rev_timestamp' => $dbw->timestamp( $importableRevision->getTimestamp() ),
78  'rev_sha1' => $importableRevision->getSha1Base36() ],
79  __METHOD__
80  );
81  if ( $prior ) {
82  // @todo FIXME: This could fail slightly for multiple matches :P
83  $this->logger->debug( __METHOD__ . ": skipping existing revision for [[" .
84  $importableRevision->getTitle()->getPrefixedText() . "]], timestamp " .
85  $importableRevision->getTimestamp() . "\n" );
86  return false;
87  }
88  }
89  }
90 
91  if ( !$pageId ) {
92  // This seems to happen if two clients simultaneously try to import the
93  // same page
94  $this->logger->debug( __METHOD__ . ': got invalid $pageId when importing revision of [[' .
95  $importableRevision->getTitle()->getPrefixedText() . ']], timestamp ' .
96  $importableRevision->getTimestamp() . "\n" );
97  return false;
98  }
99 
100  // Select previous version to make size diffs correct
101  // @todo This assumes that multiple revisions of the same page are imported
102  // in order from oldest to newest.
103  $prevId = $dbw->selectField( 'revision', 'rev_id',
104  [
105  'rev_page' => $pageId,
106  'rev_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $importableRevision->getTimestamp() ) ),
107  ],
108  __METHOD__,
109  [ 'ORDER BY' => [
110  'rev_timestamp DESC',
111  'rev_id DESC', // timestamp is not unique per page
112  ]
113  ]
114  );
115 
116  # @todo FIXME: Use original rev_id optionally (better for backups)
117  # Insert the row
118  $revisionRecord = new MutableRevisionRecord( $importableRevision->getTitle() );
119  $revisionRecord->setParentId( (int)$prevId );
120  $revisionRecord->setComment(
121  CommentStoreComment::newUnsavedComment( $importableRevision->getComment() )
122  );
123 
124  try {
125  $revUser = User::newFromAnyId(
126  $userId,
127  $userText,
128  null
129  );
130  } catch ( InvalidArgumentException $ex ) {
131  $revUser = RequestContext::getMain()->getUser();
132  }
133  $revisionRecord->setUser( $revUser );
134 
135  $revisionRecord->setContent( SlotRecord::MAIN, $importableRevision->getContent() );
136  $revisionRecord->setTimestamp( $importableRevision->getTimestamp() );
137  $revisionRecord->setMinorEdit( $importableRevision->getMinor() );
138  $revisionRecord->setPageId( $pageId );
139 
140  $inserted = MediaWikiServices::getInstance()
141  ->getRevisionStore()
142  ->insertRevisionOn( $revisionRecord, $dbw );
143 
144  $revObject = new Revision( $inserted );
145 
146  // TODO WikiPage::updateIfNewerOn is deprecated
147  $changed = $page->updateIfNewerOn( $dbw, $revObject );
148 
149  $tags = $importableRevision->getTags();
150  if ( $tags !== [] ) {
151  ChangeTags::addTags( $tags, null, $inserted->getId() );
152  }
153 
154  if ( $changed !== false && $this->doUpdates ) {
155  $this->logger->debug( __METHOD__ . ": running updates\n" );
156  // countable/oldcountable stuff is handled in WikiImporter::finishImportPage
157  // TODO WikiPgae::doEditUpdates is deprecated
158  $page->doEditUpdates(
159  $revObject,
160  $user,
161  [ 'created' => $created, 'oldcountable' => 'no-change' ]
162  );
163  }
164 
165  return true;
166  }
167 
168 }
CommentStoreComment\newUnsavedComment
static newUnsavedComment( $comment, array $data=null)
Create a new, unsaved CommentStoreComment.
Definition: CommentStoreComment.php:66
ImportableOldRevisionImporter\$doUpdates
bool $doUpdates
Definition: ImportableOldRevisionImporter.php:22
ImportableOldRevisionImporter
Definition: ImportableOldRevisionImporter.php:12
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:144
Title\clearCaches
static clearCaches()
Was this Title created from a string with a local interwiki prefix?
Definition: Title.php:3313
true
return true
Definition: router.php:90
ImportableOldRevision\getTimestamp
getTimestamp()
ImportableOldRevision\getContent
getContent()
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:533
ImportableOldRevisionImporter\$logger
LoggerInterface $logger
Definition: ImportableOldRevisionImporter.php:17
Wikimedia\Rdbms\ILoadBalancer\getConnectionRef
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)
Get a live database handle reference for a real or virtual (DB_MASTER/DB_REPLICA) server index.
ImportableOldRevision\getUser
getUser()
ImportableOldRevision\getMinor
getMinor()
Revision
Definition: Revision.php:39
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:143
ImportableOldRevision\getTags
getTags()
ImportableOldRevision\getSha1Base36
getSha1Base36()
User\newFromAnyId
static newFromAnyId( $userId, $userName, $actorId, $dbDomain=false)
Static factory method for creation from an ID, name, and/or actor ID.
Definition: User.php:614
DB_MASTER
const DB_MASTER
Definition: defines.php:26
ImportableOldRevision
Definition: ImportableOldRevision.php:6
Revision\MutableRevisionRecord
Definition: MutableRevisionRecord.php:43
ImportableOldRevision\getTitle
getTitle()
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
ImportableOldRevisionImporter\$loadBalancer
ILoadBalancer $loadBalancer
Definition: ImportableOldRevisionImporter.php:27
ImportableOldRevision\getComment
getComment()
OldRevisionImporter
Definition: OldRevisionImporter.php:6
ImportableOldRevisionImporter\__construct
__construct( $doUpdates, LoggerInterface $logger, ILoadBalancer $loadBalancer)
Definition: ImportableOldRevisionImporter.php:34
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:54
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
ChangeTags\addTags
static addTags( $tags, $rc_id=null, $rev_id=null, $log_id=null, $params=null, RecentChange $rc=null)
Add tags to a change given its rc_id, rev_id and/or log_id.
Definition: ChangeTags.php:256
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39
ImportableOldRevision\getUserObj
getUserObj()