Passed
Pull Request — main (#9)
by
unknown
07:12 queued 03:32
created

MockCache::getMetaData()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 13
ccs 0
cts 3
cp 0
crap 20
rs 10
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Spec\Mock;
13
14
use BlitzPHP\Cache\CacheInterface;
15
use BlitzPHP\Cache\Handlers\BaseHandler;
16
use BlitzPHP\Utilities\Date;
17
use DateInterval;
18
19
class MockCache extends BaseHandler implements CacheInterface
20
{
21
    /**
22
     * stockage des mocks de cache.
23
     *
24
     * @var array<string, mixed>
25
     */
26
    protected array $cache = [];
27
28
    /**
29
     * Temps d'expiration.
30
     *
31
     * @var int[]
32
     */
33
    protected array $expirations = [];
34
35
    /**
36
     * Si true, nous ne mettons aucune donnees en cache.
37
     */
38
    protected bool $bypass = false;
39
40
    /**
41
     * {@inheritDoc}
42
     *
43
     * @return bool|null
44
     */
45
    public function get(string $key, mixed $default = null): mixed
46
    {
47 10
        $key = $this->_key($key);
48
49 10
        return array_key_exists($key, $this->cache) ? $this->cache[$key] : null;
50
    }
51
52
    /**
53
     * {@inheritDoc}
54
     */
55
    public function set(string $key, mixed $value, null|DateInterval|int $ttl = null): bool
56
    {
57
        if ($this->bypass) {
58
            return false;
59
        }
60
61 2
        $key = $this->_key($key);
62
63 2
        $this->cache[$key]       = $value;
64 2
        $this->expirations[$key] = $ttl > 0 ? Date::now()->getTimestamp() + $ttl : null;
65
66 2
        return true;
67
    }
68
69
    /**
70
     * {@inheritDoc}
71
     */
72
    public function delete(string $key): bool
73
    {
74
        $key = $this->_key($key);
75
76
        if (! isset($this->cache[$key])) {
77
            return false;
78
        }
79
80
        unset($this->cache[$key], $this->expirations[$key]);
81
82
        return true;
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     *
88
     * @return int
89
     */
90
    public function deleteMatching(string $pattern)
91
    {
92
        $count = 0;
93
94
        foreach (array_keys($this->cache) as $key) {
95
            if (fnmatch($pattern, $key)) {
96
                $count++;
97
                unset($this->cache[$key], $this->expirations[$key]);
98
            }
99
        }
100
101
        return $count;
102
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107
    public function increment(string $key, int $offset = 1)
108
    {
109
        $key  = $this->_key($key);
110
        $data = $this->cache[$key] ?: null;
111
112
        if ($data === null) {
113
            $data = 0;
114
        } elseif (! is_int($data)) {
115
            return false;
116
        }
117
118
        return $this->set($key, $data + $offset);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->set($key, $data + $offset) returns the type boolean which is incompatible with the return type mandated by BlitzPHP\Cache\CacheInterface::increment() of false|integer.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     */
124
    public function decrement(string $key, int $offset = 1)
125
    {
126
        $key = $this->_key($key);
127
128
        $data = $this->cache[$key] ?: null;
129
130
        if ($data === null) {
131
            $data = 0;
132
        } elseif (! is_int($data)) {
133
            return false;
134
        }
135
136
        return $this->set($key, $data - $offset);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->set($key, $data - $offset) returns the type boolean which is incompatible with the return type mandated by BlitzPHP\Cache\CacheInterface::decrement() of false|integer.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142
    public function clear(): bool
143
    {
144 2
        $this->cache       = [];
145 2
        $this->expirations = [];
146
147 2
        return true;
148
    }
149
150
    /**
151
     * {@inheritDoc}
152
     */
153
    public function clearGroup(string $group): bool
154
    {
155
        return $this->deleteMatching($group) > 0;
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     *
161
     * @return string[] Keys currently present in the store
162
     */
163
    public function info(): array
164
    {
165
        return array_keys($this->cache);
166
    }
167
168
    /**
169
     * Renvoie des informations détaillées sur l'élément spécifique du cache.
170
     *
171
     * @return array|null Retourne null si l'élément n'existe pas, sinon array<string, mixed>
172
     *                    avec au moins la clé 'expire' pour une expiration absolue (ou null).
173
     */
174
    public function getMetaData(string $key): ?array
175
    {
176
        // n'existe pas, retourne null
177
        if (! array_key_exists($key, $this->expirations)) {
178
            return null;
179
        }
180
181
        //  Compter les elements périmés comme un manque
182
        if (is_int($this->expirations[$key]) && $this->expirations[$key] > Date::now()->getTimestamp()) {
183
            return null;
184
        }
185
186
        return ['expire' => $this->expirations[$key]];
187
    }
188
189
    // --------------------------------------------------------------------
190
    // Helpers de test
191
    // --------------------------------------------------------------------
192
193
    /**
194
     * Indique à la classe d'ignorer toutes les demandes de mise en cache d'un élément,
195
     * et de toujours "manquer" lorsqu'on vérifie la présence de données existantes.
196
     */
197
    public function bypass(bool $bypass = true): self
198
    {
199
        $this->clear();
200
        $this->bypass = $bypass;
201
202
        return $this;
203
    }
204
205
    // --------------------------------------------------------------------
206
    // Additional Assertions
207
    // --------------------------------------------------------------------
208
209
    /**
210
     * Affirme que le cache possède un élément nommé $key.
211
     * La valeur n'est pas vérifiée puisque le stockage de valeurs fausses ou nulles est valide.
212
     */
213
    public function assertHas(string $key): void
214
    {
215
        expect($this->get($key))->not->toBeNull();
216
        // Assert::assertNotNull($this->get($key), "Le cache n'a pas un élément nommé: `{$key}`");
217
    }
218
219
    /**
220
     * Affirme que le cache possède un élément nommé $key dont la valeur correspond à $value.
221
     */
222
    public function assertHasValue(string $key, mixed $value = null): void
223
    {
224
        $item = $this->get($key);
225
226
        // Laissez la fonction assertHas() gérer l'erreur de cohérence si la clé n'est pas trouvée.
227
        if ($item === null) {
228
            $this->assertHas($key);
229
        }
230
231
        expect($this->get($key))->toBe($value);
232
        // Assert::assertSame($value, $this->get($key), "L'élément `{$key}` du cache ne correspond pas à la valeur attendue. Trouvée: " . print_r($value, true));
233
    }
234
235
    /**
236
     * Affirme que le cache ne possède pas un élément nommé $key.
237
     */
238
    public function assertMissing(string $key): void
239
    {
240
        expect($this->cache)->not->toContainKey($key);
241
        // Assert::assertArrayNotHasKey($key, $this->cache, "L'élément en cache nommé `{$key}` existe.");
242
    }
243
}
244