Completed
Push — develop ( 16e50c...73e4c3 )
by Timothy
05:53
created

RoboFile.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 declare(strict_types=1);
2 View Code Duplication
if ( ! function_exists('glob_recursive'))
3
{
4
	// Does not support flag GLOB_BRACE
5
	function glob_recursive($pattern, $flags = 0)
6
	{
7
		$files = glob($pattern, $flags);
8
9
		foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
10
		{
11
			$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
12
		}
13
14
		return $files;
15
	}
16
}
17
18
/**
19
 * This is project's console commands configuration for Robo task runner.
20
 *
21
 * @see http://robo.li/
22
 */
23
class RoboFile extends \Robo\Tasks {
24
25
	/**
26
	 * Directories used by analysis tools
27
	 *
28
	 * @var array
29
	 */
30
	protected $taskDirs = [
31
		'build/logs',
32
		'build/pdepend',
33
		'build/phpdox',
34
	];
35
36
	/**
37
	 * Directories to remove with the clean task
38
	 *
39
	 * @var array
40
	 */
41
	protected $cleanDirs = [
42
		'coverage',
43
		'docs',
44
		'phpdoc',
45
		'build/logs',
46
		'build/phpdox',
47
		'build/pdepend'
48
	];
49
50
51
	/**
52
	 * Do static analysis tasks
53
	 */
54
	public function analyze()
55
	{
56
		$this->prepare();
57
		$this->lint();
58
		$this->phploc(TRUE);
59
		$this->phpcs(TRUE);
60
		$this->dependencyReport();
61
		$this->phpcpdReport();
62
	}
63
64
	/**
65
	 * Run all tests, generate coverage, generate docs, generate code statistics
66
	 */
67
	public function build()
68
	{
69
		$this->analyze();
70
		$this->coverage();
71
		$this->docs();
72
	}
73
74
	/**
75
	 * Cleanup temporary files
76
	 */
77
	public function clean()
78
	{
79
		$cleanFiles = [
80
			'build/humbug.json',
81
			'build/humbug-log.txt',
82
		];
83
		array_map(function ($file) {
84
			@unlink($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
85
		}, $cleanFiles);
86
87
		// So the task doesn't complain,
88
		// make any 'missing' dirs to cleanup
89
		array_map(function ($dir) {
90
			if ( ! is_dir($dir))
91
			{
92
				`mkdir -p {$dir}`;
93
			}
94
		}, $this->cleanDirs);
95
96
		$this->_cleanDir($this->cleanDirs);
97
		$this->_deleteDir($this->cleanDirs);
98
	}
99
100
	/**
101
	 * Run unit tests and generate coverage reports
102
	 */
103
	public function coverage()
104
	{
105
		$this->taskPhpUnit()
106
			->configFile('build/phpunit.xml')
107
			->printed(true)
108
			->run();
109
	}
110
111
	/**
112
	 * Generate documentation with phpdox
113
	 */
114
	public function docs()
115
	{
116
		$cmd_parts = [
117
			'phpdoc'
118
		];
119
		$this->_run($cmd_parts, ' && ');
120
	}
121
122
	/**
123
	 * Verify that source files are valid
124
	 */
125
	public function lint()
126
	{
127
		$files = $this->getAllSourceFiles();
128
129
		$chunks = array_chunk($files, (int)`getconf _NPROCESSORS_ONLN`);
130
131
		foreach($chunks as $chunk)
132
		{
133
			$this->parallelLint($chunk);
134
		}
135
	}
136
137
138
	/**
139
	 * Run mutation tests with humbug
140
	 *
141
	 * @param bool $stats - if true, generates stats rather than running mutation tests
142
	 */
143
	public function mutate($stats = FALSE)
144
	{
145
		$test_parts = [
146
			'vendor/bin/humbug'
147
		];
148
149
		$stat_parts = [
150
			'vendor/bin/humbug',
151
			'--skip-killed=yes',
152
			'-v',
153
			'./build/humbug.json'
154
		];
155
156
		$cmd_parts = ($stats) ? $stat_parts : $test_parts;
157
		$this->_run($cmd_parts);
158
	}
159
160
	/**
161
	 * Run the phpcs tool
162
	 *
163
	 * @param bool $report - if true, generates reports instead of direct output
164
	 */
165
	public function phpcs($report = FALSE)
166
	{
167
		$dir = __DIR__;
168
169
		$report_cmd_parts = [
170
			'vendor/bin/phpcs',
171
			"--standard=./build/CodeIgniter",
172
			"--report-checkstyle=./build/logs/phpcs.xml",
173
		];
174
175
		$normal_cmd_parts = [
176
			'vendor/bin/phpcs',
177
			"--standard=./build/CodeIgniter",
178
		];
179
180
		$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
181
182
		$this->_run($cmd_parts);
183
	}
184
185
	/**
186
	 * Run the phploc tool
187
	 *
188
	 * @param bool $report - if true, generates reports instead of direct output
189
	 */
190
	public function phploc($report = FALSE)
191
	{
192
		// Command for generating reports
193
		$report_cmd_parts = [
194
			'vendor/bin/phploc',
195
			'--count-tests',
196
			'--log-csv=build/logs/phploc.csv',
197
			'--log-xml=build/logs/phploc.xml',
198
			'src',
199
			'tests'
200
		];
201
202
		// Command for generating direct output
203
		$normal_cmd_parts = [
204
			'vendor/bin/phploc',
205
			'--count-tests',
206
			'src',
207
			'tests'
208
		];
209
210
		$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
211
212
		$this->_run($cmd_parts);
213
	}
214
215
	/**
216
	 * Create temporary directories
217
	 */
218
	public function prepare()
219
	{
220
		array_map([$this, '_mkdir'], $this->taskDirs);
221
	}
222
223
	/**
224
	 * Lint php files and run unit tests
225
	 */
226
	public function test()
227
	{
228
		$this->lint();
229
		$this->taskPHPUnit()
230
			->configFile('phpunit.xml')
231
			->printed(true)
232
			->run();
233
		$this->_run(["php tests/index.php"]);
234
	}
235
236
	/**
237
	 * Watches for file updates, and automatically runs appropriate actions
238
	 */
239
	public function watch()
240
	{
241
		$this->taskWatch()
242
			->monitor('composer.json', function() {
243
				$this->taskComposerUpdate()->run();
244
			})
245
			->monitor('src', function () {
246
				$this->taskExec('test')->run();
247
			})
248
			->monitor('tests', function () {
249
				$this->taskExec('test')->run();
250
			})
251
			->run();
252
	}
253
254
	/**
255
	 * Create pdepend reports
256
	 */
257
	protected function dependencyReport()
258
	{
259
		$cmd_parts = [
260
			'vendor/bin/pdepend',
261
			'--jdepend-xml=build/logs/jdepend.xml',
262
			'--jdepend-chart=build/pdepend/dependencies.svg',
263
			'--overview-pyramid=build/pdepend/overview-pyramid.svg',
264
			'src'
265
		];
266
		$this->_run($cmd_parts);
267
	}
268
269
	/**
270
	 * Get the total list of source files, including tests
271
	 *
272
	 * @return array
273
	 */
274
	protected function getAllSourceFiles()
275
	{
276
		$files = array_merge(
277
			glob_recursive('build/*.php'),
278
			glob_recursive('src/*.php'),
279
			glob_recursive('tests/*.php'),
280
			glob('*.php')
281
		);
282
283
		sort($files);
284
285
		return $files;
286
	}
287
288
	/**
289
	 * Run php's linter in one parallel task for the passed chunk
290
	 *
291
	 * @param array $chunk
292
	 */
293
	protected function parallelLint(array $chunk)
294
	{
295
		$task = $this->taskParallelExec()
296
			->timeout(5)
297
			->printed(FALSE);
298
299
		foreach($chunk as $file)
300
		{
301
			$task = $task->process("php -l {$file}");
302
		}
303
304
		$task->run();
305
	}
306
307
	/**
308
	 * Generate copy paste detector report
309
	 */
310
	protected function phpcpdReport()
311
	{
312
		$cmd_parts = [
313
			'vendor/bin/phpcpd',
314
			'--log-pmd build/logs/pmd-cpd.xml',
315
			'src'
316
		];
317
		$this->_run($cmd_parts);
318
	}
319
320
	/**
321
	 * Shortcut for joining an array of command arguments
322
	 * and then running it
323
	 *
324
	 * @param array $cmd_parts - command arguments
325
	 * @param string $join_on - what to join the command arguments with
326
	 */
327
	protected function _run(array $cmd_parts, $join_on = ' ')
328
	{
329
		$this->taskExec(implode($join_on, $cmd_parts))->run();
330
	}
331
}