-
Notifications
You must be signed in to change notification settings - Fork 3
/
CachingContainer.php
153 lines (137 loc) · 4.32 KB
/
CachingContainer.php
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
150
151
152
153
<?php
declare(strict_types=1);
namespace Dhii\Container;
use Dhii\Collection\ContainerInterface;
use Dhii\Container\Exception\ContainerException;
use Dhii\Container\Exception\NotFoundException;
use Dhii\Container\Util\StringTranslatingTrait;
use Exception;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* Caches entries from an internal container.
*
* @package Dhii\Container1
*/
class CachingContainer implements ContainerInterface
{
use StringTranslatingTrait;
/** @var array<array-key, mixed> */
protected $cache;
/** @var PsrContainerInterface */
protected $container;
/**
* @param PsrContainerInterface $container The container to cache entries from.
*/
public function __construct(PsrContainerInterface $container)
{
$this->container = $container;
$this->cache = [];
}
/**
* {@inheritDoc}
*/
public function get(string $key)
{
/**
* @psalm-suppress InvalidCatch
* The base interface does not extend Throwable, but in fact everything that is possible
* in theory to catch will be Throwable, and PSR-11 exceptions will implement this interface
*/
try {
/**
* @psalm-suppress MissingClosureReturnType
* Unable to specify mixed before PHP 8.
*/
$value = $this->getCached($key, function () use ($key) {
return $this->container->get($key);
});
} catch (NotFoundExceptionInterface $e) {
throw new NotFoundException($this->__('Key "%1$s" not found in inner container', [$key]), 0, $e);
} catch (Exception $e) {
throw new ContainerException(
$this->__('Could not retrieve value for key "%1$s" from inner container', [$key]),
0,
$e
);
}
return $value;
}
/**
* {@inheritDoc}
*/
public function has(string $key): bool
{
/**
* @psalm-suppress InvalidCatch
* The base interface does not extend Throwable, but in fact everything that is possible
* in theory to catch will be Throwable, and PSR-11 exceptions will implement this interface
*/
try {
if ($this->hasCached($key)) {
return true;
}
} catch (Exception $e) {
throw new ContainerException($this->__('Could not check cache for key "%1$s"', [$key]), 0, $e);
}
try {
if ($this->container->has($key)) {
return true;
}
} catch (Exception $e) {
throw new ContainerException(
$this->__('Could not check inner container for key "%1$s"', [$key]),
0,
$e
);
}
return false;
}
/**
* Retrieves a value by key from cache, creating it if it does not exist.
*
* @param string $key The key to get.
* @param callable $generator Creates the value.
*
* @return mixed The cached value.
*
* @throws Exception If problem caching.
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
*/
protected function getCached(string $key, callable $generator)
{
if (!array_key_exists($key, $this->cache)) {
$value = $this->invokeGenerator($generator);
$this->cache[$key] = $value;
}
return $this->cache[$key];
}
/**
* Checks the cache for the specified key.
*
* @param string $key The key to check for.
*
* @return bool True if cache contains the value; false otherwise.
*
* @throws Exception If problem checking.
*/
protected function hasCached(string $key): bool
{
return array_key_exists($key, $this->cache);
}
/**
* Generates a value by invoking the generator.
*
* @param callable $generator Generates a value.
*
* @return mixed The generated result.
*
* @throws Exception If problem generating.
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
*/
protected function invokeGenerator(callable $generator)
{
$result = $generator();
return $result;
}
}