Passed
Push — master ( d2ea29...d8fd67 )
by Ryuichi
42:52 queued 41:09
created

TemporaryFile   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 28
eloc 97
c 2
b 0
f 0
dl 0
loc 183
ccs 0
cts 133
cp 0
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A isAvailableCacheLibrary() 0 9 2
A add() 0 29 5
B get() 0 37 8
A delete() 0 21 4
B clear() 0 36 8
A __construct() 0 4 1
1
<?php
2
3
namespace WebStream\Cache\Driver;
4
5
use WebStream\DI\Injector;
0 ignored issues
show
Bug introduced by
The type WebStream\DI\Injector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use WebStream\Container\Container;
0 ignored issues
show
Bug introduced by
The type WebStream\Container\Container was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use WebStream\IO\File;
0 ignored issues
show
Bug introduced by
The type WebStream\IO\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use WebStream\Exception\Extend\IOException;
0 ignored issues
show
Bug introduced by
The type WebStream\Exception\Extend\IOException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
10
/**
11
 * TemporaryFile
12
 * @author Ryuichi Tanaka
13
 * @since 2015/07/12
14
 * @version 0.7
15
 */
16
class TemporaryFile implements ICache
17
{
18
    use injector;
19
20
    /**
21
     * @var Container キャッシュ依存コンテナ
22
     */
23
    private $cacheContainer;
24
25
    /**
26
     * @var string キャッシュ接頭辞
27
     */
28
    private $cachePrefix;
29
30
    /**
31
     * {@inheritdoc}
32
     */
33
    public function __construct(Container $cacheContainer)
34
    {
35
        $this->cacheContainer = $cacheContainer;
36
        $this->cachePrefix = $this->cacheContainer->cachePrefix . '.' . $this->cacheContainer->classPrefix . '.';
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function add($key, $data, $ttl = 0, $overwrite = false): bool
43
    {
44
        if (!$this->isAvailableCacheLibrary()) {
45
            return false;
46
        }
47
        $key = $this->cachePrefix . $key;
48
        $writer = null;
49
        $isAppend = !$overwrite;
50
51
        $value = base64_encode(serialize([
52
            "time" => time(),
53
            "ttl" => intval($ttl),
54
            "data" => $data
55
        ]));
56
57
        try {
58
            $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
59
            $writer = $this->cacheContainer->ioContainer->fileWriter->getWriter($file, $isAppend);
60
            $writer->write($value);
61
            $this->logger->info("Execute cache save: " . $key);
62
            return true;
63
        } catch (IOException $e) {
64
            $this->logger->warn($e->getMessage());
65
            return false;
66
        } finally {
67
            if ($writer !== null) {
68
                try {
69
                    $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...
70
                } catch (IOException $ignore) {
71
                    // Nothing to do
72
                }
73
            }
74
        }
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function get($key)
81
    {
82
        if (!$this->isAvailableCacheLibrary()) {
83
            return null;
84
        }
85
        $key = $this->cachePrefix . $key;
86
        $value = null;
87
        $reader = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $reader is dead and can be removed.
Loading history...
88
        $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
89
90
        if ($file->isReadable()) {
91
            try {
92
                $reader = $this->cacheContainer->ioContainer->fileReader->getReader($file);
93
                $data = unserialize(base64_decode($reader->read()));
94
                if ($data['ttl'] > 0) {
95
                    if (time() > $data['time'] + $data['ttl']) {
96
                        $this->logger->info("Expired cache: " . $key);
97
                        $file->delete();
98
                    }
99
                } else {
100
                    $value = $data['data'];
101
                    $this->logger->info("Execute cache read: " . $key);
102
                }
103
            } catch (IOException $e) {
104
                $this->logger->warn($e->getMessage());
105
            } finally {
106
                if ($reader !== null) {
107
                    try {
108
                        $reader->close();
109
                    } catch (IOException $ignore) {
110
                        // Nothing to do
111
                    }
112
                }
113
            }
114
        }
115
116
        return $value;
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    public function delete($key): bool
123
    {
124
        if (!$this->isAvailableCacheLibrary()) {
125
            return false;
126
        }
127
        $key = $this->cachePrefix . $key;
128
        $result = false;
129
130
        $file = new File($this->cacheContainer->cacheDir . '/' . $key . '.cache');
131
        if ($file->isWritable()) {
132
            $result = $file->delete();
133
            if ($result) {
134
                $this->logger->info("Execute cache cleared: " . $key);
135
            } else {
136
                $this->logger->warn("Failed to clear cache: " . $key);
137
            }
138
        } else {
139
            $this->logger->warn("Failed to clear cache: " . $key);
140
        }
141
142
        return $result;
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function clear(): bool
149
    {
150
        if (!$this->isAvailableCacheLibrary()) {
151
            return false;
152
        }
153
        $dir = new File($this->cacheContainer->cacheDir);
154
        $result = true;
155
156
        if ($dir->isReadable()) {
157
            $iterator = $this->cacheContainer->ioContainer->fileIterator->getIterator($dir->getFilePath());
158
            foreach ($iterator as $filepath => $fileObject) {
159
                if (strpos($filepath, $this->cachePrefix, 0) !== false) {
160
                    try {
161
                        $file = new File($filepath);
162
                        if ($file->isWritable()) {
163
                            if ($file->delete()) {
164
                                $this->logger->info("Execute cache cleared: " . $this->cachePrefix . "*");
165
                            } else {
166
                                $this->logger->warn("Failed to clear cache: " . $this->cachePrefix . "*");
167
                                $result = false;
168
                            }
169
                        } else {
170
                            $result = false;
171
                        }
172
                    } catch (IOException $e) {
173
                        $this->logger->warn($e->getMessage());
174
                        $result = false;
175
                    }
176
                }
177
            }
178
        } else {
179
            $this->logger->warn("Can't read directory:" . $dir->getFilePath());
180
            $result = false;
181
        }
182
183
        return $result;
184
    }
185
186
    /**
187
     * キャッシュライブラリが使用可能か検査する
188
     * @return bool 使用可能でtrue
189
     */
190
    private function isAvailableCacheLibrary(): bool
191
    {
192
        if ($this->cacheContainer->available) {
193
            return true;
194
        }
195
196
        $this->logger->warn("TemporaryFile cache library is unavailable.");
197
198
        return false;
199
    }
200
}
201