diff --git a/_config.php b/_config.php
index a05ee9abb..5547a6829 100644
--- a/_config.php
+++ b/_config.php
@@ -1,6 +1,6 @@
register('dbfile_link', array('DBFile', 'handle_shortcode'))
-// Zend_Cache temp directory setting
-$_ENV['TMPDIR'] = TEMP_FOLDER; // for *nix
-$_ENV['TMP'] = TEMP_FOLDER; // for Windows
-
-Cache::set_cache_lifetime('GDBackend_Manipulations', null, 100);
-
// If you don't want to see deprecation errors for the new APIs, change this to 3.2.0-dev.
Deprecation::notification_version('3.2.0');
diff --git a/_config/cache.yml b/_config/cache.yml
new file mode 100644
index 000000000..29ed1e044
--- /dev/null
+++ b/_config/cache.yml
@@ -0,0 +1,22 @@
+---
+Name: corecache
+---
+SilverStripe\Core\Injector\Injector:
+ SilverStripe\Core\Cache\CacheFactory:
+ class: 'SilverStripe\Core\Cache\DefaultCacheFactory'
+ constructor:
+ directory: `TEMP_FOLDER`
+ Psr\SimpleCache\CacheInterface.GDBackend_Manipulations:
+ factory: SilverStripe\Core\Cache\CacheFactory
+ constructor:
+ namespace: "GDBackend_Manipulations"
+ defaultLifetime: 100
+ Psr\SimpleCache\CacheInterface.cacheblock:
+ factory: SilverStripe\Core\Cache\CacheFactory
+ constructor:
+ namespace: "cacheblock"
+ defaultLifetime: 600
+ Psr\SimpleCache\CacheInterface.LeftAndMain_CMSVersion:
+ factory: SilverStripe\Core\Cache\CacheFactory
+ constructor:
+ namespace: "LeftAndMain_CMSVersion"
diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php
index 66baed982..ec4ea4a42 100644
--- a/admin/code/LeftAndMain.php
+++ b/admin/code/LeftAndMain.php
@@ -17,7 +17,7 @@ use SilverStripe\Control\Controller;
use SilverStripe\Control\PjaxResponseNegotiator;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Config\Config;
-use SilverStripe\Core\Cache;
+use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
@@ -2020,9 +2020,9 @@ class LeftAndMain extends Controller implements PermissionProvider
// Tries to obtain version number from composer.lock if it exists
$composerLockPath = BASE_PATH . '/composer.lock';
if (file_exists($composerLockPath)) {
- $cache = Cache::factory('LeftAndMain_CMSVersion');
- $cacheKey = filemtime($composerLockPath);
- $versions = $cache->load($cacheKey);
+ $cache = Injector::inst()->get(CacheInterface::class . '.LeftAndMain_CMSVersion');
+ $cacheKey = (string)filemtime($composerLockPath);
+ $versions = $cache->get($cacheKey);
if ($versions) {
$versions = json_decode($versions, true);
} else {
@@ -2038,7 +2038,7 @@ class LeftAndMain extends Controller implements PermissionProvider
$versions[$package->name] = $package->version;
}
}
- $cache->save(json_encode($versions), $cacheKey);
+ $cache->set($cacheKey, json_encode($versions));
}
}
}
diff --git a/composer.json b/composer.json
index 79160eb4b..ab7990283 100644
--- a/composer.json
+++ b/composer.json
@@ -23,6 +23,7 @@
"symfony/yaml": "~2.7",
"embed/embed": "^2.6",
"swiftmailer/swiftmailer": "~5.4",
+ "symfony/cache": "^3.3@dev",
"symfony/config": "^2.8",
"symfony/translation": "^2.8",
"vlucas/phpdotenv": "^2.4"
diff --git a/docs/en/02_Developer_Guides/01_Templates/07_Caching.md b/docs/en/02_Developer_Guides/01_Templates/07_Caching.md
index c0d2c51af..aae856118 100644
--- a/docs/en/02_Developer_Guides/01_Templates/07_Caching.md
+++ b/docs/en/02_Developer_Guides/01_Templates/07_Caching.md
@@ -30,8 +30,7 @@ When we render `$Counter` to the template we would expect the value to increase
## Partial caching
Partial caching is a feature that allows the caching of just a portion of a page. Instead of fetching the required data
-from the database to display, the contents of the area are fetched from the `TEMP_FOLDER` file-system pre-rendered and
-ready to go. More information about Partial caching is in the [Performance](../performance) guide.
+from the database to display, the contents of the area are fetched from a [cache backend](../performance/caching).
:::ss
<% cached 'MyCachedContent', LastEdited %>
diff --git a/docs/en/02_Developer_Guides/08_Performance/01_Caching.md b/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
index 98049ac41..596284e60 100644
--- a/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
+++ b/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
@@ -1,10 +1,10 @@
# Caching
-## Built-In Caches
+## Overview
The framework uses caches to store infrequently changing values.
-By default, the storage mechanism is simply the filesystem, although
-other cache backends can be configured. All caches use the [api:Cache] API.
+By default, the storage mechanism chooses the most performant adapter available
+(PHP7 opcache, APC, or filesystem). Other cache backends can be configured.
The most common caches are manifests of various resources:
@@ -21,136 +21,170 @@ executing the action is limited to the following cases when performed via a web
* A user is logged in with ADMIN permissions
* An error occurs during startup
-## The Cache API
+## Configuration
-The [api:Cache] class provides a bunch of static functions wrapping the Zend_Cache system
-in something a little more easy to use with the SilverStripe config system.
+We are using the [PSR-16](http://www.php-fig.org/psr/psr-16/) standard ("SimpleCache")
+for caching, through the [symfony/cache](https://symfony.com/doc/current/components/cache.html) library.
+Note that this library describes usage of [PSR-6](http://www.php-fig.org/psr/psr-6/) by default,
+but also exposes caches following the PSR-16 interface.
-A `Zend_Cache` has both a frontend (determines how to get the value to cache,
-and how to serialize it for storage) and a backend (handles the actual
-storage).
+Cache objects are configured via YAML
+and SilverStripe's [dependency injection](/developer-guides/extending/injector) system.
-Rather than require library code to specify the backend directly, cache
-consumers provide a name for the cache backend they want. The end developer
-can then specify which backend to use for each name in their project's
-configuration. They can also use 'all' to provide a backend for all named
-caches.
+ :::yml
+ SilverStripe\Core\Injector\Injector:
+ Psr\SimpleCache\CacheInterface.myCache:
+ factory: SilverStripe\Core\Cache\CacheFactory
+ constructor:
+ namespace: "myCache"
-End developers provide a set of named backends, then pick the specific
-backend for each named cache. There is a default File cache set up as the
-'default' named backend, which is assigned to 'all' named caches.
+Cache objects are instantiated through a [CacheFactory](SilverStripe\Core\Cache\CacheFactory),
+which determines which cache adapter is used (see "Adapters" below for details).
+This factory allows us you to globally define an adapter for all cache instances.
-## Using Caches
+ :::php
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
-Caches can be created and retrieved through the `Cache::factory()` method.
-The returned object is of type `Zend_Cache`.
+Caches are namespaced, which might allow granular clearing of a particular cache without affecting others.
+In our example, the namespace is "myCache", expressed in the service name as
+`Psr\SimpleCache\CacheInterface.myCache`. We recommend the `::class` short-hand to compose the full service name.
+
+Clearing caches by namespace is dependant on the used adapter: While the `FilesystemCache` adapter clears only the namespaced cache,
+a `MemcachedCache` adapter will clear all caches regardless of namespace, since the underlying memcached
+service doesn't support this. See "Invalidation" for alternative strategies.
+
+
+## Usage
+
+Cache objects follow the [PSR-16](http://www.php-fig.org/psr/psr-16/) class interface.
:::php
- // foo is any name (try to be specific), and is used to get configuration
- // & storage info
- $cache = Cache::factory('foo');
- if (!($result = $cache->load($cachekey))) {
- $result = caluate some how;
- $cache->save($result, $cachekey);
- }
- return $result;
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
-Normally there's no need to remove things from the cache - the cache
-backends clear out entries based on age and maximum allocated storage. If you
-include the version of the object in the cache key, even object changes
-don't need any invalidation. You can force disable the cache though,
-e.g. in development mode.
+ // create a new item by trying to get it from the cache
+ $myValue = $cache->get('myCacheKey');
+
+ // set a value and save it via the adapter
+ $cache->set('myCacheKey', 1234);
+
+ // retrieve the cache item
+ if (!$cache->has('myCacheKey')) {
+ // ... item does not exists in the cache
+ }
+
+## Invalidation
- :::php
- // Disables all caches
- Cache::set_cache_lifetime('any', -1, 100);
+Caches can be invalidated in different ways. The easiest is to actively clear the
+entire cache. If the adapter supports namespaced cache clearing,
+this will only affect a subset of cache keys ("myCache" in this example):
-You can also specifically clean a cache.
-Keep in mind that `Zend_Cache::CLEANING_MODE_ALL` deletes all cache
-entries across all caches, not just for the 'foo' cache in the example below.
+ :::php
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
+
+ // remove all items in this (namespaced) cache
+ $cache->clear();
+
+You can also delete a single item based on it's cache key:
- :::php
- $cache = Cache::factory('foo');
- $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
+ :::php
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
+
+ // remove the cache item
+ $cache->delete('myCacheKey');
-A single element can be invalidated through its cache key.
+Individual cache items can define a lifetime, after which the cached value is marked as expired:
- :::php
- $cache = Cache::factory('foo');
- $cache->remove($cachekey);
+ :::php
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
+
+ // remove the cache item
+ $cache->set('myCacheKey', 'myValue', 300); // cache for 300 seconds
+If a lifetime isn't defined on the `set()` call, it'll use the adapter default.
In order to increase the chance of your cache actually being hit,
-it often pays to increase the lifetime of caches ("TTL").
-It defaults to 10 minutes (600s) in SilverStripe, which can be
-quite short depending on how often your data changes.
-Keep in mind that data expiry should primarily be handled by your cache key,
-e.g. by including the `LastEdited` value when caching `DataObject` results.
+it often pays to increase the lifetime of caches.
+You can also set your lifetime to `0`, which means they won't expire.
+Since many adapters don't have a way to actively remove expired caches,
+you need to be careful with resources here (e.g. filesystem space).
- :::php
- // set all caches to 3 hours
- Cache::set_cache_lifetime('any', 60*60*3);
+ :::yml
+ SilverStripe\Core\Injector\Injector:
+ Psr\SimpleCache\CacheInterface.cacheblock:
+ constructor:
+ defaultLifetime: 3600
-## Alternative Cache Backends
+In most cases, invalidation and expiry should be handled by your cache key.
+For example, including the `LastEdited` value when caching `DataObject` results
+will automatically create a new cache key when the object has been changed.
+The following example caches a member's group names, and automatically
+creates a new cache key when any group is edited. Depending on the used adapter,
+old cache keys will be garbage collected as the cache fills up.
-By default, SilverStripe uses a file-based caching backend.
-Together with a file stat cache like [APC](http://us2.php.net/manual/en/book.apc.php)
-this is reasonably quick, but still requires access to slow disk I/O.
-The `Zend_Cache` API supports various caching backends ([list](http://framework.zend.com/manual/1.12/en/zend.cache.backends.html))
-which can provide better performance, including APC, Xcache, ZendServer, Memcached and SQLite.
+ :::php
+ use Psr\SimpleCache\CacheInterface
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
+
+ // Automatically changes when any group is edited
+ $cacheKey = implode(['groupNames', $member->ID, Groups::get()->max('LastEdited')]);
+ $cache->set($cacheKey, $member->Groups()->column('Title'));
-## Cleaning caches on flush=1 requests
+If `?flush=1` is requested in the URL, this will trigger a call to `flush()` on
+any classes that implement the [Flushable](/developer_guides/execution_pipeline/flushable/)
+interface. Use this interface to trigger `clear()` on your caches.
-If `?flush=1` is requested in the URL, e.g. http://mysite.com?flush=1, this will trigger a call to `flush()` on
-any classes that implement the `Flushable` interface. Using this, you can trigger your caches to clean.
+## Adapters
-See [reference documentation on Flushable](/developer_guides/execution_pipeline/flushable/) for implementation details.
+SilverStripe tries to identify the most performant cache available on your system
+through the [DefaultCacheFactory](api:SilverStripe\Core\Cache\DefaultCacheFactory) implementation:
-### Memcached
+ * - `PhpFilesCache` (PHP 5.6 or PHP 7 with [opcache](http://php.net/manual/en/book.opcache.php) enabled).
+ This cache has relatively low [memory defaults](http://php.net/manual/en/opcache.configuration.php#ini.opcache.memory-consumption).
+ We recommend increasing it for large applications, or enabling the
+ [file_cache fallback](http://php.net/manual/en/opcache.configuration.php#ini.opcache.file-cache)
+ * - `ApcuCache` (requires APC) with a `FilesystemCache` fallback (for larger cache volumes)
+ * - `FilesystemCache` if none of the above is available
+
+The library supports various [cache adapters](https://github.com/symfony/cache/tree/master/Simple)
+which can provide better performance, particularly in multi-server environments with shared caches like Memcached.
-This backends stores cache records into a [memcached](http://www.danga.com/memcached/)
-server. memcached is a high-performance, distributed memory object caching system.
-To use this backend, you need a memcached daemon and the memcache PECL extension.
+Since we're using dependency injection to create caches,
+you need to define a factory for a particular adapter,
+following the `SilverStripe\Core\Cache\CacheFactory` interface.
+Different adapters will require different constructor arguments.
+We've written factories for the most common cache scenarios:
+`FilesystemCacheFactory`, `MemcachedCacheFactory` and `ApcuCacheFactory`.
- :::php
- // _config.php
- Cache::add_backend(
- 'primary_memcached',
- 'Memcached',
- array(
- 'servers' => array(
- 'host' => 'localhost',
- 'port' => 11211,
- 'persistent' => true,
- 'weight' => 1,
- 'timeout' => 5,
- 'retry_interval' => 15,
- 'status' => true,
- 'failure_callback' => null
- )
- )
- );
- Cache::pick_backend('primary_memcached', 'any', 10);
+Example: Configure core caches to use [memcached](http://www.danga.com/memcached/),
+which requires the [memcached PHP extension](http://php.net/memcached),
+and takes a `MemcachedClient` instance as a constructor argument.
-### APC
+ :::yml
+ ---
+ After:
+ - '#corecache'
+ ---
+ SilverStripe\Core\Injector\Injector:
+ MemcachedClient:
+ class: 'Memcached'
+ calls:
+ - [ addServer, [ 'localhost', 11211 ] ]
+ SilverStripe\Core\Cache\CacheFactory:
+ class: 'SilverStripe\Core\Cache\MemcachedCacheFactory'
+ constructor:
+ client: '%$MemcachedClient
-This backends stores cache records in shared memory through the [APC](http://pecl.php.net/package/APC)
- (Alternative PHP Cache) extension (which is of course need for using this backend).
+## Additional Caches
- :::php
- Cache::add_backend('primary_apc', 'APC');
- Cache::pick_backend('primary_apc', 'any', 10);
+Unfortunately not all caches are configurable via cache adapters.
-### Two-Levels
-
-This backend is an hybrid one. It stores cache records in two other backends:
-a fast one (but limited) like Apc, Memcache... and a "slow" one like File or Sqlite.
-
- :::php
- Cache::add_backend('two_level', 'Two-Levels', array(
- 'slow_backend' => 'File',
- 'fast_backend' => 'APC',
- 'slow_backend_options' => array(
- 'cache_dir' => TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache'
- )
- ));
- Cache::pick_backend('two_level', 'any', 10);
+ * [SSViewer](api:SilverStripe\View\SSViewer) writes compiled templates as PHP files to the filesystem
+ (in order to achieve opcode caching on `include()` calls)
+ * [ConfigManifest](api:SilverStripe\Core\Manifest\ConfigManifest) is hardcoded to use `FilesystemCache`
+ * [ClassManifest](api:SilverStripe\Core\Manifest\ClassManifest) and [ThemeManifest](api:SilverStripe\View\ThemeManifest)
+ are using a custom `ManifestCache`
+ * [i18n](api:SilverStripe\i18n\i18n) uses `Symfony\Component\Config\ConfigCacheFactoryInterface` (filesystem-based)
diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md
index 921f3d3da..be56bca02 100644
--- a/docs/en/04_Changelogs/4.0.0.md
+++ b/docs/en/04_Changelogs/4.0.0.md
@@ -16,6 +16,7 @@ guide developers in preparing existing 3.x code for compatibility with 4.0
* [Filesystem API](#overview-filesystem)
* [Template and Form API](#overview-template)
* [i18n](#overview-i18n)
+ * [Cache](#overview-cache)
* [Email and Mailer](#overview-mailer)
* [Commit History](#commit-history)
@@ -49,6 +50,7 @@ guide developers in preparing existing 3.x code for compatibility with 4.0
* Themes are now configured to cascade, where you can specify a list of themes, and have the template engine
search programatically through a prioritised list when resolving template and CSS file paths.
* i18n Updated to use symfony/translation over zend Framework 1. Zend_Translate has been removed.
+* Replaced `Zend_Cache` and the `Cache` API with a PSR-16 implementation (symfony/cache)
* _ss_environment.php files have been removed in favour of `.env` and "real" environment variables.
## Upgrading
@@ -1473,6 +1475,93 @@ New `TimeField` methods replace `getConfig()` / `setConfig()`
* `i18n::get_common_locales()` removed.
* `i18n.common_locales` config removed
+### Cache API
+
+We have replaced the unsupported `Zend_Cache` library with [symfony/cache](https://github.com/symfony/cache).
+This also allowed us to remove SilverStripe's `Cache` API and use dependency injection with a standard
+[PSR-16](http://www.php-fig.org/psr/psr-16/) cache interface instead.
+
+#### Usage Changes
+
+Caches should be retrieved through `Injector` instead of `Cache::factory()`,
+and have a slightly different API (e.g. `set()` instead of `save()`).
+
+Before:
+
+ :::php
+ $cache = Cache::factory('myCache');
+
+ // create a new item by trying to get it from the cache
+ $myValue = $cache->load('myCacheKey');
+
+ // set a value and save it via the adapter
+ $cache->save(1234, 'myCacheKey');
+
+ // retrieve the cache item
+ if (!$cache->load('myCacheKey')) {
+ // ... item does not exists in the cache
+ }
+
+ // Remove a cache key
+ $cache->remove('myCacheKey');
+
+
+After:
+
+ :::php
+ use Psr\SimpleCache\CacheInterface;
+ $cache = Injector::inst()->get(CacheInterface::class . '.myCache');
+
+ // create a new item by trying to get it from the cache
+ $myValue = $cache->get('myCacheKey');
+
+ // set a value and save it via the adapter
+ $cache->set('myCacheKey', 1234);
+
+ // retrieve the cache item
+ if (!$cache->has('myCacheKey')) {
+ // ... item does not exists in the cache
+ }
+
+ $cache->delete('myCacheKey');
+
+#### Configuration Changes
+
+Caches are now configured through dependency injection services instead of PHP.
+See our ["Caching" docs](/developer-guides/performance/caching) for more details.
+
+Before (`mysite/_config.php`):
+
+ :::php
+ Cache::add_backend(
+ 'primary_memcached',
+ 'Memcached',
+ array(
+ 'servers' => array(
+ 'host' => 'localhost',
+ 'port' => 11211,
+ )
+ )
+ );
+ Cache::pick_backend('primary_memcached', 'any', 10);
+
+After (`mysite/_config/config.yml`):
+
+ :::yml
+ ---
+ After:
+ - '#corecache'
+ ---
+ SilverStripe\Core\Injector\Injector:
+ MemcachedClient:
+ class: 'Memcached'
+ calls:
+ - [ addServer, [ 'localhost', 11211 ] ]
+ SilverStripe\Core\Cache\CacheFactory:
+ class: 'SilverStripe\Core\Cache\MemcachedCacheFactory'
+ constructor:
+ client: '%$MemcachedClient
+
### Email and Mailer
#### Email Additions / Changes
diff --git a/src/Assets/GDBackend.php b/src/Assets/GDBackend.php
index b8b4e87f0..a530af2b4 100644
--- a/src/Assets/GDBackend.php
+++ b/src/Assets/GDBackend.php
@@ -4,12 +4,11 @@ namespace SilverStripe\Assets;
use SilverStripe\Assets\Storage\AssetContainer;
use SilverStripe\Assets\Storage\AssetStore;
-use SilverStripe\Core\Cache;
+use Psr\SimpleCache\CacheInterface;
+use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Object;
use SilverStripe\Core\Flushable;
use InvalidArgumentException;
-use Zend_Cache;
-use Zend_Cache_Core;
/**
* A wrapper class for GD-based images, with lots of manipulation functions.
@@ -25,7 +24,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
protected $gd;
/**
- * @var Zend_Cache_Core
+ * @var \Psr\SimpleCache\CacheInterface
*/
protected $cache;
@@ -66,7 +65,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
public function __construct(AssetContainer $assetContainer = null)
{
parent::__construct();
- $this->cache = Cache::factory('GDBackend_Manipulations');
+ $this->cache = Injector::inst()->get(CacheInterface::class . '.GDBackend_Manipulations');
if ($assetContainer) {
$this->loadFromContainer($assetContainer);
@@ -219,7 +218,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
public function failedResample($arg = null)
{
$key = sha1(implode('|', func_get_args()));
- return (bool)$this->cache->load($key);
+ return (bool)$this->cache->get($key);
}
/**
@@ -259,7 +258,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
protected function markFailed($arg = null)
{
$key = sha1(implode('|', func_get_args()));
- $this->cache->save('1', $key);
+ $this->cache->set($key, '1');
}
/**
@@ -270,7 +269,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
protected function markSucceeded($arg = null)
{
$key = sha1(implode('|', func_get_args()));
- $this->cache->save('0', $key);
+ $this->cache->set($key, '0');
}
@@ -762,8 +761,7 @@ class GDBackend extends Object implements Image_Backend, Flushable
public static function flush()
{
- // Clear factory
- $cache = Cache::factory('GDBackend_Manipulations');
- $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
+ $cache = Injector::inst()->get(CacheInterface::class . '.GDBackend_Manipulations');
+ $cache->clear();
}
}
diff --git a/src/Core/Cache.php b/src/Core/Cache.php
deleted file mode 100644
index 53089e66e..000000000
--- a/src/Core/Cache.php
+++ /dev/null
@@ -1,201 +0,0 @@
- $cachedir
- )
- );
-
- self::$cache_lifetime['default'] = array(
- 'lifetime' => 600,
- 'priority' => 1
- );
- }
- }
-
- /**
- * Add a new named cache backend.
- *
- * @see http://framework.zend.com/manual/en/zend.cache.html
- *
- * @param string $name The name of this backend as a freeform string
- * @param string $type The Zend_Cache backend ('File' or 'Sqlite' or ...)
- * @param array $options The Zend_Cache backend options
- */
- public static function add_backend($name, $type, $options = array())
- {
- self::init();
- self::$backends[$name] = array($type, $options);
- }
-
- /**
- * Pick a named cache backend for a particular named cache.
- *
- * The priority call with the highest number will be the actual backend
- * picked. A backend picked for a specific cache name will always be used
- * instead of 'any' if it exists, no matter the priority.
- *
- * @param string $name The name of the backend, as passed as the first argument to add_backend
- * @param string $for The name of the cache to pick this backend for (or 'any' for any backend)
- * @param integer $priority The priority of this pick
- */
- public static function pick_backend($name, $for, $priority = 1)
- {
- self::init();
-
- $current = -1;
-
- if (isset(self::$backend_picks[$for])) {
- $current = self::$backend_picks[$for]['priority'];
- }
-
- if ($priority >= $current) {
- self::$backend_picks[$for] = array(
- 'name' => $name,
- 'priority' => $priority
- );
- }
- }
-
- /**
- * Return the cache lifetime for a particular named cache.
- *
- * @param string $for
- *
- * @return string
- */
- public static function get_cache_lifetime($for)
- {
- if (isset(self::$cache_lifetime[$for])) {
- return self::$cache_lifetime[$for];
- }
-
- return null;
- }
-
- /**
- * Set the cache lifetime for a particular named cache
- *
- * @param string $for The name of the cache to set this lifetime for (or 'any' for all backends)
- * @param integer $lifetime The lifetime of an item of the cache, in seconds, or -1 to disable caching
- * @param integer $priority The priority. The highest priority setting is used. Unlike backends, 'any' is not
- * special in terms of priority.
- */
- public static function set_cache_lifetime($for, $lifetime = 600, $priority = 1)
- {
- self::init();
-
- $current = -1;
-
- if (isset(self::$cache_lifetime[$for])) {
- $current = self::$cache_lifetime[$for]['priority'];
- }
-
- if ($priority >= $current) {
- self::$cache_lifetime[$for] = array(
- 'lifetime' => $lifetime,
- 'priority' => $priority
- );
- }
- }
-
- /**
- * Build a cache object.
- *
- * @see http://framework.zend.com/manual/en/zend.cache.html
- *
- * @param string $for The name of the cache to build
- * @param string $frontend (optional) The type of Zend_Cache frontend
- * @param array $frontendOptions (optional) Any frontend options to use.
- * @return Zend_Cache_Core The cache object
- */
- public static function factory($for, $frontend = 'Output', $frontendOptions = null)
- {
- self::init();
-
- $backend_name = 'default';
- $backend_priority = -1;
- $cache_lifetime = self::$cache_lifetime['default']['lifetime'];
- $lifetime_priority = -1;
-
- foreach (array('any', $for) as $name) {
- if (isset(self::$backend_picks[$name])) {
- if (self::$backend_picks[$name]['priority'] > $backend_priority) {
- $backend_name = self::$backend_picks[$name]['name'];
- $backend_priority = self::$backend_picks[$name]['priority'];
- }
- }
-
- if (isset(self::$cache_lifetime[$name])) {
- if (self::$cache_lifetime[$name]['priority'] > $lifetime_priority) {
- $cache_lifetime = self::$cache_lifetime[$name]['lifetime'];
- $lifetime_priority = self::$cache_lifetime[$name]['priority'];
- }
- }
- }
-
- $backend = self::$backends[$backend_name];
-
- $basicOptions = array('cache_id_prefix' => $for);
-
- if ($cache_lifetime >= 0) {
- $basicOptions['lifetime'] = $cache_lifetime;
- } else {
- $basicOptions['caching'] = false;
- }
-
- $frontendOptions = $frontendOptions ? array_merge($basicOptions, $frontendOptions) : $basicOptions;
-
- require_once 'Zend/Cache.php';
-
- return Zend_Cache::factory(
- $frontend,
- $backend[0],
- $frontendOptions,
- $backend[1]
- );
- }
-}
diff --git a/src/Core/Cache/ApcuCacheFactory.php b/src/Core/Cache/ApcuCacheFactory.php
new file mode 100644
index 000000000..f697b67d8
--- /dev/null
+++ b/src/Core/Cache/ApcuCacheFactory.php
@@ -0,0 +1,36 @@
+version = $version;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function create($service, array $params = array())
+ {
+ return Injector::inst()->create(ApcuCache::class, false, [
+ (isset($args['namespace'])) ? $args['namespace'] : '',
+ (isset($args['defaultLifetime'])) ? $args['defaultLifetime'] : 0,
+ $this->version
+ ]);
+ }
+}
diff --git a/src/Core/Cache/CacheFactory.php b/src/Core/Cache/CacheFactory.php
new file mode 100644
index 000000000..1f216c1b0
--- /dev/null
+++ b/src/Core/Cache/CacheFactory.php
@@ -0,0 +1,20 @@
+get() call),
+ * this cache object shouldn't be a singleton itself - it has varying constructor args for the same service name.
+ *
+ * @param string $class
+ * @param array $args
+ * @return CacheInterface
+ */
+ public function create($service, array $params = array());
+}
diff --git a/src/Core/Cache/DefaultCacheFactory.php b/src/Core/Cache/DefaultCacheFactory.php
new file mode 100644
index 000000000..1c200f007
--- /dev/null
+++ b/src/Core/Cache/DefaultCacheFactory.php
@@ -0,0 +1,79 @@
+directory = $directory;
+ $this->version = $version;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function create($service, array $params = array())
+ {
+ $namespace = (isset($args['namespace'])) ? $args['namespace'] : '';
+ $defaultLifetime = (isset($args['defaultLifetime'])) ? $args['defaultLifetime'] : 0;
+ $version = $this->version;
+ $directory = $this->directory;
+
+ $apcuSupported = null;
+ $phpFilesSupported = null;
+
+ if (null === $apcuSupported) {
+ $apcuSupported = ApcuAdapter::isSupported();
+ }
+
+ if (!$apcuSupported && null === $phpFilesSupported) {
+ $phpFilesSupported = PhpFilesAdapter::isSupported();
+ }
+
+ if ($phpFilesSupported) {
+ $opcache = Injector::inst()->create(PhpFilesCache::class, false, [$namespace, $defaultLifetime, $directory]);
+ return $opcache;
+ }
+
+ $fs = Injector::inst()->create(FilesystemCache::class, false, [$namespace, $defaultLifetime, $directory]);
+ if (!$apcuSupported) {
+ return $fs;
+ }
+
+ $apcu = Injector::inst()->create(ApcuCache::class, false, [$namespace, (int) $defaultLifetime / 5, $version]);
+
+ return Injector::inst()->create(ChainCache::class, false, [[$apcu, $fs]]);
+ }
+}
diff --git a/src/Core/Cache/FilesystemCacheFactory.php b/src/Core/Cache/FilesystemCacheFactory.php
new file mode 100644
index 000000000..36094cc6e
--- /dev/null
+++ b/src/Core/Cache/FilesystemCacheFactory.php
@@ -0,0 +1,35 @@
+directory = $directory;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function create($service, array $params = array())
+ {
+ return Injector::inst()->create(FilesystemCache::class, false, [
+ (isset($args['namespace'])) ? $args['namespace'] : '',
+ (isset($args['defaultLifetime'])) ? $args['defaultLifetime'] : 0,
+ $this->directory
+ ]);
+ }
+}
diff --git a/src/Core/Cache/MemcachedCacheFactory.php b/src/Core/Cache/MemcachedCacheFactory.php
new file mode 100644
index 000000000..37269da02
--- /dev/null
+++ b/src/Core/Cache/MemcachedCacheFactory.php
@@ -0,0 +1,36 @@
+memcachedClient = $memcachedClient;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function create($service, array $params = array())
+ {
+ return Injector::inst()->create(MemcachedCache::class, false, [
+ $this->memcachedClient,
+ (isset($args['namespace'])) ? $args['namespace'] : '',
+ (isset($args['defaultLifetime'])) ? $args['defaultLifetime'] : 0
+ ]);
+ }
+}
diff --git a/src/Core/Core.php b/src/Core/Core.php
index efd99c10f..93105fc8e 100644
--- a/src/Core/Core.php
+++ b/src/Core/Core.php
@@ -54,14 +54,6 @@ mb_regex_encoding('UTF-8');
*/
gc_enable();
-/**
- * Include the Zend autoloader. This will be removed in the near future.
- */
-if (file_exists('thirdparty/Zend/Loader/Autoloader.php')) {
- require_once 'thirdparty/Zend/Loader/Autoloader.php';
- Zend_Loader_Autoloader::getInstance();
-}
-
// Initialise the dependency injector as soon as possible, as it is
// subsequently used by some of the following code
$injector = new Injector(array('locator' => 'SilverStripe\\Core\\Injector\\SilverStripeServiceConfigurationLocator'));
diff --git a/src/Core/Manifest/ConfigManifest.php b/src/Core/Manifest/ConfigManifest.php
index 48a4f09ab..883577b54 100644
--- a/src/Core/Manifest/ConfigManifest.php
+++ b/src/Core/Manifest/ConfigManifest.php
@@ -7,10 +7,9 @@ use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\DAG;
use SilverStripe\Core\Config\DAG_CyclicException;
use SilverStripe\Core\Config\Config;
-use SilverStripe\Core\Cache;
+use Symfony\Component\Cache\Simple\FilesystemCache;
use Symfony\Component\Yaml\Parser;
use Traversable;
-use Zend_Cache_Core;
/**
* A utility class which builds a manifest of configuration items
@@ -28,7 +27,7 @@ class ConfigManifest
protected $includeTests;
/**
- * @var Zend_Cache_Core
+ * @var FilesystemCache
*/
protected $cache;
@@ -114,15 +113,15 @@ class ConfigManifest
$this->key = sha1($base).'_';
$this->includeTests = $includeTests;
- // Get the Zend Cache to load/store cache into
+ // Get a cache singleton
$this->cache = $this->getCache();
// Unless we're forcing regen, try loading from cache
if (!$forceRegen) {
// The PHP config sources are always needed
- $this->phpConfigSources = $this->cache->load($this->key.'php_config_sources');
+ $this->phpConfigSources = $this->cache->get($this->key.'php_config_sources');
// Get the variant key spec
- $this->variantKeySpec = $this->cache->load($this->key.'variant_key_spec');
+ $this->variantKeySpec = $this->cache->get($this->key.'variant_key_spec');
}
// If we don't have a variantKeySpec (because we're forcing regen, or it just wasn't in the cache), generate it
@@ -136,14 +135,12 @@ class ConfigManifest
/**
* Provides a hook for mock unit tests despite no DI
- * @return Zend_Cache_Core
+ * @return \Psr\SimpleCache\CacheInterface
*/
protected function getCache()
{
- return Cache::factory('SS_Configuration', 'Core', array(
- 'automatic_serialization' => true,
- 'lifetime' => null
- ));
+ // TODO Replace with CoreConfigCreator, see https://github.com/silverstripe/silverstripe-framework/pull/6641/files#diff-f8c9b17e06432278197a7d5c3a1043cb
+ return new FilesystemCache('SS_Configuration', 0, getTempFolder());
}
/**
@@ -264,9 +261,9 @@ class ConfigManifest
$this->buildVariantKeySpec();
if ($cache) {
- $this->cache->save($this->phpConfigSources, $this->key.'php_config_sources');
- $this->cache->save($this->yamlConfigFragments, $this->key.'yaml_config_fragments');
- $this->cache->save($this->variantKeySpec, $this->key.'variant_key_spec');
+ $this->cache->set($this->key.'php_config_sources', $this->phpConfigSources);
+ $this->cache->set($this->key.'yaml_config_fragments', $this->yamlConfigFragments);
+ $this->cache->set($this->key.'variant_key_spec', $this->variantKeySpec);
}
}
@@ -650,12 +647,12 @@ class ConfigManifest
// given variant is stale compared to the complete set of fragments
if (!$this->yamlConfigFragments) {
// First try and just load the exact variant
- if ($this->yamlConfig = $this->cache->load($this->key.'yaml_config_'.$this->variantKey())) {
+ if ($this->yamlConfig = $this->cache->get($this->key.'yaml_config_'.$this->variantKey())) {
$this->yamlConfigVariantKey = $this->variantKey();
return;
} // Otherwise try and load the fragments so we can build the variant
else {
- $this->yamlConfigFragments = $this->cache->load($this->key.'yaml_config_fragments');
+ $this->yamlConfigFragments = $this->cache->get($this->key.'yaml_config_fragments');
}
}
@@ -684,7 +681,7 @@ class ConfigManifest
}
if ($cache) {
- $this->cache->save($this->yamlConfig, $this->key.'yaml_config_'.$this->variantKey());
+ $this->cache->set($this->key.'yaml_config_'.$this->variantKey(), $this->yamlConfig);
}
// Since yamlConfig has changed, call any callbacks that are interested
diff --git a/src/View/SSTemplateParser.peg b/src/View/SSTemplateParser.peg
index f91edc6a9..5d1240758 100644
--- a/src/View/SSTemplateParser.peg
+++ b/src/View/SSTemplateParser.peg
@@ -743,10 +743,10 @@ class SSTemplateParser extends Parser implements TemplateParser
// Get any condition
$condition = isset($res['condition']) ? $res['condition'] : '';
- $res['php'] .= 'if ('.$condition.'($partial = $cache->load('.$key.'))) $val .= $partial;' . PHP_EOL;
+ $res['php'] .= 'if ('.$condition.'($partial = $cache->get('.$key.'))) $val .= $partial;' . PHP_EOL;
$res['php'] .= 'else { $oldval = $val; $val = "";' . PHP_EOL;
$res['php'] .= $sub['php'] . PHP_EOL;
- $res['php'] .= $condition . ' $cache->save($val); $val = $oldval . $val;' . PHP_EOL;
+ $res['php'] .= $condition . ' $cache->set('.$key.', $val); $val = $oldval . $val;' . PHP_EOL;
$res['php'] .= '}';
}
diff --git a/src/View/SSTemplateParser.php b/src/View/SSTemplateParser.php
index 360a811c1..f5c2a30ce 100644
--- a/src/View/SSTemplateParser.php
+++ b/src/View/SSTemplateParser.php
@@ -4020,10 +4020,10 @@ class SSTemplateParser extends Parser implements TemplateParser
// Get any condition
$condition = isset($res['condition']) ? $res['condition'] : '';
- $res['php'] .= 'if ('.$condition.'($partial = $cache->load('.$key.'))) $val .= $partial;' . PHP_EOL;
+ $res['php'] .= 'if ('.$condition.'($partial = $cache->get('.$key.'))) $val .= $partial;' . PHP_EOL;
$res['php'] .= 'else { $oldval = $val; $val = "";' . PHP_EOL;
$res['php'] .= $sub['php'] . PHP_EOL;
- $res['php'] .= $condition . ' $cache->save($val); $val = $oldval . $val;' . PHP_EOL;
+ $res['php'] .= $condition . ' $cache->set('.$key.', $val); $val = $oldval . $val;' . PHP_EOL;
$res['php'] .= '}';
}
diff --git a/src/View/SSViewer.php b/src/View/SSViewer.php
index 151b5452f..6b3cc09e2 100644
--- a/src/View/SSViewer.php
+++ b/src/View/SSViewer.php
@@ -4,7 +4,7 @@ namespace SilverStripe\View;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\ClassInfo;
-use SilverStripe\Core\Cache;
+use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Flushable;
use SilverStripe\Core\Injector\Injector;
@@ -14,9 +14,6 @@ use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Security\Permission;
use InvalidArgumentException;
-use Zend_Cache_Backend_ExtendedInterface;
-use Zend_Cache;
-use Zend_Cache_Core;
/**
* Parses a template file with an *.ss file extension.
@@ -466,17 +463,8 @@ class SSViewer implements Flushable
public static function flush_cacheblock_cache($force = false)
{
if (!self::$cacheblock_cache_flushed || $force) {
- $cache = Cache::factory('cacheblock');
- $backend = $cache->getBackend();
-
- if ($backend instanceof Zend_Cache_Backend_ExtendedInterface
- && ($capabilities = $backend->getCapabilities())
- && $capabilities['tags']
- ) {
- $cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, $cache->getTags());
- } else {
- $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
- }
+ $cache = Injector::inst()->get(CacheInterface::class . '.cacheblock');
+ $cache->clear();
self::$cacheblock_cache_flushed = true;
@@ -484,14 +472,14 @@ class SSViewer implements Flushable
}
/**
- * @var Zend_Cache_Core
+ * @var CacheInterface
*/
protected $partialCacheStore = null;
/**
* Set the cache object to use when storing / retrieving partial cache blocks.
*
- * @param Zend_Cache_Core $cache
+ * @param CacheInterface $cache
*/
public function setPartialCacheStore($cache)
{
@@ -501,11 +489,11 @@ class SSViewer implements Flushable
/**
* Get the cache object to use when storing / retrieving partial cache blocks.
*
- * @return Zend_Cache_Core
+ * @return CacheInterface
*/
public function getPartialCacheStore()
{
- return $this->partialCacheStore ? $this->partialCacheStore : Cache::factory('cacheblock');
+ return $this->partialCacheStore ? $this->partialCacheStore : Injector::inst()->get(CacheInterface::class . '.cacheblock');
}
/**
diff --git a/tests/php/Assets/GDTest.php b/tests/php/Assets/GDTest.php
index fa43d6960..127d6f38c 100644
--- a/tests/php/Assets/GDTest.php
+++ b/tests/php/Assets/GDTest.php
@@ -3,7 +3,8 @@
namespace SilverStripe\Assets\Tests;
use SilverStripe\Assets\GDBackend;
-use SilverStripe\Core\Cache;
+use Psr\SimpleCache\CacheInterface;
+use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
/**
@@ -192,9 +193,9 @@ class GDTest extends SapphireTest
$gd->loadFrom($fullPath);
// Cache should refer to this file
- $cache = Cache::factory('GDBackend_Manipulations');
+ $cache = Injector::inst()->get(CacheInterface::class . '.GDBackend_Manipulations');
$key = sha1(implode('|', array($fullPath, filemtime($fullPath))));
- $data = $cache->load($key);
+ $data = $cache->get($key);
$this->assertEquals('1', $data);
}
diff --git a/tests/php/Core/CacheTest.php b/tests/php/Core/CacheTest.php
deleted file mode 100644
index b16978100..000000000
--- a/tests/php/Core/CacheTest.php
+++ /dev/null
@@ -1,77 +0,0 @@
-save('Good', 'cachekey');
- $this->assertEquals('Good', $cache->load('cachekey'));
- }
-
- public function testCacheCanBeDisabled()
- {
- Cache::set_cache_lifetime('test', -1, 10);
-
- $cache = Cache::factory('test');
-
- $cache->save('Good', 'cachekey');
- $this->assertFalse($cache->load('cachekey'));
- }
-
- public function testCacheLifetime()
- {
- Cache::set_cache_lifetime('test', 0.5, 20);
-
- $cache = Cache::factory('test');
- $this->assertEquals(0.5, $cache->getOption('lifetime'));
-
- $cache->save('Good', 'cachekey');
- $this->assertEquals('Good', $cache->load('cachekey'));
-
- // As per documentation, sleep may not sleep for the amount of time you tell it to sleep for
- // This loop can make sure it *does* sleep for that long
- $endtime = time() + 2;
- while (time() < $endtime) {
- // Sleep for another 2 seconds!
- // This may end up sleeping for 4 seconds, but it's awwwwwwwright.
- sleep(2);
- }
-
- $this->assertFalse($cache->load('cachekey'));
- }
-
- public function testCacheSeperation()
- {
- $cache1 = Cache::factory('test1');
- $cache2 = Cache::factory('test2');
-
- $cache1->save('Foo', 'cachekey');
- $cache2->save('Bar', 'cachekey');
- $this->assertEquals('Foo', $cache1->load('cachekey'));
- $this->assertEquals('Bar', $cache2->load('cachekey'));
-
- $cache1->remove('cachekey');
- $this->assertFalse($cache1->load('cachekey'));
- $this->assertEquals('Bar', $cache2->load('cachekey'));
- }
-
- public function testCacheDefault()
- {
- Cache::set_cache_lifetime('default', 1200);
- $default = Cache::get_cache_lifetime('default');
-
- $this->assertEquals(1200, $default['lifetime']);
-
- $cache = Cache::factory('somethingnew');
-
- $this->assertEquals(1200, $cache->getOption('lifetime'));
- }
-}
diff --git a/tests/php/Core/Manifest/ConfigManifestTest.php b/tests/php/Core/Manifest/ConfigManifestTest.php
index e6e7f5d01..2e9592aa1 100644
--- a/tests/php/Core/Manifest/ConfigManifestTest.php
+++ b/tests/php/Core/Manifest/ConfigManifestTest.php
@@ -7,7 +7,7 @@ use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Manifest\ConfigManifest;
use SilverStripe\Dev\SapphireTest;
use ReflectionProperty;
-use Zend_Cache_Core;
+use Symfony\Component\Cache\Simple\ArrayCache;
class ConfigManifestTest extends SapphireTest
{
@@ -34,13 +34,13 @@ class ConfigManifestTest extends SapphireTest
/**
* A helper method to return a mock of the cache in order to test expectations and reduce dependency
*
- * @return Zend_Cache_Core
+ * @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getCacheMock()
{
return $this->getMock(
- 'Zend_Cache_Core',
- array('load', 'save'),
+ ArrayCache::class,
+ array('set', 'get'),
array(),
'',
false
@@ -51,7 +51,7 @@ class ConfigManifestTest extends SapphireTest
* A helper method to return a mock of the manifest in order to test expectations and reduce dependency
*
* @param $methods
- * @return ConfigManifest
+ * @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getManifestMock($methods)
{
@@ -82,7 +82,7 @@ class ConfigManifestTest extends SapphireTest
// Set up a cache where we expect load to never be called
$cache = $this->getCacheMock();
$cache->expects($this->never())
- ->method('load');
+ ->method('get');
$manifest->expects($this->any())
->method('getCache')
@@ -95,7 +95,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->atLeastOnce())
- ->method('save');
+ ->method('set');
$manifest->expects($this->any())
->method('getCache')
@@ -119,7 +119,7 @@ class ConfigManifestTest extends SapphireTest
// Load should be called twice
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
- ->method('load');
+ ->method('get');
$manifest->expects($this->any())
->method('getCache')
@@ -133,7 +133,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
- ->method('load')
+ ->method('get')
->will($this->onConsecutiveCalls(false, false));
$manifest->expects($this->any())
@@ -151,7 +151,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
- ->method('load')
+ ->method('get')
->will($this->onConsecutiveCalls(array(), array()));
$manifest->expects($this->any())
@@ -186,7 +186,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
->will($this->returnValue(false))
- ->method('load');
+ ->method('get');
$manifest->expects($this->any())
->method('getCache')
@@ -204,7 +204,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
- ->method('load')
+ ->method('get')
->will($this->returnCallback(function ($parameter) {
if (strpos($parameter, 'variant_key_spec') !== false) {
return false;
@@ -227,7 +227,7 @@ class ConfigManifestTest extends SapphireTest
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
- ->method('load')
+ ->method('get')
->will($this->returnCallback(function ($parameter) {
if (strpos($parameter, 'php_config_sources') !== false) {
return false;
diff --git a/tests/php/ORM/GDImageTest.php b/tests/php/ORM/GDImageTest.php
index 8b594ec11..f6169156d 100644
--- a/tests/php/ORM/GDImageTest.php
+++ b/tests/php/ORM/GDImageTest.php
@@ -5,8 +5,8 @@ namespace SilverStripe\ORM\Tests;
require_once __DIR__ . "/ImageTest.php";
use SilverStripe\Core\Config\Config;
-use SilverStripe\Core\Cache;
-use Zend_Cache;
+use Psr\SimpleCache\CacheInterface;
+use SilverStripe\Core\Injector\Injector;
class GDImageTest extends ImageTest
{
@@ -32,8 +32,9 @@ class GDImageTest extends ImageTest
public function tearDown()
{
- $cache = Cache::factory('GDBackend_Manipulations');
- $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
+ $cache = Injector::inst()->get(CacheInterface::class . '.GDBackend_Manipulations');
+ $cache->clear();
+
parent::tearDown();
}
}
diff --git a/tests/php/View/SSViewerCacheBlockTest.php b/tests/php/View/SSViewerCacheBlockTest.php
index 8e021f081..7f11325e6 100644
--- a/tests/php/View/SSViewerCacheBlockTest.php
+++ b/tests/php/View/SSViewerCacheBlockTest.php
@@ -2,11 +2,14 @@
namespace SilverStripe\View\Tests;
+use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\Versioning\Versioned;
-use SilverStripe\Core\Cache;
+use Psr\SimpleCache\CacheInterface;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\Director;
use SilverStripe\View\SSViewer;
+use Symfony\Component\Cache\Simple\FilesystemCache;
+use Symfony\Component\Cache\Simple\NullCache;
// Not actually a data object, we just want a ViewableData object that's just for us
@@ -27,8 +30,15 @@ class SSViewerCacheBlockTest extends SapphireTest
{
$this->data = new SSViewerCacheBlockTest\TestModel();
- Cache::factory('cacheblock')->clean();
- Cache::set_cache_lifetime('cacheblock', $cacheOn ? 600 : -1);
+ $cache = null;
+ if ($cacheOn) {
+ $cache = new FilesystemCache('cacheblock', 0, getTempFolder()); // cache indefinitely
+ } else {
+ $cache = new NullCache();
+ }
+
+ Injector::inst()->registerService($cache, CacheInterface::class . '.cacheblock');
+ Injector::inst()->get(CacheInterface::class . '.cacheblock')->clear();
}
protected function _runtemplate($template, $data = null)