Completed
Push — master ( e090e4...18d79e )
by Damian
02:26
created

code/checks/FileAgeCheck.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Checks for the maximum age of one or more files or folders.
5
 * Useful for files which should be frequently auto-generated, 
6
 * like static caches, as well as for backup files and folders.
7
 * Does NOT check for existence of a file (will silently fail).
8
 *
9
 * Examples:
10
 * // Checks that Requirements::combine_files() has regenerated files in the last 24h
11
 * EnvironmentCheckSuite::register(
12
 * 	'check', 
13
 * 	'FileAgeCheck("' . ASSETS_PATH . '/_combined_files/*.js' . '", "-1 day", '>', " . FileAgeCheck::CHECK_ALL) . "'
14
 * );
15
 * 
16
 * // Checks that at least one backup folder has been created in the last 24h
17
 * EnvironmentCheckSuite::register(
18
 * 	'check', 
19
 * 	'FileAgeCheck("' . BASE_PATH . '/../backups/*' . '", "-1 day", '>', " . FileAgeCheck::CHECK_SINGLE) . "'
20
 * );
21
 */
22
class FileAgeCheck implements EnvironmentCheck
23
{
24
    /**
25
     * @var int
26
     */
27
    const CHECK_SINGLE = 1;
28
29
    /**
30
     * @var int
31
     */
32
    const CHECK_ALL = 2;
33
    
34
    /**
35
     * Absolute path to a file or folder, compatible with glob().
36
     *
37
     * @var string
38
     */
39
    protected $path;
40
41
    /**
42
     * Relative date specification, compatible with strtotime().
43
     *
44
     * @var string
45
     */
46
    protected $relativeAge;
47
48
    /**
49
     * The function to use for checking file age: so filemtime(), filectime(), or fileatime().
50
     *
51
     * @var string
52
     */
53
    protected $checkFn;
54
55
    /**
56
     * Constant, check for a single file to match age criteria, or all of them.
57
     *
58
     * @var int
59
     */
60
    protected $checkType;
61
62
    /**
63
     * Type of comparison (either > or <).
64
     *
65
     * @var string
66
     */
67
    protected $compareOperand;
68
69
    /**
70
     * @param string $path
71
     * @param string $relativeAge
72
     * @param string $compareOperand
73
     * @param null|int $checkType
74
     * @param string $checkFn
75
     */
76
    public function __construct($path, $relativeAge, $compareOperand = '>', $checkType = null, $checkFn = 'filemtime')
77
    {
78
        $this->path = $path;
79
        $this->relativeAge = $relativeAge;
80
        $this->checkFn = $checkFn;
81
        $this->checkType = ($checkType) ? $checkType : self::CHECK_SINGLE;
82
        $this->compareOperand = $compareOperand;
83
    }
84
85
    /**
86
     * @inheritdoc
87
     *
88
     * @return array
89
     */
90
    public function check()
91
    {
92
        $cutoffTime =  strtotime($this->relativeAge, SS_Datetime::now()->Format('U'));
93
        $files = $this->getFiles();
94
        $invalidFiles = array();
95
        $validFiles = array();
96
        $checkFn = $this->checkFn;
97
        $allValid = true;
98
        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...
99
            foreach ($files as $file) {
100
                $fileTime = $checkFn($file);
101
                $valid = ($this->compareOperand == '>') ? ($fileTime >= $cutoffTime) : ($fileTime <= $cutoffTime);
102
                if ($valid) {
103
                    $validFiles[] = $file;
104
                } else {
105
                    $invalidFiles[] = $file;
106
                    if ($this->checkType == self::CHECK_ALL) {
107
                        return array(
108
                        EnvironmentCheck::ERROR,
109
                        sprintf(
110
                            'File "%s" doesn\'t match age check (compare %s: %s, actual: %s)',
111
                            $file, $this->compareOperand, date('c', $cutoffTime), date('c', $fileTime)
112
                        )
113
                    );
114
                    }
115
                }
116
            }
117
        }
118
119
        // If at least one file was valid, count as passed
120
        if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) {
121
            return array(EnvironmentCheck::OK, '');
122
        } else {
123
            if (count($invalidFiles) == 0) {
124
                return array(EnvironmentCheck::OK, '');
125
            } else {
126
                return array(
127
                EnvironmentCheck::ERROR,
128
                sprintf('No files matched criteria (%s %s)', $this->compareOperand, date('c', $cutoffTime))
129
            );
130
            }
131
        }
132
    }
133
134
    /**
135
     * Gets a list of absolute file paths.
136
     *
137
     * @return array
138
     */
139
    protected function getFiles()
140
    {
141
        return glob($this->path);
142
    }
143
}
144