Completed
Branch master (e770d9)
by
unknown
33:41
created

APCBagOStuff::getUnserialize()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 1
dl 0
loc 8
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * Object caching using PHP's APC accelerator.
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
 * @ingroup Cache
22
 */
23
24
/**
25
 * This is a wrapper for APC's shared memory functions
26
 *
27
 * @ingroup Cache
28
 */
29
class APCBagOStuff extends BagOStuff {
30
31
	/**
32
	 * @var bool If true, trust the APC implementation to serialize and
33
	 * deserialize objects correctly. If false, (de-)serialize in PHP.
34
	 */
35
	protected $nativeSerialize;
36
37
	/**
38
	 * @var string String to append to each APC key. This may be changed
39
	 *  whenever the handling of values is changed, to prevent existing code
40
	 *  from encountering older values which it cannot handle.
41
	 */
42
	const KEY_SUFFIX = ':2';
43
44
	/**
45
	 * Constructor
46
	 *
47
	 * Available parameters are:
48
	 *   - nativeSerialize:     If true, pass objects to apc_store(), and trust it
49
	 *                          to serialize them correctly. If false, serialize
50
	 *                          all values in PHP.
51
	 *
52
	 * @param array $params
53
	 */
54
	public function __construct( array $params = [] ) {
55
		parent::__construct( $params );
56
57
		if ( isset( $params['nativeSerialize'] ) ) {
58
			$this->nativeSerialize = $params['nativeSerialize'];
59
		} elseif ( extension_loaded( 'apcu' ) && ini_get( 'apc.serializer' ) === 'default' ) {
60
			// APCu has a memory corruption bug when the serializer is set to 'default'.
61
			// See T120267, and upstream bug reports:
62
			//  - https://github.com/krakjoe/apcu/issues/38
63
			//  - https://github.com/krakjoe/apcu/issues/35
64
			//  - https://github.com/krakjoe/apcu/issues/111
65
			$this->logger->warning(
66
				'The APCu extension is loaded and the apc.serializer INI setting ' .
67
				'is set to "default". This can cause memory corruption! ' .
68
				'You should change apc.serializer to "php" instead. ' .
69
				'See <https://github.com/krakjoe/apcu/issues/38>.'
70
			);
71
			$this->nativeSerialize = false;
72
		} else {
73
			$this->nativeSerialize = true;
74
		}
75
	}
76
77
	protected function doGet( $key, $flags = 0 ) {
78
		return $this->getUnserialize(
79
			apc_fetch( $key . self::KEY_SUFFIX )
80
		);
81
	}
82
83
	protected function getUnserialize( $value ) {
84
		if ( is_string( $value ) && !$this->nativeSerialize ) {
85
			$value = $this->isInteger( $value )
86
				? intval( $value )
87
				: unserialize( $value );
88
		}
89
		return $value;
90
	}
91
92
	public function set( $key, $value, $exptime = 0, $flags = 0 ) {
93
		apc_store(
94
			$key . self::KEY_SUFFIX,
95
			$this->setSerialize( $value ),
96
			$exptime
97
		);
98
99
		return true;
100
	}
101
102
	protected function setSerialize( $value ) {
103
		if ( !$this->nativeSerialize && !$this->isInteger( $value ) ) {
104
			$value = serialize( $value );
105
		}
106
		return $value;
107
	}
108
109
	public function delete( $key ) {
110
		apc_delete( $key . self::KEY_SUFFIX );
111
112
		return true;
113
	}
114
115
	public function incr( $key, $value = 1 ) {
116
		return apc_inc( $key . self::KEY_SUFFIX, $value );
117
	}
118
119
	public function decr( $key, $value = 1 ) {
120
		return apc_dec( $key . self::KEY_SUFFIX, $value );
121
	}
122
}
123