PingParserForWindows::parseRoundTripTime()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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