Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cache File mode #4103

Merged
merged 5 commits into from
Jan 16, 2021
Merged
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
16 changes: 16 additions & 0 deletions app/Config/Cache.php
Original file line number Diff line number Diff line change
@@ -46,6 +46,8 @@ class Cache extends BaseConfig
* system.
*
* @var string
*
* @deprecated Use the driver-specific variant under $file
*/
public $storePath = WRITEPATH . 'cache/';

@@ -80,6 +82,20 @@ class Cache extends BaseConfig
*/
public $prefix = '';

/**
* --------------------------------------------------------------------------
* File settings
* --------------------------------------------------------------------------
* Your file storage preferences can be specified below, if you are using
* the File driver.
*
* @var array<string, string|int|null>
*/
public $file = [
'storePath' => WRITEPATH . 'cache/',
'mode' => 0640,
];

/**
* -------------------------------------------------------------------------
* Memcached settings
32 changes: 26 additions & 6 deletions system/Cache/Handlers/FileHandler.php
Original file line number Diff line number Diff line change
@@ -34,6 +34,16 @@ class FileHandler implements CacheInterface
*/
protected $path;

/**
* Mode for the stored files.
* Must be chmod-safe (octal).
*
* @var integer
*
* @see https://www.php.net/manual/en/function.chmod.php
*/
protected $mode;

//--------------------------------------------------------------------

/**
@@ -44,14 +54,24 @@ class FileHandler implements CacheInterface
*/
public function __construct(Cache $config)
{
$path = ! empty($config->storePath) ? $config->storePath : WRITEPATH . 'cache';
if (! is_really_writable($path))
if (! property_exists($config, 'file'))
{
$config->file = [
'storePath' => $config->storePath ?? WRITEPATH . 'cache',
'mode' => 0640,
];
}

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

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

$this->prefix = $config->prefix ?: '';
$this->path = rtrim($path, '/') . '/';
$this->mode = $config->file['mode'] ?? 0640;
$this->prefix = (string) $config->prefix;
}

//--------------------------------------------------------------------
@@ -105,7 +125,7 @@ public function save(string $key, $value, int $ttl = 60)

if ($this->writeFile($this->path . $key, serialize($contents)))
{
chmod($this->path . $key, 0640);
chmod($this->path . $key, $this->mode);

return true;
}
2 changes: 1 addition & 1 deletion system/Cache/Handlers/MemcachedHandler.php
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ class MemcachedHandler implements CacheInterface
*/
public function __construct(Cache $config)
{
$this->prefix = $config->prefix ?: '';
$this->prefix = (string) $config->prefix;

if (! empty($config))
{
2 changes: 1 addition & 1 deletion system/Cache/Handlers/PredisHandler.php
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ class PredisHandler implements CacheInterface
*/
public function __construct(Cache $config)
{
$this->prefix = $config->prefix ?: '';
$this->prefix = (string) $config->prefix;

if (isset($config->redis))
{
2 changes: 1 addition & 1 deletion system/Cache/Handlers/RedisHandler.php
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ class RedisHandler implements CacheInterface
*/
public function __construct(Cache $config)
{
$this->prefix = $config->prefix ?: '';
$this->prefix = (string) $config->prefix;

if (! empty($config))
{
2 changes: 1 addition & 1 deletion system/Cache/Handlers/WincacheHandler.php
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ class WincacheHandler implements CacheInterface
*/
public function __construct(Cache $config)
{
$this->prefix = $config->prefix ?: '';
$this->prefix = (string) $config->prefix;
}

//--------------------------------------------------------------------
71 changes: 53 additions & 18 deletions tests/system/Cache/Handlers/FileHandlerTest.php
Original file line number Diff line number Diff line change
@@ -26,13 +26,18 @@ protected function setUp(): void
{
parent::setUp();

//Initialize path
$this->config = new \Config\Cache();
$this->config->storePath .= self::$directory;
if (! function_exists('octal_permissions'))
{
helper('filesystem');
}

// Initialize path
$this->config = new \Config\Cache();
$this->config->file['storePath'] .= self::$directory;

if (! is_dir($this->config->storePath))
if (! is_dir($this->config->file['storePath']))
{
mkdir($this->config->storePath, 0777, true);
mkdir($this->config->file['storePath'], 0777, true);
}

$this->fileHandler = new FileHandler($this->config);
@@ -41,20 +46,20 @@ protected function setUp(): void

public function tearDown(): void
{
if (is_dir($this->config->storePath))
if (is_dir($this->config->file['storePath']))
{
chmod($this->config->storePath, 0777);
chmod($this->config->file['storePath'], 0777);

foreach (self::getKeyArray() as $key)
{
if (is_file($this->config->storePath . DIRECTORY_SEPARATOR . $key))
if (is_file($this->config->file['storePath'] . DIRECTORY_SEPARATOR . $key))
{
chmod($this->config->storePath . DIRECTORY_SEPARATOR . $key, 0777);
unlink($this->config->storePath . DIRECTORY_SEPARATOR . $key);
chmod($this->config->file['storePath'] . DIRECTORY_SEPARATOR . $key, 0777);
unlink($this->config->file['storePath'] . DIRECTORY_SEPARATOR . $key);
}
}

rmdir($this->config->storePath);
rmdir($this->config->file['storePath']);
}
}

@@ -67,15 +72,15 @@ public function testNewWithNonWritablePath()
{
$this->expectException('CodeIgniter\Cache\Exceptions\CacheException');

chmod($this->config->storePath, 0444);
chmod($this->config->file['storePath'], 0444);
new FileHandler($this->config);
}

public function testSetDefaultPath()
{
//Initialize path
$config = new \Config\Cache();
$config->storePath = null;
// Initialize path
$config = new \Config\Cache();
$config->file['storePath'] = null;

$this->fileHandler = new FileHandler($config);
$this->fileHandler->initialize();
@@ -98,7 +103,7 @@ public function testSave()
{
$this->assertTrue($this->fileHandler->save(self::$key1, 'value'));

chmod($this->config->storePath, 0444);
chmod($this->config->file['storePath'], 0444);
$this->assertFalse($this->fileHandler->save(self::$key2, 'value'));
}

@@ -173,6 +178,36 @@ public function testIsSupported()
$this->assertTrue($this->fileHandler->isSupported());
}

/**
* @dataProvider modeProvider
*/
public function testSaveMode($int, $string)
{
// Initialize mode
$config = new \Config\Cache();
$config->file['mode'] = $int;

$this->fileHandler = new FileHandler($config);
$this->fileHandler->initialize();

$this->fileHandler->save(self::$key1, 'value');

$file = $config->file['storePath'] . DIRECTORY_SEPARATOR . self::$key1;
$mode = octal_permissions(fileperms($file));

$this->assertEquals($string, $mode);
}

public function modeProvider()
{
return [
[0640, '640'],
[0600, '600'],
[0660, '660'],
[0777, '777'],
];
}

//--------------------------------------------------------------------

public function testFileHandler()
@@ -200,8 +235,8 @@ final class BaseTestFileHandler extends FileHandler

public function __construct()
{
$this->config = new \Config\Cache();
$this->config->storePath .= self::$directory;
$this->config = new \Config\Cache();
$this->config->file['storePath'] .= self::$directory;

parent::__construct($this->config);
}
2 changes: 2 additions & 0 deletions user_guide_src/source/changelogs/v4.0.5.rst
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ Enhancements:
- Support for setting SameSite attribute on Session and CSRF cookies has been added. For security and compatibility with latest browser versions, the default setting is ``Lax``.
- Guessing file extensions from mime type in ``Config\Mimes::guessExtensionFromType`` now only reverse searches the ``$mimes`` array if no extension is proposed (i.e., usually not for uploaded files).
- The getter functions for file extensions of uploaded files now have different fallback values (``$this->getClientExtension()`` for ``UploadedFile->getExtension()`` and ``''`` for ``UploadedFile->guessExtension()``). This is a security fix and makes the process less dependent on the client.
- The Cache ``FileHandler`` now allows setting the file permissions mode via ``Config\Cache``

Changes:

@@ -44,3 +45,4 @@ Deprecations:
- Deprecated ``CodeIgniter\Config\Config`` in favor of ``CodeIgniter\Config\Factories::config()``
- Deprecated ``CodeIgniter\HTTP\Message::getHeader`` in favor of ``header()`` to prepare for PSR-7
- Deprecated ``CodeIgniter\HTTP\Message::getHeaders`` in favor of ``headers()`` to prepare for PSR-7
- Deprecated ``Config\Cache::$storePath`` in favor of ``Config\Cache::$file['storePath']``
9 changes: 5 additions & 4 deletions user_guide_src/source/libraries/caching.rst
Original file line number Diff line number Diff line change
@@ -57,11 +57,11 @@ more complex, multi-server setups.
**$prefix**

If you have more than one application using the same cache storage, you can add a custom prefix
here that is prepended to all key names.
string here that is prepended to all key names.

**$path**
**$file**

This is used by the ``file`` handler to show where it should save the cache files to.
This is an array of settings specific to the ``File`` handler to determine how it should save the cache files.

**$memcached**

@@ -212,7 +212,8 @@ File-based Caching
Unlike caching from the Output Class, the driver file-based caching
allows for pieces of view files to be cached. Use this with care, and
make sure to benchmark your application, as a point can come where disk
I/O will negate positive gains by caching. This requires a writable cache directory to be really writable (0777).
I/O will negate positive gains by caching. This requires a cache
directory to be really writable by the application.

=================
Memcached Caching