Passed
Push — master ( 89c195...0658f3 )
by y
07:57
created

FileCache::isGzEncoding()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Helix\Asana\Api;
4
5
use DateInterval;
6
use DateTime;
7
use Psr\SimpleCache\CacheInterface;
8
9
/**
10
 * A bare bones PSR-16 "compliant" file-based cache for {@see SimpleCache}.
11
 *
12
 * Use this if you don't have a better cache.
13
 *
14
 * This is not safe for concurrency.
15
 */
16
final class FileCache implements CacheInterface {
17
18
    /**
19
     * @var string
20
     */
21
    private $dir;
22
23
    /**
24
     * Compression.
25
     *
26
     * @var bool
27
     */
28
    private $gz;
29
30
    /**
31
     * @var LoggerInterface
32
     */
33
    private $logger;
34
35
    /**
36
     * @param string $dir
37
     * @param bool $gz
38
     */
39
    public function __construct (string $dir, $gz = false) {
40
        $this->dir = $dir;
41
        $this->gz = $gz;
42
    }
43
44
    private function _path ($key): string {
45
        $path = "{$this->dir}/{$key}~";
46
        clearstatcache(true, $path);
47
        return $path;
48
    }
49
50
    private function _ref ($key): string {
51
        return "{$this->dir}/{$key}.ref";
52
    }
53
54
    public function clear () {
55
        // unused. just delete the dir.
56
    }
57
58
    public function delete ($key) {
59
        $path = $this->_path($key);
60
        if (is_link($ref = $this->_ref($key))) {
61
            $this->log('CACHE DELINK', $key);
62
            unlink($ref);
63
            unlink($path);
64
        }
65
        elseif (is_file($path)) {
66
            $this->log('CACHE DELETE', $key);
67
            unlink($path);
68
        }
69
    }
70
71
    public function deleteMultiple ($keys) {
72
        // unused
73
    }
74
75
    public function get ($key, $default = null) {
76
        $path = $this->_path($key);
77
        if (is_file($path)) {
78
            if (filemtime($path) > time()) {
79
                $this->log('CACHE HIT', $key);
80
                $data = file_get_contents($path);
81
                if ($this->gz) {
82
                    $data = gzdecode($data);
83
                }
84
                return unserialize($data);
85
            }
86
            $this->log('CACHE EXPIRE', $key);
87
            unlink($path);
88
        }
89
        else {
90
            $this->log('CACHE MISS', $key);
91
        }
92
        return $default;
93
    }
94
95
    /**
96
     * @return LoggerInterface
97
     */
98
    public function getLogger () {
99
        return $this->logger;
100
    }
101
102
    public function getMultiple ($keys, $default = null) {
103
        // unused
104
    }
105
106
    public function has ($key) {
107
        // unused
108
    }
109
110
    private function log (string $msg, string $key): void {
111
        if ($this->logger) {
112
            $this->logger->log($msg, $key);
113
        }
114
    }
115
116
    /**
117
     * @param string $key
118
     * @param string|object $value
119
     * @param DateInterval $ttl
120
     * @return void
121
     */
122
    public function set ($key, $value, $ttl = null): void {
123
        assert($ttl instanceof DateInterval);
124
        $path = $this->_path($key);
125
        $data = serialize($value);
126
        if ($this->gz) {
127
            $data = gzencode($data);
128
        }
129
        if (!is_dir(dirname($path))) {
130
            mkdir(dirname($path), 0770, true);
131
        }
132
        if (is_object($value)) {
133
            $this->log('CACHE SET', $key);
134
            file_put_contents($path, $data);
135
        }
136
        elseif (!file_exists($path)) {
137
            $this->log('CACHE LINK', "{$key} => asana/{$value}");
138
            file_put_contents($path, $data);
139
            symlink($this->_path("asana/{$value}"), $this->_ref($key));
140
        }
141
        chmod($path, 0660);
142
        touch($path, (new DateTime())->add($ttl)->getTimeStamp());
143
    }
144
145
    /**
146
     * @param null|LoggerInterface $logger
147
     * @return $this
148
     */
149
    public function setLogger (?LoggerInterface $logger) {
150
        $this->logger = $logger;
151
        return $this;
152
    }
153
154
    public function setMultiple ($values, $ttl = null) {
155
        // unused
156
    }
157
}