FileAgeCheck   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 44
dl 0
loc 121
rs 10
c 0
b 0
f 0
wmc 12

3 Methods

Rating   Name   Duplication   Size   Complexity  
B check() 0 42 9
A __construct() 0 7 2
A getFiles() 0 3 1
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
SilverStripe\ORM\FieldTy...ime::now()->Format('U') of type string is incompatible with the type integer expected by parameter $now of strtotime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
        $cutoffTime =  strtotime($this->relativeAge, /** @scrutinizer ignore-type */ DBDatetime::now()->Format('U'));
Loading history...
100
        $files = $this->getFiles();
101
        $invalidFiles = [];
102
        $validFiles = [];
103
        $checkFn = $this->checkFn;
104
        $allValid = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $allValid is dead and can be removed.
Loading history...
105
        if ($files) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
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
Bug Best Practice introduced by
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.

Loading history...
150
    }
151
}
152