Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
HistoryBlobStub
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 7
240
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLocation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLocation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setReferrer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getReferrer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getText
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
90
 getHash
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Efficient concatenated text storage.
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 */
8
9use MediaWiki\MediaWikiServices;
10
11/**
12 * Pointer object for an item within a CGZ blob stored in the text table.
13 *
14 * WARNING: Objects of this class are serialized and permanently stored in the DB.
15 * Do not change the name or visibility of any property!
16 *
17 * Note: the property visibility was changed in 2020 from public to protected.
18 * This may cause problems in future.
19 */
20class HistoryBlobStub {
21    /**
22     * @var array One-step cache variable to hold base blobs; operations that
23     * pull multiple revisions may often pull multiple times from the same
24     * blob. By keeping the last-used one open, we avoid redundant
25     * unserialization and decompression overhead.
26     */
27    protected static $blobCache = [];
28
29    /** @var int */
30    protected $mOldId;
31
32    /** @var string */
33    protected $mHash;
34
35    /** @var string */
36    protected $mRef;
37
38    /**
39     * @param string $hash The content hash of the text
40     * @param int $oldid The old_id for the CGZ object
41     */
42    public function __construct( $hash = '', $oldid = 0 ) {
43        $this->mHash = $hash;
44    }
45
46    /**
47     * Sets the location (old_id) of the main object to which this object
48     * points
49     * @param int $id
50     */
51    public function setLocation( $id ) {
52        $this->mOldId = $id;
53    }
54
55    /**
56     * Gets the location of the main object
57     * @return int
58     */
59    public function getLocation() {
60        return $this->mOldId;
61    }
62
63    /**
64     * Sets the location (old_id) of the referring object
65     * @param string $id
66     */
67    public function setReferrer( $id ) {
68        $this->mRef = $id;
69    }
70
71    /**
72     * Gets the location of the referring object
73     * @return string
74     */
75    public function getReferrer() {
76        return $this->mRef;
77    }
78
79    /**
80     * @return string|false
81     */
82    public function getText() {
83        if ( isset( self::$blobCache[$this->mOldId] ) ) {
84            $obj = self::$blobCache[$this->mOldId];
85        } else {
86            $dbr = MediaWikiServices::getInstance()->getConnectionProvider()->getReplicaDatabase();
87            $row = $dbr->newSelectQueryBuilder()
88                ->select( [ 'old_flags', 'old_text' ] )
89                ->from( 'text' )
90                ->where( [ 'old_id' => $this->mOldId ] )
91                ->caller( __METHOD__ )->fetchRow();
92
93            if ( !$row ) {
94                return false;
95            }
96
97            $flags = explode( ',', $row->old_flags );
98            if ( in_array( 'external', $flags ) ) {
99                $url = $row->old_text;
100                $parts = explode( '://', $url, 2 );
101                if ( !isset( $parts[1] ) || $parts[1] == '' ) {
102                    return false;
103                }
104                $row->old_text = MediaWikiServices::getInstance()
105                    ->getExternalStoreAccess()
106                    ->fetchFromURL( $url );
107            }
108
109            if ( !in_array( 'object', $flags ) ) {
110                return false;
111            }
112
113            if ( in_array( 'gzip', $flags ) ) {
114                // This shouldn't happen, but a bug in the compress script
115                // may at times gzip-compress a HistoryBlob object row.
116                $obj = HistoryBlobUtils::unserialize( gzinflate( $row->old_text ), true );
117            } else {
118                $obj = HistoryBlobUtils::unserialize( $row->old_text, true );
119            }
120
121            // Save this item for reference; if pulling many
122            // items in a row we'll likely use it again.
123            self::$blobCache = [ $this->mOldId => $obj ];
124        }
125
126        if ( method_exists( $obj, 'getItem' ) ) {
127            return $obj->getItem( $this->mHash );
128        }
129
130        return false;
131    }
132
133    /**
134     * Get the content hash
135     *
136     * @return string
137     */
138    public function getHash() {
139        return $this->mHash;
140    }
141}
142
143// Blobs generated by MediaWiki < 1.5 on PHP 4 were serialized with the
144// class name coerced to lowercase. We can improve efficiency by adding
145// autoload entries for the lowercase variants of these classes (T166759).
146// The code below is never executed, but it is picked up by the AutoloadGenerator
147// parser, which scans for class_alias() calls.
148/*
149class_alias( HistoryBlobStub::class, 'historyblobstub' );
150*/