2022-06-17 17:51:59 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Kirby\Cms;
|
|
|
|
|
2022-12-19 14:56:05 +01:00
|
|
|
use Kirby\Cache\Cache;
|
2022-06-17 17:51:59 +02:00
|
|
|
use Kirby\Cache\NullCache;
|
|
|
|
use Kirby\Exception\InvalidArgumentException;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AppCaches
|
|
|
|
*
|
|
|
|
* @package Kirby Cms
|
|
|
|
* @author Bastian Allgeier <bastian@getkirby.com>
|
|
|
|
* @link https://getkirby.com
|
|
|
|
* @copyright Bastian Allgeier
|
|
|
|
* @license https://getkirby.com/license
|
|
|
|
*/
|
|
|
|
trait AppCaches
|
|
|
|
{
|
2025-04-21 18:57:21 +02:00
|
|
|
protected array $caches = [];
|
2022-08-31 15:02:43 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a cache instance by key
|
|
|
|
*/
|
2025-04-21 18:57:21 +02:00
|
|
|
public function cache(string $key): Cache
|
2022-08-31 15:02:43 +02:00
|
|
|
{
|
|
|
|
if (isset($this->caches[$key]) === true) {
|
|
|
|
return $this->caches[$key];
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the options for this cache type
|
|
|
|
$options = $this->cacheOptions($key);
|
|
|
|
|
|
|
|
if ($options['active'] === false) {
|
|
|
|
// use a dummy cache that does nothing
|
|
|
|
return $this->caches[$key] = new NullCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
$type = strtolower($options['type']);
|
|
|
|
$types = $this->extensions['cacheTypes'] ?? [];
|
|
|
|
|
|
|
|
if (array_key_exists($type, $types) === false) {
|
|
|
|
throw new InvalidArgumentException([
|
2023-04-14 16:34:06 +02:00
|
|
|
'key' => 'cache.type.invalid',
|
2022-08-31 15:02:43 +02:00
|
|
|
'data' => ['type' => $type]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
$className = $types[$type];
|
|
|
|
|
|
|
|
// initialize the cache class
|
|
|
|
$cache = new $className($options);
|
|
|
|
|
|
|
|
// check if it is a usable cache object
|
2022-12-19 14:56:05 +01:00
|
|
|
if ($cache instanceof Cache === false) {
|
2022-08-31 15:02:43 +02:00
|
|
|
throw new InvalidArgumentException([
|
2023-04-14 16:34:06 +02:00
|
|
|
'key' => 'cache.type.invalid',
|
2022-08-31 15:02:43 +02:00
|
|
|
'data' => ['type' => $type]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->caches[$key] = $cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the cache options by key
|
|
|
|
*/
|
|
|
|
protected function cacheOptions(string $key): array
|
|
|
|
{
|
2022-12-19 14:56:05 +01:00
|
|
|
$options = $this->option($this->cacheOptionsKey($key), null);
|
|
|
|
$options ??= $this->core()->caches()[$key] ?? false;
|
2022-08-31 15:02:43 +02:00
|
|
|
|
|
|
|
if ($options === false) {
|
|
|
|
return [
|
|
|
|
'active' => false
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2023-04-14 16:34:06 +02:00
|
|
|
$prefix =
|
|
|
|
str_replace(['/', ':'], '_', $this->system()->indexUrl()) .
|
|
|
|
'/' .
|
2025-07-04 15:08:52 +02:00
|
|
|
str_replace(['/', '.'], ['_', '/'], $key);
|
2022-08-31 15:02:43 +02:00
|
|
|
|
|
|
|
$defaults = [
|
|
|
|
'active' => true,
|
|
|
|
'type' => 'file',
|
|
|
|
'extension' => 'cache',
|
|
|
|
'root' => $this->root('cache'),
|
|
|
|
'prefix' => $prefix
|
|
|
|
];
|
|
|
|
|
|
|
|
if ($options === true) {
|
|
|
|
return $defaults;
|
|
|
|
}
|
2022-12-19 14:56:05 +01:00
|
|
|
|
|
|
|
return array_merge($defaults, $options);
|
2022-08-31 15:02:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes care of converting prefixed plugin cache setups
|
|
|
|
* to the right cache key, while leaving regular cache
|
|
|
|
* setups untouched.
|
|
|
|
*/
|
|
|
|
protected function cacheOptionsKey(string $key): string
|
|
|
|
{
|
|
|
|
$prefixedKey = 'cache.' . $key;
|
|
|
|
|
|
|
|
if (isset($this->options[$prefixedKey])) {
|
|
|
|
return $prefixedKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
// plain keys without dots don't need further investigation
|
|
|
|
// since they can never be from a plugin.
|
|
|
|
if (strpos($key, '.') === false) {
|
|
|
|
return $prefixedKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
// try to extract the plugin name
|
|
|
|
$parts = explode('.', $key);
|
|
|
|
$pluginName = implode('/', array_slice($parts, 0, 2));
|
|
|
|
$pluginPrefix = implode('.', array_slice($parts, 0, 2));
|
|
|
|
$cacheName = implode('.', array_slice($parts, 2));
|
|
|
|
|
|
|
|
// check if such a plugin exists
|
|
|
|
if ($this->plugin($pluginName)) {
|
|
|
|
return empty($cacheName) === true ? $pluginPrefix . '.cache' : $pluginPrefix . '.cache.' . $cacheName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $prefixedKey;
|
|
|
|
}
|
2022-06-17 17:51:59 +02:00
|
|
|
}
|