Executable::runCommand()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 4 Features 1
Metric Value
cc 3
eloc 7
c 8
b 4
f 1
nc 2
nop 1
dl 0
loc 15
rs 10
1
<?php
2
3
/*
4
 * This file is part of the PHINT package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\Phint\Util;
13
14
use Ahc\Cli\Helper\Shell;
15
use Ahc\Cli\IO\Interactor;
16
17
abstract class Executable
18
{
19
    /** @var bool Last command successful? */
20
    protected $isSuccessful = true;
21
22
    /** @var Interactor */
23
    protected $io;
24
25
    /** @var string The binary executable */
26
    protected $binary;
27
28
    /** @var string */
29
    protected $workDir;
30
31
    /** @var string Full path of log file */
32
    protected $logFile;
33
34
    public function __construct($binary = null, string $logFile = '')
35
    {
36
        $this->workDir = \getcwd();
37
        $this->logFile = $logFile;
38
        $this->binary  = $this->findBinary($binary ?? $this->binary);
39
    }
40
41
    public function withWorkDir($workDir = null)
42
    {
43
        if (!\is_dir($workDir)) {
44
            throw new \InvalidArgumentException('Not a valid working dir: ' . $workDir);
45
        }
46
47
        $this->workDir = $workDir;
48
49
        return $this;
50
    }
51
52
    public function successful(): bool
53
    {
54
        return $this->isSuccessful;
55
    }
56
57
    protected function findBinary(string $binary): string
58
    {
59
        if (\is_executable($binary)) {
60
            return '"' . $binary . '"';
61
        }
62
63
        $isWin = \DIRECTORY_SEPARATOR === '\\';
64
65
        return $isWin ? $this->findWindowsBinary($binary) : '"' . $binary . '"';
66
    }
67
68
    protected function findWindowsBinary(string $binary): string
69
    {
70
        $paths = \explode(\PATH_SEPARATOR, \getenv('PATH') ?: \getenv('Path'));
71
72
        foreach ($paths as $path) {
73
            foreach (['.exe', '.bat', '.cmd'] as $ext) {
74
                if (\is_file($file = $path . '\\' . $binary . $ext)) {
75
                    return '"' . $file . '"';
76
                }
77
            }
78
        }
79
80
        return '"' . $binary . '"';
81
    }
82
83
    /**
84
     * Runs the command using underlying binary.
85
     *
86
     * @param string $command
87
     *
88
     * @return string|null The output of command.
89
     */
90
    protected function runCommand($command)
91
    {
92
        $proc = new Shell($this->binary . ' ' . $command);
93
94
        $proc->setOptions($this->workDir)->execute();
95
96
        if ($this->logFile && \is_writable(\dirname($this->logFile))) {
97
            $data = $proc->getOutput() . \PHP_EOL . $proc->getErrorOutput();
98
99
            (new Path)->writeFile($this->logFile, $data, \FILE_APPEND);
100
        }
101
102
        $this->isSuccessful = 0 === $proc->getExitCode();
103
104
        return $proc->getOutput();
105
    }
106
}
107