From 7d8cfdca21cfc957747aef1bdedbe4d467379f4b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Mar 2005 04:32:55 +0000 Subject: [PATCH] Lazy loading of revision text; needed for separate text storage backend. Use Revision for Article::loadLastEdit --- includes/Article.php | 22 +++----- includes/Group.php | 39 +++++++++++-- includes/Revision.php | 112 +++++++++++++++++++++++++++++-------- includes/SpecialExport.php | 2 +- 4 files changed, 133 insertions(+), 42 deletions(-) diff --git a/includes/Article.php b/includes/Article.php index e68a8893c3..7dd7584b71 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -501,7 +501,7 @@ class Article { */ function loadLastEdit() { global $wgOut; - + if ( -1 != $this->mUser ) return; @@ -509,19 +509,13 @@ class Article { $id = $this->getID(); if ( 0 == $id ) return; - $fname = 'Article::loadLastEdit'; - - $dbr =& $this->getDB(); - $s = $dbr->selectRow( array( 'revision', 'page') , - array( 'rev_user','rev_user_text','rev_timestamp', 'rev_comment','rev_minor_edit' ), - array( 'page_id' => $id, 'page_latest=rev_id' ), $fname, $this->getSelectOptions() ); - - if ( $s !== false ) { - $this->mUser = $s->rev_user; - $this->mUserText = $s->rev_user_text; - $this->mTimestamp = wfTimestamp(TS_MW,$s->rev_timestamp); - $this->mComment = $s->rev_comment; - $this->mMinorEdit = $s->rev_minor_edit; + $this->mLastRevision = Revision::loadFromPageId( $this->getDB(), $id ); + if( !is_null( $this->mLastRevision ) ) { + $this->mUser = $this->mLastRevision->getUser(); + $this->mUserText = $this->mLastRevision->getUserText(); + $this->mTimestamp = $this->mLastRevision->getTimestamp(); + $this->mComment = $this->mLastRevision->getComment(); + $this->mMinorEdit = $this->mLastRevision->isMinor(); } } diff --git a/includes/Group.php b/includes/Group.php index 1502eabb92..88b5166628 100644 --- a/includes/Group.php +++ b/includes/Group.php @@ -50,7 +50,10 @@ class Group { if($this->id) { $dbr =& wfGetDB( DB_SLAVE ); - $r = $dbr->selectRow('group', array('group_id', 'group_name', 'group_description', 'group_rights'), array( 'group_id' => $this->id ), $fname ); + $r = $dbr->selectRow('group', + array('group_id', 'group_name', 'group_description', 'group_rights'), + array( 'group_id' => $this->id ), + $fname ); $this->id = $r->group_id; $this->name = $r->group_name; $this->description = $r->group_description; @@ -58,7 +61,10 @@ class Group { $this->dataLoaded = true; } else { $dbr =& wfGetDB( DB_SLAVE ); - $r = $dbr->selectRow('group', array('group_id', 'group_name', 'group_description', 'group_rights'), array( 'group_name' => $this->name ), $fname ); + $r = $dbr->selectRow('group', + array('group_id', 'group_name', 'group_description', 'group_rights'), + array( 'group_name' => $this->name ), + $fname ); $this->id = $r->group_id; $this->name = $r->group_name; $this->description = $r->group_description; @@ -100,14 +106,37 @@ class Group { } // Factories - /** @param integer $id Group database id */ + /** + * Uses Memcached if available. + * @param integer $id Group database id + */ function newFromId($id) { + global $wgMemc, $wgDBname; $fname = 'Group::newFromId'; + + $key = "$wgDBname:groups:id:$id"; + if( $group = $wgMemc->get( $key ) ) { + wfDebug( "$fname loaded group $id from cache\n" ); + return $group; + } + $g = new Group(); $name = $g->nameFromId(IntVal($id)); - if($name == '') { return; } - else { return $g->newFromName($name); } + if($name == '') { + wfDebug( "$fname can't find group $id\n" ); + return null; + } else { + $group = $g->newFromName($name); + if( $group ) { + wfDebug( "$fname caching group $id (name $name)\n" ); + $group->loadFromDatabase(); + $wgMemc->add( $key, $group, 3600 ); + } else { + wfDebug( "$fname failed to laod group id $d (name $name)\n" ); + } + return $group; + } } diff --git a/includes/Revision.php b/includes/Revision.php index 6b099ff054..fc9e8d3b74 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -24,8 +24,7 @@ class Revision { function &newFromId( $id ) { return Revision::newFromConds( array( 'page_id=rev_page', - 'rev_id' => IntVal( $id ), - 'rev_id=old_id' ) ); + 'rev_id' => IntVal( $id ) ) ); } /** @@ -48,8 +47,31 @@ class Revision { array( "rev_id=$matchId", 'page_id=rev_page', 'page_namespace' => $title->getNamespace(), - 'page_title' => $title->getDbkey(), - 'rev_id=old_id' ) ); + 'page_title' => $title->getDbkey() ) ); + } + + /** + * Load either the current, or a specified, revision + * that's attached to a given page. If not attached + * to that page, will return null. + * + * @param Database $db + * @param int $pageid + * @param int $id + * @return Revision + * @access public + */ + function &loadFromPageId( &$db, $pageid, $id = 0 ) { + if( $id ) { + $matchId = IntVal( $id ); + } else { + $matchId = 'page_latest'; + } + return Revision::loadFromConds( + $db, + array( "rev_id=$matchId", + 'rev_page' => IntVal( $pageid ), + 'page_id=rev_page' ) ); } /** @@ -61,7 +83,22 @@ class Revision { * @access private */ function &newFromConds( $conditions ) { - $res =& Revision::fetchFromConds( $conditions ); + $db =& wfGetDB( DB_SLAVE ); + return Revision::loadFromConds( $db, $conditions ); + } + + /** + * Given a set of conditions, fetch a revision from + * the given database connection. + * + * @param Database $db + * @param array $conditions + * @return Revision + * @static + * @access private + */ + function &loadFromConds( &$db, $conditions ) { + $res =& Revision::fetchFromConds( $db, $conditions ); if( $res ) { $row = $res->fetchObject(); $res->free(); @@ -84,10 +121,10 @@ class Revision { */ function &fetchAllRevisions( &$title ) { return Revision::fetchFromConds( + wfGetDB( DB_SLAVE ), array( 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDbkey(), - 'page_id=rev_page', - 'rev_id=old_id' ) ); + 'page_id=rev_page' ) ); } /** @@ -102,26 +139,27 @@ class Revision { */ function &fetchRevision( &$title ) { return Revision::fetchFromConds( + wfGetDB( DB_SLAVE ), array( 'rev_id=page_latest', 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDbkey(), - 'page_id=rev_page', - 'rev_id=old_id' ) ); + 'page_id=rev_page' ) ); } - /** + + /** * Given a set of conditions, return a ResultWrapper * which will return matching database rows with the * fields necessary to build Revision objects. * + * @param Database $db * @param array $conditions * @return ResultWrapper * @static * @access private */ - function &fetchFromConds( $conditions ) { - $dbr =& wfGetDB( DB_SLAVE ); - $res = $dbr->select( - array( 'page', 'revision', 'text' ), + function &fetchFromConds( &$db, $conditions ) { + $res = $db->select( + array( 'page', 'revision' ), array( 'page_namespace', 'page_title', 'page_latest', @@ -131,12 +169,10 @@ class Revision { 'rev_user_text', 'rev_user', 'rev_minor_edit', - 'rev_timestamp', - 'old_flags', - 'old_text' ), + 'rev_timestamp' ), $conditions, 'Revision::fetchRow' ); - return $dbr->resultObject( $res ); + return $db->resultObject( $res ); } /** @@ -156,7 +192,12 @@ class Revision { $this->mCurrent = ( $row->rev_id == $row->page_latest ); $this->mTitle = Title::makeTitle( $row->page_namespace, $row->page_title ); - $this->mText = $this->getRevisionText( $row ); + + if( isset( $row->old_text ) ) { + $this->mText = $this->getRevisionText( $row ); + } else { + $this->mText = null; + } } elseif( is_array( $row ) ) { // Build a new revision to be saved... global $wgUser; @@ -168,7 +209,7 @@ class Revision { $this->mUser = isset( $row['user'] ) ? IntVal( $row['user'] ) : $wgUser->getId(); $this->mMinorEdit = isset( $row['minor_edit'] ) ? IntVal( $row['minor_edit'] ) : 0; $this->mTimestamp = isset( $row['timestamp'] ) ? StrVal( $row['timestamp'] ) : wfTimestamp( TS_MW ); - $this->mText = isset( $row['text'] ) ? StrVal( $row['text'] ) : ''; + $this->mText = isset( $row['text'] ) ? StrVal( $row['text'] ) : null; $this->mTitle = null; # Load on demand if needed $this->mCurrent = false; @@ -249,6 +290,10 @@ class Revision { * @return string */ function getText() { + if( is_null( $this->mText ) ) { + // Revision text is immutable. Load on demand: + $this->mText = $this->loadText(); + } return $this->mText; } @@ -393,8 +438,8 @@ class Revision { : $dbw->nextSequenceValue( 'text_old_id_val' ); $dbw->insert( 'text', array( - 'old_id' => $old_id, - 'old_text' => $mungedText, + 'old_id' => $old_id, + 'old_text' => $mungedText, 'old_flags' => $flags, ), $fname ); @@ -418,5 +463,28 @@ class Revision { wfProfileOut( $fname ); return $revisionId; } + + /** + * Lazy-load the revision's text. + * Currently hardcoded to the 'text' table storage engine. + * + * @return string + * @access private + */ + function loadText() { + $fname = 'Revision::loadText'; + wfProfileIn( $fname ); + + $dbr =& wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow( 'text', + array( 'old_text', 'old_flags' ), + array( 'old_id' => $this->getId() ), + $fname); + + $text = Revision::getRevisionText( $row ); + wfProfileOut( $fname ); + + return $text; + } } ?> \ No newline at end of file diff --git a/includes/SpecialExport.php b/includes/SpecialExport.php index 2dd079fe58..1101e4f9ad 100644 --- a/includes/SpecialExport.php +++ b/includes/SpecialExport.php @@ -50,7 +50,7 @@ function wfSpecialExport( $page = '' ) { $wgOut->addWikiText( wfMsg( "exporttext" ) ); $titleObj = Title::makeTitle( NS_SPECIAL, "Export" ); - $action = $titleObj->escapeLocalURL(); + $action = $titleObj->escapeLocalURL( 'action=submit' ); $wgOut->addHTML( "
-- 2.20.1