Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
84 / 84 |
|
100.00% |
12 / 12 |
CRAP | |
100.00% |
1 / 1 |
File | |
100.00% |
84 / 84 |
|
100.00% |
12 / 12 |
51 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getFolder | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPrefix | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getId | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
decode | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
send | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
4 | |||
getStates | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
7 | |||
getStateById | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
getStateByModel | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 | |||
getStateByTimestamp | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
9 | |||
getStateByDate | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
12 | |||
getSnapshot | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
5 |
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-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Audit\Adapter; |
15 | |
16 | /** |
17 | * Auditor file class |
18 | * |
19 | * @category Pop |
20 | * @package Pop\Audit |
21 | * @author Nick Sagona, III <dev@nolainteractive.com> |
22 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
23 | * @license http://www.popphp.org/license New BSD License |
24 | * @version 1.3.0 |
25 | */ |
26 | class File extends AbstractAdapter |
27 | { |
28 | |
29 | /** |
30 | * Folder to store the audit results |
31 | * @var string |
32 | */ |
33 | protected $folder = null; |
34 | |
35 | |
36 | /** |
37 | * File prefix |
38 | * @var string |
39 | */ |
40 | protected $prefix = 'pop-audit-'; |
41 | |
42 | /** |
43 | * Constructor |
44 | * |
45 | * Instantiate the file adapter object |
46 | * |
47 | * @param string $folder |
48 | * @param string $prefix |
49 | * @throws Exception |
50 | */ |
51 | public function __construct($folder, $prefix = 'pop-audit-') |
52 | { |
53 | if (!file_exists($folder)) { |
54 | throw new Exception('That folder does not exist.'); |
55 | } |
56 | $this->folder = $folder; |
57 | $this->prefix = $prefix; |
58 | } |
59 | |
60 | /** |
61 | * Get the folder |
62 | * |
63 | * @return string |
64 | */ |
65 | public function getFolder() |
66 | { |
67 | return $this->folder; |
68 | } |
69 | |
70 | /** |
71 | * Get the prefix |
72 | * |
73 | * @return string |
74 | */ |
75 | public function getPrefix() |
76 | { |
77 | return $this->prefix; |
78 | } |
79 | |
80 | /** |
81 | * Get ID from filename |
82 | * |
83 | * @param string $filename |
84 | * @throws Exception |
85 | * @return string |
86 | */ |
87 | public function getId($filename) |
88 | { |
89 | $filename = substr($filename, 0, strrpos($filename, '.')); |
90 | $filename = substr($filename, 0, strrpos($filename, '-')); |
91 | return substr($filename, (strrpos($filename, '-') + 1)); |
92 | } |
93 | |
94 | /** |
95 | * Decode the audit file |
96 | * |
97 | * @param string $filename |
98 | * @throws Exception |
99 | * @return array |
100 | */ |
101 | public function decode($filename) |
102 | { |
103 | if (!file_exists($this->folder . DIRECTORY_SEPARATOR . $filename)) { |
104 | throw new Exception('That audit file does not exist.'); |
105 | } |
106 | |
107 | return json_decode(file_get_contents($this->folder . DIRECTORY_SEPARATOR . $filename), true); |
108 | } |
109 | |
110 | /** |
111 | * Send the results of the audit |
112 | * |
113 | * @throws Exception |
114 | * @return string |
115 | */ |
116 | public function send() |
117 | { |
118 | if (null === $this->action) { |
119 | throw new Exception('The model state differences have not been resolved.'); |
120 | } |
121 | if ((null === $this->model) || (null === $this->modelId)) { |
122 | throw new Exception('The model has not been set.'); |
123 | } |
124 | |
125 | $id = md5($this->model . '-' . $this->modelId) . '-' .uniqid() . '-' . time(); |
126 | $filename = $this->prefix . $id . '.log'; |
127 | file_put_contents( |
128 | $this->folder . DIRECTORY_SEPARATOR . $filename, |
129 | json_encode($this->prepareData(false), JSON_PRETTY_PRINT) |
130 | ); |
131 | |
132 | return $filename; |
133 | } |
134 | |
135 | /** |
136 | * Get model states |
137 | * |
138 | * @param string $sort |
139 | * @param int $limit |
140 | * @param int $offset |
141 | * @return array |
142 | */ |
143 | public function getStates($sort = 'DESC', $limit = null, $offset = null) |
144 | { |
145 | $files = scandir($this->folder); |
146 | $fileNames = []; |
147 | $results = []; |
148 | |
149 | foreach ($files as $file) { |
150 | if (($file != '.') && ($file != '..')) { |
151 | $mtime = filemtime($this->folder . DIRECTORY_SEPARATOR . $file); |
152 | $fileNames[$mtime] = $file; |
153 | } |
154 | } |
155 | |
156 | if ($sort == 'ASC') { |
157 | ksort($fileNames, SORT_NUMERIC); |
158 | } else { |
159 | krsort($fileNames, SORT_NUMERIC); |
160 | } |
161 | |
162 | if (null !== $limit) { |
163 | $fileNames = array_slice($fileNames, (int)$offset, (int)$limit); |
164 | } |
165 | |
166 | foreach ($fileNames as $fileName) { |
167 | $results[$fileName] = $this->decode($fileName); |
168 | } |
169 | |
170 | return $results; |
171 | } |
172 | |
173 | /** |
174 | * Get model state by ID |
175 | * |
176 | * @param int $id |
177 | * @return array |
178 | */ |
179 | public function getStateById($id) |
180 | { |
181 | $files = scandir($this->folder); |
182 | $results = []; |
183 | |
184 | foreach ($files as $file) { |
185 | if (strpos($file, $id) !== false) { |
186 | $results[$file] = $this->decode($file); |
187 | break; |
188 | } |
189 | } |
190 | |
191 | return $results; |
192 | } |
193 | |
194 | /** |
195 | * Get model state by model |
196 | * |
197 | * @param string $model |
198 | * @param int $modelId |
199 | * @throws Exception |
200 | * @return array |
201 | */ |
202 | public function getStateByModel($model, $modelId = null) |
203 | { |
204 | if (null === $modelId) { |
205 | throw new Exception('You must pass a model ID.'); |
206 | } |
207 | |
208 | $files = scandir($this->folder); |
209 | $id = md5($model . '-' . $modelId); |
210 | $results = []; |
211 | |
212 | foreach ($files as $file) { |
213 | if (strpos($file, $id) !== false) { |
214 | $results[$file] = $this->decode($file); |
215 | } |
216 | } |
217 | |
218 | return $results; |
219 | } |
220 | |
221 | /** |
222 | * Get model state by timestamp |
223 | * |
224 | * @param string $from |
225 | * @param string $backTo |
226 | * @return array |
227 | */ |
228 | public function getStateByTimestamp($from, $backTo = null) |
229 | { |
230 | $files = scandir($this->folder); |
231 | $results = []; |
232 | |
233 | foreach ($files as $file) { |
234 | if (($file != '.') && ($file != '..')) { |
235 | $mtime = filemtime($this->folder . DIRECTORY_SEPARATOR . $file); |
236 | if (((null !== $backTo) && ($mtime <= $from) && ($mtime >= $backTo)) || |
237 | ((null === $backTo) && ($mtime <= $from))) { |
238 | $results[$file] = $this->decode($file); |
239 | } |
240 | } |
241 | } |
242 | |
243 | return $results; |
244 | } |
245 | |
246 | /** |
247 | * Get model state by date |
248 | * |
249 | * @param string $from |
250 | * @param string $backTo |
251 | * @return array |
252 | */ |
253 | public function getStateByDate($from, $backTo = null) |
254 | { |
255 | $results = []; |
256 | |
257 | if (strpos($from, ' ') === false) { |
258 | $from .= ' 23:59:59'; |
259 | } |
260 | |
261 | $from = strtotime($from); |
262 | |
263 | if (null !== $backTo) { |
264 | if (strpos($backTo, ' ') === false) { |
265 | $backTo .= ' 00:00:00'; |
266 | } |
267 | $backTo = strtotime($backTo); |
268 | } |
269 | |
270 | $files = scandir($this->folder); |
271 | foreach ($files as $file) { |
272 | if (($file != '.') && ($file != '..')) { |
273 | $mtime = filemtime($this->folder . DIRECTORY_SEPARATOR . $file); |
274 | if (((null !== $backTo) && ($mtime <= $from) && ($mtime >= $backTo)) || |
275 | ((null === $backTo) && ($mtime <= $from))) { |
276 | $results[$file] = $this->decode($file); |
277 | } |
278 | } |
279 | } |
280 | |
281 | return $results; |
282 | } |
283 | |
284 | /** |
285 | * Get model snapshot by ID |
286 | * |
287 | * @param int $id |
288 | * @param boolean $post |
289 | * @return array |
290 | */ |
291 | public function getSnapshot($id, $post = false) |
292 | { |
293 | $result = $this->getStateById($id); |
294 | $result = reset($result); |
295 | $snapshot = []; |
296 | |
297 | if (!($post) && !empty($result['old'])) { |
298 | $snapshot = $result['old']; |
299 | } else if (($post) && !empty($result['new'])) { |
300 | $snapshot = $result['new']; |
301 | } |
302 | |
303 | return $snapshot; |
304 | } |
305 | |
306 | } |