From 63601400e476c6cf43d985f3e7b9864681695ed4 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Fri, 18 Jan 2013 16:46:04 +0100 Subject: Update to MediaWiki 1.20.2 this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024 --- includes/Revision.php | 255 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 181 insertions(+), 74 deletions(-) (limited to 'includes/Revision.php') diff --git a/includes/Revision.php b/includes/Revision.php index 445211c9..20cc8f58 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -1,9 +1,29 @@ intval( $id ) ) ); + public static function newFromId( $id, $flags = 0 ) { + return self::newFromConds( array( 'rev_id' => intval( $id ) ), $flags ); } /** @@ -48,11 +74,16 @@ class Revision { * that's attached to a given title. If not attached * to that title, will return null. * + * $flags include: + * Revision::READ_LATEST : Select the data from the master + * Revision::READ_LOCKING : Select & lock the data from the master + * * @param $title Title * @param $id Integer (optional) + * @param $flags Integer Bitfield (optional) * @return Revision or null */ - public static function newFromTitle( $title, $id = 0 ) { + public static function newFromTitle( $title, $id = 0, $flags = null ) { $conds = array( 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey() @@ -60,19 +91,13 @@ class Revision { if ( $id ) { // Use the specified ID $conds['rev_id'] = $id; - } elseif ( wfGetLB()->getServerCount() > 1 ) { - // Get the latest revision ID from the master - $dbw = wfGetDB( DB_MASTER ); - $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ ); - if ( $latest === false ) { - return null; // page does not exist - } - $conds['rev_id'] = $latest; } else { // Use a join to get the latest revision $conds[] = 'rev_id=page_latest'; + // Callers assume this will be up-to-date + $flags = is_int( $flags ) ? $flags : self::READ_LATEST; // b/c } - return Revision::newFromConds( $conds ); + return self::newFromConds( $conds, (int)$flags ); } /** @@ -80,26 +105,26 @@ class Revision { * that's attached to a given page ID. * Returns null if no such revision can be found. * + * $flags include: + * Revision::READ_LATEST : Select the data from the master + * Revision::READ_LOCKING : Select & lock the data from the master + * * @param $revId Integer * @param $pageId Integer (optional) + * @param $flags Integer Bitfield (optional) * @return Revision or null */ - public static function newFromPageId( $pageId, $revId = 0 ) { + public static function newFromPageId( $pageId, $revId = 0, $flags = null ) { $conds = array( 'page_id' => $pageId ); if ( $revId ) { $conds['rev_id'] = $revId; - } elseif ( wfGetLB()->getServerCount() > 1 ) { - // Get the latest revision ID from the master - $dbw = wfGetDB( DB_MASTER ); - $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ ); - if ( $latest === false ) { - return null; // page does not exist - } - $conds['rev_id'] = $latest; } else { + // Use a join to get the latest revision $conds[] = 'rev_id = page_latest'; + // Callers assume this will be up-to-date + $flags = is_int( $flags ) ? $flags : self::READ_LATEST; // b/c } - return Revision::newFromConds( $conds ); + return self::newFromConds( $conds, (int)$flags ); } /** @@ -155,7 +180,7 @@ class Revision { * @return Revision or null */ public static function loadFromId( $db, $id ) { - return Revision::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) ); + return self::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) ); } /** @@ -175,7 +200,7 @@ class Revision { } else { $conds[] = 'rev_id=page_latest'; } - return Revision::loadFromConds( $db, $conds ); + return self::loadFromConds( $db, $conds ); } /** @@ -194,7 +219,7 @@ class Revision { } else { $matchId = 'page_latest'; } - return Revision::loadFromConds( $db, + return self::loadFromConds( $db, array( "rev_id=$matchId", 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey() ) @@ -212,7 +237,7 @@ class Revision { * @return Revision or null */ public static function loadFromTimestamp( $db, $title, $timestamp ) { - return Revision::loadFromConds( $db, + return self::loadFromConds( $db, array( 'rev_timestamp' => $db->timestamp( $timestamp ), 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey() ) @@ -223,14 +248,17 @@ class Revision { * Given a set of conditions, fetch a revision. * * @param $conditions Array + * @param $flags integer (optional) * @return Revision or null */ - public static function newFromConds( $conditions ) { - $db = wfGetDB( DB_SLAVE ); - $rev = Revision::loadFromConds( $db, $conditions ); - if( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) { - $dbw = wfGetDB( DB_MASTER ); - $rev = Revision::loadFromConds( $dbw, $conditions ); + private static function newFromConds( $conditions, $flags = 0 ) { + $db = wfGetDB( ( $flags & self::READ_LATEST ) ? DB_MASTER : DB_SLAVE ); + $rev = self::loadFromConds( $db, $conditions, $flags ); + if ( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) { + if ( !( $flags & self::READ_LATEST ) ) { + $dbw = wfGetDB( DB_MASTER ); + $rev = self::loadFromConds( $dbw, $conditions, $flags ); + } } return $rev; } @@ -241,10 +269,11 @@ class Revision { * * @param $db DatabaseBase * @param $conditions Array + * @param $flags integer (optional) * @return Revision or null */ - private static function loadFromConds( $db, $conditions ) { - $res = Revision::fetchFromConds( $db, $conditions ); + private static function loadFromConds( $db, $conditions, $flags = 0 ) { + $res = self::fetchFromConds( $db, $conditions, $flags ); if( $res ) { $row = $res->fetchObject(); if( $row ) { @@ -265,7 +294,7 @@ class Revision { * @return ResultWrapper */ public static function fetchRevision( $title ) { - return Revision::fetchFromConds( + return self::fetchFromConds( wfGetDB( DB_SLAVE ), array( 'rev_id=page_latest', 'page_namespace' => $title->getNamespace(), @@ -280,20 +309,25 @@ class Revision { * * @param $db DatabaseBase * @param $conditions Array + * @param $flags integer (optional) * @return ResultWrapper */ - private static function fetchFromConds( $db, $conditions ) { + private static function fetchFromConds( $db, $conditions, $flags = 0 ) { $fields = array_merge( self::selectFields(), self::selectPageFields(), self::selectUserFields() ); + $options = array( 'LIMIT' => 1 ); + if ( ( $flags & self::READ_LOCKING ) == self::READ_LOCKING ) { + $options[] = 'FOR UPDATE'; + } return $db->select( array( 'revision', 'page', 'user' ), $fields, $conditions, __METHOD__, - array( 'LIMIT' => 1 ), + $options, array( 'page' => self::pageJoinCond(), 'user' => self::userJoinCond() ) ); } @@ -321,6 +355,7 @@ class Revision { /** * Return the list of revision fields that should be selected to create * a new revision. + * @return array */ public static function selectFields() { return array( @@ -342,6 +377,7 @@ class Revision { /** * Return the list of text fields that should be selected to read the * revision text + * @return array */ public static function selectTextFields() { return array( @@ -352,23 +388,50 @@ class Revision { /** * Return the list of page fields that should be selected from page table + * @return array */ public static function selectPageFields() { return array( 'page_namespace', 'page_title', 'page_id', - 'page_latest' + 'page_latest', + 'page_is_redirect', + 'page_len', ); } /** * Return the list of user fields that should be selected from user table + * @return array */ public static function selectUserFields() { return array( 'user_name' ); } + /** + * Do a batched query to get the parent revision lengths + * @param $db DatabaseBase + * @param $revIds Array + * @return array + */ + public static function getParentLengths( $db, array $revIds ) { + $revLens = array(); + if ( !$revIds ) { + return $revLens; // empty + } + wfProfileIn( __METHOD__ ); + $res = $db->select( 'revision', + array( 'rev_id', 'rev_len' ), + array( 'rev_id' => $revIds ), + __METHOD__ ); + foreach ( $res as $row ) { + $revLens[$row->rev_id] = $row->rev_len; + } + wfProfileOut( __METHOD__ ); + return $revLens; + } + /** * Constructor * @@ -469,7 +532,7 @@ class Revision { /** * Get revision ID * - * @return Integer + * @return Integer|null */ public function getId() { return $this->mId; @@ -488,7 +551,7 @@ class Revision { /** * Get text row ID * - * @return Integer + * @return Integer|null */ public function getTextId() { return $this->mTextId; @@ -497,7 +560,7 @@ class Revision { /** * Get parent revision ID (the original previous page revision) * - * @return Integer + * @return Integer|null */ public function getParentId() { return $this->mParentId; @@ -506,7 +569,7 @@ class Revision { /** * Returns the length of the text in this revision, or null if unknown. * - * @return Integer + * @return Integer|null */ public function getSize() { return $this->mSize; @@ -515,30 +578,34 @@ class Revision { /** * Returns the base36 sha1 of the text in this revision, or null if unknown. * - * @return String + * @return String|null */ public function getSha1() { return $this->mSha1; } /** - * Returns the title of the page associated with this entry. + * Returns the title of the page associated with this entry or null. + * + * Will do a query, when title is not set and id is given. * - * @return Title + * @return Title|null */ public function getTitle() { if( isset( $this->mTitle ) ) { return $this->mTitle; } - $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( - array( 'page', 'revision' ), - self::selectPageFields(), - array( 'page_id=rev_page', - 'rev_id' => $this->mId ), - __METHOD__ ); - if ( $row ) { - $this->mTitle = Title::newFromRow( $row ); + if( !is_null( $this->mId ) ) { //rev_id is defined as NOT NULL + $dbr = wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow( + array( 'page', 'revision' ), + self::selectPageFields(), + array( 'page_id=rev_page', + 'rev_id' => $this->mId ), + __METHOD__ ); + if ( $row ) { + $this->mTitle = Title::newFromRow( $row ); + } } return $this->mTitle; } @@ -555,7 +622,7 @@ class Revision { /** * Get the page ID * - * @return Integer + * @return Integer|null */ public function getPage() { return $this->mPage; @@ -568,7 +635,7 @@ class Revision { * * @param $audience Integer: one of: * Revision::FOR_PUBLIC to be displayed to all users - * Revision::FOR_THIS_USER to be displayed to $wgUser + * Revision::FOR_THIS_USER to be displayed to the given user * Revision::RAW get the ID regardless of permissions * @param $user User object to check for, only if FOR_THIS_USER is passed * to the $audience parameter @@ -600,7 +667,7 @@ class Revision { * * @param $audience Integer: one of: * Revision::FOR_PUBLIC to be displayed to all users - * Revision::FOR_THIS_USER to be displayed to $wgUser + * Revision::FOR_THIS_USER to be displayed to the given user * Revision::RAW get the text regardless of permissions * @param $user User object to check for, only if FOR_THIS_USER is passed * to the $audience parameter @@ -640,7 +707,7 @@ class Revision { * * @param $audience Integer: one of: * Revision::FOR_PUBLIC to be displayed to all users - * Revision::FOR_THIS_USER to be displayed to $wgUser + * Revision::FOR_THIS_USER to be displayed to the given user * Revision::RAW get the text regardless of permissions * @param $user User object to check for, only if FOR_THIS_USER is passed * to the $audience parameter @@ -718,7 +785,7 @@ class Revision { * * @param $audience Integer: one of: * Revision::FOR_PUBLIC to be displayed to all users - * Revision::FOR_THIS_USER to be displayed to $wgUser + * Revision::FOR_THIS_USER to be displayed to the given user * Revision::RAW get the text regardless of permissions * @param $user User object to check for, only if FOR_THIS_USER is passed * to the $audience parameter @@ -781,7 +848,7 @@ class Revision { if( $this->getTitle() ) { $prev = $this->getTitle()->getPreviousRevisionID( $this->getId() ); if( $prev ) { - return Revision::newFromTitle( $this->getTitle(), $prev ); + return self::newFromTitle( $this->getTitle(), $prev ); } } return null; @@ -796,7 +863,7 @@ class Revision { if( $this->getTitle() ) { $next = $this->getTitle()->getNextRevisionID( $this->getId() ); if ( $next ) { - return Revision::newFromTitle( $this->getTitle(), $next ); + return self::newFromTitle( $this->getTitle(), $next ); } } return null; @@ -926,7 +993,7 @@ class Revision { $text = gzdeflate( $text ); $flags[] = 'gzip'; } else { - wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" ); + wfDebug( __METHOD__ . " -- no zlib support, not compressing\n" ); } } return implode( ',', $flags ); @@ -945,7 +1012,7 @@ class Revision { wfProfileIn( __METHOD__ ); $data = $this->mText; - $flags = Revision::compressRevisionText( $data ); + $flags = self::compressRevisionText( $data ); # Write to external storage if required if( $wgDefaultExternalStore ) { @@ -995,7 +1062,7 @@ class Revision { ? $this->getPreviousRevisionId( $dbw ) : $this->mParentId, 'rev_sha1' => is_null( $this->mSha1 ) - ? Revision::base36Sha1( $this->mText ) + ? self::base36Sha1( $this->mText ) : $this->mSha1 ), __METHOD__ ); @@ -1096,7 +1163,8 @@ class Revision { $current = $dbw->selectRow( array( 'page', 'revision' ), - array( 'page_latest', 'rev_text_id', 'rev_len', 'rev_sha1' ), + array( 'page_latest', 'page_namespace', 'page_title', + 'rev_text_id', 'rev_len', 'rev_sha1' ), array( 'page_id' => $pageId, 'page_latest=rev_id', @@ -1113,6 +1181,7 @@ class Revision { 'len' => $current->rev_len, 'sha1' => $current->rev_sha1 ) ); + $revision->setTitle( Title::makeTitle( $current->page_namespace, $current->page_title ) ); } else { $revision = null; } @@ -1181,7 +1250,7 @@ class Revision { $id = 0; } $conds = array( 'rev_id' => $id ); - $conds['rev_page'] = $title->getArticleId(); + $conds['rev_page'] = $title->getArticleID(); $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', $conds, __METHOD__ ); if ( $timestamp === false && wfGetLB()->getServerCount() > 1 ) { # Not in slave, try master @@ -1199,7 +1268,7 @@ class Revision { * @return Integer */ static function countByPageId( $db, $id ) { - $row = $db->selectRow( 'revision', 'COUNT(*) AS revCount', + $row = $db->selectRow( 'revision', array( 'revCount' => 'COUNT(*)' ), array( 'rev_page' => $id ), __METHOD__ ); if( $row ) { return $row->revCount; @@ -1215,10 +1284,48 @@ class Revision { * @return Integer */ static function countByTitle( $db, $title ) { - $id = $title->getArticleId(); + $id = $title->getArticleID(); if( $id ) { - return Revision::countByPageId( $db, $id ); + return self::countByPageId( $db, $id ); } 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; + } +} \ No newline at end of file -- cgit v1.2.2