Skip to content

Commit

Permalink
Merge pull request doctrine#151 from FabioBatSilva/DCOM101
Browse files Browse the repository at this point in the history
[DCOM-101] Implement FilesystemCache / PhpFileCache
  • Loading branch information
guilhermeblanco committed Jun 24, 2012
2 parents f0b548a + d06d9d5 commit 8df9cdf
Show file tree
Hide file tree
Showing 8 changed files with 613 additions and 5 deletions.
132 changes: 132 additions & 0 deletions lib/Doctrine/Common/Cache/FileCache.php
@@ -0,0 +1,132 @@
<?php

/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\Common\Cache;

/**
* Base file cache driver.
*
* @since 2.3
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
abstract class FileCache extends CacheProvider
{
/**
* @var string Cache directory.
*/
protected $directory;

/**
* @var string Cache file extension.
*/
protected $extension;

/**
* Constructor
*
* @param string $directory Cache directory.
* @param string $directory Cache file extension.
*
* @throws \InvalidArgumentException
*/
public function __construct($directory, $extension = null)
{
if ( ! is_dir($directory) && ! @mkdir($directory, 0777, true)) {
throw new \InvalidArgumentException(sprintf(
'The directory "%s" does not exist and could not be created.',
$directory
));
}

if ( ! is_writable($directory)) {
throw new \InvalidArgumentException(sprintf(
'The directory "%s" is not writable.',
$directory
));
}

$this->directory = realpath($directory);
$this->extension = $extension ?: $this->extension;
}

/**
* Gets the cache directory.
*
* @return string
*/
public function getDirectory()
{
return $this->directory;
}

/**
* Gets the cache file extension.
*
* @return string
*/
public function getExtension()
{
return $this->extension;
}

/**
* @return string
*/
protected function getFilename($id)
{
$path = implode(str_split(md5($id), 12), DIRECTORY_SEPARATOR);
$path = $this->directory . DIRECTORY_SEPARATOR . $path;

return $path . DIRECTORY_SEPARATOR . $id . $this->extension;
}

/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return unlink($this->getFilename($id));
}

/**
* {@inheritdoc}
*/
protected function doFlush()
{
$pattern = '/^.+\\' . $this->extension . '$/i';
$iterator = new \RecursiveDirectoryIterator($this->directory);
$iterator = new \RecursiveIteratorIterator($iterator);
$iterator = new \RegexIterator($iterator, $pattern);

foreach ($iterator as $name => $file) {
unlink($name);
}

return true;
}

/**
* {@inheritdoc}
*/
protected function doGetStats()
{
return null;
}
}
114 changes: 114 additions & 0 deletions lib/Doctrine/Common/Cache/FilesystemCache.php
@@ -0,0 +1,114 @@
<?php

/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\Common\Cache;

/**
* Filesystem cache driver.
*
* @since 2.3
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class FilesystemCache extends FileCache
{
const EXTENSION = '.doctrinecache.data';

/**
* {@inheritdoc}
*/
protected $extension = self::EXTENSION;

/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
$data = '';
$lifetime = -1;
$filename = $this->getFilename($id);

if ( ! file_exists($filename)) {
return false;
}

$resource = fopen($filename, "r");

if (false !== ($line = fgets($resource))) {
$lifetime = (integer) $line;
}

if ($lifetime !== 0 && $lifetime < time()) {
fclose($resource);

return false;
}

while (false !== ($line = fgets($resource))) {
$data .= $line;
}

fclose($resource);

return unserialize($data);
}

/**
* {@inheritdoc}
*/
protected function doContains($id)
{
$lifetime = -1;
$filename = $this->getFilename($id);

if ( ! file_exists($filename)) {
return false;
}

$resource = fopen($filename, "r");

if (false !== ($line = fgets($resource))) {
$lifetime = (integer) $line;
}

fclose($resource);

return $lifetime === 0 || $lifetime > time();
}

/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 0) {
$lifeTime = time() + $lifeTime;
}

$data = serialize($data);
$filename = $this->getFilename($id);
$filepath = pathinfo($filename, PATHINFO_DIRNAME);

if ( ! is_dir($filepath)) {
mkdir($filepath, 0777, true);
}

return file_put_contents($filename, $lifeTime . PHP_EOL . $data);
}
}
106 changes: 106 additions & 0 deletions lib/Doctrine/Common/Cache/PhpFileCache.php
@@ -0,0 +1,106 @@
<?php

/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\Common\Cache;

/**
* Php file cache driver.
*
* @since 2.3
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class PhpFileCache extends FileCache
{
const EXTENSION = '.doctrinecache.php';

/**
* {@inheritdoc}
*/
protected $extension = self::EXTENSION;

/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
$filename = $this->getFilename($id);

if ( ! file_exists($filename)) {
return false;
}

$value = include $filename;

if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) {
return false;
}

return $value['data'];
}

/**
* {@inheritdoc}
*/
protected function doContains($id)
{
$filename = $this->getFilename($id);

if ( ! file_exists($filename)) {
return false;
}

$value = include $filename;

return $value['lifetime'] === 0 || $value['lifetime'] > time();
}

/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 0) {
$lifeTime = time() + $lifeTime;
}

$filename = $this->getFilename($id);
$filepath = pathinfo($filename, PATHINFO_DIRNAME);
$serialize = is_object($data) && ! method_exists($data, '__set_state');

if ( ! is_dir($filepath)) {
mkdir($filepath, 0777, true);
}

$value = array(
'lifetime' => $lifeTime,
'data' => $data
);

if ($serialize) {
$value = serialize($value);
}

$value = var_export($value, true);
$code = $serialize ? "unserialize($value)" : $value;
$code = sprintf('<?php return %s;', $code);

return file_put_contents($filename, $code);
}
}
8 changes: 8 additions & 0 deletions tests/Doctrine/Tests/Common/Cache/ArrayCacheTest.php
Expand Up @@ -10,4 +10,12 @@ protected function _getCacheDriver()
{
return new ArrayCache();
}

public function testGetStats()
{
$cache = $this->_getCacheDriver();
$stats = $cache->getStats();

$this->assertNull($stats);
}
}
5 changes: 0 additions & 5 deletions tests/Doctrine/Tests/Common/Cache/CacheTest.php
Expand Up @@ -69,14 +69,9 @@ public function testNamespace()
*/
public function testGetStats()
{
if ($this instanceof ArrayCacheTest || $this instanceof ZendDataCacheTest ) {
$this->markTestSkipped("Statistics are not available for this driver");
}

$cache = $this->_getCacheDriver();
$stats = $cache->getStats();


$this->assertArrayHasKey(Cache::STATS_HITS, $stats);
$this->assertArrayHasKey(Cache::STATS_MISSES, $stats);
$this->assertArrayHasKey(Cache::STATS_UPTIME, $stats);
Expand Down

0 comments on commit 8df9cdf

Please sign in to comment.