Passed
Push — master ( 5573de...df67a9 )
by Angel
02:20
created

PingParserForWindows   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 69
c 3
b 1
f 0
dl 0
loc 206
rs 10
wmc 19

11 Methods

Rating   Name   Duplication   Size   Complexity  
A parseRoundTripTime() 0 12 1
A setRoundTripTime() 0 3 1
A isUnreachable() 0 19 3
A setSequence() 0 3 1
A getSequence() 0 29 2
A parseStatistics() 0 15 1
A __construct() 0 15 2
A getHostStatus() 0 3 2
A setStatistics() 0 3 1
A setHostStatus() 0 3 1
A parse() 0 21 4
1
<?php
2
3
namespace Acamposm\Ping\Parsers;
4
5
use Acamposm\Ping\Interfaces\PingParserInterface;
6
7
final class PingParserForWindows extends PingParser implements PingParserInterface
8
{
9
    private bool $unreachable;
10
11
    /**
12
     * PingParserForWindows constructor.
13
     *
14
     * @param array $ping
15
     */
16
    public function __construct(array $ping)
17
    {
18
        parent::__construct($ping);
19
20
        $this->unreachable = $this->isUnreachable($ping);
21
22
        if ($this->unreachable) {
23
            $this->setStatistics($ping[count($ping) - 2]);
24
        } else {
25
            $this->setRoundTripTime($ping[count($ping) - 1]);
26
            $this->setSequence();
27
            $this->setStatistics($ping[count($ping) - 4]);
28
        }
29
30
        $this->setHostStatus();
31
    }
32
33
    /**
34
     * Get the host status.
35
     *
36
     * @return string
37
     */
38
    private function getHostStatus(): string
39
    {
40
        return ($this->statistics['packet_loss'] < 100) ? 'Ok' : 'Unreachable';
41
    }
42
43
    /**
44
     * Return an array with the Ping sequence and latency.
45
     *
46
     * @return array
47
     */
48
    private function getSequence(): array
49
    {
50
        $ping = $this->raw;
51
52
        $items_count = count($ping);
53
54
        // First remove items from final of the array
55
        unset($ping[$items_count - 6]);
56
        unset($ping[$items_count - 5]);
57
        unset($ping[$items_count - 4]);
58
        unset($ping[$items_count - 3]);
59
        unset($ping[$items_count - 2]);
60
        unset($ping[$items_count - 1]);
61
62
        // Then remove first items
63
        unset($ping[1]);
64
        unset($ping[0]);
65
66
        $key = 0;
67
68
        $sequence = [];
69
70
        foreach ($ping as $row) {
71
            $sequence[$key] = $row;
72
73
            $key++;
74
        }
75
76
        return $sequence;
77
    }
78
79
    /**
80
     * Check if the last element of the array has 100% value string.
81
     *
82
     * @param array $ping
83
     * @return bool
84
     */
85
    private function isUnreachable(array $ping): bool
86
    {
87
        $needles = 'perdidos|lost';
88
89
        $result = $ping[count($ping) - 1];
90
91
        $unreachable = false;
92
93
        foreach (explode('|', $needles) as $needle) {
94
95
            $search = strpos($result, '100% '.$needle);
96
97
            if ($search !== false) {
98
                $unreachable = true;
99
                break;
100
            }
101
        }
102
103
        return $unreachable;
104
    }
105
106
    /**
107
     * Return an object with Ping Round Trip Time.
108
     *
109
     * @param string $row
110
     * @return array
111
     */
112
    private function parseRoundTripTime(string $row): array
113
    {
114
        $rtt = explode(',', str_replace('ms', '', $row));
115
116
        $min = (float) explode(' = ', $rtt[0])[1] / 1000;
117
        $max = (float) explode(' = ', $rtt[1])[1] / 1000;
118
        $avg = (float) explode(' = ', $rtt[2])[1] / 1000;
119
120
        return [
121
            'avg' => $avg,
122
            'min' => $min,
123
            'max' => $max,
124
        ];
125
    }
126
127
    /**
128
     * Return an object with Ping Statistics.
129
     *
130
     * @param string $row
131
     * @return array
132
     */
133
    private function parseStatistics(string $row): array
134
    {
135
        $ping_statistics = explode(', ', explode(':', $row)[1]);
136
137
        $transmitted = (int) explode(' = ', $ping_statistics[0])[1];
138
139
        $received = (int) explode(' = ', $ping_statistics[1])[1];
140
141
        $lost = (int) explode(' = ', $ping_statistics[2])[1];
142
143
        return [
144
            'packets_transmitted' => $transmitted,
145
            'packets_received' => $received,
146
            'packets_lost' => $lost,
147
            'packet_loss' => (int) (100 - (($received * 100) / $transmitted)),
148
        ];
149
    }
150
151
    /**
152
     * Set the host status.
153
     */
154
    private function setHostStatus(): void
155
    {
156
        $this->host_status = $this->getHostStatus();
157
    }
158
159
    /**
160
     * Set the Round Trip Time statistics.
161
     *
162
     * @param string $rtt
163
     */
164
    private function setRoundTripTime(string $rtt): void
165
    {
166
        $this->round_trip_time = $this->parseRoundTripTime($rtt);
167
    }
168
169
    /**
170
     * Set the Ping sequence.
171
     */
172
    private function setSequence(): void
173
    {
174
        $this->sequence = $this->getSequence();
175
    }
176
177
    /**
178
     * Set the Statistics.
179
     *
180
     * @param string $statistics
181
     */
182
    private function setStatistics(string $statistics): void
183
    {
184
        $this->statistics = $this->parseStatistics($statistics);
185
    }
186
187
    /**
188
     * Return the Ping execution result parsed as object.
189
     *
190
     * @return object
191
     */
192
    public function parse(): object
193
    {
194
        $parsed = [
195
            'host_status' => $this->host_status,
196
            'raw' => $this->raw,
197
        ];
198
199
        if (count($this->round_trip_time) > 0) {
200
            $parsed['latency'] = $this->round_trip_time['avg'];
201
            $parsed['rtt'] = (object) $this->round_trip_time;
202
        }
203
204
        if (count($this->sequence) > 0) {
205
            $parsed['sequence'] = (object) $this->sequence;
206
        }
207
208
        if (count($this->statistics) > 0) {
209
            $parsed['statistics'] = (object) $this->statistics;
210
        }
211
212
        return (object) $parsed;
213
    }
214
}
215