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 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
 
621 lars 397
        $value = $callback();
148 lars 398
 
621 lars 399
        $this->put($key, $value, value($ttl, $value));
400
 
148 lars 401
        return $value;
402
    }
403
 
404
    /**
405
     * Get an item from the cache, or execute the given Closure and store the result forever.
406
     *
407
     * @template TCacheValue
408
     *
409
     * @param  string  $key
410
     * @param  \Closure(): TCacheValue  $callback
411
     * @return TCacheValue
412
     */
413
    public function sear($key, Closure $callback)
414
    {
415
        return $this->rememberForever($key, $callback);
416
    }
417
 
418
    /**
419
     * Get an item from the cache, or execute the given Closure and store the result forever.
420
     *
421
     * @template TCacheValue
422
     *
423
     * @param  string  $key
424
     * @param  \Closure(): TCacheValue  $callback
425
     * @return TCacheValue
426
     */
427
    public function rememberForever($key, Closure $callback)
428
    {
429
        $value = $this->get($key);
430
 
431
        // If the item exists in the cache we will just return this immediately
432
        // and if not we will execute the given Closure and cache the result
433
        // of that forever so it is available for all subsequent requests.
434
        if (! is_null($value)) {
435
            return $value;
436
        }
437
 
438
        $this->forever($key, $value = $callback());
439
 
440
        return $value;
441
    }
442
 
443
    /**
444
     * Remove an item from the cache.
445
     *
446
     * @param  string  $key
447
     * @return bool
448
     */
449
    public function forget($key)
450
    {
451
        return tap($this->store->forget($this->itemKey($key)), function ($result) use ($key) {
452
            if ($result) {
453
                $this->event(new KeyForgotten($key));
454
            }
455
        });
456
    }
457
 
458
    /**
459
     * {@inheritdoc}
460
     *
461
     * @return bool
462
     */
463
    public function delete($key): bool
464
    {
465
        return $this->forget($key);
466
    }
467
 
468
    /**
469
     * {@inheritdoc}
470
     *
471
     * @return bool
472
     */
473
    public function deleteMultiple($keys): bool
474
    {
475
        $result = true;
476
 
477
        foreach ($keys as $key) {
478
            if (! $this->forget($key)) {
479
                $result = false;
480
            }
481
        }
482
 
483
        return $result;
484
    }
485
 
486
    /**
487
     * {@inheritdoc}
488
     *
489
     * @return bool
490
     */
491
    public function clear(): bool
492
    {
493
        return $this->store->flush();
494
    }
495
 
496
    /**
497
     * Begin executing a new tags operation if the store supports it.
498
     *
499
     * @param  array|mixed  $names
500
     * @return \Illuminate\Cache\TaggedCache
501
     *
502
     * @throws \BadMethodCallException
503
     */
504
    public function tags($names)
505
    {
506
        if (! $this->supportsTags()) {
507
            throw new BadMethodCallException('This cache store does not support tagging.');
508
        }
509
 
510
        $cache = $this->store->tags(is_array($names) ? $names : func_get_args());
511
 
512
        if (! is_null($this->events)) {
513
            $cache->setEventDispatcher($this->events);
514
        }
515
 
516
        return $cache->setDefaultCacheTime($this->default);
517
    }
518
 
519
    /**
520
     * Format the key for a cache item.
521
     *
522
     * @param  string  $key
523
     * @return string
524
     */
525
    protected function itemKey($key)
526
    {
527
        return $key;
528
    }
529
 
530
    /**
531
     * Calculate the number of seconds for the given TTL.
532
     *
533
     * @param  \DateTimeInterface|\DateInterval|int  $ttl
534
     * @return int
535
     */
536
    protected function getSeconds($ttl)
537
    {
538
        $duration = $this->parseDateInterval($ttl);
539
 
540
        if ($duration instanceof DateTimeInterface) {
541
            $duration = Carbon::now()->diffInRealSeconds($duration, false);
542
        }
543
 
544
        return (int) ($duration > 0 ? $duration : 0);
545
    }
546
 
547
    /**
548
     * Determine if the current store supports tags.
549
     *
550
     * @return bool
551
     */
552
    public function supportsTags()
553
    {
554
        return method_exists($this->store, 'tags');
555
    }
556
 
557
    /**
558
     * Get the default cache time.
559
     *
560
     * @return int|null
561
     */
562
    public function getDefaultCacheTime()
563
    {
564
        return $this->default;
565
    }
566
 
567
    /**
568
     * Set the default cache time in seconds.
569
     *
570
     * @param  int|null  $seconds
571
     * @return $this
572
     */
573
    public function setDefaultCacheTime($seconds)
574
    {
575
        $this->default = $seconds;
576
 
577
        return $this;
578
    }
579
 
580
    /**
581
     * Get the cache store implementation.
582
     *
583
     * @return \Illuminate\Contracts\Cache\Store
584
     */
585
    public function getStore()
586
    {
587
        return $this->store;
588
    }
589
 
590
    /**
591
     * Fire an event for this cache instance.
592
     *
593
     * @param  object|string  $event
594
     * @return void
595
     */
596
    protected function event($event)
597
    {
598
        $this->events?->dispatch($event);
599
    }
600
 
601
    /**
602
     * Get the event dispatcher instance.
603
     *
604
     * @return \Illuminate\Contracts\Events\Dispatcher
605
     */
606
    public function getEventDispatcher()
607
    {
608
        return $this->events;
609
    }
610
 
611
    /**
612
     * Set the event dispatcher instance.
613
     *
614
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
615
     * @return void
616
     */
617
    public function setEventDispatcher(Dispatcher $events)
618
    {
619
        $this->events = $events;
620
    }
621
 
622
    /**
623
     * Determine if a cached value exists.
624
     *
625
     * @param  string  $key
626
     * @return bool
627
     */
628
    public function offsetExists($key): bool
629
    {
630
        return $this->has($key);
631
    }
632
 
633
    /**
634
     * Retrieve an item from the cache by key.
635
     *
636
     * @param  string  $key
637
     * @return mixed
638
     */
639
    public function offsetGet($key): mixed
640
    {
641
        return $this->get($key);
642
    }
643
 
644
    /**
645
     * Store an item in the cache for the default time.
646
     *
647
     * @param  string  $key
648
     * @param  mixed  $value
649
     * @return void
650
     */
651
    public function offsetSet($key, $value): void
652
    {
653
        $this->put($key, $value, $this->default);
654
    }
655
 
656
    /**
657
     * Remove an item from the cache.
658
     *
659
     * @param  string  $key
660
     * @return void
661
     */
662
    public function offsetUnset($key): void
663
    {
664
        $this->forget($key);
665
    }
666
 
667
    /**
668
     * Handle dynamic calls into macros or pass missing methods to the store.
669
     *
670
     * @param  string  $method
671
     * @param  array  $parameters
672
     * @return mixed
673
     */
674
    public function __call($method, $parameters)
675
    {
676
        if (static::hasMacro($method)) {
677
            return $this->macroCall($method, $parameters);
678
        }
679
 
680
        return $this->store->$method(...$parameters);
681
    }
682
 
683
    /**
684
     * Clone cache repository instance.
685
     *
686
     * @return void
687
     */
688
    public function __clone()
689
    {
690
        $this->store = clone $this->store;
691
    }
692
}