Merge pull request #9749 from tersmitten/make-it-possible-to-filter-values-per-method-in-dbosourcecachemethod

Make it possible to filter values per method in DboSource::cacheMethod
This commit is contained in:
Mark Story 2016-11-14 10:08:00 -05:00 committed by GitHub
commit de3a249199
2 changed files with 148 additions and 0 deletions

View file

@ -786,10 +786,57 @@ class DboSource extends DataSource {
if ($value === null) { if ($value === null) {
return (isset(static::$methodCache[$method][$key])) ? static::$methodCache[$method][$key] : null; return (isset(static::$methodCache[$method][$key])) ? static::$methodCache[$method][$key] : null;
} }
if (!$this->cacheMethodFilter($method, $key, $value)) {
return $value;
}
$this->_methodCacheChange = true; $this->_methodCacheChange = true;
return static::$methodCache[$method][$key] = $value; return static::$methodCache[$method][$key] = $value;
} }
/**
* Filters to apply to the results of `name` and `fields`. When the filter for a given method does not return `true`
* then the result is not added to the memory cache.
*
* Some examples:
*
* ```
* // For method fields, do not cache values that contain floats
* if ($method === 'fields') {
* $hasFloat = preg_grep('/(\d+)?\.\d+/', $value);
*
* return count($hasFloat) === 0;
* }
*
* return true;
* ```
*
* ```
* // For method name, do not cache values that have the name created
* if ($method === 'name') {
* return preg_match('/^`created`$/', $value) !== 1;
* }
*
* return true;
* ```
*
* ```
* // For method name, do not cache values that have the key 472551d38e1f8bbc78d7dfd28106166f
* if ($key === '472551d38e1f8bbc78d7dfd28106166f') {
* return false;
* }
*
* return true;
* ```
*
* @param string $method Name of the method being cached.
* @param string $key The key name for the cache operation.
* @param mixed $value The value to cache into memory.
* @return bool Whether or not to cache
*/
public function cacheMethodFilter($method, $key, $value) {
return true;
}
/** /**
* Returns a quoted name of $data for use in an SQL statement. * Returns a quoted name of $data for use in an SQL statement.
* Strips fields out of SQL functions before quoting. * Strips fields out of SQL functions before quoting.

View file

@ -109,6 +109,35 @@ class DboSecondTestSource extends DboSource {
} }
/**
* DboFourthTestSource
*
* @package Cake.Test.Case.Model.Datasource
*/
class DboFourthTestSource extends DboSource {
public function connect($config = array()) {
$this->connected = true;
}
public function cacheMethodFilter($method, $key, $value) {
if ($method === 'name') {
if ($value === '`menus`') {
return false;
} elseif ($key === '1fca740733997f1ebbedacfc7678592a') {
return false;
}
} elseif ($method === 'fields') {
$endsWithName = preg_grep('/`name`$/', $value);
return count($endsWithName) === 0;
}
return true;
}
}
/** /**
* DboSourceTest class * DboSourceTest class
* *
@ -737,6 +766,78 @@ class DboSourceTest extends CakeTestCase {
$this->assertNull($result); $this->assertNull($result);
} }
/**
* Test that cacheMethodFilter does not filter by default.
*
* @return void
*/
public function testCacheMethodFilter() {
$method = 'name';
$key = '49d9207adfce6df1dd3ee8c30c434414';
$value = '`menus`';
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'fields';
$key = '2b57253ab1fffb3e95fa4f95299220b1';
$value = array("`Menu`.`id`", "`Menu`.`name`");
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'non-existing';
$key = '';
$value = '``';
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
}
/**
* Test that cacheMethodFilter can be overridden to do actual filtering.
*
* @return void
*/
public function testCacheMethodFilterOverridden() {
$testDb = new DboFourthTestSource();
$method = 'name';
$key = '49d9207adfce6df1dd3ee8c30c434414';
$value = '`menus`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'name';
$key = '1fca740733997f1ebbedacfc7678592a';
$value = '`Menu`.`id`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'fields';
$key = '2b57253ab1fffb3e95fa4f95299220b1';
$value = array("`Menu`.`id`", "`Menu`.`name`");
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'name';
$key = 'd2bc458620afb092c61ab4383b7475e0';
$value = '`Menu`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'non-existing';
$key = '';
$value = '``';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
}
/** /**
* Test that rare collisions do not happen with method caching * Test that rare collisions do not happen with method caching
* *