Test Failed
Push — master ( e8758d...435d87 )
by Mihail
01:58
created

Application::deploidStructureInit()   C

Complexity

Conditions 14
Paths 22

Size

Total Lines 69
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 21.7649

Importance

Changes 0
Metric Value
cc 14
eloc 52
nc 22
nop 1
dl 0
loc 69
ccs 29
cts 44
cp 0.6591
crap 21.7649
rs 6.2666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Deploid;
4
5
use Symfony\Component\Console\Application as ConsoleApplication;
6
use Psr\Log\LoggerAwareInterface;
7
use Psr\Log\LoggerInterface;
8
use Symfony\Component\Process\Process;
9
10
class Application extends ConsoleApplication implements LoggerAwareInterface {
11
12
	/** @var string */
13
	private $releaseNameFormat = 'Y-m-d_H-i-s';
14
15
	/** @var string */
16
	private $chmod = '0775';
17
18
	/** @var array */
19
	private $structure = [
20
		'dirs' => [
21
			'releases',
22
			'releases/first',
23
			'shared',
24
		],
25
		'files' => [
26
			'deploid.log',
27
		],
28
		'links' => [
29
			'current:releases/first',
30
		],
31
	];
32
33
	/** @var LoggerInterface */
34
	private $logger;
35
36
	/* mutators */
37
38
	public function getReleaseNameFormat() {
39
		return $this->releaseNameFormat;
40
	}
41
42
	public function setReleaseNameFormat($releaseNameFormat) {
43
		$this->releaseNameFormat = $releaseNameFormat;
44
	}
45
46
	public function getChmod() {
47
		return $this->chmod;
48
	}
49
50
	public function setChmod($chmod) {
51
		$this->chmod = $chmod;
52
	}
53
54
	/**
55
	 * @return LoggerInterface
56
	 */
57
	public function getLogger() {
58
		return $this->logger;
59
	}
60
61
	/**
62
	 * @param LoggerInterface $logger
63
	 * @return void
64
	 */
65
	public function setLogger(LoggerInterface $logger) {
66
		$this->logger = $logger;
67
	}
68
69
	public function getStructure() {
70
		return $this->structure;
71
	}
72
73
	public function setStructure(array $structure) {
74
		$this->structure = $structure;
75
	}
76
77
	public function makeStructure($path, array $structure) {
78
		if (empty($path)) throw new \InvalidArgumentException('empty path');
79
		if (empty($structure)) throw new \InvalidArgumentException('empty structure');
80
81
		foreach ($structure as $section => $items) {
82
			if (empty($items)) continue;
83
			foreach ($items as $item) {
84
				if (empty($item)) continue;
85
				if ($section == 'dirs') mkdir($path . DIRECTORY_SEPARATOR . $item, $this->chmod, true);
0 ignored issues
show
Bug introduced by
$this->chmod of type string is incompatible with the type integer expected by parameter $mode of mkdir(). ( Ignorable by Annotation )

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

85
				if ($section == 'dirs') mkdir($path . DIRECTORY_SEPARATOR . $item, /** @scrutinizer ignore-type */ $this->chmod, true);
Loading history...
86
				if ($section == 'files') touch($path . DIRECTORY_SEPARATOR . $item);
87
				if ($section == 'links') symlink($path . DIRECTORY_SEPARATOR . (explode(':', $item)[1]), $path . DIRECTORY_SEPARATOR . (explode(':', $item)[0]));
88
			}
89
		}
90
91
		return true;
92
	}
93 1
94 1
	/* tools */
95
96 1
	/**
97
	 * @param string $path
98
	 * @return \Deploid\Payload
99
	 */
100
	public function deploidStructureValidate($path) {
101
		$payload = new Payload();
102
103 1
		$path = $this->absolutePath($path, getcwd());
104 1
105
		$releasesDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases';
106 1
		if (!is_dir($releasesDir)) {
107 1
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
108 1
			$payload->setMessage('directory "' . $releasesDir . '" does not exist');
109 1
			$payload->setCode(255);
110
			return $payload;
111
		}
112
113
		$sharedDir = realpath($path) . DIRECTORY_SEPARATOR . 'shared';
114
		if (!is_dir($sharedDir)) {
115 1
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
116
			$payload->setMessage('directory "' . $sharedDir . '" does not exist');
117 1
			$payload->setCode(255);
118 1
			return $payload;
119 1
		}
120 1
121 1
		$logFile = realpath($path) . DIRECTORY_SEPARATOR . 'deploid.log';
122
		if (!is_file($logFile)) {
123
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
124
			$payload->setMessage('file "' . $logFile . '" does not exist');
125
			$payload->setCode(255);
126
			return $payload;
127 1
		}
128
129 1
		$payload->setType(Payload::STRUCTURE_VALIDATE_SUCCESS);
130 1
		$payload->setMessage('structure is valid');
131 1
		$payload->setCode(0);
132 1
		return $payload;
133 1
	}
134
135
	/**
136
	 * @param string $path
137
	 * @return \Deploid\Payload
138
	 */
139 1
	public function deploidStructureInit($path) {
140
		$payload = new Payload();
141 1
142 1
		if (!strlen($path)) {
143 1
			$payload->setType(Payload::STRUCTURE_INIT_FAIL);
144 1
			$payload->setMessage('empty path');
145 1
			$payload->setCode(255);
146
			return $payload;
147
		}
148
149
		$path = $this->absolutePath($path, getcwd());
150
		$messages = [];
151 1
152
		if (!is_dir($path)) {
153 1
			if (mkdir($path, $this->chmod, true)) {
0 ignored issues
show
Bug introduced by
$this->chmod of type string is incompatible with the type integer expected by parameter $mode of mkdir(). ( Ignorable by Annotation )

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

153
			if (mkdir($path, /** @scrutinizer ignore-type */ $this->chmod, true)) {
Loading history...
154 1
				$messages[] = 'directory "' . realpath($path) . '" created';
155 1
			} else {
156 1
				$payload->setType(Payload::STRUCTURE_INIT_FAIL);
157
				$payload->setMessage('directory "' . $path . '" does not created');
158
				$payload->setCode(255);
159
				return $payload;
160
			}
161
		}
162
163 1
		foreach ($structure as $section => $items) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $structure seems to be never defined.
Loading history...
164 1
			if (empty($items)) continue;
165
			foreach ($items as $item) {
166 1
				if (empty($item)) continue;
167
				if ($section == 'dirs') {
168
					$dir = $path . DIRECTORY_SEPARATOR . $item;
169
					if (mkdir($dir, $this->chmod, true)) {
170
						$messages[] = 'directory "' . realpath($dir) . '" created';
171
					} else {
172
						$payload->setType(Payload::STRUCTURE_INIT_FAIL);
173 1
						$payload->setMessage('directory "' . $dir . '" does not created');
174
						$payload->setCode(255);
175 1
						return $payload;
176
					}
177
				}
178 1
				if ($section == 'files') {
179 1
					$file = $path . DIRECTORY_SEPARATOR . $item;
180
					if (touch($file)) {
181 1
						$messages[] = 'file "' . realpath($file) . '" created';
182 1
					} else {
183 1
						$payload->setType(Payload::STRUCTURE_INIT_FAIL);
184 1
						$payload->setMessage('file"' . $file . '" does not created');
185 1
						$payload->setCode(255);
186 1
						return $payload;
187 1
					}
188
				}
189 1
				if ($section == 'links') {
190 1
					$target = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[1]);
191 1
					$link = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[0]);
192 1
					if (symlink($target, $link)) {
193
						$messages[] = 'link "' . realpath($link) . '" created';
194
					} else {
195
						$payload->setType(Payload::STRUCTURE_INIT_FAIL);
196
						$payload->setMessage('link ' . $link . '" does not created');
197
						$payload->setCode(255);
198
						return $payload;
199
					}
200
				}
201
			}
202
		}
203
204
		$payload->setType(Payload::STRUCTURE_INIT_SUCCESS);
205
		$payload->setMessage($messages);
206
		$payload->setCode(0);
207
		return $payload;
208
	}
209
210
	/**
211
	 * @param string $path
212
	 * @return \Deploid\Payload
213
	 */
214
	public function deploidStructureClean($path) {
215
		$payload = new Payload();
216
217
		if (!strlen($path)) {
218
			$payload->setType(Payload::STRUCTURE_CLEAN_FAIL);
219
			$payload->setMessage('empty path');
220
			$payload->setCode(255);
221
			return $payload;
222
		}
223
224
		$path = $this->absolutePath($path, getcwd());
225
226
		$paths = glob(realpath($path) . DIRECTORY_SEPARATOR . '*');
227
228
		$paths = array_filter($paths, function ($path) {
229
			return !in_array(basename($path), $this->structure['dirs'] + $this->structure['links'] + $this->structure['files']);
230
		});
231
232
		foreach ($paths as $pathname) {
233
			if (is_file($pathname)) {
234
				unlink($pathname);
235
			} else if (is_link($pathname)) {
236
				unlink($pathname);
237
			} else if (is_dir($pathname)) {
238
				rmdir($pathname);
239
			}
240
		}
241
242
		$payload->setType(Payload::STRUCTURE_CLEAN_SUCCESS);
243
		$payload->setMessage(array_merge(['cleaned items:'], $paths));
244
		$payload->setCode(0);
245
		return $payload;
246
	}
247
248
	/**
249
	 * @param string $release
250
	 * @param string $path
251
	 * @return \Deploid\Payload
252
	 */
253
	public function deploidReleaseExist($release, $path) {
254
		$payload = new Payload();
255
256
		if (!strlen($release)) {
257
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
258
			$payload->setMessage('empty release name');
259
			$payload->setCode(255);
260
			return $payload;
261
		}
262
263
		if (!strlen($path)) {
264
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
265
			$payload->setMessage('empty path');
266
			$payload->setCode(255);
267
			return $payload;
268
		}
269
270
		$path = $this->absolutePath($path, getcwd());
271
272
		$releaseDir = $path . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
273
		if (!is_dir($releaseDir)) {
274
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
275
			$payload->setMessage('release "' . $release . '" does not exist');
276
			$payload->setCode(255);
277
			return $payload;
278
		}
279
280
		$payload->setType(Payload::RELEASE_EXIST_SUCCESS);
281
		$payload->setMessage('release "' . $release . '" exist');
282
		$payload->setCode(0);
283
		return $payload;
284
	}
285
286
	/**
287
	 * @param string $release
288
	 * @param string $path
289
	 * @return \Deploid\Payload
290
	 */
291
	public function deploidReleaseCreate($release, $path) {
292
		$payload = new Payload();
293
294
		if (!strlen($release)) {
295
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
296
			$payload->setMessage('empty release name');
297
			$payload->setCode(255);
298
			return $payload;
299
		}
300
301
		if (!strlen($path)) {
302
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
303
			$payload->setMessage('empty path');
304
			$payload->setCode(255);
305
			return $payload;
306
		}
307
308
		$path = $this->absolutePath($path, getcwd());
309
310
		$releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
311
312
		if (!mkdir($releaseDir, $this->chmod, true)) {
0 ignored issues
show
Bug introduced by
$this->chmod of type string is incompatible with the type integer expected by parameter $mode of mkdir(). ( Ignorable by Annotation )

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

312
		if (!mkdir($releaseDir, /** @scrutinizer ignore-type */ $this->chmod, true)) {
Loading history...
313
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
314
			$payload->setMessage('release "' . $release . '" does not created');
315
			$payload->setCode(255);
316
			return $payload;
317
		}
318
319
		$payload->setType(Payload::RELEASE_CREATE_SUCCESS);
320
		$payload->setMessage('release "' . $release . '" created');
321
		$payload->setCode(0);
322
		return $payload;
323
	}
324
325
	/**
326
	 * @param string $release
327
	 * @param string $path
328
	 * @return \Deploid\Payload
329
	 */
330
	public function deploidReleaseRemove($release, $path) {
331
		$payload = new Payload();
332
333
		if (!strlen($release)) {
334
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
335
			$payload->setMessage('empty release name');
336
			$payload->setCode(255);
337
			return $payload;
338
		}
339
340
		if (!strlen($path)) {
341
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
342
			$payload->setMessage('empty path');
343
			$payload->setCode(255);
344
			return $payload;
345
		}
346
347
		$path = $this->absolutePath($path, getcwd());
348
349
		$proccess = new Process('rm -r ' . realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release);
350
		$proccess->run();
351
352
		if (!$proccess->isSuccessful()) {
353
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
354
			$payload->setMessage($proccess->getErrorOutput());
355
			$payload->setCode($proccess->getExitCode());
356
			return $payload;
357
		}
358
359
		$payload->setType(Payload::RELEASE_REMOVE_SUCCESS);
360
		$payload->setMessage('release "' . ($release == '*' ? 'all' : $release) . '" removed');
361
		$payload->setCode(0);
362
		return $payload;
363
	}
364
365
	/**
366
	 * @param string $path
367
	 * @return \Deploid\Payload
368
	 */
369
	public function deploidReleaseList($path) {
370
		$payload = new Payload();
371
372
		if (!strlen($path)) {
373
			$payload->setType(Payload::RELEASE_LIST_FAIL);
374
			$payload->setMessage('path "' . $path . '" invalid');
375
			$payload->setCode(255);
376
			return $payload;
377
		}
378
379
		$path = $this->absolutePath($path, getcwd());
380
381
		$dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
382
383
		if (empty($dirs)) {
384
			$payload->setType(Payload::RELEASE_LIST_FAIL);
385
			$payload->setMessage('release not found');
386
			$payload->setCode(0);
387
			return $payload;
388
		}
389
390
		$dirs = array_map(function ($path) {
391
			return basename($path);
392
		}, $dirs);
393
394
		$payload->setType(Payload::RELEASE_LIST_SUCCESS);
395
		$payload->setMessage($dirs);
396
		$payload->setCode(0);
397
		return $payload;
398
	}
399
400
	/**
401
	 * @param string $path
402
	 * @return \Deploid\Payload
403
	 */
404
	public function deploidReleaseLatest($path) {
405
		$payload = new Payload();
406
407
		if (!strlen($path)) {
408
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
409
			$payload->setMessage('empty path');
410
			$payload->setCode(255);
411
			return $payload;
412
		}
413
414
		$path = $this->absolutePath($path, getcwd());
415
416
		$dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
417
418
		if (empty($dirs)) {
419
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
420
			$payload->setMessage('release not found');
421
			$payload->setCode(255);
422
			return $payload;
423
		}
424
425
		$dirs = array_map(function ($path) {
426
			return basename($path);
427
		}, $dirs);
428
429
		if (!rsort($dirs)) {
430
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
431
			$payload->setMessage('fail sorted');
432
			$payload->setCode(255);
433
			return $payload;
434
		}
435
436
		$payload->setType(Payload::RELEASE_LATEST_SUCCESS);
437
		$payload->setMessage(current($dirs));
438
		$payload->setCode(0);
439
		return $payload;
440
	}
441
442
	/**
443
	 * @param string $path
444
	 * @return \Deploid\Payload
445
	 */
446
	public function deploidReleaseCurrent($path) {
447
		$payload = new Payload();
448
449
		if (!strlen($path)) {
450
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
451
			$payload->setMessage('empty path');
452
			$payload->setCode(255);
453
			return $payload;
454
		}
455
456
		$path = $this->absolutePath($path, getcwd());
457
458
		$link = realpath($path) . DIRECTORY_SEPARATOR . 'current';
459
460
		if (!file_exists($link)) {
461
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
462
			$payload->setMessage('current release does not exist');
463
			$payload->setCode(255);
464
			return $payload;
465
		}
466
467
		if (!is_link($link)) {
468
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
469
			$payload->setMessage('link to current release does not exist');
470
			$payload->setCode(255);
471
			return $payload;
472
		}
473
474
		$linkpath = readlink($link);
475
476
		if (!$linkpath) {
477
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
478
			$payload->setMessage('fail read link to current release');
479
			$payload->setCode(255);
480
			return $payload;
481
		}
482
483
		$payload->setType(Payload::RELEASE_CURRENT_SUCCESS);
484
		$payload->setMessage(basename($linkpath));
485
		$payload->setCode(0);
486
		return $payload;
487
	}
488
489
	/**
490
	 * @param string $release
491
	 * @param string $path
492
	 * @return \Deploid\Payload
493
	 */
494
	public function deploidReleaseSetup($release, $path) {
495
		$payload = new Payload();
496
497
		if (!strlen($path)) {
498
			$payload->setType(Payload::RELEASE_SETUP_FAIL);
499
			$payload->setMessage('path "' . $path . '" invalid');
500
			$payload->setCode(255);
501
			return $payload;
502
		}
503
504
		$path = $this->absolutePath($path, getcwd());
505
506
		$releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
507
		$currentDir = realpath($path) . DIRECTORY_SEPARATOR . 'current';
508
509
		$proccess = new Process('ln -sfn ' . $releaseDir . ' ' . $currentDir);
510
		$proccess->run();
511
512
		if (!$proccess->isSuccessful()) {
513
			$payload->setType(Payload::RELEASE_SETUP_FAIL);
514
			$payload->setMessage($proccess->getErrorOutput());
515
			$payload->setCode($proccess->getExitCode());
516
			return $payload;
517
		}
518
519
		$payload->setType(Payload::RELEASE_SETUP_SUCCESS);
520
		$payload->setMessage('release "' . $release . '" setup');
521
		$payload->setCode(0);
522
		return $payload;
523
	}
524
525
	/**
526
	 * @param int $quantity
527
	 * @param string $path
528
	 * @return \Deploid\Payload
529
	 */
530
	public function deploidReleaseRotate($quantity, $path) {
531
		$payload = new Payload();
532
533
		if (!$quantity || $quantity < 1) {
534
			$payload->setType(Payload::RELEASE_ROTATE_FAIL);
535
			$payload->setMessage('empty or invalid quantity');
536
			$payload->setCode(255);
537
			return $payload;
538
		}
539
540
		if (!strlen($path)) {
541
			$payload->setType(Payload::RELEASE_ROTATE_FAIL);
542
			$payload->setMessage('empty path');
543
			$payload->setCode(255);
544
			return $payload;
545
		}
546
547
		$path = $this->absolutePath($path, getcwd());
548
549
		$releases = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
550
551
		if (count($releases) <= $quantity) {
552
			$payload->setType(Payload::RELEASE_ROTATE_SUCCESS);
553
			$payload->setMessage('not found releases to rotate');
554
			$payload->setCode(0);
555
		}
556
557
		foreach (array_reverse($releases) as $idx => $release) {
558
			if ($idx <= ($quantity - 1)) continue;
559
			$proccess = new Process('rm -r ' . $release);
560
			$proccess->run();
561
		}
562
563
		$payload->setType(Payload::RELEASE_ROTATE_SUCCESS);
564
		$payload->setMessage('releases are rotated');
565
		$payload->setCode(0);
566
		return $payload;
567
	}
568
569
	public function absolutePath($path, $cwd) {
570
		if (empty($path)) throw new \InvalidArgumentException('empty path');
571
		if (empty($cwd)) throw new \InvalidArgumentException('empty cwd');
572
573
		if ($path[0] == '/') return $path;
574
575
		return $cwd . DIRECTORY_SEPARATOR . $path;
576
	}
577
578
}