BuildTypeFromLsbRelease::extractField()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
/**
4
 * Copyright (c) 2016-present Ganbaro Digital Ltd
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *
14
 *   * Redistributions in binary form must reproduce the above copyright
15
 *     notice, this list of conditions and the following disclaimer in
16
 *     the documentation and/or other materials provided with the
17
 *     distribution.
18
 *
19
 *   * Neither the names of the copyright holders nor the names of his
20
 *     contributors may be used to endorse or promote products derived
21
 *     from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category  Libraries
37
 * @package   OperatingSystem/OsType/ValueBuilders
38
 * @author    Stuart Herbert <[email protected]>
39
 * @copyright 2016-present Ganbaro Digital Ltd www.ganbarodigital.com
40
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
41
 * @link      http://code.ganbarodigital.com/php-operating-system
42
 */
43
44
namespace GanbaroDigital\OperatingSystem\OsType\ValueBuilders;
45
46
use GanbaroDigital\Filesystem\Checks\IsExecutableFile;
47
use GanbaroDigital\OperatingSystem\OsType\Values\CentOS;
48
use GanbaroDigital\OperatingSystem\OsType\Values\Debian;
49
use GanbaroDigital\OperatingSystem\OsType\Values\LinuxMint;
50
use GanbaroDigital\OperatingSystem\OsType\Values\OsType;
51
use GanbaroDigital\OperatingSystem\OsType\Values\Ubuntu;
52
use GanbaroDigital\ProcessRunner\ProcessRunners\PopenProcessRunner;
53
use GanbaroDigital\TextTools\Editors\TrimWhitespace;
54
use GanbaroDigital\TextTools\Filters\FilterForMatchingString;
55
use GanbaroDigital\TextTools\Filters\FilterColumns;
56
57
class BuildTypeFromLsbRelease implements BuildTypeFromFile
58
{
59
    /**
60
     * use the output of /usr/bin/lsb_release (if present) to determine which
61
     * Linux distro we are using
62
     *
63
     * @param  string $pathToBinary
64
     *         path to the binary to run
65
     * @return null|OsType
0 ignored issues
show
Documentation introduced by
Should the return type not be null|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
66
     *         OsType if we know which Linux distro we are using
67
     *         null otherwise
68
     */
69
    public function __invoke($pathToBinary = "/usr/bin/lsb_release")
70
    {
71
        return self::usingPath($pathToBinary);
72
    }
73
74
    /**
75
     * use the output of /usr/bin/lsb_release (if present) to determine which
76
     * Linux distro we are using
77
     *
78
     * @return null|OsType
0 ignored issues
show
Documentation introduced by
Should the return type not be null|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
79
     *         OsType if we know which Linux distro we are using
80
     *         null otherwise
81
     */
82
    public static function usingDefaultPath()
83
    {
84
        return self::usingPath("/usr/bin/lsb_release");
85
    }
86
87
    /**
88
     * use the output of /usr/bin/lsb_release (if present) to determine which
89
     * Linux distro we are using
90
     *
91
     * @param  string $pathToBinary
92
     *         path to the binary to run
93
     * @return null|OsType
0 ignored issues
show
Documentation introduced by
Should the return type not be null|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
94
     *         OsType if we know which Linux distro we are using
95
     *         null otherwise
96
     */
97
    public static function usingPath($pathToBinary)
98
    {
99
        list($distroName, $distroVersion) = self::getDistroDetails($pathToBinary);
100
        if ($distroName === null || $distroVersion === null) {
101
            return null;
102
        }
103
104
        // do we have a match?
105
        if (!isset(self::$osTypes[$distroName])) {
106
            return null;
107
        }
108
109
        // yes, we have a match
110
        /** @var OsType */
111
        $osType = new self::$osTypes[$distroName]($distroVersion);
112
        return $osType;
113
    }
114
115
    /**
116
     * get the Linux distro name & version from /usr/bin/lsb_release
117
     *
118
     * @param  string $pathToBinary
119
     *         the binary to call to get the LSB details
120
     * @return array
121
     *         [0] is the Linux distro name
122
     *         [1] is the Linux distro version
123
     */
124
    private static function getDistroDetails($pathToBinary)
125
    {
126
        $output = self::getOutputFromBinary($pathToBinary);
127
        if ($output === null) {
128
            return [null, null];
129
        }
130
131
        return self::extractDistroDetails($output);
132
    }
133
134
    /**
135
     * call /usr/bin/lsb_release and return the output
136
     *
137
     * @param  string $pathToBinary
138
     *         path to the binary to call
139
     * @return string
140
     *         output from the binary
141
     */
142
    private static function getOutputFromBinary($pathToBinary)
143
    {
144
        // make sure we have an executable binary
145
        if (!IsExecutableFile::check($pathToBinary)) {
146
            return null;
147
        }
148
149
        // get the info
150
        $result = PopenProcessRunner::run([$pathToBinary, '-a']);
151
        if ($result->getReturnCode() !== 0) {
152
            return null;
153
        }
154
155
        // at this point, return the output
156
        return $result->getOutput();
157
    }
158
159
    /**
160
     * extract the info we need from the output of /usr/bin/lsb_release
161
     *
162
     * @param  string $output
163
     *         the output from running the command
164
     * @return array
165
     *         [0] is the Linux distro name
166
     *         [1] is the Linux distro version
167
     */
168
    private static function extractDistroDetails($output)
169
    {
170
        // what do we have?
171
        $lines = explode(PHP_EOL, $output);
172
        $distroName = self::extractField($lines, 'Distributor ID:');
173
        $distroVersion = self::extractField($lines, 'Release:');
174
175
        if ($distroVersion !== null) {
176
            $distroVersion = FilterColumns::from($distroVersion, '0-1', '.');
177
        }
178
179
        return [$distroName, $distroVersion];
180
    }
181
182
    /**
183
     * extract a named field from the output of /usr/bin/lsb_release
184
     *
185
     * @param  array $lines
186
     *         the output of /usr/bin/lsb_release
187
     * @param  string $fieldName
188
     *         the field that we are looking for
189
     * @return string|null
190
     *         the value of the field (if found)
191
     */
192
    private static function extractField($lines, $fieldName)
193
    {
194
        $matches = FilterForMatchingString::against($lines, $fieldName);
195
        if (empty($matches)) {
196
            return null;
197
        }
198
        return TrimWhitespace::from(FilterColumns::from($matches[0], '1', ':'));
199
    }
200
201
    /**
202
     * a map of distro names onto OsType classes
203
     * @var array
204
     */
205
    private static $osTypes = [
206
        'CentOS' => CentOS::class,
207
        'Debian' => Debian::class,
208
        'LinuxMint' => LinuxMint::class,
209
        'Ubuntu' => Ubuntu::class,
210
    ];
211
}
212