Passed
Push — master ( 9ec6c5...85fa92 )
by y
02:17
created

FileCache   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 43
dl 0
loc 126
rs 10
c 1
b 0
f 0
wmc 24

15 Methods

Rating   Name   Duplication   Size   Complexity  
A isGzEncoding() 0 2 1
A __construct() 0 2 1
A getLogger() 0 2 1
A deleteMultiple() 0 1 1
A get() 0 14 4
A set() 0 18 5
A has() 0 1 1
A log() 0 3 2
A setLogger() 0 3 1
A clear() 0 1 1
A setMultiple() 0 1 1
A delete() 0 5 2
A setGzEncoding() 0 3 1
A getMultiple() 0 1 1
A _path() 0 4 1
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
     * @var bool
25
     */
26
    private $gzEncoding = false;
27
28
    /**
29
     * @var LoggerInterface
30
     */
31
    private $logger;
32
33
    public function __construct (string $dir) {
34
        $this->dir = $dir;
35
    }
36
37
    private function _path ($key) {
38
        $file = "{$this->dir}/{$key}~";
39
        clearstatcache(true, $file);
40
        return $file;
41
    }
42
43
    public function clear () {
44
        // unused. just delete the dir.
45
    }
46
47
    public function delete ($key) {
48
        $path = $this->_path($key);
49
        if (file_exists($path)) {
50
            $this->log('CACHE DELETE', $key);
51
            unlink($path);
52
        }
53
    }
54
55
    public function deleteMultiple ($keys) {
56
        // unused
57
    }
58
59
    public function get ($key, $default = null) {
60
        $path = $this->_path($key);
61
        if (file_exists($path)) {
62
            if (filemtime($path) > time()) {
63
                $this->log('CACHE HIT', $key);
64
                return unserialize($this->gzEncoding ? gzdecode(file_get_contents($path)) : file_get_contents($path));
65
            }
66
            $this->log('CACHE EXPIRE', $key);
67
            unlink($path);
68
        }
69
        else {
70
            $this->log('CACHE MISS', $key);
71
        }
72
        return $default;
73
    }
74
75
    /**
76
     * @return LoggerInterface
77
     */
78
    public function getLogger () {
79
        return $this->logger;
80
    }
81
82
    public function getMultiple ($keys, $default = null) {
83
        // unused
84
    }
85
86
    public function has ($key) {
87
        // unused
88
    }
89
90
    /**
91
     * @return bool
92
     */
93
    public function isGzEncoding (): bool {
94
        return $this->gzEncoding;
95
    }
96
97
    private function log (string $msg, string $key): void {
98
        if ($this->logger) {
99
            $this->logger->log($msg, $key);
100
        }
101
    }
102
103
    public function set ($key, $value, $ttl = null) {
104
        assert($ttl instanceof DateInterval);
105
        $this->log('CACHE SET', $key);
106
        $path = $this->_path($key);
107
        if (!is_dir(dirname($path))) {
108
            mkdir(dirname($path), 0770, true);
109
        }
110
        // if a gid ref is being stashed, make a symlink for quality of life.
111
        if (is_scalar($value)) {
112
            $link = substr($path, 0, -1) . '.ref';
113
            $real = $this->_path("asana/{$value}");
114
            if (!is_link($link)) {
115
                symlink($real, $link);
116
            }
117
        }
118
        file_put_contents($path, $this->gzEncoding ? gzencode(serialize($value)) : serialize($value));
119
        chmod($path, 0660);
120
        touch($path, (new DateTime())->add($ttl)->getTimeStamp());
121
    }
122
123
    /**
124
     * @param bool $gzEncoding
125
     * @return $this
126
     */
127
    public function setGzEncoding (bool $gzEncoding) {
128
        $this->gzEncoding = $gzEncoding;
129
        return $this;
130
    }
131
132
    /**
133
     * @param null|LoggerInterface $logger
134
     * @return $this
135
     */
136
    public function setLogger (?LoggerInterface $logger) {
137
        $this->logger = $logger;
138
        return $this;
139
    }
140
141
    public function setMultiple ($values, $ttl = null) {
142
        // unused
143
    }
144
}