Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0acca48

Browse files
committed
feature #17721 [Cache] Add FilesystemAdapter (nicolas-grekas)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Cache] Add FilesystemAdapter | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Commits ------- e5d6db5 [Cache] Add FilesystemAdapter
2 parents fb9a094 + e5d6db5 commit 0acca48

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Adapter;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Nicolas Grekas <[email protected]>
18+
*/
19+
class FilesystemAdapter extends AbstractAdapter
20+
{
21+
private $directory;
22+
23+
public function __construct($directory, $defaultLifetime = null)
24+
{
25+
parent::__construct('', $defaultLifetime);
26+
27+
if (!file_exists($dir = $directory.'/.')) {
28+
@mkdir($directory, 0777, true);
29+
}
30+
if (false === $dir = realpath($dir)) {
31+
throw new InvalidArgumentException(sprintf('Cache directory does not exist (%s)', $directory));
32+
}
33+
if (!is_writable($dir .= DIRECTORY_SEPARATOR)) {
34+
throw new InvalidArgumentException(sprintf('Cache directory is not writable (%s)', $directory));
35+
}
36+
// On Windows the whole path is limited to 258 chars
37+
if ('\\' === DIRECTORY_SEPARATOR && strlen($dir) > 190) {
38+
throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory));
39+
}
40+
41+
$this->directory = $dir;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
protected function doFetch(array $ids)
48+
{
49+
$values = array();
50+
$now = time();
51+
52+
foreach ($ids as $id) {
53+
$file = $this->getFile($id);
54+
if (!$h = @fopen($file, 'rb')) {
55+
continue;
56+
}
57+
flock($h, LOCK_SH);
58+
if ($now >= (int) $expiresAt = fgets($h)) {
59+
flock($h, LOCK_UN);
60+
fclose($h);
61+
if (isset($expiresAt[0])) {
62+
@unlink($file);
63+
}
64+
} else {
65+
$value = stream_get_contents($h);
66+
flock($h, LOCK_UN);
67+
fclose($h);
68+
$values[$id] = unserialize($value);
69+
}
70+
}
71+
72+
return $values;
73+
}
74+
75+
/**
76+
* {@inheritdoc}
77+
*/
78+
protected function doHave($id)
79+
{
80+
$file = $this->getFile($id);
81+
82+
return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
83+
}
84+
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
protected function doClear($namespace)
89+
{
90+
$ok = true;
91+
92+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
93+
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
94+
}
95+
96+
return $ok;
97+
}
98+
99+
/**
100+
* {@inheritdoc}
101+
*/
102+
protected function doDelete(array $ids)
103+
{
104+
$ok = true;
105+
106+
foreach ($ids as $id) {
107+
$file = $this->getFile($id);
108+
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
109+
}
110+
111+
return $ok;
112+
}
113+
114+
/**
115+
* {@inheritdoc}
116+
*/
117+
protected function doSave(array $values, $lifetime)
118+
{
119+
$ok = true;
120+
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
121+
122+
foreach ($values as $id => $value) {
123+
$file = $this->getFile($id);
124+
$dir = dirname($file);
125+
if (!file_exists($dir)) {
126+
@mkdir($dir, 0777, true);
127+
}
128+
$value = $expiresAt."\n".serialize($value);
129+
if (false !== @file_put_contents($file, $value, LOCK_EX)) {
130+
@touch($file, $expiresAt);
131+
} else {
132+
$ok = false;
133+
}
134+
}
135+
136+
return $ok;
137+
}
138+
139+
private function getFile($id)
140+
{
141+
$hash = hash('sha256', $id);
142+
143+
return $this->directory.$hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR.$hash;
144+
}
145+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Tests\Adapter;
13+
14+
use Cache\IntegrationTests\CachePoolTest;
15+
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
16+
17+
/**
18+
* @group time-sensitive
19+
*/
20+
class FilesystemAdapterTest extends CachePoolTest
21+
{
22+
public function createCachePool()
23+
{
24+
if (defined('HHVM_VERSION')) {
25+
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
26+
}
27+
28+
return new FilesystemAdapter(sys_get_temp_dir().DIRECTORY_SEPARATOR.'sf-cache');
29+
}
30+
}

0 commit comments

Comments
 (0)