DriverBaseTrait::driverUnwrapMdate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 *
5
 * This file is part of Phpfastcache.
6
 *
7
 * @license MIT License (MIT)
8
 *
9
 * For full copyright and license information, please see the docs/CREDITS.txt and LICENCE files.
10
 *
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 * @author Contributors  https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phpfastcache\Core\Pool;
18
19
use DateTime;
20
use DateTimeInterface;
21
use Phpfastcache\Config\ConfigurationOptionInterface;
22
use Phpfastcache\Event\Event;
23
use Phpfastcache\Event\EventManagerDispatcherTrait;
24
use Phpfastcache\Event\EventManagerInterface;
25
use Phpfastcache\Exceptions\PhpfastcacheCorruptedDataException;
26
use Phpfastcache\Exceptions\PhpfastcacheDriverException;
27
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
28
use Phpfastcache\Util\ClassNamespaceResolverTrait;
29
use Throwable;
30
use Phpfastcache\Config\ConfigurationOption;
31
use Phpfastcache\Core\Item\ExtendedCacheItemInterface;
32
use Phpfastcache\Entities\DriverIO;
33
use Phpfastcache\Exceptions\PhpfastcacheCoreException;
34
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
35
use Phpfastcache\Exceptions\PhpfastcacheDriverConnectException;
36
use Phpfastcache\Exceptions\PhpfastcacheIOException;
37
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
38
use ReflectionObject;
39
40
trait DriverBaseTrait
41
{
42
    use DriverPoolAbstractTrait;
43
    use ClassNamespaceResolverTrait;
44
    use EventManagerDispatcherTrait;
45
46
    /**
47
     * @var string[]
48
     */
49
    protected static array $cacheItemClasses = [];
50
51
    protected ConfigurationOptionInterface $config;
52
53
    /**
54
     * @var object|null
55
     */
56
    protected ?object $instance;
57
58
    protected string $driverName;
59
60
    protected string $instanceId;
61
62
    /**
63
     * Driver constructor.
64
     * @param ConfigurationOptionInterface $config
65
     * @param string $instanceId
66
     * @param EventManagerInterface $em
67
     * @throws PhpfastcacheCoreException
68
     * @throws PhpfastcacheDriverCheckException
69
     * @throws PhpfastcacheDriverConnectException
70
     * @throws PhpfastcacheIOException
71
     * @throws PhpfastcacheInvalidArgumentException
72
     */
73
    public function __construct(#[\SensitiveParameter] ConfigurationOptionInterface $config, string $instanceId, EventManagerInterface $em)
74
    {
75
        $this->setEventManager($em->getScopedEventManager($this));
0 ignored issues
show
Bug introduced by
$this of type Phpfastcache\Core\Pool\DriverBaseTrait is incompatible with the type Phpfastcache\Core\Pool\E...dCacheItemPoolInterface expected by parameter $pool of Phpfastcache\Event\Event...getScopedEventManager(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        $this->setEventManager($em->getScopedEventManager(/** @scrutinizer ignore-type */ $this));
Loading history...
76
        $this->setConfig($config);
77
        $this->instanceId = $instanceId;
78
79
        if (!$this->driverCheck()) {
80
            throw new PhpfastcacheDriverCheckException(
81
                \sprintf(
82
                    ExtendedCacheItemPoolInterface::DRIVER_CHECK_FAILURE,
83
                    $this->getDriverName(),
84
                    $this->getHelp() ? " Additionally, {$this->getHelp()}" : ''
0 ignored issues
show
Bug introduced by
It seems like getHelp() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

84
                    $this->/** @scrutinizer ignore-call */ 
85
                           getHelp() ? " Additionally, {$this->getHelp()}" : ''
Loading history...
85
                )
86
            );
87
        }
88
        $this->eventManager->dispatch(Event::CACHE_DRIVER_CHECKED, $this);
89
90
        try {
91
            $this->driverConnect();
92
            $config->lock($this); // Lock the config only after a successful driver connection.
0 ignored issues
show
Bug introduced by
$this of type Phpfastcache\Core\Pool\DriverBaseTrait is incompatible with the type Phpfastcache\Core\Pool\E...dCacheItemPoolInterface expected by parameter $poolInstance of Phpfastcache\Config\Lock...rationInterface::lock(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

92
            $config->lock(/** @scrutinizer ignore-type */ $this); // Lock the config only after a successful driver connection.
Loading history...
93
            $this->eventManager->dispatch(Event::CACHE_DRIVER_CONNECTED, $this, $this->instance ?? null);
94
        } catch (Throwable $e) {
95
            throw new PhpfastcacheDriverConnectException(
96
                sprintf(
97
                    ExtendedCacheItemPoolInterface::DRIVER_CONNECT_FAILURE,
98
                    $this->getDriverName(),
99
                    $e->getMessage(),
100
                    $e->getLine() ?: 'unknown line',
101
                    $e->getFile() ?: 'unknown file',
102
                ),
103
                0,
104
                $e
105
            );
106
        }
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    public function getDriverName(): string
113
    {
114
        if (!isset($this->driverName)) {
115
            $this->driverName = \ucfirst(\substr(\strrchr((new ReflectionObject($this))->getNamespaceName(), '\\'), 1));
116
        }
117
        return $this->driverName;
118
    }
119
120
    /**
121
     * @return ConfigurationOptionInterface
122
     */
123
    public function getDefaultConfig(): ConfigurationOptionInterface
124
    {
125
        $className = $this::getConfigClass();
126
127
        return new $className();
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public static function getConfigClass(): string
134
    {
135
        $localConfigClass = \substr(static::class, 0, \strrpos(static::class, '\\')) . '\Config';
136
        if (\class_exists($localConfigClass) && \is_a($localConfigClass, ConfigurationOption::class, true)) {
137
            return $localConfigClass;
138
        }
139
        return ConfigurationOption::class;
140
    }
141
142
    public static function getItemClass(): string
143
    {
144
        if (!isset(self::$cacheItemClasses[static::class])) {
145
            self::$cacheItemClasses[static::class] = self::getClassNamespace() . '\\' . 'Item';
146
        }
147
148
        return self::$cacheItemClasses[static::class];
149
    }
150
151
    /**
152
     * @inheritDoc
153
     */
154
    public function getEncodedKey(string $key): string
155
    {
156
        $keyHashFunction = $this->getConfig()->getDefaultKeyHashFunction();
157
158
        if ($keyHashFunction) {
159
            if (\is_callable($keyHashFunction)) {
160
                return $keyHashFunction($key);
161
            }
162
            throw new PhpfastcacheLogicException('Unable to build the encoded key (defaultKeyHashFunction is not callable)');
163
        }
164
165
        return $key;
166
    }
167
168
169
170
    /**
171
     * @param ExtendedCacheItemInterface $item
172
     * @param bool $stringifyDate
173
     * @return array<string, mixed>
174
     * @throws PhpfastcacheLogicException
175
     */
176
    public function driverPreWrap(ExtendedCacheItemInterface $item, bool $stringifyDate = false): array
177
    {
178
        $wrap = [
179
            ExtendedCacheItemPoolInterface::DRIVER_KEY_WRAPPER_INDEX => $item->getKey(), // Stored but not really used, allow you to quickly identify the cache key
180
            ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX => $item->_getData(),
181
            ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX => $item->getExpirationDate(),
182
            TaggableCacheItemPoolInterface::DRIVER_TAGS_WRAPPER_INDEX => $item->getTags(),
183
        ];
184
185
        if ($this->getConfig()->isItemDetailedDate()) {
186
            $wrap[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX] = new DateTime();// Always on the latest date
187
            /**
188
             * If the creation date exists
189
             * reuse it else set a new Date
190
             */
191
            $wrap[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX] = $item->getCreationDate();
192
        } else {
193
            $wrap[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX] = null;
194
            $wrap[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX] = null;
195
        }
196
197
        if ($stringifyDate) {
198
            \array_walk($wrap, static function (mixed &$value, string $key): void {
199
                if ($value instanceof DateTimeInterface && $key !== ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX) {
200
                    $value = $value->format(DateTimeInterface::W3C);
201
                }
202
            });
203
        }
204
205
        return $wrap;
206
    }
207
208
    /**
209
     * @return ConfigurationOptionInterface
210
     */
211
    public function getConfig(): ConfigurationOptionInterface
212
    {
213
        return $this->config;
214
    }
215
216
    /**
217
     * @param ConfigurationOptionInterface $config
218
     * @return static
219
     */
220
    public function setConfig(ConfigurationOptionInterface $config): static
221
    {
222
        $this->config = $config;
223
224
        return $this;
225
    }
226
227
    /**
228
     * @param array<string, mixed> $wrapper
229
     * @return mixed
230
     * @throws \Exception
231
     */
232
    public function driverUnwrapData(array $wrapper): mixed
233
    {
234
        return $wrapper[ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX];
235
    }
236
237
    /**
238
     * @param array<string, mixed> $wrapper
239
     * @return DateTimeInterface
240
     */
241
    public function driverUnwrapEdate(array $wrapper): \DateTimeInterface
242
    {
243
        if ($wrapper[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX] instanceof \DateTimeInterface) {
244
            return $wrapper[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX];
245
        }
246
247
        return DateTime::createFromFormat(\DateTimeInterface::W3C, $wrapper[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX]);
248
    }
249
250
    /**
251
     * @param array<string, mixed> $wrapper
252
     * @return DateTimeInterface|null
253
     */
254
    public function driverUnwrapCdate(array $wrapper): ?\DateTimeInterface
255
    {
256
        if ($wrapper[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX] instanceof \DateTimeInterface) {
257
            return $wrapper[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX];
258
        }
259
260
        return DateTime::createFromFormat(\DateTimeInterface::W3C, $wrapper[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX]);
261
    }
262
263
    /**
264
     * @param array<string, mixed> $wrapper
265
     * @return DateTimeInterface|null
266
     */
267
    public function driverUnwrapMdate(array $wrapper): ?\DateTimeInterface
268
    {
269
        if ($wrapper[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX] instanceof \DateTimeInterface) {
270
            return $wrapper[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX];
271
        }
272
273
        return DateTime::createFromFormat(\DateTimeInterface::W3C, $wrapper[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX]);
274
    }
275
276
    /**
277
     * @return string
278
     */
279
    public function getInstanceId(): string
280
    {
281
        return $this->instanceId;
282
    }
283
284
    /**
285
     * Encode data types such as object/array
286
     * for driver that does not support
287
     * non-scalar value
288
     * @param mixed $data
289
     * @return string
290
     */
291
    protected function encode(mixed $data): string
292
    {
293
        return \serialize($data);
294
    }
295
296
    /**
297
     * Decode data stored in the cache
298
     * for driver that does not support
299
     * non-scalar value storage.
300
     * @param string|null $value
301
     * @return array<string, mixed>|null
302
     * @throws PhpfastcacheDriverException
303
     */
304
    protected function decode(?string $value): ?array
305
    {
306
        $decoded = $this->unserialize($value);
307
308
        if ($decoded === null || is_array($decoded)) {
309
            return $decoded;
310
        }
311
        throw new PhpfastcacheCorruptedDataException(
312
            sprintf(
313
                'Failed to unserialize data from the cache, expected array or null but got "%s". Stored data may be corrupted.',
314
                gettype($decoded)
315
            ),
316
            $value
317
        );
318
    }
319
320
    protected function unserialize(?string $value): mixed
321
    {
322
        return $value ? \unserialize($value, ['allowed_classes' => true]) : null;
323
    }
324
}
325