Merge pull request #8780 from jrbasso/2.x-apcu-php7

2.x - Fix ApcEngine to work on PHP 7
This commit is contained in:
Mark Story 2016-05-08 08:25:28 -04:00
commit 2bcf787b74
3 changed files with 65 additions and 23 deletions

View file

@ -41,6 +41,8 @@ before_script:
- sh -c "if [ '$PHPCS' = '1' ]; then composer global require 'cakephp/cakephp-codesniffer:1.*'; fi" - sh -c "if [ '$PHPCS' = '1' ]; then composer global require 'cakephp/cakephp-codesniffer:1.*'; fi"
- sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/cakephp/cakephp-codesniffer; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/cakephp/cakephp-codesniffer; fi"
- echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]] ; then print "yes" | pecl install apcu-5.1.3; else print "yes" | pecl install apcu-4.0.11; fi
- echo -e "extension = apcu.so\napc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- phpenv rehash - phpenv rehash
- set +H - set +H
- echo "<?php - echo "<?php

View file

@ -31,6 +31,13 @@ class ApcEngine extends CacheEngine {
*/ */
protected $_compiledGroupNames = array(); protected $_compiledGroupNames = array();
/**
* APC or APCu extension
*
* @var string
*/
protected $_apcExtension = 'apc';
/** /**
* Initialize the Cache Engine * Initialize the Cache Engine
* *
@ -47,6 +54,10 @@ class ApcEngine extends CacheEngine {
} }
$settings += array('engine' => 'Apc'); $settings += array('engine' => 'Apc');
parent::init($settings); parent::init($settings);
if (function_exists('apcu_dec')) {
$this->_apcExtension = 'apcu';
return true;
}
return function_exists('apc_dec'); return function_exists('apc_dec');
} }
@ -63,8 +74,9 @@ class ApcEngine extends CacheEngine {
if ($duration) { if ($duration) {
$expires = time() + $duration; $expires = time() + $duration;
} }
apc_store($key . '_expires', $expires, $duration); $func = $this->_apcExtension . '_store';
return apc_store($key, $value, $duration); $func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
} }
/** /**
@ -75,11 +87,12 @@ class ApcEngine extends CacheEngine {
*/ */
public function read($key) { public function read($key) {
$time = time(); $time = time();
$cachetime = (int)apc_fetch($key . '_expires'); $func = $this->_apcExtension . '_fetch';
$cachetime = (int)$func($key . '_expires');
if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) { if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
return false; return false;
} }
return apc_fetch($key); return $func($key);
} }
/** /**
@ -90,7 +103,8 @@ class ApcEngine extends CacheEngine {
* @return New incremented value, false otherwise * @return New incremented value, false otherwise
*/ */
public function increment($key, $offset = 1) { public function increment($key, $offset = 1) {
return apc_inc($key, $offset); $func = $this->_apcExtension . '_inc';
return $func($key, $offset);
} }
/** /**
@ -101,7 +115,8 @@ class ApcEngine extends CacheEngine {
* @return New decremented value, false otherwise * @return New decremented value, false otherwise
*/ */
public function decrement($key, $offset = 1) { public function decrement($key, $offset = 1) {
return apc_dec($key, $offset); $func = $this->_apcExtension . '_dec';
return $func($key, $offset);
} }
/** /**
@ -111,7 +126,8 @@ class ApcEngine extends CacheEngine {
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/ */
public function delete($key) { public function delete($key) {
return apc_delete($key); $func = $this->_apcExtension . '_delete';
return $func($key);
} }
/** /**
@ -125,19 +141,20 @@ class ApcEngine extends CacheEngine {
if ($check) { if ($check) {
return true; return true;
} }
$func = $this->_apcExtension . '_delete';
if (class_exists('APCIterator', false)) { if (class_exists('APCIterator', false)) {
$iterator = new APCIterator( $iterator = new APCIterator(
'user', 'user',
'/^' . preg_quote($this->settings['prefix'], '/') . '/', '/^' . preg_quote($this->settings['prefix'], '/') . '/',
APC_ITER_NONE APC_ITER_NONE
); );
apc_delete($iterator); $func($iterator);
return true; return true;
} }
$cache = apc_cache_info('user'); $cache = $this->_apcExtension === 'apc' ? apc_cache_info('user') : apcu_cache_info();
foreach ($cache['cache_list'] as $key) { foreach ($cache['cache_list'] as $key) {
if (strpos($key['info'], $this->settings['prefix']) === 0) { if (strpos($key['info'], $this->settings['prefix']) === 0) {
apc_delete($key['info']); $func($key['info']);
} }
} }
return true; return true;
@ -157,11 +174,13 @@ class ApcEngine extends CacheEngine {
} }
} }
$groups = apc_fetch($this->_compiledGroupNames); $fetchFunc = $this->_apcExtension . '_fetch';
$storeFunc = $this->_apcExtension . '_store';
$groups = $fetchFunc($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) { if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) { foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) { if (!isset($groups[$group])) {
apc_store($group, 1); $storeFunc($group, 1);
$groups[$group] = 1; $groups[$group] = 1;
} }
} }
@ -184,7 +203,8 @@ class ApcEngine extends CacheEngine {
* @return bool success * @return bool success
*/ */
public function clearGroup($group) { public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success); $func = $this->_apcExtension . '_inc';
$func($this->settings['prefix'] . $group, 1, $success);
return $success; return $success;
} }
@ -203,7 +223,8 @@ class ApcEngine extends CacheEngine {
if ($duration) { if ($duration) {
$expires = time() + $duration; $expires = time() + $duration;
} }
apc_add($key . '_expires', $expires, $duration); $func = $this->_apcExtension . '_add';
return apc_add($key, $value, $duration); $func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
} }
} }

View file

@ -25,6 +25,13 @@ App::uses('Cache', 'Cache');
*/ */
class ApcEngineTest extends CakeTestCase { class ApcEngineTest extends CakeTestCase {
/**
* APC extension to be used
*
* @var string
*/
protected $_apcExtension = 'apc';
/** /**
* setUp method * setUp method
* *
@ -32,12 +39,17 @@ class ApcEngineTest extends CakeTestCase {
*/ */
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->skipIf(!function_exists('apc_store'), 'Apc is not installed or configured properly.'); $hasApc = extension_loaded('apc') || extension_loaded('apcu');
$this->skipIf(!$hasApc, 'Apc is not installed or configured properly.');
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
$this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.'); $this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.');
} }
if (extension_loaded('apcu')) {
$this->_apcExtension = 'apcu';
}
$this->_cacheDisable = Configure::read('Cache.disable'); $this->_cacheDisable = Configure::read('Cache.disable');
Configure::write('Cache.disable', false); Configure::write('Cache.disable', false);
Cache::config('apc', array('engine' => 'Apc', 'prefix' => 'cake_')); Cache::config('apc', array('engine' => 'Apc', 'prefix' => 'cake_'));
@ -147,7 +159,8 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDecrement() { public function testDecrement() {
$this->skipIf(!function_exists('apc_dec'), 'No apc_dec() function, cannot test decrement().'); $hasSupport = function_exists('apc_dec') || function_exists('apcu_dec');
$this->skipIf(!$hasSupport, 'No apc_dec()/apcu_dec() function, cannot test decrement().');
$result = Cache::write('test_decrement', 5, 'apc'); $result = Cache::write('test_decrement', 5, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
@ -171,7 +184,8 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testIncrement() { public function testIncrement() {
$this->skipIf(!function_exists('apc_inc'), 'No apc_inc() function, cannot test increment().'); $hasSupport = function_exists('apc_inc') || function_exists('apcu_inc');
$this->skipIf(!function_exists('apc_inc'), 'No apc_inc()/apcu_inc() function, cannot test increment().');
$result = Cache::write('test_increment', 5, 'apc'); $result = Cache::write('test_increment', 5, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
@ -195,14 +209,18 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testClear() { public function testClear() {
apc_store('not_cake', 'survive'); $storeFunc = $this->_apcExtension . '_store';
$fetchFunc = $this->_apcExtension . '_fetch';
$deleteFunc = $this->_apcExtension . '_delete';
$storeFunc('not_cake', 'survive');
Cache::write('some_value', 'value', 'apc'); Cache::write('some_value', 'value', 'apc');
$result = Cache::clear(false, 'apc'); $result = Cache::clear(false, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
$this->assertFalse(Cache::read('some_value', 'apc')); $this->assertFalse(Cache::read('some_value', 'apc'));
$this->assertEquals('survive', apc_fetch('not_cake')); $this->assertEquals('survive', $fetchFunc('not_cake'));
apc_delete('not_cake'); $deleteFunc('not_cake');
} }
/** /**
@ -213,6 +231,7 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testGroupsReadWrite() { public function testGroupsReadWrite() {
$incFunc = $this->_apcExtension . '_inc';
Cache::config('apc_groups', array( Cache::config('apc_groups', array(
'engine' => 'Apc', 'engine' => 'Apc',
'duration' => 0, 'duration' => 0,
@ -222,12 +241,12 @@ class ApcEngineTest extends CakeTestCase {
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_a'); $incFunc('test_group_a');
$this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_b'); $incFunc('test_group_b');
$this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'apc_groups'));