if ( $id ) {
// Use the specified ID
$conds['rev_id'] = $id;
- // This uses slave->master fallback with READ_NORMAL. Assuming revdelete,
- // moves, and merges are rare, callers can use this to reduce master queries.
return self::newFromConds( $conds, $flags );
} else {
// Use a join to get the latest revision
$conds = array( 'page_id' => $pageId );
if ( $revId ) {
$conds['rev_id'] = $revId;
- // This uses slave->master fallback with READ_NORMAL. Assuming revdelete
- // and merges are rare, callers can use this to reduce master queries.
return self::newFromConds( $conds, $flags );
} else {
// Use a join to get the latest revision
if ( !isset( $attribs['title'] )
&& isset( $row->ar_namespace )
- && isset( $row->ar_title ) ) {
-
+ && isset( $row->ar_title )
+ ) {
$attribs['title'] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
}
}
/**
- * Given a set of conditions, fetch a revision.
+ * Given a set of conditions, fetch a revision
+ *
+ * This method is used then a revision ID is qualified and
+ * will incorporate some basic slave/master fallback logic
*
* @param array $conditions
* @param int $flags (optional)
*/
private static function newFromConds( $conditions, $flags = 0 ) {
$db = wfGetDB( ( $flags & self::READ_LATEST ) ? DB_MASTER : DB_SLAVE );
+
$rev = self::loadFromConds( $db, $conditions, $flags );
- if ( $rev === null && wfGetLB()->getServerCount() > 1 ) {
- if ( !( $flags & self::READ_LATEST ) ) {
- $dbw = wfGetDB( DB_MASTER );
- $rev = self::loadFromConds( $dbw, $conditions, $flags );
- }
+ // Make sure new pending/committed revision are visibile later on
+ // within web requests to certain avoid bugs like T93866 and T94407.
+ if ( !$rev
+ && !( $flags & self::READ_LATEST )
+ && wfGetLB()->getServerCount() > 1
+ && wfGetLB()->hasOrMadeRecentMasterChanges()
+ ) {
+ $flags = self::READ_LATEST;
+ $db = wfGetDB( DB_MASTER );
+ $rev = self::loadFromConds( $db, $conditions, $flags );
}
+
if ( $rev ) {
$rev->mQueryFlags = $flags;
}
+
return $rev;
}
/**
* Returns the content model for this revision.
*
- * If no content model was stored in the database, $this->getTitle()->getContentModel() is
+ * If no content model was stored in the database, the default content model for the title is
* used to determine the content model to use. If no title is know, CONTENT_MODEL_WIKITEXT
* is used as a last resort.
*
public function getContentModel() {
if ( !$this->mContentModel ) {
$title = $this->getTitle();
- $this->mContentModel = ( $title ? $title->getContentModel() : CONTENT_MODEL_WIKITEXT );
+ if ( $title ) {
+ $this->mContentModel = ContentHandler::getDefaultModelFor( $title );
+ } else {
+ $this->mContentModel = CONTENT_MODEL_WIKITEXT;
+ }
assert( !empty( $this->mContentModel ) );
}
if ( $wgCompressRevisions ) {
if ( function_exists( 'gzdeflate' ) ) {
- $text = gzdeflate( $text );
- $flags[] = 'gzip';
+ $deflated = gzdeflate( $text );
+
+ if ( $deflated === false ) {
+ wfLogWarning( __METHOD__ . ': gzdeflate() failed' );
+ } else {
+ $text = $deflated;
+ $flags[] = 'gzip';
+ }
} else {
wfDebug( __METHOD__ . " -- no zlib support, not compressing\n" );
}
# This can be done periodically via maintenance/compressOld.php, and
# as pages are saved if $wgCompressRevisions is set.
$text = gzinflate( $text );
+
+ if ( $text === false ) {
+ wfLogWarning( __METHOD__ . ': gzinflate() failed' );
+ return false;
+ }
}
if ( in_array( 'object', $flags ) ) {
$this->mId = $rev_id !== null ? $rev_id : $dbw->insertId();
+ // Assertion to try to catch T92046
+ if ( (int)$this->mId === 0 ) {
+ throw new UnexpectedValueException(
+ 'After insert, Revision mId is ' . var_export( $this->mId, 1 ) . ': ' .
+ var_export( $row, 1 )
+ );
+ }
+
Hooks::run( 'RevisionInsertComplete', array( &$this, $data, $flags ) );
return $this->mId;
* @return string|bool The revision's text, or false on failure
*/
protected function loadText() {
-
// Caching may be beneficial for massive use of external storage
global $wgRevisionCacheExpiry, $wgMemc;
+
$textId = $this->getTextId();
$key = wfMemcKey( 'revisiontext', 'textid', $textId );
if ( $wgRevisionCacheExpiry ) {
* @return Revision|null Revision or null on error
*/
public static function newNullRevision( $dbw, $pageId, $summary, $minor, $user = null ) {
- global $wgContentHandlerUseDB;
+ global $wgContentHandlerUseDB, $wgContLang;
$fields = array( 'page_latest', 'page_namespace', 'page_title',
'rev_text_id', 'rev_len', 'rev_sha1' );
$user = $wgUser;
}
+ // Truncate for whole multibyte characters
+ $summary = $wgContLang->truncate( $summary, 255 );
+
$row = array(
'page' => $pageId,
'user_text' => $user->getName(),
$row['content_format'] = $current->rev_content_format;
}
+ $row['title'] = Title::makeTitle( $current->page_namespace, $current->page_title );
+
$revision = new Revision( $row );
- $revision->setTitle( Title::makeTitle( $current->page_namespace, $current->page_title ) );
} else {
$revision = null;
}
*
* @param Title $title
* @param int $id
- * @return string
+ * @return string|bool False if not found
*/
- static function getTimestampFromId( $title, $id ) {
- $dbr = wfGetDB( DB_SLAVE );
+ static function getTimestampFromId( $title, $id, $flags = 0 ) {
+ $db = ( $flags & self::READ_LATEST )
+ ? wfGetDB( DB_MASTER )
+ : wfGetDB( DB_SLAVE );
// Casting fix for databases that can't take '' for rev_id
if ( $id == '' ) {
$id = 0;
}
$conds = array( 'rev_id' => $id );
$conds['rev_page'] = $title->getArticleID();
- $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', $conds, __METHOD__ );
- if ( $timestamp === false && wfGetLB()->getServerCount() > 1 ) {
- # Not in slave, try master
- $dbw = wfGetDB( DB_MASTER );
- $timestamp = $dbw->selectField( 'revision', 'rev_timestamp', $conds, __METHOD__ );
- }
- return wfTimestamp( TS_MW, $timestamp );
+ $timestamp = $db->selectField( 'revision', 'rev_timestamp', $conds, __METHOD__ );
+
+ return ( $timestamp !== false ) ? wfTimestamp( TS_MW, $timestamp ) : false;
}
/**