Project

General

Profile

1
<?php
2

    
3
/*
4
 * This file is part of Twig.
5
 *
6
 * (c) 2015 Fabien Potencier
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
/**
13
 * Implements a cache on the filesystem.
14
 *
15
 * @author Andrew Tch <andrew@noop.lv>
16
 */
17
class Twig_Cache_Filesystem implements Twig_CacheInterface
18
{
19
    const FORCE_BYTECODE_INVALIDATION = 1;
20

    
21
    private $directory;
22
    private $options;
23

    
24
    /**
25
     * @param $directory string The root cache directory
26
     * @param $options   int    A set of options
27
     */
28
    public function __construct($directory, $options = 0)
29
    {
30
        $this->directory = rtrim($directory, '\/').'/';
31
        $this->options = $options;
32
    }
33

    
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function generateKey($name, $className)
38
    {
39
        $hash = hash('sha256', $className);
40

    
41
        return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
42
    }
43

    
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function load($key)
48
    {
49
        @include_once $key;
50
    }
51

    
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function write($key, $content)
56
    {
57
        $dir = dirname($key);
58
        if (!is_dir($dir)) {
59
            if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
60
                throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
61
            }
62
        } elseif (!is_writable($dir)) {
63
            throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
64
        }
65

    
66
        $tmpFile = tempnam($dir, basename($key));
67
        if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
68
            @chmod($key, 0666 & ~umask());
69

    
70
            if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
71
                // Compile cached file into bytecode cache
72
                if (function_exists('opcache_invalidate')) {
73
                    opcache_invalidate($key, true);
74
                } elseif (function_exists('apc_compile_file')) {
75
                    apc_compile_file($key);
76
                }
77
            }
78

    
79
            return;
80
        }
81

    
82
        throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key));
83
    }
84

    
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function getTimestamp($key)
89
    {
90
        if (!file_exists($key)) {
91
            return 0;
92
        }
93

    
94
        return (int) @filemtime($key);
95
    }
96
}
(1-1/2)