Merge r81448 from REL1_17: reverting RevisionMove feature back out until somebody has the time to work on it again. Reverts r67094 and its followups in trunk: r67099, r67111, r67112, r67115, r67398, r81425, r81427

This commit is contained in:
Chad Horohoe 2011-04-15 23:28:13 +00:00
parent 5801abee00
commit efe4525d2c
11 changed files with 5 additions and 469 deletions

View file

@ -1762,12 +1762,10 @@ class Article {
* on.
* @param $lastRevIsRedirect Boolean: if given, will optimize adding and
* removing rows in redirect table.
* @param $setNewFlag Boolean: Set to true if a page flag should be set
* Needed when $lastRevision has to be set to sth. !=0
* @return bool true on success, false on failure
* @private
*/
public function updateRevisionOn( &$dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null, $setNewFlag = false ) {
public function updateRevisionOn( &$dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
wfProfileIn( __METHOD__ );
$text = $revision->getText();
@ -1780,15 +1778,11 @@ class Article {
$conditions['page_latest'] = $lastRevision;
}
if ( !$setNewFlag ) {
$setNewFlag = ( $lastRevision === 0 );
}
$dbw->update( 'page',
array( /* SET */
'page_latest' => $revision->getId(),
'page_touched' => $dbw->timestamp(),
'page_is_new' => $setNewFlag,
'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0,
'page_is_redirect' => $rt !== null ? 1 : 0,
'page_len' => strlen( $text ),
),

View file

@ -673,7 +673,6 @@ $wgAutoloadLocalClasses = array(
'RevDel_ArchivedFileItem' => 'includes/revisiondelete/RevisionDelete.php',
'RevDel_LogList' => 'includes/revisiondelete/RevisionDelete.php',
'RevDel_LogItem' => 'includes/revisiondelete/RevisionDelete.php',
'SpecialRevisionMove' => 'includes/specials/SpecialRevisionMove.php',
'ShortPagesPage' => 'includes/specials/SpecialShortpages.php',
'SpecialActiveUsers' => 'includes/specials/SpecialActiveusers.php',
'SpecialAllpages' => 'includes/specials/SpecialAllpages.php',

View file

@ -4834,7 +4834,6 @@ $wgLogActions = array(
'upload/revert' => 'uploadedimage',
'move/move' => '1movedto2',
'move/move_redir' => '1movedto2_redir',
'move/move_rev' => 'moverevlogentry',
'import/upload' => 'import-logentry-upload',
'import/interwiki' => 'import-logentry-interwiki',
'merge/merge' => 'pagemerge-logentry',

View file

@ -403,9 +403,6 @@ class HistoryPager extends ReverseChronologicalPager {
if ( $wgUser->isAllowed( 'deleterevision' ) ) {
$s .= $this->getRevisionButton( 'revisiondelete', 'showhideselectedversions' );
}
if ( $wgUser->isAllowed( 'revisionmove' ) ) {
$s .= $this->getRevisionButton( 'revisionmove', 'revisionmoveselectedversions' );
}
$this->buttons .= '</div>';
$s .= '</div><ul id="pagehistory">' . "\n";
return $s;
@ -510,11 +507,10 @@ class HistoryPager extends ReverseChronologicalPager {
$del = '';
// Show checkboxes for each revision
if ( $wgUser->isAllowedAny( 'deleterevision', 'revisionmove' ) ) {
if ( $wgUser->isAllowed( 'deleterevision' ) ) {
$this->preventClickjacking();
// If revision was hidden from sysops, disable the checkbox
// However, if the user has revisionmove rights, we cannot disable the checkbox
if ( !$rev->userCan( Revision::DELETED_RESTRICTED ) && !$wgUser->isAllowed( 'revisionmove' ) ) {
if ( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
$del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
// Otherwise, enable the checkbox...
} else {

View file

@ -259,7 +259,7 @@ class LogPage {
}
// Page moves
} elseif ( $type == 'move' && count( $params ) == 3 && $action != 'move_rev' ) {
} elseif ( $type == 'move' && count( $params ) == 3 ) {
if( $params[2] ) {
if ( $skin ) {
$details .= ' [' . wfMsg( 'move-redirect-suppressed' ) . ']';

View file

@ -194,7 +194,6 @@ class SpecialPage {
'Myuploads' => 'SpecialMyuploads',
'PermanentLink' => 'SpecialPermanentLink',
'Revisiondelete' => 'SpecialRevisionDelete',
'RevisionMove' => 'SpecialRevisionMove',
'Specialpages' => 'SpecialSpecialpages',
'Userlogout' => 'SpecialUserlogout',
);

View file

@ -556,11 +556,6 @@ class MediaWiki {
$special = SpecialPage::getPage( 'Revisiondelete' );
$special->execute( '' );
break;
case 'revisionmove':
// For revision move submission from history page
$special = SpecialPage::getPage( 'RevisionMove' );
$special->execute( '' );
break;
default:
if ( wfRunHooks( 'UnknownAction', array( $act, $article ) ) ) {
$this->context->output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );

View file

@ -1,400 +0,0 @@
<?php
/**
* Implements Special:RevisionMove
*
* 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
* @ingroup SpecialPage
*/
/**
* Special page allowing users with the appropriate permissions to
* move revisions of a page to a new target (either an existing page or not)
*
* The user selects revisions in the page history (HistoryPage.php),
* clicks on the submit button and gets this special page.
* A form is shown (showForm()) where the user has to enter a target page
* name and confirm the action with a post request & edit token.
* Then submit() is called, which does some checks and calls moveRevisions().
* If the target doesn't exist, a new page gets created. rev_page of the
* selected revisions is updated, after that it is determined whether page_latest
* of the target page and the source page require an update.
*
* **** NOTE: This feature is EXPERIMENTAL. ****
* **** Do not use on any productive system. ****
*
* @ingroup SpecialPage
* @todo In case page_deleted gets introduced some day, use it.
* Currently it is possible with RevisionMove to make the latest revision
* of a page a RevisionDeleted one. When that happens, the user is presented
* an empty page with no error message whatsoever (in case he is not permitted
* to view deleted edits).
*/
class SpecialRevisionMove extends UnlistedSpecialPage {
# common objects
var $mOldTitle; # Title object.
var $mNewTitle; # Title object. Desired new title
var $request; # WebRequest object, $wgRequest by default
var $skin; # Skin object
var $user; # User object
# variables
var $mIds; # Array of Ids to look at
var $mRevlist; # RevDel_RevisionList object - borrowed from RevisionDelete
var $mReason; # User-supplied reason for performing the move operation
var $mSubmit; # Boolean: Is this a submitted request?
var $mIsAllowedRevisionMove = false;
public function __construct( $name = 'RevisionMove' ) {
parent::__construct( $name );
}
/**
* @param $par subpage part, standard special page parameter, is ignored here
*
* Mostly initializes variables and calls either showForm() or submit()
*/
public function execute( $par ) {
global $wgUser, $wgOut;
$this->setHeaders();
$this->outputHeader();
$this->mIsAllowedRevisionMove = $wgUser->isAllowed( 'revisionmove' );
$this->user = $wgUser;
$this->skin = $wgUser->getSkin();
if ( !$this->request instanceof WebRequest ) {
$this->request = $GLOBALS['wgRequest'];
}
# Get correct title
if ( $this->request->getVal( 'action' ) == 'historysubmit' ) {
$this->mOldTitle = Title::newFromText( $this->request->getVal( 'title' ) );
} else {
$this->mOldTitle = Title::newFromText( $this->request->getVal( 'oldTitle' ) );
}
if ( !$this->mOldTitle instanceof Title ) {
$wgOut->showErrorPage( 'revmove-badparam-title', 'revmove-badparam' );
return;
}
$wgOut->setPagetitle( wfMsg( 'revisionmove', $this->mOldTitle->getPrefixedText() ) );
$oldTitleLink = $this->skin->link( $this->mOldTitle );
$wgOut->setSubtitle( wfMsg( 'revisionmove-backlink', $oldTitleLink ) );
$this->mReason = $this->request->getText( 'wpReason' );
# TODO maybe not needed here? Copied from SpecialRevisiondelete.php.
# Keep for now, allow different inputs
# Handle our many different possible input types for ids
$ids = $this->request->getVal( 'ids' );
if ( !is_null( $ids ) ) {
# Allow CSV, for backwards compatibility, or a single ID for show/hide links
$this->mIds = explode( ',', $ids );
} else {
# Array input
$this->mIds = array_keys( $this->request->getArray( 'ids', array() ) );
}
$this->mIds = array_unique( array_filter( $this->mIds ) );
if ( is_null ( $this->mIds ) ) {
$wgOut->showErrorPage( 'revmove-badparam-title', 'revmove-badparam' );
return;
}
$this->mRevlist = new RevDel_RevisionList( $this, $this->mOldTitle, $this->mIds );
# Decide what to do: Show the form, or submit the changes
if ( $this->request->wasPosted() ) {
$this->submit();
} else {
$this->showForm();
}
}
/**
* Show a list of items that we will operate on and a field for the target name
*/
public function showForm() {
global $wgOut, $wgUser;
if ( !$this->mIsAllowedRevisionMove ) {
$permErrors = $this->mOldTitle->getUserPermissionsErrors( 'revisionmove', $this->user );
$wgOut->showPermissionsErrorPage( $permErrors, 'revisionmove' );
return false;
}
$wgOut->addWikiMsg( 'revmove-explain', $this->mOldTitle->getPrefixedText() );
$listNotEmpty = $this->listItems();
if ( !$listNotEmpty ) {
return; # we're done, we already displayed an error earlier
}
$out = Xml::openElement( 'form', array( 'method' => 'post',
'action' => $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) ),
'id' => 'mw-revmove-form' ) ) .
Xml::fieldset( wfMsg( 'revmove-legend' ) ) .
Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
Html::hidden( 'oldTitle', $this->mOldTitle->getPrefixedText() ) .
'<div>' . Xml::inputLabel( wfMsg( 'revmove-reasonfield' ), 'wpReason',
'revmove-reasonfield', 60 ) . '</div>' .
Xml::inputLabel( wfMsg( 'revmove-titlefield' ), 'newTitle', 'revmove-titlefield', 20,
$this->mOldTitle->getPrefixedText() ) .
Html::hidden( 'ids', implode( ',', $this->mIds ) ) .
Xml::submitButton( wfMsg( 'revmove-submit' ),
array( 'name' => 'wpSubmit' ) ) .
Xml::closeElement( 'fieldset' ) . "\n" .
Xml::closeElement( 'form' ) . "\n";
$wgOut->addHTML( $out );
}
/**
* Show a list of selected revisions and check the input
*/
protected function listItems() {
global $wgOut;
$wgOut->addHTML( "<ul>" );
$numRevisions = 0;
# No revisions specified at all
if ( $this->mIds == array() ) {
$wgOut->showErrorPage( 'revmove-norevisions-title', 'revmove-norevisions' );
return false;
}
for ( $this->mRevlist->reset(); $this->mRevlist->current(); $this->mRevlist->next() ) {
$item = $this->mRevlist->current();
$numRevisions++;
$wgOut->addHTML( $item->getHTML() );
}
# No valid revisions specified (e.g. only revs belonging to another page)
if ( $numRevisions == 0 ) {
$wgOut->showErrorPage( 'revmove-norevisions-title', 'revmove-norevisions' );
return false;
}
$wgOut->addHTML( "</ul>" );
return true;
}
/**
* Submit the posted changes (in $this->request).
*
* This function does some checks and then calls moveRevisions(), which does the real work
*/
public function submit() {
global $wgUser, $wgOut;
# Confirm permissions
if ( !$this->mIsAllowedRevisionMove ) {
$permErrors = $this->mOldTitle->getUserPermissionsErrors( 'revisionmove', $this->user );
$wgOut->showPermissionsErrorPage( $permErrors, 'revisionmove' );
return false;
}
# Confirm Token
if ( !$wgUser->matchEditToken( $this->request->getVal( 'wpEditToken' ) ) ) {
$wgOut->showErrorPage( 'sessionfailure-title', 'sessionfailure' );
return false;
}
$this->mNewTitle = Title::newFromText( $this->request->getVal( 'newTitle' ) );
if ( !$this->mNewTitle instanceof Title ) {
$wgOut->showErrorPage( 'badtitle', 'badtitletext' );
return false;
}
if ( $this->mNewTitle->getPrefixedText() == $this->mOldTitle->getPrefixedText() ) {
$pagename = array( $this->mOldTitle->getPrefixedText() );
$wgOut->showErrorPage( 'revmove-nullmove-title', 'revmove-nullmove', $pagename );
return;
}
$this->moveRevisions();
}
/**
* This function actually move the revision. NEVER call this function, call submit()
*/
protected function moveRevisions() {
$oldArticle = new Article( $this->mOldTitle );
$newArticle = new Article( $this->mNewTitle );
# Get DB connection and begin transaction
$dbw = wfGetDB( DB_MASTER );
$dbw->begin();
# Check if the target exists. If not, try creating it
if ( !$this->mNewTitle->exists() ) {
$newArticle->insertOn( $dbw );
$this->createArticle = true;
} else {
$this->createArticle = false;
}
# This is where the magic happens:
# Update revision table
$dbw->update( 'revision',
array( 'rev_page' => $this->mNewTitle->getArticleID() ),
array(
'rev_id' => $this->mIds,
'rev_page' => $this->mOldTitle->getArticleID(),
),
__METHOD__
);
$modifiedRevsNum = $dbw->affectedRows();
# Check if we need to update page_latest
# Get the latest version of the revisions we are moving
$timestampNewPage = $this->queryLatestTimestamp(
$this->mNewTitle->getArticleID(),
array( 'rev_id' => $this->mIds )
);
# Compare the new page's page_latest against db query.
# If we create a new page, we have to update anyway
$currentNewPageRev = Revision::newFromId( $this->mNewTitle->getLatestRevID() );
if ( $this->createArticle || $timestampNewPage > $currentNewPageRev->getTimestamp() ) {
# we have to set page_latest to $timestampNewPage's revid
$this->updatePageLatest(
$this->mNewTitle,
$newArticle,
$timestampNewPage,
array( 'rev_id' => $this->mIds )
);
}
# Update the old page's page_latest field
$timestampOldPage = $this->queryLatestTimestamp(
$this->mOldTitle->getArticleID()
);
# If the timestamp is null that means the page doesn't have
# any revisions associated and should be deleted. In other words,
# someone misused revisionmove for the normal move function.
if ( is_null( $timestampOldPage ) ) {
$dbw->delete(
'page',
array( 'page_id' => $this->mOldTitle->getArticleID() ),
__METHOD__
);
} else {
# page_latest has to be updated
$currentOldPageRev = Revision::newFromId( $this->mOldTitle->getLatestRevID() );
if ( $timestampOldPage < $currentOldPageRev->getTimestamp() ) {
$this->updatePageLatest(
$this->mOldTitle,
$oldArticle,
$timestampOldPage
);
}
# Purge the old one only if it hasn't been deleted
$oldArticle->doPurge();
}
# All done, commit
$dbw->commit();
$this->logMove( $modifiedRevsNum );
# Purge new article
$newArticle->doPurge();
# If noting went wrong (i.e. returned), we are successful
$this->showSuccess( $modifiedRevsNum );
}
/**
* Query for the latest timestamp in order to update page_latest and
* page_timestamp.
* @param $articleId Integer page_id
* @param $conds array database conditions
*
* @return String timestamp
*/
protected function queryLatestTimestamp( $articleId, $conds = array() ) {
$dbw = wfGetDB( DB_MASTER );
$timestampNewRow = $dbw->selectRow(
'revision',
'max(rev_timestamp) AS maxtime',
array_merge( array( 'rev_page' => $articleId ), $conds ),
__METHOD__
);
return $timestampNewRow->maxtime;
}
/**
* Updates page_latest and similar database fields (see Article::updateRevisionOn).
* Called two times, for the new and the old page
*
* @param $articleTitle Title object of the page
* @param $articleObj Article object of the page
* @param $timestamp to search for (use queryLatestTimestamp to get the latest)
* @param $conds array database conditions
*
* @return boolean indicating success
*/
protected function updatePageLatest( $articleTitle, $articleObj, $timestamp, $conds = array() ) {
$dbw = wfGetDB( DB_MASTER );
# Query to find out the rev_id
$revisionRow = $dbw->selectRow(
'revision',
'rev_id',
array_merge( array(
'rev_timestamp' => $timestamp,
'rev_page' => $articleTitle->getArticleID(),
), $conds ),
__METHOD__
);
# Update page_latest
$latestRev = Revision::newFromId( $revisionRow->rev_id );
return $articleObj->updateRevisionOn( $dbw, $latestRev, $articleTitle->getLatestRevID(), null,
/* set new page flag */ true );
}
/**
* Add a log entry for the revision move
*/
protected function logMove( $modifiedRevsNum ) {
$paramArray = array(
$this->mNewTitle->getPrefixedText(),
$modifiedRevsNum
);
$log = new LogPage( 'move' );
$log->addEntry( 'move_rev', $this->mOldTitle, $this->mReason, $paramArray, $this->user );
}
protected function showSuccess( $modifiedRevsNum ) {
global $wgOut;
if ( $this->createArticle ) {
$wgOut->addWikiMsg( 'revmove-success-created', $modifiedRevsNum,
$this->mOldTitle->getPrefixedText(), $this->mNewTitle->getPrefixedText() );
} else {
$wgOut->addWikiMsg( 'revmove-success-existing', $modifiedRevsNum,
$this->mOldTitle->getPrefixedText(), $this->mNewTitle->getPrefixedText() );
}
}
}

View file

@ -1579,27 +1579,6 @@ Please check the logs.',
'suppressionlogtext' => 'Below is a list of deletions and blocks involving content hidden from administrators.
See the [[Special:BlockList|IP block list]] for the list of currently operational bans and blocks.',
# Revision move
'moverevlogentry' => 'moved {{PLURAL:$3|one revision|$3 revisions}} from $1 to $2',
'revisionmove' => 'Move revisions from "$1"',
'revisionmove-backlink' => '← $1', # only translate this message to other languages if you have to change it
'revmove-explain' => 'The following revisions will be moved from $1 to the specified target page. If the target does not exist, it is created. Otherwise, these revisions will be merged into the page history.',
'revmove-legend' => 'Set target page and summary',
'revmove-submit' => 'Move revisions to selected page',
'revisionmoveselectedversions' => 'Move selected revisions',
'revmove-reasonfield' => 'Reason:',
'revmove-titlefield' => 'Target page:',
'revmove-badparam-title' => 'Bad parameters',
'revmove-badparam' => 'Your request contains illegal or insufficient parameters.
Go back to the previous page and try again.',
'revmove-norevisions-title' => 'Invalid target revision',
'revmove-norevisions' => 'You have not specified one or more target revisions to perform this function or the specified revision does not exist.',
'revmove-nullmove-title' => 'Bad title',
'revmove-nullmove' => 'The target page cannot be the same as the source page.
Go back to the previous page and choose a different name from "$1".',
'revmove-success-existing' => '{{PLURAL:$1|One revision from [[$2]] has|$1 revisions from [[$2]] have}} been moved to the existing page [[$3]].',
'revmove-success-created' => '{{PLURAL:$1|One revision from [[$2]] has|$1 revisions from [[$2]] have}} been moved to the newly created page [[$3]].',
# History merging
'mergehistory' => 'Merge page histories',
'mergehistory-header' => 'This page lets you merge revisions of the history of one source page into a newer page.
@ -1968,7 +1947,6 @@ If you choose to provide it, this will be used for giving you attribution for yo
'right-reset-passwords' => "Reset other users' passwords",
'right-override-export-depth' => 'Export pages including linked pages up to a depth of 5',
'right-sendemail' => 'Send e-mail to other users',
'right-revisionmove' => 'Move revisions',
# User rights log
'rightslog' => 'User rights log',
@ -2011,7 +1989,6 @@ If you choose to provide it, this will be used for giving you attribution for yo
'action-userrights' => 'edit all user rights',
'action-userrights-interwiki' => 'edit user rights of users on other wikis',
'action-siteadmin' => 'lock or unlock the database',
'action-revisionmove' => 'move revisions',
# Recent changes
'nchanges' => '$1 {{PLURAL:$1|change|changes}}',

View file

@ -388,7 +388,6 @@ $wgOptionalMessages = array(
'prefs-memberingroups-type',
'shared-repo-name-wikimediacommons',
'usermessage-template',
'revisionmove-backlink',
'filepage.css',
'nocookiesforlogin',
);

View file

@ -783,25 +783,6 @@ $wgMessageStructure = array(
'suppressionlog',
'suppressionlogtext',
),
'revisionmove' => array(
'moverevlogentry',
'revisionmove',
'revisionmove-backlink',
'revmove-explain',
'revmove-legend',
'revmove-submit',
'revisionmoveselectedversions',
'revmove-reasonfield',
'revmove-titlefield',
'revmove-badparam-title' ,
'revmove-badparam',
'revmove-norevisions-title',
'revmove-norevisions',
'revmove-nullmove-title',
'revmove-nullmove',
'revmove-success-existing',
'revmove-success-created',
),
'mergehistory' => array(
'mergehistory',
'mergehistory-header',
@ -1148,7 +1129,6 @@ $wgMessageStructure = array(
'right-reset-passwords',
'right-override-export-depth',
'right-sendemail',
'right-revisionmove',
),
'rightslog' => array(
'rightslog',
@ -1191,7 +1171,6 @@ $wgMessageStructure = array(
'action-userrights',
'action-userrights-interwiki',
'action-siteadmin',
'action-revisionmove',
),
'recentchanges' => array(
'nchanges',
@ -3341,7 +3320,6 @@ XHTML id names.",
'history-feed' => 'Revision feed',
'revdelete' => 'Revision deletion',
'suppression' => 'Suppression log',
'revisionmove' => 'Revision move',
'mergehistory' => 'History merging',
'mergelog' => 'Merge log',
'diffs' => 'Diffs',