File::setTtl()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.1158

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 5
nop 3
dl 0
loc 17
ccs 10
cts 12
cp 0.8333
crap 5.1158
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Cache package.
5
 *
6
 * Copyright (c) Daniel González
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @author Daniel González <[email protected]>
12
 * @author Arnold Daniels <[email protected]>
13
 */
14
15
declare(strict_types=1);
16
17
namespace Desarrolla2\Cache;
18
19
use Desarrolla2\Cache\Exception\InvalidArgumentException;
20
use Desarrolla2\Cache\Exception\UnexpectedValueException;
21
use Desarrolla2\Cache\Packer\PackerInterface;
22
use Desarrolla2\Cache\Packer\SerializePacker;
23
24
/**
25
 * Cache file.
26
 */
27
class File extends AbstractFile
28
{
29
    /**
30
     * @var string  'embed', 'file', 'mtime'
31
     */
32
    protected $ttlStrategy = 'embed';
33
34
    /**
35
     * Create the default packer for this cache implementation
36
     *
37
     * @return PackerInterface
38
     */
39 474
    protected static function createDefaultPacker(): PackerInterface
40
    {
41 474
        return new SerializePacker();
42
    }
43
44
    /**
45
     * Set TTL strategy
46
     *
47
     * @param string $strategy
48
     */
49 197
    protected function setTtlStrategyOption($strategy)
50
    {
51 197
        if (!in_array($strategy, ['embed', 'file', 'mtime'])) {
52
            throw new InvalidArgumentException("Unknown strategy '$strategy', should be 'embed', 'file' or 'mtime'");
53
        }
54
55 197
        $this->ttlStrategy = $strategy;
56
    }
57
58
    /**
59
     * Get TTL strategy
60
     *
61
     * @return string
62
     */
63
    protected function getTtlStrategyOption(): string
64
    {
65
        return $this->ttlStrategy;
66
    }
67
68
69
    /**
70
     * Get the TTL using one of the strategies
71
     *
72
     * @param string $cacheFile
73
     * @return int
74
     */
75 117
    protected function getTtl(string $cacheFile)
76
    {
77 117
        switch ($this->ttlStrategy) {
78 117
            case 'embed':
79 78
                return (int)$this->readLine($cacheFile);
80 39
            case 'file':
81 39
                return file_exists("$cacheFile.ttl")
82 4
                    ? (int)file_get_contents("$cacheFile.ttl")
83 39
                    : PHP_INT_MAX;
84
            case 'mtime':
85
                return $this->getTtl($cacheFile) > 0 ? filemtime($cacheFile) + $this->ttl : PHP_INT_MAX;
86
        }
87
88
        throw new \InvalidArgumentException("Invalid TTL strategy '{$this->ttlStrategy}'");
89
    }
90
91
    /**
92
     * Set the TTL using one of the strategies
93
     *
94
     * @param int|null $expiration
95
     * @param string   $contents
96
     * @param string   $cacheFile
97
     * @return string  The (modified) contents
98
     */
99 180
    protected function setTtl($expiration, $contents, $cacheFile)
100
    {
101 180
        switch ($this->ttlStrategy) {
102 180
            case 'embed':
103 120
                $contents = ($expiration ?? PHP_INT_MAX) . "\n" . $contents;
104 120
                break;
105 60
            case 'file':
106 60
                if ($expiration !== null) {
107 4
                    file_put_contents("$cacheFile.ttl", $expiration);
108
                }
109 60
                break;
110
            case 'mtime':
111
                // nothing
112
                break;
113
        }
114
115 180
        return $contents;
116
    }
117
118
119
    /**
120
     * {@inheritdoc}
121
     */
122 237
    public function get($key, $default = null)
123
    {
124 237
        if (!$this->has($key)) {
125 90
            return $default;
126
        }
127
128 108
        $cacheFile = $this->getFilename($key);
129 108
        $packed = $this->readFile($cacheFile);
130
131 108
        if ($this->ttlStrategy === 'embed') {
132 72
            $packed = substr($packed, strpos($packed, "\n") + 1);
133
        }
134
        
135 108
        return $this->unpack($packed);
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 294
    public function has($key)
142
    {
143 294
        $cacheFile = $this->getFilename($key);
144
145 186
        if (!file_exists($cacheFile)) {
146 84
            return false;
147
        }
148
149 117
        $ttl = $this->getTtl($cacheFile);
150
151 117
        if ($ttl <= time()) {
152 12
            $this->deleteFile($cacheFile);
153 12
            return false;
154
        }
155
156 111
        return true;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162 294
    public function set($key, $value, $ttl = null)
163
    {
164 294
        $cacheFile = $this->getFilename($key);
165 240
        $packed = $this->pack($value);
166
167 240
        if (!is_string($packed)) {
168
            throw new UnexpectedValueException("Packer must create a string for the data to be cached to file");
169
        }
170
171 240
        $contents = $this->setTtl($this->ttlToTimestamp($ttl), $packed, $cacheFile);
172
173 180
        return $this->writeFile($cacheFile, $contents);
174
    }
175
}
176