- return Wikimedia\base_convert( sha1( $text ), 16, 36, 31 );
- }
-
- /**
- * Get the text cache TTL
- *
- * @param WANObjectCache $cache
- * @return int
- */
- private static function getCacheTTL( WANObjectCache $cache ) {
- global $wgRevisionCacheExpiry;
-
- if ( $cache->getQoS( $cache::ATTR_EMULATION ) <= $cache::QOS_EMULATION_SQL ) {
- // Do not cache RDBMs blobs in...the RDBMs store
- $ttl = $cache::TTL_UNCACHEABLE;
- } else {
- $ttl = $wgRevisionCacheExpiry ?: $cache::TTL_UNCACHEABLE;
- }
-
- return $ttl;
- }
-
- /**
- * Lazy-load the revision's text.
- * Currently hardcoded to the 'text' table storage engine.
- *
- * @return string|bool The revision's text, or false on failure
- */
- private function loadText() {
- $cache = ObjectCache::getMainWANInstance();
-
- // No negative caching; negative hits on text rows may be due to corrupted replica DBs
- return $cache->getWithSetCallback(
- $cache->makeKey( 'revisiontext', 'textid', $this->getTextId() ),
- self::getCacheTTL( $cache ),
- function () {
- return $this->fetchText();
- },
- [ 'pcGroup' => self::TEXT_CACHE_GROUP, 'pcTTL' => $cache::TTL_PROC_LONG ]
- );
- }
-
- private function fetchText() {
- $textId = $this->getTextId();
-
- // If we kept data for lazy extraction, use it now...
- if ( $this->mTextRow !== null ) {
- $row = $this->mTextRow;
- $this->mTextRow = null;
- } else {
- $row = null;
- }
-
- // Callers doing updates will pass in READ_LATEST as usual. Since the text/blob tables
- // do not normally get rows changed around, set READ_LATEST_IMMUTABLE in those cases.
- $flags = $this->mQueryFlags;
- $flags |= DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST )
- ? self::READ_LATEST_IMMUTABLE
- : 0;
-
- list( $index, $options, $fallbackIndex, $fallbackOptions ) =
- DBAccessObjectUtils::getDBOptions( $flags );
-
- if ( !$row ) {
- // Text data is immutable; check replica DBs first.
- $row = wfGetDB( $index )->selectRow(
- 'text',
- [ 'old_text', 'old_flags' ],
- [ 'old_id' => $textId ],
- __METHOD__,
- $options
- );
- }
-
- // Fallback to DB_MASTER in some cases if the row was not found
- if ( !$row && $fallbackIndex !== null ) {
- // Use FOR UPDATE if it was used to fetch this revision. This avoids missing the row
- // due to REPEATABLE-READ. Also fallback to the master if READ_LATEST is provided.
- $row = wfGetDB( $fallbackIndex )->selectRow(
- 'text',
- [ 'old_text', 'old_flags' ],
- [ 'old_id' => $textId ],
- __METHOD__,
- $fallbackOptions
- );
- }
-
- if ( !$row ) {
- wfDebugLog( 'Revision', "No text row with ID '$textId' (revision {$this->getId()})." );
- }
-
- $text = self::getRevisionText( $row );
- if ( $row && $text === false ) {
- wfDebugLog( 'Revision', "No blob for text row '$textId' (revision {$this->getId()})." );
- }
-
- return is_string( $text ) ? $text : false;