Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
84 / 84
100.00% covered (success)
100.00%
12 / 12
CRAP
100.00% covered (success)
100.00%
1 / 1
File
100.00% covered (success)
100.00%
84 / 84
100.00% covered (success)
100.00%
12 / 12
51
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getFolder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPrefix
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 decode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 send
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 getStates
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
 getStateById
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 getStateByModel
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 getStateByTimestamp
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
9
 getStateByDate
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
12
 getSnapshot
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
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 */
14namespace 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 */
26class 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}