1 | <?php |
||
2 | |||
3 | namespace SilverStripe\EnvironmentCheck\Checks; |
||
4 | |||
5 | use SilverStripe\EnvironmentCheck\EnvironmentCheck; |
||
6 | use SilverStripe\ORM\FieldType\DBDatetime; |
||
7 | |||
8 | /** |
||
9 | * Checks for the maximum age of one or more files or folders. |
||
10 | * Useful for files which should be frequently auto-generated, |
||
11 | * like static caches, as well as for backup files and folders. |
||
12 | * Does NOT check for existence of a file (will silently fail). |
||
13 | * |
||
14 | * Examples: |
||
15 | * // Checks that Requirements::combine_files() has regenerated files in the last 24h |
||
16 | * EnvironmentCheckSuite::register( |
||
17 | * 'check', |
||
18 | * 'FileAgeCheck("' . ASSETS_PATH . '/_combined_files/*.js' . '", "-1 day", '>', " . FileAgeCheck::CHECK_ALL) . "' |
||
19 | * ); |
||
20 | * |
||
21 | * // Checks that at least one backup folder has been created in the last 24h |
||
22 | * EnvironmentCheckSuite::register( |
||
23 | * 'check', |
||
24 | * 'FileAgeCheck("' . BASE_PATH . '/../backups/*' . '", "-1 day", '>', " . FileAgeCheck::CHECK_SINGLE) . "' |
||
25 | * ); |
||
26 | * |
||
27 | * @package environmentcheck |
||
28 | */ |
||
29 | class FileAgeCheck implements EnvironmentCheck |
||
30 | { |
||
31 | /** |
||
32 | * @var int |
||
33 | */ |
||
34 | const CHECK_SINGLE = 1; |
||
35 | |||
36 | /** |
||
37 | * @var int |
||
38 | */ |
||
39 | const CHECK_ALL = 2; |
||
40 | |||
41 | /** |
||
42 | * Absolute path to a file or folder, compatible with glob(). |
||
43 | * |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $path; |
||
47 | |||
48 | /** |
||
49 | * Relative date specification, compatible with strtotime(). |
||
50 | * |
||
51 | * @var string |
||
52 | */ |
||
53 | protected $relativeAge; |
||
54 | |||
55 | /** |
||
56 | * The function to use for checking file age: so filemtime(), filectime(), or fileatime(). |
||
57 | * |
||
58 | * @var string |
||
59 | */ |
||
60 | protected $checkFn; |
||
61 | |||
62 | /** |
||
63 | * Constant, check for a single file to match age criteria, or all of them. |
||
64 | * |
||
65 | * @var int |
||
66 | */ |
||
67 | protected $checkType; |
||
68 | |||
69 | /** |
||
70 | * Type of comparison (either > or <). |
||
71 | * |
||
72 | * @var string |
||
73 | */ |
||
74 | protected $compareOperand; |
||
75 | |||
76 | /** |
||
77 | * @param string $path |
||
78 | * @param string $relativeAge |
||
79 | * @param string $compareOperand |
||
80 | * @param null|int $checkType |
||
81 | * @param string $checkFn |
||
82 | */ |
||
83 | public function __construct($path, $relativeAge, $compareOperand = '>', $checkType = null, $checkFn = 'filemtime') |
||
84 | { |
||
85 | $this->path = $path; |
||
86 | $this->relativeAge = $relativeAge; |
||
87 | $this->checkFn = $checkFn; |
||
88 | $this->checkType = ($checkType) ? $checkType : self::CHECK_SINGLE; |
||
89 | $this->compareOperand = $compareOperand; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * {@inheritDoc} |
||
94 | * |
||
95 | * @return array |
||
96 | */ |
||
97 | public function check() |
||
98 | { |
||
99 | $cutoffTime = strtotime($this->relativeAge, DBDatetime::now()->Format('U')); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
100 | $files = $this->getFiles(); |
||
101 | $invalidFiles = []; |
||
102 | $validFiles = []; |
||
103 | $checkFn = $this->checkFn; |
||
104 | $allValid = true; |
||
0 ignored issues
–
show
|
|||
105 | if ($files) { |
||
0 ignored issues
–
show
The expression
$files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
106 | foreach ($files as $file) { |
||
107 | $fileTime = $checkFn($file); |
||
108 | $valid = ($this->compareOperand == '>') ? ($fileTime >= $cutoffTime) : ($fileTime <= $cutoffTime); |
||
109 | if ($valid) { |
||
110 | $validFiles[] = $file; |
||
111 | } else { |
||
112 | $invalidFiles[] = $file; |
||
113 | if ($this->checkType == self::CHECK_ALL) { |
||
114 | return [ |
||
115 | EnvironmentCheck::ERROR, |
||
116 | sprintf( |
||
117 | 'File "%s" doesn\'t match age check (compare %s: %s, actual: %s)', |
||
118 | $file, |
||
119 | $this->compareOperand, |
||
120 | date('c', $cutoffTime), |
||
121 | date('c', $fileTime) |
||
122 | ) |
||
123 | ]; |
||
124 | } |
||
125 | } |
||
126 | } |
||
127 | } |
||
128 | |||
129 | // If at least one file was valid, count as passed |
||
130 | if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) { |
||
131 | return [EnvironmentCheck::OK, '']; |
||
132 | } |
||
133 | if (count($invalidFiles) == 0) { |
||
134 | return [EnvironmentCheck::OK, '']; |
||
135 | } |
||
136 | return [ |
||
137 | EnvironmentCheck::ERROR, |
||
138 | sprintf('No files matched criteria (%s %s)', $this->compareOperand, date('c', $cutoffTime)) |
||
139 | ]; |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Gets a list of absolute file paths. |
||
144 | * |
||
145 | * @return array |
||
146 | */ |
||
147 | protected function getFiles() |
||
148 | { |
||
149 | return glob($this->path); |
||
0 ignored issues
–
show
The expression
return glob($this->path) could also return false which is incompatible with the documented return type array . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||
150 | } |
||
151 | } |
||
152 |