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

code/checks/FileAgeCheck.php (4 issues)

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 {
0 ignored issues
show
As per PSR2, the opening brace for this class should be on a new line.
Loading history...
23
	/**
24
	 * @var int
25
	 */
26
	const CHECK_SINGLE = 1;
27
28
	/**
29
	 * @var int
30
	 */
31
	const CHECK_ALL = 2;
32
	
33
	/**
34
	 * Absolute path to a file or folder, compatible with glob().
35
	 *
36
	 * @var string
37
	 */
38
	protected $path;
39
40
	/**
41
	 * Relative date specification, compatible with strtotime().
42
	 *
43
	 * @var string
44
	 */
45
	protected $relativeAge;
46
47
	/**
48
	 * The function to use for checking file age: so filemtime(), filectime(), or fileatime().
49
	 *
50
	 * @var string
51
	 */
52
	protected $checkFn;
53
54
	/**
55
	 * Constant, check for a single file to match age criteria, or all of them.
56
	 *
57
	 * @var int
58
	 */
59
	protected $checkType;
60
61
	/**
62
	 * Type of comparison (either > or <).
63
	 *
64
	 * @var string
65
	 */
66
	protected $compareOperand;
67
68
	/**
69
	 * @param string $path
70
	 * @param string $relativeAge
71
	 * @param string $compareOperand
72
	 * @param null|int $checkType
73
	 * @param string $checkFn
74
	 */
75
	function __construct($path, $relativeAge, $compareOperand = '>', $checkType = null, $checkFn = 'filemtime') {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
76
		$this->path = $path;
77
		$this->relativeAge = $relativeAge;
78
		$this->checkFn = $checkFn;
79
		$this->checkType = ($checkType) ? $checkType : self::CHECK_SINGLE;
80
		$this->compareOperand = $compareOperand;
81
	}
82
83
	/**
84
	 * @inheritdoc
85
	 *
86
	 * @return array
87
	 */
88
	function check() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
89
		$cutoffTime =  strtotime($this->relativeAge, SS_Datetime::now()->Format('U'));
90
		$files = $this->getFiles();
91
		$invalidFiles = array();
92
		$validFiles = array();
93
		$checkFn = $this->checkFn;
94
		$allValid = true;
95
		if($files) foreach($files as $file) {
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...
96
			$fileTime = $checkFn($file);
97
			$valid = ($this->compareOperand == '>') ? ($fileTime >= $cutoffTime) : ($fileTime <= $cutoffTime);
98
			if($valid) {
99
				$validFiles[] = $file;
100
			} else {
101
				$invalidFiles[] = $file;
102
				if($this->checkType == self::CHECK_ALL) {
103
					return array(
104
						EnvironmentCheck::ERROR,
105
						sprintf(
106
							'File "%s" doesn\'t match age check (compare %s: %s, actual: %s)', 
107
							$file, $this->compareOperand, date('c', $cutoffTime), date('c', $fileTime)
108
						)
109
					);	
110
				}
111
			}
112
		}
113
114
		// If at least one file was valid, count as passed
115
		if($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) {
116
			return array(EnvironmentCheck::OK, '');
117
		} else {
118
	       if (count($invalidFiles) == 0) return array(EnvironmentCheck::OK, '');
119
	       else return array(
120
				EnvironmentCheck::ERROR,
121
				sprintf('No files matched criteria (%s %s)', $this->compareOperand, date('c', $cutoffTime))
122
			);
123
		}
124
			
125
	}
126
127
	/**
128
	 * Gets a list of absolute file paths.
129
	 *
130
	 * @return array
131
	 */
132
	protected function getFiles() {
133
		return glob($this->path);
134
	}
135
}
136