Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Cache;
4
 
5
use Exception;
6
use Illuminate\Contracts\Cache\LockProvider;
7
use Illuminate\Contracts\Cache\Store;
8
use Illuminate\Contracts\Filesystem\LockTimeoutException;
9
use Illuminate\Filesystem\Filesystem;
10
use Illuminate\Filesystem\LockableFile;
11
use Illuminate\Support\InteractsWithTime;
12
 
13
class FileStore implements Store, LockProvider
14
{
621 lars 15
    use InteractsWithTime, RetrievesMultipleKeys;
148 lars 16
 
17
    /**
18
     * The Illuminate Filesystem instance.
19
     *
20
     * @var \Illuminate\Filesystem\Filesystem
21
     */
22
    protected $files;
23
 
24
    /**
25
     * The file cache directory.
26
     *
27
     * @var string
28
     */
29
    protected $directory;
30
 
31
    /**
32
     * Octal representation of the cache file permissions.
33
     *
34
     * @var int|null
35
     */
36
    protected $filePermission;
37
 
38
    /**
39
     * Create a new file cache store instance.
40
     *
41
     * @param  \Illuminate\Filesystem\Filesystem  $files
42
     * @param  string  $directory
43
     * @param  int|null  $filePermission
44
     * @return void
45
     */
46
    public function __construct(Filesystem $files, $directory, $filePermission = null)
47
    {
48
        $this->files = $files;
49
        $this->directory = $directory;
50
        $this->filePermission = $filePermission;
51
    }
52
 
53
    /**
54
     * Retrieve an item from the cache by key.
55
     *
56
     * @param  string|array  $key
57
     * @return mixed
58
     */
59
    public function get($key)
60
    {
61
        return $this->getPayload($key)['data'] ?? null;
62
    }
63
 
64
    /**
65
     * Store an item in the cache for a given number of seconds.
66
     *
67
     * @param  string  $key
68
     * @param  mixed  $value
69
     * @param  int  $seconds
70
     * @return bool
71
     */
72
    public function put($key, $value, $seconds)
73
    {
74
        $this->ensureCacheDirectoryExists($path = $this->path($key));
75
 
76
        $result = $this->files->put(
77
            $path, $this->expiration($seconds).serialize($value), true
78
        );
79
 
80
        if ($result !== false && $result > 0) {
81
            $this->ensurePermissionsAreCorrect($path);
82
 
83
            return true;
84
        }
85
 
86
        return false;
87
    }
88
 
89
    /**
90
     * Store an item in the cache if the key doesn't exist.
91
     *
92
     * @param  string  $key
93
     * @param  mixed  $value
94
     * @param  int  $seconds
95
     * @return bool
96
     */
97
    public function add($key, $value, $seconds)
98
    {
99
        $this->ensureCacheDirectoryExists($path = $this->path($key));
100
 
101
        $file = new LockableFile($path, 'c+');
102
 
103
        try {
104
            $file->getExclusiveLock();
105
        } catch (LockTimeoutException $e) {
106
            $file->close();
107
 
108
            return false;
109
        }
110
 
111
        $expire = $file->read(10);
112
 
113
        if (empty($expire) || $this->currentTime() >= $expire) {
114
            $file->truncate()
115
                ->write($this->expiration($seconds).serialize($value))
116
                ->close();
117
 
118
            $this->ensurePermissionsAreCorrect($path);
119
 
120
            return true;
121
        }
122
 
123
        $file->close();
124
 
125
        return false;
126
    }
127
 
128
    /**
129
     * Create the file cache directory if necessary.
130
     *
131
     * @param  string  $path
132
     * @return void
133
     */
134
    protected function ensureCacheDirectoryExists($path)
135
    {
136
        $directory = dirname($path);
137
 
138
        if (! $this->files->exists($directory)) {
139
            $this->files->makeDirectory($directory, 0777, true, true);
140
 
141
            // We're creating two levels of directories (e.g. 7e/24), so we check them both...
142
            $this->ensurePermissionsAreCorrect($directory);
143
            $this->ensurePermissionsAreCorrect(dirname($directory));
144
        }
145
    }
146
 
147
    /**
148
     * Ensure the created node has the correct permissions.
149
     *
150
     * @param  string  $path
151
     * @return void
152
     */
153
    protected function ensurePermissionsAreCorrect($path)
154
    {
155
        if (is_null($this->filePermission) ||
156
            intval($this->files->chmod($path), 8) == $this->filePermission) {
157
            return;
158
        }
159
 
160
        $this->files->chmod($path, $this->filePermission);
161
    }
162
 
163
    /**
164
     * Increment the value of an item in the cache.
165
     *
166
     * @param  string  $key
167
     * @param  mixed  $value
168
     * @return int
169
     */
170
    public function increment($key, $value = 1)
171
    {
172
        $raw = $this->getPayload($key);
173
 
174
        return tap(((int) $raw['data']) + $value, function ($newValue) use ($key, $raw) {
175
            $this->put($key, $newValue, $raw['time'] ?? 0);
176
        });
177
    }
178
 
179
    /**
180
     * Decrement the value of an item in the cache.
181
     *
182
     * @param  string  $key
183
     * @param  mixed  $value
184
     * @return int
185
     */
186
    public function decrement($key, $value = 1)
187
    {
188
        return $this->increment($key, $value * -1);
189
    }
190
 
191
    /**
192
     * Store an item in the cache indefinitely.
193
     *
194
     * @param  string  $key
195
     * @param  mixed  $value
196
     * @return bool
197
     */
198
    public function forever($key, $value)
199
    {
200
        return $this->put($key, $value, 0);
201
    }
202
 
203
    /**
621 lars 204
     * Get a lock instance.
205
     *
206
     * @param  string  $name
207
     * @param  int  $seconds
208
     * @param  string|null  $owner
209
     * @return \Illuminate\Contracts\Cache\Lock
210
     */
211
    public function lock($name, $seconds = 0, $owner = null)
212
    {
213
        return new FileLock($this, $name, $seconds, $owner);
214
    }
215
 
216
    /**
217
     * Restore a lock instance using the owner identifier.
218
     *
219
     * @param  string  $name
220
     * @param  string  $owner
221
     * @return \Illuminate\Contracts\Cache\Lock
222
     */
223
    public function restoreLock($name, $owner)
224
    {
225
        return $this->lock($name, 0, $owner);
226
    }
227
 
228
    /**
148 lars 229
     * Remove an item from the cache.
230
     *
231
     * @param  string  $key
232
     * @return bool
233
     */
234
    public function forget($key)
235
    {
236
        if ($this->files->exists($file = $this->path($key))) {
237
            return $this->files->delete($file);
238
        }
239
 
240
        return false;
241
    }
242
 
243
    /**
244
     * Remove all items from the cache.
245
     *
246
     * @return bool
247
     */
248
    public function flush()
249
    {
250
        if (! $this->files->isDirectory($this->directory)) {
251
            return false;
252
        }
253
 
254
        foreach ($this->files->directories($this->directory) as $directory) {
255
            $deleted = $this->files->deleteDirectory($directory);
256
 
257
            if (! $deleted || $this->files->exists($directory)) {
258
                return false;
259
            }
260
        }
261
 
262
        return true;
263
    }
264
 
265
    /**
266
     * Retrieve an item and expiry time from the cache by key.
267
     *
268
     * @param  string  $key
269
     * @return array
270
     */
271
    protected function getPayload($key)
272
    {
273
        $path = $this->path($key);
274
 
275
        // If the file doesn't exist, we obviously cannot return the cache so we will
276
        // just return null. Otherwise, we'll get the contents of the file and get
277
        // the expiration UNIX timestamps from the start of the file's contents.
278
        try {
279
            $expire = substr(
280
                $contents = $this->files->get($path, true), 0, 10
281
            );
282
        } catch (Exception $e) {
283
            return $this->emptyPayload();
284
        }
285
 
286
        // If the current time is greater than expiration timestamps we will delete
287
        // the file and return null. This helps clean up the old files and keeps
288
        // this directory much cleaner for us as old files aren't hanging out.
289
        if ($this->currentTime() >= $expire) {
290
            $this->forget($key);
291
 
292
            return $this->emptyPayload();
293
        }
294
 
295
        try {
296
            $data = unserialize(substr($contents, 10));
297
        } catch (Exception $e) {
298
            $this->forget($key);
299
 
300
            return $this->emptyPayload();
301
        }
302
 
303
        // Next, we'll extract the number of seconds that are remaining for a cache
304
        // so that we can properly retain the time for things like the increment
305
        // operation that may be performed on this cache on a later operation.
306
        $time = $expire - $this->currentTime();
307
 
308
        return compact('data', 'time');
309
    }
310
 
311
    /**
312
     * Get a default empty payload for the cache.
313
     *
314
     * @return array
315
     */
316
    protected function emptyPayload()
317
    {
318
        return ['data' => null, 'time' => null];
319
    }
320
 
321
    /**
322
     * Get the full path for the given cache key.
323
     *
324
     * @param  string  $key
325
     * @return string
326
     */
327
    protected function path($key)
328
    {
329
        $parts = array_slice(str_split($hash = sha1($key), 2), 0, 2);
330
 
331
        return $this->directory.'/'.implode('/', $parts).'/'.$hash;
332
    }
333
 
334
    /**
335
     * Get the expiration time based on the given seconds.
336
     *
337
     * @param  int  $seconds
338
     * @return int
339
     */
340
    protected function expiration($seconds)
341
    {
342
        $time = $this->availableAt($seconds);
343
 
344
        return $seconds === 0 || $time > 9999999999 ? 9999999999 : $time;
345
    }
346
 
347
    /**
348
     * Get the Filesystem instance.
349
     *
350
     * @return \Illuminate\Filesystem\Filesystem
351
     */
352
    public function getFilesystem()
353
    {
354
        return $this->files;
355
    }
356
 
357
    /**
358
     * Get the working directory of the cache.
359
     *
360
     * @return string
361
     */
362
    public function getDirectory()
363
    {
364
        return $this->directory;
365
    }
366
 
367
    /**
368
     * Get the cache key prefix.
369
     *
370
     * @return string
371
     */
372
    public function getPrefix()
373
    {
374
        return '';
375
    }
376
}