Completed
Push — master ( 51d90f...0beef0 )
by Alexander
03:54
created

SystemdState   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 1
dl 0
loc 142
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A addCheckUnit() 0 6 1
A addAllUnits() 0 6 1
A getSystemdInfo() 0 6 1
B getReport() 0 40 7
A checkState() 0 19 4
A handleServiceResponse() 0 26 4
1
<?php
2
3
namespace CyberLine\SystemdState;
4
5
class SystemdState
6
{
7
    private static $command = '/bin/systemctl show %s --no-page';
8
9
    private $services = [];
10
11
    private $reports = [];
12
13
    /**
14
     * SystemdState constructor.
15
     * @param array $services
16
     */
17
    public function __construct(array $services = [])
18
    {
19
        foreach ($services as $service) {
20
            $this->addCheckUnit($service);
21
        }
22
    }
23
24
    /**
25
     * @param string $name
26
     * @return SystemdState
27
     */
28
    public function addCheckUnit(string $name): self
29
    {
30
        $this->services[] = escapeshellcmd($name);
31
32
        return $this;
33
    }
34
35
    public function addAllUnits(): self
36
    {
37
        $this->addCheckUnit('*');
38
39
        return $this;
40
    }
41
42
    /**
43
     * @return array
44
     */
45
    public function getSystemdInfo()
46
    {
47
        $this->addCheckUnit('');
48
49
        return $this->getReport('systemd');
50
    }
51
52
    /**
53
     * @param null $unitName
54
     * @return array
55
     */
56
    public function getReport($unitName = null): array
57
    {
58
        if (!$this->reports) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->reports 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...
59
            $this->checkState();
60
        }
61
62
        if (!$unitName) {
63
            return $this->reports;
64
        }
65
66
        if (array_key_exists($unitName, $this->reports)) {
67
            return [$this->reports[$unitName]];
68
        }
69
70
        $retval = [];
71
        foreach ([
72
             'service',
73
             'target',
74
             'timer',
75
             'slice',
76
             'socket',
77
             'path',
78
             'device',
79
             'mount',
80
             'automount',
81
             'scope',
82
             'swap',
83
         ] as $suffix) {
84
            $tempName = $unitName . '.' . $suffix;
85
            if (array_key_exists($tempName, $this->reports)) {
86
                $retval[$tempName] = $this->reports[$tempName];
87
            }
88
        }
89
90
        if (count($retval)) {
91
            return $retval;
92
        }
93
94
        throw new \RangeException(sprintf('No report found for `%s`. Maybe misspelled?', $unitName));
95
    }
96
97
    private function checkState()
98
    {
99
        if (!count($this->services)) {
100
            throw new \InvalidArgumentException('You have to add at least one unit to check!');
101
        }
102
103
        $command = sprintf(self::$command, implode(' ', $this->services));
104
        $exec = shell_exec($command);
105
106
        if ($exec === null) {
107
            throw new \RuntimeException(sprintf('There was an error executing the command: `%s`', $command));
108
        }
109
110
        $services = explode(PHP_EOL . PHP_EOL, $exec);
111
112
        foreach ($services as $service) {
113
            $this->handleServiceResponse($service);
114
        }
115
    }
116
117
    /**
118
     * @param string $service
119
     */
120
    private function handleServiceResponse(string $service)
121
    {
122
        $split = explode(PHP_EOL, $service);
123
124
        preg_match('/Id=(?<name>.*)/m', $service, $matches);
125
        if (!$matches) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matches of type string[] 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...
126
            $type = 'Systemd';
127
        } else {
128
            $explode = explode('.', $matches['name']);
129
            $type = ucfirst($explode[count($explode) - 1]);
130
        }
131
132
        $class = 'CyberLine\SystemdState\Types\\' . $type;
133
        $class = new $class();
134
135
        foreach ($split as $line) {
136
            $explode = explode('=', $line);
137
            if (empty($explode[0])) {
138
                continue;
139
            }
140
141
            $class->{'set' . $explode[0]}(Parser::parseValueByContent($explode));
142
        }
143
144
        $this->reports[$class->getId()] = $class;
145
    }
146
}
147