-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathShmopClient.php
More file actions
149 lines (135 loc) · 4.05 KB
/
Copy pathShmopClient.php
File metadata and controls
149 lines (135 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
/*
* This file is part of the Koded package.
*
* (c) Mihail Binev <mihail@kodeart.com>
*
* Please view the LICENSE distributed with this source code
* for the full copyright and license information.
*/
namespace Koded\Caching\Client;
use Koded\Caching\{Cache, CacheException};
use function chmod;
use function file_get_contents;
use function file_put_contents;
use function fileinode;
use function glob;
use function is_dir;
use function Koded\Caching\verify_key;
use function mkdir;
use function rtrim;
use function serialize;
use function sha1;
use function shmop_delete;
use function shmop_open;
use function shmop_read;
use function shmop_size;
use function shmop_write;
use function strlen;
use function sys_get_temp_dir;
use function time;
use function touch;
use function umask;
use function unlink;
use function unserialize;
/**
* @property ShmopClient client
*
*/
final class ShmopClient implements Cache
{
use ClientTrait, MultiplesTrait;
private string $dir;
public function __construct(string $dir, ?int $ttl)
{
$this->dir = $dir;
$this->ttl = $ttl;
$this->setDirectory($dir);
}
public function get(string $key, mixed $default = null): mixed
{
if (false === $this->has($key, $filename)) {
return $default;
}
$resource = shmop_open(fileinode($filename), 'a', 0, 0);
return unserialize(shmop_read($resource, 0, shmop_size($resource)));
}
public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool
{
verify_key($key);
if (1 > $expiration = $this->timestampWithGlobalTtl($ttl, Cache::DATE_FAR_FAR_AWAY)) {
// The item is considered expired and must be deleted
return $this->delete($key);
}
$value = serialize($value);
$size = strlen($value);
$filename = $this->filename($key, true);
if (false === $resource = @shmop_open(fileinode($filename), 'n', 0666, $size)) {
$resource = shmop_open(fileinode($filename), 'w', 0666, $size);
}
return shmop_write($resource, $value, 0) === $size
&& false !== file_put_contents($filename . '-ttl', $expiration);
}
public function delete(string $key): bool
{
if (false === $this->has($key, $filename)) {
return true;
}
return $this->expire($filename);
}
public function clear(): bool
{
foreach ((glob($this->dir . 'shmop-*.cache*') ?: []) as $filename) {
$this->expire($filename);
}
return true;
}
public function has(string $key, &$filename = ''): bool
{
verify_key($key);
$filename = $this->filename($key, false);
$expiration = (int)(@file_get_contents($filename . '-ttl') ?: 0);
if ($expiration <= time()) {
$this->expire($filename);
return false;
}
return true;
}
private function filename(string $key, bool $create): string
{
$filename = $this->dir . 'shmop-' . sha1($key) . '.cache';
if ($create) {
touch($filename);
touch($filename . '-ttl');
chmod($filename, 0666);
chmod($filename . '-ttl', 0666);
}
return $filename;
}
/**
* Prepares the cache directory.
*
* @param string $directory
*
* @throws CacheException
*/
private function setDirectory(string $directory): void
{
// Overrule shell misconfiguration or the web server
umask(umask() | 0002);
$dir = $directory ?: sys_get_temp_dir();
$dir = rtrim($dir, '/') . '/';
if (false === is_dir($dir) && false === mkdir($dir, 0775, true)) {
throw CacheException::forCreatingDirectory($dir);
}
$this->dir = $dir;
}
private function expire(string $filename): bool
{
if (false === $resource = @shmop_open(fileinode($filename), 'w', 0, 0)) {
return false;
}
unlink($filename . '-ttl');
return shmop_delete($resource);
}
}