Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.00% covered (success)
96.00%
48 / 50
80.00% covered (success)
80.00%
8 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
File
96.00% covered (success)
96.00%
48 / 50
80.00% covered (success)
80.00%
8 / 10
26
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setDir
83.33% covered (success)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getDir
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getItemTtl
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 saveItem
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getItem
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 hasItem
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 deleteItem
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 clear
87.50% covered (success)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
7.10
 destroy
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Cache\Adapter;
15
16/**
17 * File adapter cache class
18 *
19 * @category   Pop
20 * @package    Pop\Cache
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    4.0.0
25 */
26class File extends AbstractAdapter
27{
28
29    /**
30     * Cache dir
31     * @var ?string
32     */
33    protected ?string $dir = null;
34
35    /**
36     * Constructor
37     *
38     * Instantiate the cache file object
39     *
40     * @param  string $dir
41     * @param  int    $ttl
42     */
43    public function __construct(string $dir, int $ttl = 0)
44    {
45        parent::__construct($ttl);
46        $this->setDir($dir);
47    }
48
49    /**
50     * Set the current cache dir
51     *
52     * @param  string $dir
53     * @throws Exception
54     * @return File
55     */
56    public function setDir(string $dir): File
57    {
58        if (!file_exists($dir)) {
59            throw new Exception('Error: That cache directory does not exist.');
60        } else if (!is_writable($dir)) {
61            throw new Exception('Error: That cache directory is not writable.');
62        }
63
64        $this->dir = realpath($dir);
65
66        return $this;
67    }
68
69    /**
70     * Get the current cache dir
71     *
72     * @return ?string
73     */
74    public function getDir(): ?string
75    {
76        return $this->dir;
77    }
78
79    /**
80     * Get the time-to-live for an item in cache
81     *
82     * @param  string $id
83     * @return int
84     */
85    public function getItemTtl(string $id): int
86    {
87        $fileId = $this->dir . DIRECTORY_SEPARATOR . sha1($id);
88        $ttl    = 0;
89
90        if (file_exists($fileId)) {
91            $cacheValue = unserialize(file_get_contents($fileId));
92            $ttl        = $cacheValue['ttl'];
93        }
94
95        return $ttl;
96    }
97
98    /**
99     * Save an item to cache
100     *
101     * @param  string $id
102     * @param  mixed  $value
103     * @param  ?int   $ttl
104     * @return File
105     */
106    public function saveItem(string $id, mixed $value, ?int $ttl = null): File
107    {
108        file_put_contents($this->dir . DIRECTORY_SEPARATOR . sha1($id), serialize([
109            'start' => time(),
110            'ttl'   => ($ttl !== null) ? $ttl : $this->ttl,
111            'value' => $value
112        ]));
113
114        return $this;
115    }
116
117    /**
118     * Get an item from cache
119     *
120     * @param  string $id
121     * @return mixed
122     */
123    public function getItem(string $id): mixed
124    {
125        $fileId = $this->dir . DIRECTORY_SEPARATOR . sha1($id);
126        $value  = false;
127
128        if (file_exists($fileId)) {
129            $cacheValue = unserialize(file_get_contents($fileId));
130            if (($cacheValue['ttl'] == 0) || ((time() - $cacheValue['start']) <= $cacheValue['ttl'])) {
131                $value = $cacheValue['value'];
132            } else {
133                $this->deleteItem($id);
134            }
135        }
136
137        return $value;
138    }
139
140    /**
141     * Determine if the item exist in cache
142     *
143     * @param  string $id
144     * @return bool
145     */
146    public function hasItem(string $id): bool
147    {
148        $fileId = $this->dir . DIRECTORY_SEPARATOR . sha1($id);
149        $result = false;
150
151        if (file_exists($fileId)) {
152            $cacheValue = unserialize(file_get_contents($fileId));
153            $result     = (($cacheValue['ttl'] == 0) || ((time() - $cacheValue['start']) <= $cacheValue['ttl']));
154        }
155
156        return $result;
157    }
158
159    /**
160     * Delete a value in cache
161     *
162     * @param  string $id
163     * @return File
164     */
165    public function deleteItem(string $id): File
166    {
167        $fileId = $this->dir . DIRECTORY_SEPARATOR . sha1($id);
168        if (file_exists($fileId)) {
169            unlink($fileId);
170        }
171        return $this;
172    }
173
174    /**
175     * Clear all stored values from cache
176     *
177     * @return File
178     */
179    public function clear(): File
180    {
181        if (!$dh = @opendir($this->dir)) {
182            return $this;
183        }
184
185        while (false !== ($obj = readdir($dh))) {
186            if (($obj != '.') && ($obj != '..') &&
187                !is_dir($this->dir . DIRECTORY_SEPARATOR . $obj) && is_file($this->dir . DIRECTORY_SEPARATOR . $obj)) {
188                unlink($this->dir . DIRECTORY_SEPARATOR . $obj);
189            }
190        }
191
192        closedir($dh);
193
194        return $this;
195    }
196
197    /**
198     * Destroy cache resource
199     *
200     * @return File
201     */
202    public function destroy(): File
203    {
204        $this->clear();
205        @rmdir($this->dir);
206
207        return $this;
208    }
209
210}