8000 [Cache] Add FilesystemAdapter · symfony/symfony@9708558 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9708558

Browse files
[Cache] Add FilesystemAdapter
1 parent 80f3410 commit 9708558

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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 <p@tchwork.com>
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+
$dir = rtrim($directory, '/'.DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
28+
29+
if (!file_exists($dir)) {
30+
@mkdir($dir, 0777, true);
31+
}
32+
if (false === $dir = realpath($dir)) {
33+
throw new InvalidArgumentException(sprintf('Cache directory does not exist (%s)', $directory));
34+
}
35+
if (!is_writable($dir .= DIRECTORY_SEPARATOR)) {
36+
throw new InvalidArgumentException(sprintf('Cache directory is not writable (%s)', $directory));
37+
}
38+
// On Windows the whole path is limited to 258 chars
39+
if ('\\' === DIRECTORY_SEPARATOR && strlen($dir) > 190) {
40+
throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory));
41+
}
42+
43+
$this->directory = $dir;
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
protected function doFetch(array $ids)
50+
{
51+
$values = array();
52+
$now = time();
53+
54+
foreach ($ids as $id) {
55+
$file = $this->getFile($id);
56+
if (!$h = @fopen($file, 'rb')) {
57+
continue;
58+
}
59+
flock($h, LOCK_SH);
60+
if ($now >= (int) $expiresAt = fgets($h)) {
61+
flock($h, LOCK_UN);
62+
fclose($h);
63+
if (isset($expiresAt[0])) {
64+
@unlink($file);
65+
}
66+
} else {
67+
$value = stream_get_contents($h);
68+
flock($h, LOCK_UN);
69+
fclose($h);
70+
$values[$id] = unserialize($value);
71+
}
72+
}
73+
74+
return $values;
75+
}
76+
77+
/**
78+
* {@inheritdoc}
79+
*/
80+
protected function doHave($id)
81+
{
82+
$file = $this->getFile($id);
83+
84+
return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
protected function doClear($namespace)
91+
{
92+
$ok = true;
93+
94+
A3D4 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
95+
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
96+
}
97+
98+
return $ok;
99+
}
100+
101+
/**
102+
* {@inheritdoc}
103+
*/
104+
protected function doDelete(array $ids)
105+
{
106+
$ok = true;
107+
108+
foreach ($ids as $id) {
109+
$file = $this->getFile($id);
110+
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
111+
}
112+
113+
return $ok;
114+
}
115+
116+
/**
117+
* {@inheritdoc}
118+
*/
119+
protected function doSave(array $values, $lifetime)
120+
{
121+
$ok = true;
122+
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
123+
124+
foreach ($values as $id => $value) {
125+
$file = $this->getFile($id);
126+
$dir = dirname($file);
127+
if (!file_exists($dir)) {
128+
@mkdir($dir, 0777, true);
129+
}
130+
$value = $expiresAt."\n".serialize($value);
131+
if (false !== @file_put_contents($file, $value, LOCK_EX)) {
132+
@touch($file, $expiresAt);
133+
} else {
134+
$ok = false;
135+
}
136+
}
137+
138+
return $ok;
139+
}
140+
141+
private function getFile($id)
142+
{
143+
$hash = hash('sha256', $id);
144+
145+
return $this->directory.$hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR.$hash;
146+
}
147+
}
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 <fabien@symfony.com>
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)
0