Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Cache;
4
 
5
use ArrayAccess;
6
use BadMethodCallException;
7
use Closure;
8
use DateTimeInterface;
9
use Illuminate\Cache\Events\CacheHit;
10
use Illuminate\Cache\Events\CacheMissed;
11
use Illuminate\Cache\Events\KeyForgotten;
12
use Illuminate\Cache\Events\KeyWritten;
13
use Illuminate\Contracts\Cache\Repository as CacheContract;
14
use Illuminate\Contracts\Cache\Store;
15
use Illuminate\Contracts\Events\Dispatcher;
16
use Illuminate\Support\Carbon;
17
use Illuminate\Support\InteractsWithTime;
18
use Illuminate\Support\Traits\Macroable;
19
 
20
/**
21
 * @mixin \Illuminate\Contracts\Cache\Store
22
 */
23
class Repository implements ArrayAccess, CacheContract
24
{
25
    use InteractsWithTime;
26
    use Macroable {
27
        __call as macroCall;
28
    }
29
 
30
    /**
31
     * The cache store implementation.
32
     *
33
     * @var \Illuminate\Contracts\Cache\Store
34
     */
35
    protected $store;
36
 
37
    /**
38
     * The event dispatcher implementation.
39
     *
40
     * @var \Illuminate\Contracts\Events\Dispatcher
41
     */
42
    protected $events;
43
 
44
    /**
45
     * The default number of seconds to store items.
46
     *
47
     * @var int|null
48
     */
49
    protected $default = 3600;
50
 
51
    /**
52
     * Create a new cache repository instance.
53
     *
54
     * @param  \Illuminate\Contracts\Cache\Store  $store
55
     * @return void
56
     */
57
    public function __construct(Store $store)
58
    {
59
        $this->store = $store;
60
    }
61
 
62
    /**
63
     * Determine if an item exists in the cache.
64
     *
65
     * @param  array|string  $key
66
     * @return bool
67
     */
68
    public function has($key): bool
69
    {
70
        return ! is_null($this->get($key));
71
    }
72
 
73
    /**
74
     * Determine if an item doesn't exist in the cache.
75
     *
76
     * @param  string  $key
77
     * @return bool
78
     */
79
    public function missing($key)
80
    {
81
        return ! $this->has($key);
82
    }
83
 
84
    /**
85
     * Retrieve an item from the cache by key.
86
     *
87
     * @template TCacheValue
88
     *
89
     * @param  array|string  $key
90
     * @param  TCacheValue|(\Closure(): TCacheValue)  $default
91
     * @return (TCacheValue is null ? mixed : TCacheValue)
92
     */
93
    public function get($key, $default = null): mixed
94
    {
95
        if (is_array($key)) {
96
            return $this->many($key);
97
        }
98
 
99
        $value = $this->store->get($this->itemKey($key));
100
 
101
        // If we could not find the cache value, we will fire the missed event and get
102
        // the default value for this cache value. This default could be a callback
103
        // so we will execute the value function which will resolve it if needed.
104
        if (is_null($value)) {
105
            $this->event(new CacheMissed($key));
106
 
107
            $value = value($default);
108
        } else {
109
            $this->event(new CacheHit($key, $value));
110
        }
111
 
112
        return $value;
113
    }
114
 
115
    /**
116
     * Retrieve multiple items from the cache by key.
117
     *
118
     * Items not found in the cache will have a null value.
119
     *
120
     * @param  array  $keys
121
     * @return array
122
     */
123
    public function many(array $keys)
124
    {
125
        $values = $this->store->many(collect($keys)->map(function ($value, $key) {
126
            return is_string($key) ? $key : $value;
127
        })->values()->all());
128
 
129
        return collect($values)->map(function ($value, $key) use ($keys) {
130
            return $this->handleManyResult($keys, $key, $value);
131
        })->all();
132
    }
133
 
134
    /**
135
     * {@inheritdoc}
136
     *
137
     * @return iterable
138
     */
139
    public function getMultiple($keys, $default = null): iterable
140
    {
141
        $defaults = [];
142
 
143
        foreach ($keys as $key) {
144
            $defaults[$key] = $default;
145
        }
146
 
147
        return $this->many($defaults);
148
    }
149
 
150
    /**
151
     * Handle a result for the "many" method.
152
     *
153
     * @param  array  $keys
154
     * @param  string  $key
155
     * @param  mixed  $value
156
     * @return mixed
157
     */
158
    protected function handleManyResult($keys, $key, $value)
159
    {
160
        // If we could not find the cache value, we will fire the missed event and get
161
        // the default value for this cache value. This default could be a callback
162
        // so we will execute the value function which will resolve it if needed.
163
        if (is_null($value)) {
164
            $this->event(new CacheMissed($key));
165
 
166
            return isset($keys[$key]) ? value($keys[$key]) : null;
167
        }
168
 
169
        // If we found a valid value we will fire the "hit" event and return the value
170
        // back from this function. The "hit" event gives developers an opportunity
171
        // to listen for every possible cache "hit" throughout this applications.
172
        $this->event(new CacheHit($key, $value));
173
 
174
        return $value;
175
    }
176
 
177
    /**
178
     * Retrieve an item from the cache and delete it.
179
     *
180
     * @template TCacheValue
181
     *
182
     * @param  array|string  $key
183
     * @param  TCacheValue|(\Closure(): TCacheValue)  $default
184
     * @return (TCacheValue is null ? mixed : TCacheValue)
185
     */
186
    public function pull($key, $default = null)
187
    {
188
        return tap($this->get($key, $default), function () use ($key) {
189
            $this->forget($key);
190
        });
191
    }
192
 
193
    /**
194
     * Store an item in the cache.
195
     *
196
     * @param  array|string  $key
197
     * @param  mixed  $value
198
     * @param  \DateTimeInterface|\DateInterval|int|null  $ttl
199
     * @return bool
200
     */
201
    public function put($key, $value, $ttl = null)
202
    {
203
        if (is_array($key)) {
204
            return $this->putMany($key, $value);
205
        }
206
 
207
        if ($ttl === null) {
208
            return $this->forever($key, $value);
209
        }
210
 
211
        $seconds = $this->getSeconds($ttl);
212
 
213
        if ($seconds <= 0) {
214
            return $this->forget($key);
215
        }
216
 
217
        $result = $this->store->put($this->itemKey($key), $value, $seconds);
218
 
219
        if ($result) {
220
            $this->event(new KeyWritten($key, $value, $seconds));
221
        }
222
 
223
        return $result;
224
    }
225
 
226
    /**
227
     * {@inheritdoc}
228
     *
229
     * @return bool
230
     */
231
    public function set($key, $value, $ttl = null): bool
232
    {
233
        return $this->put($key, $value, $ttl);
234
    }
235
 
236
    /**
237
     * Store multiple items in the cache for a given number of seconds.
238
     *
239
     * @param  array  $values
240
     * @param  \DateTimeInterface|\DateInterval|int|null  $ttl
241
     * @return bool
242
     */
243
    public function putMany(array $values, $ttl = null)
244
    {
245
        if ($ttl === null) {
246
            return $this->putManyForever($values);
247
        }
248
 
249
        $seconds = $this->getSeconds($ttl);
250
 
251
        if ($seconds <= 0) {
252
            return $this->deleteMultiple(array_keys($values));
253
        }
254
 
255
        $result = $this->store->putMany($values, $seconds);
256
 
257
        if ($result) {
258
            foreach ($values as $key => $value) {
259
                $this->event(new KeyWritten($key, $value, $seconds));
260
            }
261
        }
262
 
263
        return $result;
264
    }
265
 
266
    /**
267
     * Store multiple items in the cache indefinitely.
268
     *
269
     * @param  array  $values
270
     * @return bool
271
     */
272
    protected function putManyForever(array $values)
273
    {
274
        $result = true;
275
 
276
        foreach ($values as $key => $value) {
277
            if (! $this->forever($key, $value)) {
278
                $result = false;
279
            }
280
        }
281
 
282
        return $result;
283
    }
284
 
285
    /**
286
     * {@inheritdoc}
287
     *
288
     * @return bool
289
     */
290
    public function setMultiple($values, $ttl = null): bool
291
    {
292
        return $this->putMany(is_array($values) ? $values : iterator_to_array($values), $ttl);
293
    }
294
 
295
    /**
296
     * Store an item in the cache if the key does not exist.
297
     *
298
     * @param  string  $key
299
     * @param  mixed  $value
300
     * @param  \DateTimeInterface|\DateInterval|int|null  $ttl
301
     * @return bool
302
     */
303
    public function add($key, $value, $ttl = null)
304
    {
305
        $seconds = null;
306
 
307
        if ($ttl !== null) {
308
            $seconds = $this->getSeconds($ttl);
309
 
310
            if ($seconds <= 0) {
311
                return false;
312
            }
313
 
314
            // If the store has an "add" method we will call the method on the store so it
315
            // has a chance to override this logic. Some drivers better support the way
316
            // this operation should work with a total "atomic" implementation of it.
317
            if (method_exists($this->store, 'add')) {
318
                return $this->store->add(
319
                    $this->itemKey($key), $value, $seconds
320
                );
321
            }
322
        }
323
 
324
        // If the value did not exist in the cache, we will put the value in the cache
325
        // so it exists for subsequent requests. Then, we will return true so it is
326
        // easy to know if the value gets added. Otherwise, we will return false.
327
        if (is_null($this->get($key))) {
328
            return $this->put($key, $value, $seconds);
329
        }
330
 
331
        return false;
332
    }
333
 
334
    /**
335
     * Increment the value of an item in the cache.
336
     *
337
     * @param  string  $key
338
     * @param  mixed  $value
339
     * @return int|bool
340
     */
341
    public function increment($key, $value = 1)
342
    {
343
        return $this->store->increment($key, $value);
344
    }
345
 
346
    /**
347
     * Decrement the value of an item in the cache.
348
     *
349
     * @param  string  $key
350
     * @param  mixed  $value
351
     * @return int|bool
352
     */
353
    public function decrement($key, $value = 1)
354
    {
355
        return $this->store->decrement($key, $value);
356
    }
357
 
358
    /**
359
     * Store an item in the cache indefinitely.
360
     *
361
     * @param  string  $key
362
     * @param  mixed  $value
363
     * @return bool
364
     */
365
    public function forever($key, $value)
366
    {
367
        $result = $this->store->forever($this->itemKey($key), $value);
368
 
369
        if ($result) {
370
            $this->event(new KeyWritten($key, $value));
371
        }
372
 
373
        return $result;
374
    }
375
 
376
    /**
377
     * Get an item from the cache, or execute the given Closure and store the result.
378
     *
379
     * @template TCacheValue
380
     *
381
     * @param  string  $key
382
     * @param  \Closure|\DateTimeInterface|\DateInterval|int|null  $ttl
383
     * @param  \Closure(): TCacheValue  $callback
384
     * @return TCacheValue
385
     */
386
    public function remember($key, $ttl, Closure $callback)
387
    {
388
        $value = $this->get($key);
389
 
390
        // If the item exists in the cache we will just return this immediately and if
391
        // not we will execute the given Closure and cache the result of that for a
392
        // given number of seconds so it's available for all subsequent requests.
393
        if (! is_null($value)) {
394
            return $value;
395
        }
396
 
397
        $this->put($key, $value = $callback(), value($ttl));
398
 
399
        return $value;
400
    }
401
 
402
    /**
403
     * Get an item from the cache, or execute the given Closure and store the result forever.
404
     *
405
     * @template TCacheValue
406
     *
407
     * @param  string  $key
408
     * @param  \Closure(): TCacheValue  $callback
409
     * @return TCacheValue
410
     */
411
    public function sear($key, Closure $callback)
412
    {
413
        return $this->rememberForever($key, $callback);
414
    }
415
 
416
    /**
417
     * Get an item from the cache, or execute the given Closure and store the result forever.
418
     *
419
     * @template TCacheValue
420
     *
421
     * @param  string  $key
422
     * @param  \Closure(): TCacheValue  $callback
423
     * @return TCacheValue
424
     */
425
    public function rememberForever($key, Closure $callback)
426
    {
427
        $value = $this->get($key);
428
 
429
        // If the item exists in the cache we will just return this immediately
430
        // and if not we will execute the given Closure and cache the result
431
        // of that forever so it is available for all subsequent requests.
432
        if (! is_null($value)) {
433
            return $value;
434
        }
435
 
436
        $this->forever($key, $value = $callback());
437
 
438
        return $value;
439
    }
440
 
441
    /**
442
     * Remove an item from the cache.
443
     *
444
     * @param  string  $key
445
     * @return bool
446
     */
447
    public function forget($key)
448
    {
449
        return tap($this->store->forget($this->itemKey($key)), function ($result) use ($key) {
450
            if ($result) {
451
                $this->event(new KeyForgotten($key));
452
            }
453
        });
454
    }
455
 
456
    /**
457
     * {@inheritdoc}
458
     *
459
     * @return bool
460
     */
461
    public function delete($key): bool
462
    {
463
        return $this->forget($key);
464
    }
465
 
466
    /**
467
     * {@inheritdoc}
468
     *
469
     * @return bool
470
     */
471
    public function deleteMultiple($keys): bool
472
    {
473
        $result = true;
474
 
475
        foreach ($keys as $key) {
476
            if (! $this->forget($key)) {
477
                $result = false;
478
            }
479
        }
480
 
481
        return $result;
482
    }
483
 
484
    /**
485
     * {@inheritdoc}
486
     *
487
     * @return bool
488
     */
489
    public function clear(): bool
490
    {
491
        return $this->store->flush();
492
    }
493
 
494
    /**
495
     * Begin executing a new tags operation if the store supports it.
496
     *
497
     * @param  array|mixed  $names
498
     * @return \Illuminate\Cache\TaggedCache
499
     *
500
     * @throws \BadMethodCallException
501
     */
502
    public function tags($names)
503
    {
504
        if (! $this->supportsTags()) {
505
            throw new BadMethodCallException('This cache store does not support tagging.');
506
        }
507
 
508
        $cache = $this->store->tags(is_array($names) ? $names : func_get_args());
509
 
510
        if (! is_null($this->events)) {
511
            $cache->setEventDispatcher($this->events);
512
        }
513
 
514
        return $cache->setDefaultCacheTime($this->default);
515
    }
516
 
517
    /**
518
     * Format the key for a cache item.
519
     *
520
     * @param  string  $key
521
     * @return string
522
     */
523
    protected function itemKey($key)
524
    {
525
        return $key;
526
    }
527
 
528
    /**
529
     * Calculate the number of seconds for the given TTL.
530
     *
531
     * @param  \DateTimeInterface|\DateInterval|int  $ttl
532
     * @return int
533
     */
534
    protected function getSeconds($ttl)
535
    {
536
        $duration = $this->parseDateInterval($ttl);
537
 
538
        if ($duration instanceof DateTimeInterface) {
539
            $duration = Carbon::now()->diffInRealSeconds($duration, false);
540
        }
541
 
542
        return (int) ($duration > 0 ? $duration : 0);
543
    }
544
 
545
    /**
546
     * Determine if the current store supports tags.
547
     *
548
     * @return bool
549
     */
550
    public function supportsTags()
551
    {
552
        return method_exists($this->store, 'tags');
553
    }
554
 
555
    /**
556
     * Get the default cache time.
557
     *
558
     * @return int|null
559
     */
560
    public function getDefaultCacheTime()
561
    {
562
        return $this->default;
563
    }
564
 
565
    /**
566
     * Set the default cache time in seconds.
567
     *
568
     * @param  int|null  $seconds
569
     * @return $this
570
     */
571
    public function setDefaultCacheTime($seconds)
572
    {
573
        $this->default = $seconds;
574
 
575
        return $this;
576
    }
577
 
578
    /**
579
     * Get the cache store implementation.
580
     *
581
     * @return \Illuminate\Contracts\Cache\Store
582
     */
583
    public function getStore()
584
    {
585
        return $this->store;
586
    }
587
 
588
    /**
589
     * Fire an event for this cache instance.
590
     *
591
     * @param  object|string  $event
592
     * @return void
593
     */
594
    protected function event($event)
595
    {
596
        $this->events?->dispatch($event);
597
    }
598
 
599
    /**
600
     * Get the event dispatcher instance.
601
     *
602
     * @return \Illuminate\Contracts\Events\Dispatcher
603
     */
604
    public function getEventDispatcher()
605
    {
606
        return $this->events;
607
    }
608
 
609
    /**
610
     * Set the event dispatcher instance.
611
     *
612
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
613
     * @return void
614
     */
615
    public function setEventDispatcher(Dispatcher $events)
616
    {
617
        $this->events = $events;
618
    }
619
 
620
    /**
621
     * Determine if a cached value exists.
622
     *
623
     * @param  string  $key
624
     * @return bool
625
     */
626
    public function offsetExists($key): bool
627
    {
628
        return $this->has($key);
629
    }
630
 
631
    /**
632
     * Retrieve an item from the cache by key.
633
     *
634
     * @param  string  $key
635
     * @return mixed
636
     */
637
    public function offsetGet($key): mixed
638
    {
639
        return $this->get($key);
640
    }
641
 
642
    /**
643
     * Store an item in the cache for the default time.
644
     *
645
     * @param  string  $key
646
     * @param  mixed  $value
647
     * @return void
648
     */
649
    public function offsetSet($key, $value): void
650
    {
651
        $this->put($key, $value, $this->default);
652
    }
653
 
654
    /**
655
     * Remove an item from the cache.
656
     *
657
     * @param  string  $key
658
     * @return void
659
     */
660
    public function offsetUnset($key): void
661
    {
662
        $this->forget($key);
663
    }
664
 
665
    /**
666
     * Handle dynamic calls into macros or pass missing methods to the store.
667
     *
668
     * @param  string  $method
669
     * @param  array  $parameters
670
     * @return mixed
671
     */
672
    public function __call($method, $parameters)
673
    {
674
        if (static::hasMacro($method)) {
675
            return $this->macroCall($method, $parameters);
676
        }
677
 
678
        return $this->store->$method(...$parameters);
679
    }
680
 
681
    /**
682
     * Clone cache repository instance.
683
     *
684
     * @return void
685
     */
686
    public function __clone()
687
    {
688
        $this->store = clone $this->store;
689
    }
690
}