Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/Config/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Cache extends BaseConfig
* Your file storage preferences can be specified below, if you are using
* the File driver.
*
* @var array<string, int|string|null>
* @var array{storePath?: string, mode?: int}
*/
public array $file = [
'storePath' => WRITEPATH . 'cache/',
Expand All @@ -95,7 +95,7 @@ class Cache extends BaseConfig
*
* @see https://codeigniter.com/user_guide/libraries/caching.html#memcached
*
* @var array<string, bool|int|string>
* @var array{host?: string, port?: int, weight?: int, raw?: bool}
*/
public array $memcached = [
'host' => '127.0.0.1',
Expand All @@ -112,7 +112,7 @@ class Cache extends BaseConfig
* Your Redis server can be specified below, if you are using
* the Redis or Predis drivers.
*
* @var array<string, int|string|null>
* @var array{host?: string, password?: string|null, port?: int, timeout?: int, database?: int}
*/
public array $redis = [
'host' => '127.0.0.1',
Expand Down
2 changes: 1 addition & 1 deletion system/Cache/CacheFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static function getHandler(Cache $config, ?string $handler = null, ?strin
}
}

// If $adapter->initialization throws a CriticalError exception, we will attempt to
// If $adapter->initialize() throws a CriticalError exception, we will attempt to
// use the $backup handler, if that also fails, we resort to the dummy handler.
try {
$adapter->initialize();
Expand Down
20 changes: 8 additions & 12 deletions system/Cache/CacheInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@

namespace CodeIgniter\Cache;

/**
* Cache interface
*/
interface CacheInterface
{
/**
Expand All @@ -30,16 +27,16 @@ public function initialize();
*
* @param string $key Cache item name
*
* @return array|bool|float|int|object|string|null
* @return mixed
*/
public function get(string $key);

/**
* Saves an item to the cache store.
*
* @param string $key Cache item name
* @param array|bool|float|int|object|string|null $value The data to save
* @param int $ttl Time To Live, in seconds (default 60)
* @param string $key Cache item name
* @param mixed $value The data to save
* @param int $ttl Time To Live, in seconds (default 60)
*
* @return bool Success or failure
*/
Expand Down Expand Up @@ -87,7 +84,7 @@ public function clean();
* The information returned and the structure of the data
* varies depending on the handler.
*
* @return array|false|object|null
* @return array<array-key, mixed>|false|object|null
*/
public function getCacheInfo();

Expand All @@ -96,10 +93,9 @@ public function getCacheInfo();
*
* @param string $key Cache item name.
*
* @return array|false|null
* Returns null if the item does not exist, otherwise array<string, mixed>
* with at least the 'expire' key for absolute epoch expiry (or null).
* Some handlers may return false when an item does not exist, which is deprecated.
* @return array<string, mixed>|false|null Returns null if the item does not exist, otherwise array<string, mixed>
* with at least the 'expire' key for absolute epoch expiry (or null).
* Some handlers may return false when an item does not exist, which is deprecated.
*/
public function getMetaData(string $key);

Expand Down
11 changes: 4 additions & 7 deletions system/Cache/Exceptions/CacheException.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@
use CodeIgniter\Exceptions\DebugTraceableTrait;
use CodeIgniter\Exceptions\RuntimeException;

/**
* CacheException
*/
class CacheException extends RuntimeException
{
use DebugTraceableTrait;

/**
* Thrown when handler has no permission to write cache.
*
* @return CacheException
* @return static
*/
public static function forUnableToWrite(string $path)
{
Expand All @@ -36,7 +33,7 @@ public static function forUnableToWrite(string $path)
/**
* Thrown when an unrecognized handler is used.
*
* @return CacheException
* @return static
*/
public static function forInvalidHandlers()
{
Expand All @@ -46,7 +43,7 @@ public static function forInvalidHandlers()
/**
* Thrown when no backup handler is setup in config.
*
* @return CacheException
* @return static
*/
public static function forNoBackup()
{
Expand All @@ -56,7 +53,7 @@ public static function forNoBackup()
/**
* Thrown when specified handler was not found.
*
* @return CacheException
* @return static
*/
public static function forHandlerNotFound()
{
Expand Down
16 changes: 6 additions & 10 deletions system/Cache/FactoriesCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,9 @@

final class FactoriesCache
{
/**
* @var CacheInterface|FileVarExportHandler
*/
private $cache;

/**
* @param CacheInterface|FileVarExportHandler|null $cache
*/
public function __construct($cache = null)
private readonly CacheInterface|FileVarExportHandler $cache;

public function __construct(CacheInterface|FileVarExportHandler|null $cache = null)
{
$this->cache = $cache ?? new FileVarExportHandler();
}
Expand All @@ -51,7 +45,9 @@ public function load(string $component): bool
{
$key = $this->getCacheKey($component);

if (! $data = $this->cache->get($key)) {
$data = $this->cache->get($key);

if (! is_array($data) || $data === []) {
return false;
}

Expand Down
10 changes: 2 additions & 8 deletions system/Cache/FactoriesCache/FileVarExportHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ final class FileVarExportHandler
{
private string $path = WRITEPATH . 'cache';

/**
* @param array|bool|float|int|object|string|null $val
*/
public function save(string $key, $val): void
public function save(string $key, mixed $val): void
{
$val = var_export($val, true);

Expand All @@ -36,10 +33,7 @@ public function delete(string $key): void
@unlink($this->path . "/{$key}");
}

/**
* @return array|bool|float|int|object|string|null
*/
public function get(string $key)
public function get(string $key): mixed
{
return @include $this->path . "/{$key}";
}
Expand Down
9 changes: 5 additions & 4 deletions system/Cache/Handlers/BaseHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class BaseHandler implements CacheInterface
* Keys that exceed MAX_KEY_LENGTH are hashed.
* From https://github.com/symfony/cache/blob/7b024c6726af21fd4984ac8d1eae2b9f3d90de88/CacheItem.php#L158
*
* @param string $key The key to validate
* @param mixed $key The key to validate
* @param string $prefix Optional prefix to include in length calculations
*
* @throws InvalidArgumentException When $key is not valid
Expand All @@ -67,7 +67,8 @@ public static function validateKey($key, $prefix = ''): string
throw new InvalidArgumentException('Cache key cannot be empty.');
}

$reserved = config(Cache::class)->reservedCharacters ?? self::RESERVED_CHARACTERS;
$reserved = config(Cache::class)->reservedCharacters;

if ($reserved !== '' && strpbrk($key, $reserved) !== false) {
throw new InvalidArgumentException('Cache key contains reserved characters ' . $reserved);
}
Expand All @@ -83,7 +84,7 @@ public static function validateKey($key, $prefix = ''): string
* @param int $ttl Time to live
* @param Closure(): mixed $callback Callback return value
*
* @return array|bool|float|int|object|string|null
* @return mixed
*/
public function remember(string $key, int $ttl, Closure $callback)
{
Expand All @@ -103,7 +104,7 @@ public function remember(string $key, int $ttl, Closure $callback)
*
* @param string $pattern Cache items glob-style pattern
*
* @return int|never
* @return int
*
* @throws Exception
*/
Expand Down
61 changes: 44 additions & 17 deletions system/Cache/Handlers/FileHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,19 @@ class FileHandler extends BaseHandler
*/
public function __construct(Cache $config)
{
$this->path = ! empty($config->file['storePath']) ? $config->file['storePath'] : WRITEPATH . 'cache';
$this->path = rtrim($this->path, '/') . '/';
$options = [
...['storePath' => WRITEPATH . 'cache', 'mode' => 0640],
...$config->file,
];

$this->path = $options['storePath'] !== '' ? $options['storePath'] : WRITEPATH . 'cache';
$this->path = rtrim($this->path, '\\/') . '/';

if (! is_really_writable($this->path)) {
throw CacheException::forUnableToWrite($this->path);
}

$this->mode = $config->file['mode'] ?? 0640;
$this->mode = $options['mode'];
$this->prefix = $config->prefix;

helper('filesystem');
Expand Down Expand Up @@ -342,33 +347,46 @@ protected function deleteFiles(string $path, bool $delDir = false, bool $htdocs
* @param bool $topLevelOnly Look only at the top level directory specified?
* @param bool $_recursion Internal variable to determine recursion status - do not use in calls
*
* @return array|false
* @return array<string, array{
* name: string,
* server_path: string,
* size: int,
* date: int,
* relative_path: string,
* }>|false
*/
protected function getDirFileInfo(string $sourceDir, bool $topLevelOnly = true, bool $_recursion = false)
{
static $_filedata = [];
$relativePath = $sourceDir;
static $filedata = [];

$relativePath = $sourceDir;
$filePointer = @opendir($sourceDir);

if ($fp = @opendir($sourceDir)) {
if (! is_bool($filePointer)) {
// reset the array and make sure $sourceDir has a trailing slash on the initial call
if ($_recursion === false) {
$_filedata = [];
$sourceDir = rtrim(realpath($sourceDir) ?: $sourceDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$filedata = [];

$resolvedSrc = realpath($sourceDir);
$resolvedSrc = $resolvedSrc === false ? $sourceDir : $resolvedSrc;

$sourceDir = rtrim($resolvedSrc, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}

// Used to be foreach (scandir($sourceDir, 1) as $file), but scandir() is simply not as fast
while (false !== ($file = readdir($fp))) {
while (false !== $file = readdir($filePointer)) {
if (is_dir($sourceDir . $file) && $file[0] !== '.' && $topLevelOnly === false) {
$this->getDirFileInfo($sourceDir . $file . DIRECTORY_SEPARATOR, $topLevelOnly, true);
} elseif (! is_dir($sourceDir . $file) && $file[0] !== '.') {
$_filedata[$file] = $this->getFileInfo($sourceDir . $file);
$_filedata[$file]['relative_path'] = $relativePath;
$filedata[$file] = $this->getFileInfo($sourceDir . $file);

$filedata[$file]['relative_path'] = $relativePath;
}
}

closedir($fp);
closedir($filePointer);

return $_filedata;
return $filedata;
}

return false;
Expand All @@ -382,10 +400,19 @@ protected function getDirFileInfo(string $sourceDir, bool $topLevelOnly = true,
*
* @deprecated 4.6.1 Use `get_file_info()` instead.
*
* @param string $file Path to file
* @param array|string $returnedValues Array or comma separated string of information returned
* @param string $file Path to file
* @param list<string>|string $returnedValues Array or comma separated string of information returned
*
* @return array|false
* @return array{
* name?: string,
* server_path?: string,
* size?: int,
* date?: int,
* readable?: bool,
* writable?: bool,
* executable?: bool,
* fileperms?: int
* }|false
*/
protected function getFileInfo(string $file, $returnedValues = ['name', 'server_path', 'size', 'date'])
{
Expand Down
19 changes: 4 additions & 15 deletions system/Cache/Handlers/MemcachedHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MemcachedHandler extends BaseHandler
/**
* Memcached Configuration
*
* @var array
* @var array{host: string, port: int, weight: int, raw: bool}
*/
protected $config = [
'host' => '127.0.0.1',
Expand Down Expand Up @@ -76,43 +76,32 @@ public function initialize()
{
try {
if (class_exists(Memcached::class)) {
// Create new instance of Memcached
$this->memcached = new Memcached();

if ($this->config['raw']) {
$this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
}

// Add server
$this->memcached->addServer(
$this->config['host'],
$this->config['port'],
$this->config['weight'],
);

// attempt to get status of servers
$stats = $this->memcached->getStats();

// $stats should be an associate array with a key in the format of host:port.
// If it doesn't have the key, we know the server is not working as expected.
if (! isset($stats[$this->config['host'] . ':' . $this->config['port']])) {
if (! is_array($stats) || ! isset($stats[$this->config['host'] . ':' . $this->config['port']])) {
throw new CriticalError('Cache: Memcached connection failed.');
}
} elseif (class_exists(Memcache::class)) {
// Create new instance of Memcache
$this->memcached = new Memcache();

// Check if we can connect to the server
$canConnect = $this->memcached->connect(
$this->config['host'],
$this->config['port'],
);

// If we can't connect, throw a CriticalError exception
if ($canConnect === false) {
if (! $this->memcached->connect($this->config['host'], $this->config['port'])) {
throw new CriticalError('Cache: Memcache connection failed.');
}

// Add server, third parameter is persistence and defaults to TRUE.
$this->memcached->addServer(
$this->config['host'],
$this->config['port'],
Expand Down
Loading
Loading