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