Completed
Branch master (9dcfc4)
by Daniel
24:32
created

FileAgeCheck::check()   D

Complexity

Conditions 9
Paths 8

Size

Total Lines 44
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 44
rs 4.909
c 0
b 0
f 0
cc 9
eloc 31
nc 8
nop 0
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'));
100
        $files = $this->getFiles();
101
        $invalidFiles = [];
102
        $validFiles = [];
103
        $checkFn = $this->checkFn;
104
        $allValid = true;
0 ignored issues
show
Unused Code introduced by
$allValid is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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);
150
    }
151
}
152