Merge "Exclude redirects from Special:Fewestrevisions"
[lhc/web/wiklou.git] / includes / historyblob / ConcatenatedGzipHistoryBlob.php
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 /**
24 * Concatenated gzip (CGZ) storage
25 * Improves compression ratio by concatenating like objects before gzipping
26 */
27 class ConcatenatedGzipHistoryBlob implements HistoryBlob {
28 public $mVersion = 0, $mCompressed = false, $mItems = [], $mDefaultHash = '';
29 public $mSize = 0;
30 public $mMaxSize = 10000000;
31 public $mMaxCount = 100;
32
33 public function __construct() {
34 if ( !function_exists( 'gzdeflate' ) ) {
35 throw new MWException( "Need zlib support to read or write this "
36 . "kind of history object (ConcatenatedGzipHistoryBlob)\n" );
37 }
38 }
39
40 /**
41 * @param string $text
42 * @return string
43 */
44 public function addItem( $text ) {
45 $this->uncompress();
46 $hash = md5( $text );
47 if ( !isset( $this->mItems[$hash] ) ) {
48 $this->mItems[$hash] = $text;
49 $this->mSize += strlen( $text );
50 }
51 return $hash;
52 }
53
54 /**
55 * @param string $hash
56 * @return array|bool
57 */
58 public function getItem( $hash ) {
59 $this->uncompress();
60 if ( array_key_exists( $hash, $this->mItems ) ) {
61 return $this->mItems[$hash];
62 } else {
63 return false;
64 }
65 }
66
67 /**
68 * @param string $text
69 * @return void
70 */
71 public function setText( $text ) {
72 $this->uncompress();
73 $this->mDefaultHash = $this->addItem( $text );
74 }
75
76 /**
77 * @return array|bool
78 */
79 public function getText() {
80 $this->uncompress();
81 return $this->getItem( $this->mDefaultHash );
82 }
83
84 /**
85 * Remove an item
86 *
87 * @param string $hash
88 */
89 public function removeItem( $hash ) {
90 $this->mSize -= strlen( $this->mItems[$hash] );
91 unset( $this->mItems[$hash] );
92 }
93
94 /**
95 * Compress the bulk data in the object
96 */
97 public function compress() {
98 if ( !$this->mCompressed ) {
99 $this->mItems = gzdeflate( serialize( $this->mItems ) );
100 $this->mCompressed = true;
101 }
102 }
103
104 /**
105 * Uncompress bulk data
106 */
107 public function uncompress() {
108 if ( $this->mCompressed ) {
109 $this->mItems = unserialize( gzinflate( $this->mItems ) );
110 $this->mCompressed = false;
111 }
112 }
113
114 /**
115 * @return array
116 */
117 function __sleep() {
118 $this->compress();
119 return [ 'mVersion', 'mCompressed', 'mItems', 'mDefaultHash' ];
120 }
121
122 function __wakeup() {
123 $this->uncompress();
124 }
125
126 /**
127 * Helper function for compression jobs
128 * Returns true until the object is "full" and ready to be committed
129 *
130 * @return bool
131 */
132 public function isHappy() {
133 return $this->mSize < $this->mMaxSize
134 && count( $this->mItems ) < $this->mMaxCount;
135 }
136 }
137
138 // phpcs:ignore Generic.CodeAnalysis.UnconditionalIfStatement.Found
139 if ( false ) {
140 // Blobs generated by MediaWiki < 1.5 on PHP 4 were serialized with the
141 // class name coerced to lowercase. We can improve efficiency by adding
142 // autoload entries for the lowercase variants of these classes (T166759).
143 // The code below is never executed, but it is picked up by the AutoloadGenerator
144 // parser, which scans for class_alias() calls.
145 // @phan-suppress-next-line PhanRedefineClassAlias
146 class_alias( ConcatenatedGzipHistoryBlob::class, 'concatenatedgziphistoryblob' );
147 }