CacheItem::expiresAt()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Cache
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Cache;
16
17
use Phossa2\Shared\Base\ObjectAbstract;
18
use Phossa2\Cache\Interfaces\CacheItemExtendedInterface;
19
20
/**
21
 * CacheItem
22
 *
23
 * @package Phossa2\Cache
24
 * @author  Hong Zhang <[email protected]>
25
 * @see     ObjectAbstract
26
 * @see     CacheItemExtendedInterface
27
 * @version 2.0.0
28
 * @since   2.0.0 added
29
 */
30
class CacheItem extends ObjectAbstract implements CacheItemExtendedInterface
31
{
32
    /**
33
     * cache pool
34
     *
35
     * @var    CachePool
36
     * @access protected
37
     */
38
    protected $pool;
39
40
    /**
41
     * item key
42
     *
43
     * @var    string
44
     * @access protected
45
     */
46
    protected $key;
47
48
    /**
49
     * flag for cache hit
50
     *
51
     * @var    bool
52
     * @access protected
53
     */
54
    protected $hit;
55
56
    /**
57
     * flag for got value already
58
     *
59
     * @var    bool
60
     * @access protected
61
     */
62
    protected $got = false;
63
64
    /**
65
     * Item exact value
66
     *
67
     * @var    mixed
68
     * @access protected
69
     */
70
    protected $value;
71
72
    /**
73
     * Processed item value
74
     *
75
     * @var    string
76
     * @access protected
77
     */
78
    protected $strval;
79
80
    /**
81
     * default expiration timestamp in seconds
82
     *
83
     * - 0 for no expiration
84
     *
85
     * - max value is 0x7fffffff
86
     *
87
     * @var    int
88
     * @access protected
89
     */
90
    protected $expire = 0;
91
92
    /**
93
     * default TTL in seconds
94
     *
95
     * @var    int
96
     * @access protected
97
     */
98
    protected $ttl = 28800;
99
100
    /**
101
     * Constructor
102
     *
103
     * @param  string $key
104
     * @param  CachePool $pool
105
     * @param  array $properties optional properties
106
     * @access public
107
     */
108
    public function __construct(
109
        /*# string */ $key,
110
        CachePool $pool,
111
        array $properties = []
112
    ) {
113
        $this->key = $key;
114
        $this->pool = $pool;
115
        $this->setProperties($properties);
116
    }
117
118
    /**
119
     * {@inheritDoc}
120
     */
121
    public function getKey()
122
    {
123
        return $this->key;
124
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129
    public function get()
130
    {
131
        if ($this->got) {
132
            return $this->value;
133
        } else {
134
            $this->got = true;
135
            if (!$this->isHit()) {
136
                return null;
137
            }
138
            return $this->getValue();
139
        }
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public function isHit()
146
    {
147
        if (is_bool($this->hit)) {
148
            return $this->hit;
149
        } else {
150
            return $this->hasHit();
151
        }
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157
    public function set($value)
158
    {
159
        if ($this->trigger(CachePool::EVENT_SET_BEFORE)) {
160
            $this->got = true;
161
            $this->value = $value;
162
            $this->strval = null;
163
            $this->trigger(CachePool::EVENT_SET_AFTER);
164
        }
165
        return $this;
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171
    public function expiresAt($expiration)
172
    {
173
        if ($expiration instanceof \DateTime) {
174
            $this->expire = $expiration->getTimestamp();
175
        } elseif (is_int($expiration)) {
176
            $this->expire = $expiration;
177
        } else {
178
            $this->expire = time() + $this->ttl;
179
        }
180
        return $this;
181
    }
182
183
    /**
184
     * {@inheritDoc}
185
     */
186
    public function expiresAfter($time)
187
    {
188
        if ($time instanceof \DateInterval) {
189
            $time = $time->format("%s");
190
        } elseif (!is_numeric($time)) {
191
            $time = $this->ttl;
192
        } else {
193
            $time = (int) $time;
194
        }
195
        $this->expire = time() + $time;
196
197
        return $this;
198
    }
199
200
    /**
201
     * {@inheritDoc}
202
     */
203
    public function getExpiration()/*# : \DateTime */
204
    {
205
        // set default expiration if not yet
206
        if ($this->expire === 0) {
207
            $this->expiresAt(null);
208
        }
209
210
        return new \DateTime('@' . $this->expire);
211
    }
212
213
    /**
214
     * {@inheritDoc}
215
     */
216
    public function setStrVal($strval)
217
    {
218
        $this->strval = $strval;
219
        return $this;
220
    }
221
222
    /**
223
     * {@inheritDoc}
224
     */
225
    public function getStrVal()
226
    {
227
        return $this->strval;
228
    }
229
230
    /**
231
     * {@inheritDoc}
232
     */
233
    public function __toString()/*# : string */
234
    {
235
        if (is_string($this->strval)) {
236
            return $this->strval;
237
        } elseif (is_string($this->value)) {
238
            return $this->value;
239
        } else {
240
            return serialize($this->value);
241
        }
242
    }
243
244
    /**
245
     * Set hit status
246
     *
247
     * @param  bool $hit
248
     * @return bool current hit status
249
     * @access protected
250
     */
251
    protected function setHit(/*# bool */ $hit)/*# : bool */
252
    {
253
        $this->hit = (bool) $hit;
254
        return $this->hit;
255
    }
256
257
    /**
258
     * Get value from the cache pool
259
     *
260
     * @return mixed
261
     * @access protected
262
     */
263
    protected function getValue()
264
    {
265
        // before get
266
        if (!$this->trigger(CachePool::EVENT_GET_BEFORE)) {
267
            $this->setHit(false);
268
            return null;
269
        }
270
271
        // get string value from the pool
272
        $this->strval = $this->pool->getDriver()->get($this->key);
273
274
        // after get
275
        if (!$this->trigger(CachePool::EVENT_GET_AFTER)) {
276
            $this->setHit(false);
277
            $this->set(null);
278
        }
279
280
        return $this->postGetValue();
281
    }
282
283
    /**
284
     * Convert $this->strval to $this->value if not yet
285
     *
286
     * @return mixed
287
     * @access protected
288
     */
289
    protected function postGetValue()
290
    {
291
        if (is_null($this->value)) {
292
            $val = @unserialize($this->strval);
293
            $this->value = false === $val ? $this->strval : $val;
294
        }
295
        return $this->value;
296
    }
297
298
    /**
299
     * Get hit status from driver
300
     *
301
     * @return bool
302
     * @access protected
303
     */
304
    protected function hasHit()/*# : bool */
305
    {
306
        if (!$this->trigger(CachePool::EVENT_HAS_BEFORE)) {
307
            return $this->setHit(false);
308
        }
309
310
        $meta = $this->pool->getDriver()->has($this->key);
311
        if (isset($meta['expire'])) {
312
            $this->expire = $meta['expire'];
313
        } else {
314
            return $this->setHit(false);
315
        }
316
317
        if (!$this->trigger(CachePool::EVENT_HAS_AFTER)) {
318
            return $this->setHit(false);
319
        }
320
321
        return $this->setHit(true);
322
    }
323
324
    /**
325
     * Trigger cache pool event
326
     *
327
     * @param  string $eventName
328
     * @return bool
329
     * @access protected
330
     */
331
    protected function trigger(/*# string */ $eventName)/*# : bool */
332
    {
333
        return $this->pool->trigger($eventName, ['item' => $this]);
334
    }
335
}
336