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 * 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
23use 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 */
34class 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/*
163class_alias( HistoryBlobStub::class, 'historyblobstub' );
164*/