Completed
Push — v5.1 ( bb10e4...1e2251 )
by Georges
03:39
created

CacheItemPoolTrait::saveDeferred()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 5
Ratio 50 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 3
eloc 6
c 2
b 0
f 1
nc 3
nop 1
dl 5
loc 10
rs 9.4285
1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> http://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
15
namespace phpFastCache\Core\Pool;
16
17
use phpFastCache\Core\Item\ExtendedCacheItemInterface;
18
use phpFastCache\CacheManager;
19
use Psr\Cache\CacheItemInterface;
20
use phpFastCache\Util\ClassNamespaceResolverTrait;
21
22
/**
23
 * Trait StandardPsr6StructureTrait
24
 * @package phpFastCache\Core
25
 *
26
 */
27
trait CacheItemPoolTrait
28
{
29
    use ClassNamespaceResolverTrait;
30
31
    /**
32
     * @var array
33
     */
34
    protected $deferredList = [];
35
36
    /**
37
     * @var ExtendedCacheItemInterface[]
38
     */
39
    protected $itemInstances = [];
40
41
    /**
42
     * @param string $key
43
     * @return \phpFastCache\Core\Item\ExtendedCacheItemInterface
44
     * @throws \InvalidArgumentException
45
     * @throws \LogicException
46
     */
47
    public function getItem($key)
48
    {
49
        if (is_string($key)) {
50
            if (!array_key_exists($key, $this->itemInstances)) {
51
52
                /**
53
                 * @var $item ExtendedCacheItemInterface
54
                 */
55
                CacheManager::$ReadHits++;
56
                $class = new \ReflectionClass((new \ReflectionObject($this))->getNamespaceName() . '\Item');
57
                $item = $class->newInstanceArgs([$this, $key]);
58
                $driverArray = $this->driverRead($item);
59
60
                if ($driverArray) {
61
                    $item->set($this->driverUnwrapData($driverArray));
62
                    $item->expiresAt($this->driverUnwrapEdate($driverArray));
63
64
                    if($this->config['itemDetailedDate']){
0 ignored issues
show
Bug introduced by
The property config does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
65
66
                        /**
67
                         * If the itemDetailedDate has been
68
                         * set after caching, we MUST inject
69
                         * a new DateTime object on the fly
70
                         */
71
                        $item->setCreationDate($this->driverUnwrapCdate($driverArray) ?: new \DateTime());
72
                        $item->setModificationDate($this->driverUnwrapMdate($driverArray) ?: new \DateTime());
73
                    }
74
75
                    $item->setTags($this->driverUnwrapTags($driverArray));
76
                    if ($item->isExpired()) {
77
                        /**
78
                         * Using driverDelete() instead of delete()
79
                         * to avoid infinite loop caused by
80
                         * getItem() call in delete() method
81
                         * As we MUST return an item in any
82
                         * way, we do not de-register here
83
                         */
84
                        $this->driverDelete($item);
85
                    } else {
86
                        $item->setHit(true);
87
                    }
88
                }else{
89
                    $item->expiresAfter(abs((int) $this->getConfig()[ 'defaultTtl' ]));
90
                }
91
92
            }
93
        } else {
94
            throw new \InvalidArgumentException(sprintf('$key must be a string, got type "%s" instead.', gettype($key)));
95
        }
96
97
        return $this->itemInstances[ $key ];
98
    }
99
100
    /**
101
     * @param \Psr\Cache\CacheItemInterface $item
102
     * @return $this
103
     * @throws \InvalidArgumentException
104
     */
105
    public function setItem(CacheItemInterface $item)
106
    {
107
        if ($this->getClassNamespace() . '\\Item' === get_class($item)) {
108
            $this->itemInstances[ $item->getKey() ] = $item;
109
110
            return $this;
111
        } else {
112
            throw new \InvalidArgumentException(sprintf('Invalid Item Class "%s" for this driver.', get_class($item)));
113
        }
114
    }
115
116
    /**
117
     * @param array $keys
118
     * @return CacheItemInterface[]
119
     * @throws \InvalidArgumentException
120
     */
121
    public function getItems(array $keys = [])
122
    {
123
        $collection = [];
124
        foreach ($keys as $key) {
125
            $collection[ $key ] = $this->getItem($key);
126
        }
127
128
        return $collection;
129
    }
130
131
    /**
132
     * @param string $key
133
     * @return bool
134
     * @throws \InvalidArgumentException
135
     */
136
    public function hasItem($key)
137
    {
138
        CacheManager::$ReadHits++;
139
140
        return $this->getItem($key)->isHit();
141
    }
142
143
    /**
144
     * @return bool
145
     */
146
    public function clear()
147
    {
148
        CacheManager::$WriteHits++;
149
        $this->itemInstances = [];
150
151
        return $this->driverClear();
152
    }
153
154
    /**
155
     * @param string $key
156
     * @return bool
157
     * @throws \InvalidArgumentException
158
     */
159
    public function deleteItem($key)
160
    {
161
        $item = $this->getItem($key);
162
        if ($this->hasItem($key) && $this->driverDelete($item)) {
163
            $item->setHit(false);
164
            CacheManager::$WriteHits++;
165
            /**
166
             * De-register the item instance
167
             * then collect gc cycles
168
             */
169
            $this->deregisterItem($key);
170
171
            return true;
172
        }
173
174
        return false;
175
    }
176
177
    /**
178
     * @param array $keys
179
     * @return bool
180
     * @throws \InvalidArgumentException
181
     */
182
    public function deleteItems(array $keys)
183
    {
184
        $return = null;
185
        foreach ($keys as $key) {
186
            $result = $this->deleteItem($key);
187
            if ($result !== false) {
188
                $return = $result;
189
            }
190
        }
191
192
        return (bool) $return;
193
    }
194
195
    /**
196
     * @param \Psr\Cache\CacheItemInterface $item
197
     * @return mixed
198
     * @throws \InvalidArgumentException
199
     * @throws \RuntimeException
200
     */
201
    public function save(CacheItemInterface $item)
202
    {
203
        /**
204
         * @var ExtendedCacheItemInterface $item
205
         */
206 View Code Duplication
        if (!array_key_exists($item->getKey(), $this->itemInstances)) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
            $this->itemInstances[ $item->getKey() ] = $item;
208
        } else if(spl_object_hash($item) !== spl_object_hash($this->itemInstances[ $item->getKey() ])){
209
            throw new \RuntimeException('Spl object hash mismatches ! You probably tried to save a detached item which has been already retrieved from cache.');
210
        }
211
212
        if ($this->driverWrite($item) && $this->driverWriteTags($item)) {
213
            $item->setHit(true);
214
            CacheManager::$WriteHits++;
215
216
            return true;
217
        }
218
219
        return false;
220
    }
221
222
223
    /**
224
     * @param \Psr\Cache\CacheItemInterface $item
225
     * @return \Psr\Cache\CacheItemInterface
226
     * @throws \RuntimeException
227
     */
228
    public function saveDeferred(CacheItemInterface $item)
229
    {
230 View Code Duplication
        if (!array_key_exists($item->getKey(), $this->itemInstances)) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
            $this->itemInstances[ $item->getKey() ] = $item;
232
        }else if(spl_object_hash($item) !== spl_object_hash($this->itemInstances[ $item->getKey() ])){
233
            throw new \RuntimeException('Spl object hash mismatches ! You probably tried to save a detached item which has been already retrieved from cache.');
234
        }
235
236
        return $this->deferredList[ $item->getKey() ] = $item;
237
    }
238
239
    /**
240
     * @return mixed|null
241
     * @throws \InvalidArgumentException
242
     */
243
    public function commit()
244
    {
245
        $return = null;
246
        foreach ($this->deferredList as $key => $item) {
247
            $result = $this->save($item);
248
            if ($return !== false) {
249
                unset($this->deferredList[ $key ]);
250
                $return = $result;
251
            }
252
        }
253
254
        return (bool) $return;
255
    }
256
}