Completed
Push — develop ( 68ffd2...867c28 )
by Stuart
02:03
created

BuildTypeFromLsbRelease::usingPath()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 16
rs 9.2
cc 4
eloc 8
nc 3
nop 1
1
<?php
2
3
/**
4
 * Copyright (c) 2015-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 2015-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-text-tools
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 $path
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($path = "/usr/bin/lsb_release")
70
    {
71
        return self::usingPath($path);
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 $path
0 ignored issues
show
Bug introduced by
There is no parameter named $path. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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 do :)
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

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