Make userWasLastToEdit reusable.

Make userWasLastToEdit a static method in the Revision class, so it can be
reused by extensions, etc.

Change-Id: Ib44423c3544dabab3be7fe6eb675315f2480838e
This commit is contained in:
daniel 2012-08-30 19:17:14 +02:00
parent cff88497b9
commit c4ff922e64
3 changed files with 139 additions and 31 deletions

View file

@ -1295,7 +1295,7 @@ class EditPage {
$this->isConflict = false;
wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
}
} elseif ( $this->section == '' && $this->userWasLastToEdit( $wgUser->getId(), $this->edittime ) ) {
} elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER, $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime ) ) {
# Suppress edit conflict with self, except for section edits where merging is required.
wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
$this->isConflict = false;
@ -1489,35 +1489,6 @@ class EditPage {
}
}
/**
* Check if no edits were made by other users since
* the time a user started editing the page. Limit to
* 50 revisions for the sake of performance.
*
* @param $id int
* @param $edittime string
*
* @return bool
*/
protected function userWasLastToEdit( $id, $edittime ) {
if ( !$id ) return false;
$dbw = wfGetDB( DB_MASTER );
$res = $dbw->select( 'revision',
'rev_user',
array(
'rev_page' => $this->mTitle->getArticleID(),
'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $edittime ) )
),
__METHOD__,
array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 50 ) );
foreach ( $res as $row ) {
if ( $row->rev_user != $id ) {
return false;
}
}
return true;
}
/**
* @private
* @todo document

View file

@ -1290,4 +1290,42 @@ class Revision implements IDBAccessObject {
}
return 0;
}
}
/**
* Check if no edits were made by other users since
* the time a user started editing the page. Limit to
* 50 revisions for the sake of performance.
*
* @since 1.20
*
* @param DatabaseBase|int $db the Database to perform the check on. May be given as a Database object or
* a database identifier usable with wfGetDB.
* @param int $pageId the ID of the page in question
* @param int $userId the ID of the user in question
* @param string $since look at edits since this time
*
* @return bool True if the given user was the only one to edit since the given timestamp
*/
public static function userWasLastToEdit( $db, $pageId, $userId, $since ) {
if ( !$userId ) return false;
if ( is_int( $db ) ) {
$db = wfGetDB( $db );
}
$res = $db->select( 'revision',
'rev_user',
array(
'rev_page' => $pageId,
'rev_timestamp > ' . $db->addQuotes( $db->timestamp( $since ) )
),
__METHOD__,
array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 50 ) );
foreach ( $res as $row ) {
if ( $row->rev_user != $userId ) {
return false;
}
}
return true;
}
}

View file

@ -5,6 +5,9 @@
*
* @group Database
* ^--- important, causes temporary tables to be used instead of the real database
*
* @group medium
* ^--- important, causes tests not to fail with timeout
*/
class RevisionStorageTest extends MediaWikiTestCase {
@ -306,4 +309,100 @@ class RevisionStorageTest extends MediaWikiTestCase {
$this->assertEquals( $orig->getTextId(), $rev->getTextId(), 'new null revision shold have the same text id as the original revision' );
$this->assertEquals( 'some testing text', $rev->getText() );
}
public function dataUserWasLastToEdit() {
return array(
array( #0
3, true, # actually the last edit
),
array( #1
2, true, # not the current edit, but still by this user
),
array( #2
1, false, # edit by another user
),
array( #3
0, false, # first edit, by this user, but another user edited in the mean time
),
);
}
/**
* @dataProvider dataUserWasLastToEdit
*/
public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
$userA = \User::newFromName( "RevisionStorageTest_userA" );
$userB = \User::newFromName( "RevisionStorageTest_userB" );
if ( $userA->getId() === 0 ) {
$userA = \User::createNew( $userA->getName() );
}
if ( $userB->getId() === 0 ) {
$userB = \User::createNew( $userB->getName() );
}
$dbw = wfGetDB( DB_MASTER );
$revisions = array();
// create revisions -----------------------------
$page = WikiPage::factory( Title::newFromText( 'RevisionStorageTest_testUserWasLastToEdit' ) );
# zero
$revisions[0] = new Revision( array(
'page' => $page->getId(),
'timestamp' => '20120101000000',
'user' => $userA->getId(),
'text' => 'zero',
'summary' => 'edit zero'
) );
$revisions[0]->insertOn( $dbw );
# one
$revisions[1] = new Revision( array(
'page' => $page->getId(),
'timestamp' => '20120101000100',
'user' => $userA->getId(),
'text' => 'one',
'summary' => 'edit one'
) );
$revisions[1]->insertOn( $dbw );
# two
$revisions[2] = new Revision( array(
'page' => $page->getId(),
'timestamp' => '20120101000200',
'user' => $userB->getId(),
'text' => 'two',
'summary' => 'edit two'
) );
$revisions[2]->insertOn( $dbw );
# three
$revisions[3] = new Revision( array(
'page' => $page->getId(),
'timestamp' => '20120101000300',
'user' => $userA->getId(),
'text' => 'three',
'summary' => 'edit three'
) );
$revisions[3]->insertOn( $dbw );
# four
$revisions[4] = new Revision( array(
'page' => $page->getId(),
'timestamp' => '20120101000200',
'user' => $userA->getId(),
'text' => 'zero',
'summary' => 'edit four'
) );
$revisions[4]->insertOn( $dbw );
// test it ---------------------------------
$since = $revisions[ $sinceIdx ]->getTimestamp();
$wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
$this->assertEquals( $expectedLast, $wasLast );
}
}