Passed
Push — feature/0.7.0 ( 0c7d59...ae5b22 )
by Ryuichi
78:01 queued 33:04
created

TemporaryFile::isAvailableCacheLibrary()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
namespace WebStream\Cache\Driver;
3
4
use WebStream\DI\Injector;
5
use WebStream\Container\Container;
6
use WebStream\IO\File;
7
use WebStream\Exception\Extend\IOException;
8
9
/**
10
 * TemporaryFile
11
 * @author Ryuichi Tanaka
12
 * @since 2015/07/12
13
 * @version 0.7
14
 */
15
class TemporaryFile implements ICache
16
{
17
    use injector;
18
19
    /**
20
     * @var Container キャッシュ依存コンテナ
21
     */
22
    private $cacheContainer;
23
24
    /**
25
     * @var string キャッシュ接頭辞
26
     */
27
    private $cachePrefix;
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function __construct(Container $cacheContainer)
33
    {
34
        $this->cacheContainer = $cacheContainer;
35
        $this->cachePrefix = $this->cacheContainer->cachePrefix . '.' . $this->cacheContainer->classPrefix . '.';
0 ignored issues
show
Bug Best Practice introduced by
The property classPrefix does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property cachePrefix does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function add($key, $data, $ttl = 0, $overwrite = false): bool
42
    {
43
        if (!$this->isAvailableCacheLibrary()) {
44
            return false;
45
        }
46
        $key = $this->cachePrefix . $key;
47
        $writer = null;
48
        $isAppend = !$overwrite;
49
50
        $value = base64_encode(serialize([
51
            "time" => time(),
52
            "ttl" => intval($ttl),
53
            "data" => $data
54
        ]));
55
56
        try {
57
            $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
0 ignored issues
show
Bug Best Practice introduced by
The property cacheDir does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
58
            $writer = $this->cacheContainer->ioContainer->fileWriter->getWriter($file, $isAppend);
0 ignored issues
show
Bug Best Practice introduced by
The property ioContainer does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
59
            $writer->write($value);
60
            $this->logger->info("Execute cache save: " . $key);
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Cache\Driver\TemporaryFile. Since you implemented __get, consider adding a @property annotation.
Loading history...
61
            return true;
62
        } catch (IOException $e) {
63
            $this->logger->warn($e->getMessage());
64
            return false;
65
        } finally {
66
            if ($writer !== null) {
67
                try {
68
                    $writer->close();
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
69
                } catch (IOException $ignore) {
70
                    // Nothing to do
71
                }
72
            }
73
        }
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function get($key)
80
    {
81
        if (!$this->isAvailableCacheLibrary()) {
82
            return null;
83
        }
84
        $key = $this->cachePrefix . $key;
85
        $value = null;
86
        $reader = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $reader is dead and can be removed.
Loading history...
87
        $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
0 ignored issues
show
Bug Best Practice introduced by
The property cacheDir does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
88
89
        if ($file->isReadable()) {
90
            try {
91
                $reader = $this->cacheContainer->ioContainer->fileReader->getReader($file);
0 ignored issues
show
Bug Best Practice introduced by
The property ioContainer does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
92
                $data = unserialize(base64_decode($reader->read()));
93
                if ($data['ttl'] > 0) {
94
                    if (time() > $data['time'] + $data['ttl']) {
95
                        $this->logger->info("Expired cache: " . $key);
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Cache\Driver\TemporaryFile. Since you implemented __get, consider adding a @property annotation.
Loading history...
96
                        $file->delete();
97
                    }
98
                } else {
99
                    $value = $data['data'];
100
                    $this->logger->info("Execute cache read: " . $key);
101
                }
102
            } catch (IOException $e) {
103
                $this->logger->warn($e->getMessage());
104
            } finally {
105
                if ($reader !== null) {
106
                    try {
107
                        $reader->close();
108
                    } catch (IOException $ignore) {
109
                        // Nothing to do
110
                    }
111
                }
112
            }
113
        }
114
115
        return $value;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function delete($key): bool
122
    {
123
        if (!$this->isAvailableCacheLibrary()) {
124
            return false;
125
        }
126
        $key = $this->cachePrefix . $key;
127
        $result = false;
128
129
        $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
0 ignored issues
show
Bug Best Practice introduced by
The property cacheDir does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
130
        if ($file->isWritable()) {
131
            $result = $file->delete();
132
            if ($result) {
133
                $this->logger->info("Execute cache cleared: " . $key);
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Cache\Driver\TemporaryFile. Since you implemented __get, consider adding a @property annotation.
Loading history...
134
            } else {
135
                $this->logger->warn("Failed to clear cache: " . $key);
136
            }
137
        } else {
138
            $this->logger->warn("Failed to clear cache: " . $key);
139
        }
140
141
        return $result;
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147
    public function clear(): bool
148
    {
149
        if (!$this->isAvailableCacheLibrary()) {
150
            return false;
151
        }
152
        $dir = new File($this->cacheContainer->cacheDir);
0 ignored issues
show
Bug Best Practice introduced by
The property cacheDir does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
It seems like $this->cacheContainer->cacheDir can also be of type null; however, parameter $filePath of WebStream\IO\File::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

152
        $dir = new File(/** @scrutinizer ignore-type */ $this->cacheContainer->cacheDir);
Loading history...
153
        $result = true;
154
155
        if ($dir->isReadable()) {
156
            $iterator = $this->cacheContainer->ioContainer->fileIterator->getIterator($dir->getFilePath());
0 ignored issues
show
Bug Best Practice introduced by
The property ioContainer does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
157
            foreach ($iterator as $filepath => $fileObject) {
158
                if (strpos($filepath, $this->cachePrefix, 0) !== false) {
159
                    try {
160
                        $file = new File($filepath);
161
                        if ($file->isWritable()) {
162
                            if ($file->delete()) {
163
                                $this->logger->info("Execute cache cleared: " . $this->cachePrefix . "*");
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Cache\Driver\TemporaryFile. Since you implemented __get, consider adding a @property annotation.
Loading history...
164
                            } else {
165
                                $this->logger->warn("Failed to clear cache: " . $this->cachePrefix . "*");
166
                                $result = false;
167
                            }
168
                        } else {
169
                            $result = false;
170
                        }
171
                    } catch (IOException $e) {
172
                        $this->logger->warn($e->getMessage());
173
                        $result = false;
174
                    }
175
                }
176
            }
177
        } else {
178
            $this->logger->warn("Can't read directory:" . $dir->getFilePath());
179
            $result = false;
180
        }
181
182
        return $result;
183
    }
184
185
    /**
186
     * キャッシュライブラリが使用可能か検査する
187
     * @return bool 使用可能でtrue
188
     */
189
    private function isAvailableCacheLibrary(): bool
190
    {
191
        if ($this->cacheContainer->available) {
0 ignored issues
show
Bug Best Practice introduced by
The property available does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
192
            return true;
193
        }
194
195
        $this->logger->warn("TemporaryFile cache library is unavailable.");
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Cache\Driver\TemporaryFile. Since you implemented __get, consider adding a @property annotation.
Loading history...
196
197
        return false;
198
    }
199
}
200