mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Merge pull request #8451 from creative-commoners/pulls/4.3/memory-cache-findtemplate
NEW Add memory cache to ThemeResourceLoader::findTemplate()
This commit is contained in:
commit
36b1066413
@ -32,3 +32,7 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
namespace: "InheritedPermissions"
|
namespace: "InheritedPermissions"
|
||||||
args:
|
args:
|
||||||
disable-container: true
|
disable-container: true
|
||||||
|
Psr\SimpleCache\CacheInterface.ThemeResourceLoader:
|
||||||
|
factory: SilverStripe\Core\Cache\CacheFactory
|
||||||
|
constructor:
|
||||||
|
namespace: 'ThemeResourceLoader'
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
namespace SilverStripe\View;
|
namespace SilverStripe\View;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use Psr\SimpleCache\CacheInterface;
|
||||||
|
use SilverStripe\Core\Flushable;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
use SilverStripe\Core\Path;
|
use SilverStripe\Core\Path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles finding templates from a stack of template manifest objects.
|
* Handles finding templates from a stack of template manifest objects.
|
||||||
*/
|
*/
|
||||||
class ThemeResourceLoader
|
class ThemeResourceLoader implements Flushable
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,6 +20,13 @@ class ThemeResourceLoader
|
|||||||
*/
|
*/
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal memory cache for large sets of repeated calls
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $cacheData = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base path of the application
|
* The base path of the application
|
||||||
*
|
*
|
||||||
@ -32,6 +42,11 @@ class ThemeResourceLoader
|
|||||||
*/
|
*/
|
||||||
protected $sets = [];
|
protected $sets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CacheInterface
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ThemeResourceLoader
|
* @return ThemeResourceLoader
|
||||||
*/
|
*/
|
||||||
@ -161,6 +176,8 @@ class ThemeResourceLoader
|
|||||||
* format "type/name", where type is the type of template to search for
|
* format "type/name", where type is the type of template to search for
|
||||||
* (e.g. Includes, Layout).
|
* (e.g. Includes, Layout).
|
||||||
*
|
*
|
||||||
|
* The results of this method will be cached for future use.
|
||||||
|
*
|
||||||
* @param string|array $template Template name, or template spec in array format with the keys
|
* @param string|array $template Template name, or template spec in array format with the keys
|
||||||
* 'type' (type string) and 'templates' (template hierarchy in order of precedence).
|
* 'type' (type string) and 'templates' (template hierarchy in order of precedence).
|
||||||
* If 'templates' is ommitted then any other item in the array will be treated as the template
|
* If 'templates' is ommitted then any other item in the array will be treated as the template
|
||||||
@ -178,6 +195,12 @@ class ThemeResourceLoader
|
|||||||
$themes = SSViewer::get_themes();
|
$themes = SSViewer::get_themes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look for a cached result for this data set
|
||||||
|
$cacheKey = md5(json_encode($template) . json_encode($themes));
|
||||||
|
if ($this->getCache()->has($cacheKey)) {
|
||||||
|
return $this->getCache()->get($cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
$type = '';
|
$type = '';
|
||||||
if (is_array($template)) {
|
if (is_array($template)) {
|
||||||
// Check if templates has type specified
|
// Check if templates has type specified
|
||||||
@ -196,6 +219,7 @@ class ThemeResourceLoader
|
|||||||
if (is_array($template)) {
|
if (is_array($template)) {
|
||||||
$path = $this->findTemplate($template, $themes);
|
$path = $this->findTemplate($template, $themes);
|
||||||
if ($path) {
|
if ($path) {
|
||||||
|
$this->getCache()->set($cacheKey, $path);
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -205,6 +229,7 @@ class ThemeResourceLoader
|
|||||||
// pass in templates without extensions in order for template manifest to find
|
// pass in templates without extensions in order for template manifest to find
|
||||||
// files dynamically.
|
// files dynamically.
|
||||||
if (substr($template, -3) == '.ss' && file_exists($template)) {
|
if (substr($template, -3) == '.ss' && file_exists($template)) {
|
||||||
|
$this->getCache()->set($cacheKey, $template);
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +245,14 @@ class ThemeResourceLoader
|
|||||||
$pathParts = [ $this->base, $themePath, 'templates', $head, $type, $tail ];
|
$pathParts = [ $this->base, $themePath, 'templates', $head, $type, $tail ];
|
||||||
$path = Path::join($pathParts) . '.ss';
|
$path = Path::join($pathParts) . '.ss';
|
||||||
if (file_exists($path)) {
|
if (file_exists($path)) {
|
||||||
|
$this->getCache()->set($cacheKey, $path);
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No template found
|
// No template found
|
||||||
|
$this->getCache()->set($cacheKey, null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,4 +364,33 @@ class ThemeResourceLoader
|
|||||||
}
|
}
|
||||||
return $paths;
|
return $paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush any cached data
|
||||||
|
*/
|
||||||
|
public static function flush()
|
||||||
|
{
|
||||||
|
self::inst()->getCache()->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return CacheInterface
|
||||||
|
*/
|
||||||
|
public function getCache()
|
||||||
|
{
|
||||||
|
if (!$this->cache) {
|
||||||
|
$this->setCache(Injector::inst()->get(CacheInterface::class . '.ThemeResourceLoader'));
|
||||||
|
}
|
||||||
|
return $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CacheInterface $cache
|
||||||
|
* @return ThemeResourceLoader
|
||||||
|
*/
|
||||||
|
public function setCache(CacheInterface $cache)
|
||||||
|
{
|
||||||
|
$this->cache = $cache;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Core\Tests\Manifest;
|
namespace SilverStripe\Core\Tests\Manifest;
|
||||||
|
|
||||||
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
use SilverStripe\View\ThemeResourceLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
@ -54,6 +55,9 @@ class ThemeResourceLoaderTest extends SapphireTest
|
|||||||
// New Loader for that root
|
// New Loader for that root
|
||||||
$this->loader = new ThemeResourceLoader($this->base);
|
$this->loader = new ThemeResourceLoader($this->base);
|
||||||
$this->loader->addSet('$default', $this->manifest);
|
$this->loader->addSet('$default', $this->manifest);
|
||||||
|
|
||||||
|
// Ensure the cache is flushed between tests
|
||||||
|
ThemeResourceLoader::flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown()
|
protected function tearDown()
|
||||||
@ -377,4 +381,28 @@ class ThemeResourceLoaderTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$this->assertEquals($path, $this->loader->getPath($name));
|
$this->assertEquals($path, $this->loader->getPath($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFindTemplateWithCacheMiss()
|
||||||
|
{
|
||||||
|
$mockCache = $this->createMock(CacheInterface::class);
|
||||||
|
$mockCache->expects($this->once())->method('has')->willReturn(false);
|
||||||
|
$mockCache->expects($this->never())->method('get');
|
||||||
|
$mockCache->expects($this->once())->method('set');
|
||||||
|
|
||||||
|
$loader = new ThemeResourceLoader();
|
||||||
|
$loader->setCache($mockCache);
|
||||||
|
$loader->findTemplate('Page', ['$default']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindTemplateWithCacheHit()
|
||||||
|
{
|
||||||
|
$mockCache = $this->createMock(CacheInterface::class);
|
||||||
|
$mockCache->expects($this->once())->method('has')->willReturn(true);
|
||||||
|
$mockCache->expects($this->never())->method('set');
|
||||||
|
$mockCache->expects($this->once())->method('get')->willReturn('mock_template.ss');
|
||||||
|
|
||||||
|
$loader = new ThemeResourceLoader();
|
||||||
|
$loader->setCache($mockCache);
|
||||||
|
$this->assertSame('mock_template.ss', $loader->findTemplate('Page', ['$default']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user