FileCache::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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