diff --git a/tests/view/ViewableDataTest.php b/tests/view/ViewableDataTest.php index e2cd3b67f..5c2451556 100644 --- a/tests/view/ViewableDataTest.php +++ b/tests/view/ViewableDataTest.php @@ -156,6 +156,25 @@ class ViewableDataTest extends SapphireTest { $this->assertEquals($uncastedData, $castedData->getValue(), 'Casted and uncasted strings are not equal.'); } + + public function testCaching() { + $objCached = new ViewableDataTest_Cached(); + $objNotCached = new ViewableDataTest_NotCached(); + + $objCached->Test = 'AAA'; + $objNotCached->Test = 'AAA'; + + $this->assertEquals('AAA', $objCached->obj('Test', null, true, true)); + $this->assertEquals('AAA', $objNotCached->obj('Test', null, true, true)); + + $objCached->Test = 'BBB'; + $objNotCached->Test = 'BBB'; + + // Cached data must be always the same + $this->assertEquals('AAA', $objCached->obj('Test', null, true, true)); + $this->assertEquals('BBB', $objNotCached->obj('Test', null, true, true)); + } + } /**#@+ @@ -253,4 +272,17 @@ class ViewableDataTest_NoCastingInformation extends ViewableData { } } +class ViewableDataTest_Cached extends ViewableData { + public $Test; +} + +class ViewableDataTest_NotCached extends ViewableData { + public $Test; + + protected function objCacheGet($key) { + // Disable caching + return null; + } +} + /**#@-*/ diff --git a/view/ViewableData.php b/view/ViewableData.php index 6d56dc7dc..70b29134f 100644 --- a/view/ViewableData.php +++ b/view/ViewableData.php @@ -345,6 +345,38 @@ class ViewableData extends Object implements IteratorAggregate { "ViewableData::renderWith(): unexpected $template->class object, expected an SSViewer instance" ); } + + /** + * Generate the cache name for a field + * + * @param string $fieldName Name of field + * @param array $arguments List of optional arguments given + */ + protected function objCacheName($fieldName, $arguments) { + return $arguments + ? $fieldName . ":" . implode(',', $arguments) + : $fieldName; + } + + /** + * Get a cached value from the field cache + * + * @param string $key Cache key + * @return mixed + */ + protected function objCacheGet($key) { + if(isset($this->objCache[$key])) return $this->objCache[$key]; + } + + /** + * Store a value in the field cache + * + * @param string $key Cache key + * @param mixed $value + */ + protected function objCacheSet($key, $value) { + $this->objCache[$key] = $value; + } /** * Get the value of a field on this object, automatically inserting the value into any available casting objects @@ -354,12 +386,14 @@ class ViewableData extends Object implements IteratorAggregate { * @param array $arguments * @param bool $forceReturnedObject if TRUE, the value will ALWAYS be casted to an object before being returned, * even if there is no explicit casting information + * @param bool $cache Cache this object * @param string $cacheName a custom cache name */ public function obj($fieldName, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) { - if(!$cacheName) $cacheName = $arguments ? $fieldName . implode(',', $arguments) : $fieldName; - - if(!isset($this->objCache[$cacheName])) { + if(!$cacheName && $cache) $cacheName = $this->objCacheName($fieldName, $arguments); + + $value = $cache ? $this->objCacheGet($cacheName) : null; + if(!isset($value)) { // HACK: Don't call the deprecated FormField::Name() method $methodIsAllowed = true; if($this instanceof FormField && $fieldName == 'Name') $methodIsAllowed = false; @@ -381,9 +415,7 @@ class ViewableData extends Object implements IteratorAggregate { $value = $valueObject; } - if($cache) $this->objCache[$cacheName] = $value; - } else { - $value = $this->objCache[$cacheName]; + if($cache) $this->objCacheSet($cacheName, $value); } if(!is_object($value) && $forceReturnedObject) {