+
+ // Update *_from_namespace in links tables
+ $fromNamespaceTables = array(
+ array( 'pagelinks', 'pl' ),
+ array( 'templatelinks', 'tl' ),
+ array( 'imagelinks', 'il' ) );
+ foreach ( $fromNamespaceTables as $tableInfo ) {
+ list( $table, $fieldPrefix ) = $tableInfo;
+ $this->db->update( $table,
+ // SET
+ array( "{$fieldPrefix}_from_namespace" => $newTitle->getNamespace() ),
+ // WHERE
+ array( "{$fieldPrefix}_from" => $id ),
+ __METHOD__ );
+ }
+
+ return true;
+ }
+
+ /**
+ * Determine if we can merge a page.
+ * We check if an inaccessible revision would become the latest and
+ * deny the merge if so -- it's theoretically possible to update the
+ * latest revision, but opens a can of worms -- search engine updates,
+ * recentchanges review, etc.
+ *
+ * @param integer $id The page_id
+ * @param Title $newTitle The new title
+ * @param string $logStatus This is set to the log status message on failure
+ * @return bool
+ */
+ private function canMerge( $id, Title $newTitle, &$logStatus ) {
+ $latestDest = Revision::newFromTitle( $newTitle, 0, Revision::READ_LATEST );
+ $latestSource = Revision::newFromPageId( $id, 0, Revision::READ_LATEST );
+ if ( $latestSource->getTimestamp() > $latestDest->getTimestamp() ) {
+ $logStatus = 'cannot merge since source is later';
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Merge page histories
+ *
+ * @param integer $id The page_id
+ * @param Title $newTitle The new title
+ */
+ private function mergePage( $row, Title $newTitle ) {
+ $id = $row->page_id;
+
+ // Construct the WikiPage object we will need later, while the
+ // page_id still exists. Note that this cannot use makeTitleSafe(),
+ // we are deliberately constructing an invalid title.
+ $sourceTitle = Title::makeTitle( $row->page_namespace, $row->page_title );
+ $sourceTitle->resetArticleID( $id );
+ $wikiPage = new WikiPage( $sourceTitle );
+ $wikiPage->loadPageData( 'fromdbmaster' );
+
+ $destId = $newTitle->getArticleId();
+ $this->db->begin( __METHOD__ );
+ $this->db->update( 'revision',
+ // SET
+ array( 'rev_page' => $destId ),
+ // WHERE
+ array( 'rev_page' => $id ),
+ __METHOD__ );
+
+ $this->db->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
+
+ // Call LinksDeletionUpdate to delete outgoing links from the old title,
+ // and update category counts.
+ //
+ // Calling external code with a fake broken Title is a fairly dubious
+ // idea. It's necessary because it's quite a lot of code to duplicate,
+ // but that also makes it fragile since it would be easy for someone to
+ // accidentally introduce an assumption of title validity to the code we
+ // are calling.
+ $update = new LinksDeletionUpdate( $wikiPage );
+ $update->doUpdate();
+ $this->db->commit( __METHOD__ );