Runner   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 35
c 6
b 0
f 0
dl 0
loc 80
rs 10
wmc 13

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 7 2
A setRemote() 0 7 1
A __construct() 0 7 2
A getFileContents() 0 3 1
A outputToArray() 0 3 1
A fileExists() 0 3 1
A commandExists() 0 8 2
A run() 0 17 3
1
<?php
2
3
namespace Startwind\Inventorio\Exec;
4
5
use Spatie\Ssh\Ssh;
6
use Symfony\Component\Process\Process;
7
8
class Runner
9
{
10
    private bool $timeout = false;
11
12
    private static ?Runner $instance = null;
13
14
    private bool $remoteOn = false;
15
    private string $remoteDsn;
16
    private Ssh $sshConnection;
17
18
    public function setRemote($dsn)
19
    {
20
        $this->remoteOn = true;
21
        $this->remoteDsn = $dsn;
22
23
        $sshCredentials = explode('@', $this->remoteDsn);
24
        $this->sshConnection = Ssh::create($sshCredentials[0], $sshCredentials[1]);
25
    }
26
27
    static public function getInstance(): Runner
28
    {
29
        if (self::$instance === null) {
30
            self::$instance = new self();
31
        }
32
33
        return self::$instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::instance could return the type null which is incompatible with the type-hinted return Startwind\Inventorio\Exec\Runner. Consider adding an additional type-check to rule them out.
Loading history...
34
    }
35
36
    public function __construct()
37
    {
38
        $process = $this->run('timeout --version');
39
        if ($process->isSuccessful()) {
40
            $this->timeout = true;
41
        } else {
42
            $this->timeout = false;
43
        }
44
    }
45
46
    public function run($command, $killAfterSeconds = 5): Process
47
    {
48
        if ($this->timeout) {
49
            $shellCommandLine = "timeout --kill-after=" . $killAfterSeconds . "s 1m " . $command;
50
        } else {
51
            $shellCommandLine = $command;
52
        }
53
54
        if ($this->remoteOn) {
55
            // echo "DEBUG: " . $command . "\n";
56
            $process = $this->sshConnection->execute($shellCommandLine);
57
        } else {
58
            $process = Process::fromShellCommandline($shellCommandLine);
59
            $process->run();
60
        }
61
62
        return $process;
63
    }
64
65
    public function commandExists(string $command): bool
66
    {
67
        $which = $this->run('which ' . $command)->getOutput();
68
        if (empty($which)) {
69
            return false;
70
        }
71
72
        return true;
73
    }
74
75
    public static function outputToArray(string $output): array
76
    {
77
        return explode("\n", trim($output));
78
    }
79
80
    public function getFileContents(string $path, bool $asArray = false): string|false|array
81
    {
82
        return File::getInstance()->getContents($path, $asArray);
83
    }
84
85
    public function fileExists(string $path): bool
86
    {
87
        return File::getInstance()->fileExists($path);
88
    }
89
}