Completed
Push — develop ( 8c914c...95d5bd )
by Stuart
01:57
created

ParseIpAddrOutput::from()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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/NetInterface/Parsers
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\IpRoute\Parsers;
45
46
use GanbaroDigital\OperatingSystem\IpRoute\Classifiers\ClassifyIpAddrLine;
47
use GanbaroDigital\OperatingSystem\Exceptions\E4xx_CannotParseIpAddrOutput;
48
use GanbaroDigital\OperatingSystem\Exceptions\E4xx_OperatingSystemException;
49
use GanbaroDigital\OperatingSystem\Exceptions\E4xx_UnsupportedType;
50
use GanbaroDigital\OperatingSystem\Exceptions\E5xx_CannotParseIpAddrOutput;
51
use GanbaroDigital\OperatingSystem\Exceptions\E5xx_OperatingSystemException;
52
use GanbaroDigital\Reflection\Maps\MapTypeToMethod;
53
use GanbaroDigital\Reflection\ValueBuilders\SimpleType;
54
55
/**
56
 * parser for the output of the 'ip addr show' command
57
 */
58
class ParseIpAddrOutput
59
{
60
    /**
61
     * parse the output of the 'ip addr show' command
62
     *
63
     * @param  mixed $output
64
     *         the output to parse
65
     * @return array<NetInterface>
66
     *         a list of the network interfaces extracted from the given
67
     *         command output
68
     */
69
    public function __invoke($output)
70
    {
71
        return self::from($output);
72
    }
73
74
    /**
75
     * parse the output of the 'ip addr show' command
76
     *
77
     * @param  mixed $output
78
     *         the output to parse
79
     * @return array<NetInterface>
80
     *         a list of the network interfaces extracted from the given
81
     *         command output
82
     */
83
    public static function from($output)
84
    {
85
        $method = MapTypeToMethod::using($output, self::$dispatchMap);
86
        return self::$method($output);
87
    }
88
89
    /**
90
     * parse the output of the 'ip addr show' command
91
     *
92
     * @param  Traversable $output
93
     *         the output to parse
94
     * @return array<NetInterface>
95
     *         a list of the network interfaces extracted from the given
96
     *         command output
97
     */
98
     private static function fromTraversable($output)
99
     {
100
         // our return value
101
         $retval = [];
102
103
         try {
104
             // group the output into smaller chunks for parsing
105
             $groups = self::groupOutputIntoInterfaces($output);
106
107
             foreach($groups as $interfaceLines) {
108
                 $interface = ParseNetInterface::from($interfaceLines);
109
                 $retval[] = $interface;
110
             }
111
         }
112
         catch (E4xx_OperatingSystemException $e) {
113
             throw new E4xx_CannotParseIpAddrOutput($output, $e);
114
         }
115
         catch (E5xx_OperatingSystemException $e) {
116
             throw new E5xx_CannotParseIpAddrOutput($output, $e);
117
         }
118
119
         // all done
120
         return $retval;
121
     }
122
123
     /**
124
      * convert the output of the 'ip addr show' command into smaller groups
125
      * that are easier to parse
126
      *
127
      * @param  array|Traversable $lines
128
      *         the output to group
129
      * @return array
130
      *         the grouped output
131
      */
132
     private static function groupOutputIntoInterfaces($lines)
133
     {
134
         $interfaces=[];
135
136
         // what do we have?
137
         foreach ($lines as $line) {
138
             // skip empty lines
139
             if (trim($line) === '') {
140
                 continue;
141
             }
142
143
             // what do we have?
144
             $lineType = ClassifyIpAddrLine::from($line);
145
             switch ($lineType) {
146
                 case ClassifyIpAddrLine::LINK_START:
147
                     $interfaces[] = [ $line ];
148
                     break;
149
                 default:
150
                     $interfaces[count($interfaces) - 1][] = $line;
151
             }
152
         }
153
154
         // all done
155
         return $interfaces;
156
     }
157
158
    /**
159
     * parse the output of the 'ip addr show' command
160
     *
161
     * @param  string $output
162
     *         the output to parse
163
     * @return array<NetInterface>
164
     *         a list of the network interfaces extracted from the given
165
     *         command output
166
     */
167
    private static function fromString($output)
168
    {
169
        $lines = explode("\n", (string)$output);
170
        return self::fromTraversable($lines);
0 ignored issues
show
Documentation introduced by
$lines is of type array, but the function expects a object<GanbaroDigital\Op...te\Parsers\Traversable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
171
    }
172
173
    /**
174
     * called when we've been given a data type that we do not support
175
     *
176
     * @param  mixed $output
177
     *         the unsupported data
178
     * @return void
179
     * @throws E4xx_UnsupportedType
180
     */
181
    private static function nothingMatchesTheInputType($output)
182
    {
183
        throw new E4xx_UnsupportedType(SimpleType::from($output));
184
    }
185
186
    /**
187
     * a map of which method to use for which type of data we're asked to
188
     * process
189
     *
190
     * @var array
191
     */
192
    private static $dispatchMap = [
193
        'Traversable' => 'fromTraversable',
194
        'String' => 'fromString',
195
    ];
196
}
197