Completed
Branch Message (d15af3)
by Sam
05:12
created

Message   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 465
Duplicated Lines 0 %

Test Coverage

Coverage 44.08%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 111
dl 0
loc 465
ccs 67
cts 152
cp 0.4408
rs 8.4
c 1
b 0
f 0
wmc 50

38 Methods

Rating   Name   Duplication   Size   Complexity  
A setRecursionDesired() 0 3 1
A setResponse() 0 3 1
A isRecursionDesired() 0 3 1
A addAuthoritative() 0 3 1
A getAdditionals() 0 3 1
A toWire() 0 39 5
A setId() 0 3 1
A getOpcode() 0 3 1
A setAuthoritatives() 0 5 2
A getRcode() 0 3 1
A isResponse() 0 3 1
A isAuthoritative() 0 3 1
A countQuestions() 0 3 1
A setAuthoritative() 0 3 1
A countAuthoritatives() 0 3 1
A setRcode() 0 3 1
A setQuery() 0 3 1
A addAdditional() 0 3 1
A isQuery() 0 3 1
A addQuestion() 0 3 1
A isTruncated() 0 3 1
A getZ() 0 3 1
A setTruncated() 0 3 1
A setOpcode() 0 3 1
A addAnswer() 0 3 1
A getQuestions() 0 3 1
A setAnswers() 0 5 2
A getAnswers() 0 3 1
A fromWire() 0 39 5
A setAdditionals() 0 5 2
A setZ() 0 3 1
A setQuestions() 0 5 2
A getId() 0 3 1
A countAdditionals() 0 3 1
A getAuthoritatives() 0 3 1
A isRecursionAvailable() 0 3 1
A setRecursionAvailable() 0 3 1
A countAnswers() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Message often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Message, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Badcow DNS Library.
7
 *
8
 * (c) Samuel Williams <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Badcow\DNS;
15
16
use Badcow\DNS\Rdata\UnsupportedTypeException;
17
18
class Message
19
{
20
    /**
21
     * ID.
22
     *
23
     * @var int
24
     */
25
    private $id;
26
27
    /**
28
     * QR.
29
     *
30
     * @var bool
31
     */
32
    private $isResponse;
33
34
    /**
35
     * OPCODE.
36
     *
37
     * @var int
38
     */
39
    private $opcode;
40
41
    /**
42
     * AA.
43
     *
44
     * @var bool
45
     */
46
    private $isAuthoritative;
47
48
    /**
49
     * TC.
50
     *
51
     * @var bool
52
     */
53
    private $isTruncated;
54
55
    /**
56
     * RD.
57
     *
58
     * @var bool
59
     */
60
    private $isRecursionDesired;
61
62
    /**
63
     * RA.
64
     *
65
     * @var bool
66
     */
67
    private $isRecursionAvailable;
68
69
    /**
70
     * A.
71
     *
72
     * @var int
73
     */
74
    private $z = 0;
75
76
    /**
77
     * RCODE.
78
     *
79
     * @var int
80
     */
81
    private $rcode;
82
83
    /**
84
     * @var Question[]
85
     */
86
    private $questions = [];
87
88
    /**
89
     * @var ResourceRecord[]
90
     */
91
    private $answers = [];
92
93
    /**
94
     * @var ResourceRecord[]
95
     */
96
    private $authoritatives = [];
97
98
    /**
99
     * @var ResourceRecord[]
100
     */
101
    private $additionals = [];
102
103
    /**
104
     * @return int
105
     */
106
    public function getId(): int
107
    {
108
        return $this->id;
109
    }
110
111
    /**
112
     * @param int $id
113
     */
114 4
    public function setId(int $id): void
115
    {
116 4
        $this->id = $id;
117 4
    }
118
119
    /**
120
     * @return bool
121
     */
122
    public function isResponse(): bool
123
    {
124
        return $this->isResponse;
125
    }
126
127
    /**
128
     * @param bool $isResponse
129
     */
130 4
    public function setResponse(bool $isResponse): void
131
    {
132 4
        $this->isResponse = $isResponse;
133 4
    }
134
135
    /**
136
     * @return bool
137
     */
138
    public function isQuery(): bool
139
    {
140
        return !$this->isResponse;
141
    }
142
143
    /**
144
     * @param bool $query
145
     */
146
    public function setQuery(bool $query): void
147
    {
148
        $this->setResponse(!$query);
149
    }
150
151
    /**
152
     * @return int
153
     */
154
    public function getOpcode(): int
155
    {
156
        return $this->opcode;
157
    }
158
159
    /**
160
     * @param int $opcode
161
     */
162 4
    public function setOpcode(int $opcode): void
163
    {
164 4
        $this->opcode = $opcode;
165 4
    }
166
167
    /**
168
     * @return bool
169
     */
170
    public function isAuthoritative(): bool
171
    {
172
        return $this->isAuthoritative;
173
    }
174
175
    /**
176
     * @param bool $isAuthoritative
177
     */
178 4
    public function setAuthoritative(bool $isAuthoritative): void
179
    {
180 4
        $this->isAuthoritative = $isAuthoritative;
181 4
    }
182
183
    /**
184
     * @return bool
185
     */
186
    public function isTruncated(): bool
187
    {
188
        return $this->isTruncated;
189
    }
190
191
    /**
192
     * @param bool $isTruncated
193
     */
194 4
    public function setTruncated(bool $isTruncated): void
195
    {
196 4
        $this->isTruncated = $isTruncated;
197 4
    }
198
199
    /**
200
     * @return bool
201
     */
202
    public function isRecursionDesired(): bool
203
    {
204
        return $this->isRecursionDesired;
205
    }
206
207
    /**
208
     * @param bool $isRecursionDesired
209
     */
210 4
    public function setRecursionDesired(bool $isRecursionDesired): void
211
    {
212 4
        $this->isRecursionDesired = $isRecursionDesired;
213 4
    }
214
215
    /**
216
     * @return bool
217
     */
218
    public function isRecursionAvailable(): bool
219
    {
220
        return $this->isRecursionAvailable;
221
    }
222
223
    /**
224
     * @param bool $isRecursionAvailable
225
     */
226 4
    public function setRecursionAvailable(bool $isRecursionAvailable): void
227
    {
228 4
        $this->isRecursionAvailable = $isRecursionAvailable;
229 4
    }
230
231
    /**
232
     * @return int
233
     */
234
    public function getZ(): int
235
    {
236
        return $this->z;
237
    }
238
239
    /**
240
     * @param int $z
241
     */
242 4
    public function setZ(int $z): void
243
    {
244 4
        $this->z = $z;
245 4
    }
246
247
    /**
248
     * @return int
249
     */
250
    public function getRcode(): int
251
    {
252
        return $this->rcode;
253
    }
254
255
    /**
256
     * @param int $rcode
257
     */
258 4
    public function setRcode(int $rcode): void
259
    {
260 4
        $this->rcode = $rcode;
261 4
    }
262
263
    /**
264
     * @return Question[]
265
     */
266
    public function getQuestions(): array
267
    {
268
        return $this->questions;
269
    }
270
271
    /**
272
     * @param Question $question
273
     */
274 4
    public function addQuestion(Question $question): void
275
    {
276 4
        $this->questions[] = $question;
277 4
    }
278
279
    /**
280
     * @param Question[] $questions
281
     */
282
    public function setQuestions(array $questions): void
283
    {
284
        $this->questions = [];
285
        foreach ($questions as $question) {
286
            $this->addQuestion($question);
287
        }
288
    }
289
290
    /**
291
     * @return ResourceRecord[]
292
     */
293
    public function getAnswers(): array
294
    {
295
        return $this->answers;
296
    }
297
298
    /**
299
     * @param ResourceRecord $answer
300
     */
301 4
    public function addAnswer(ResourceRecord $answer): void
302
    {
303 4
        $this->answers[] = $answer;
304 4
    }
305
306
    /**
307
     * @param ResourceRecord[] $answers
308
     */
309
    public function setAnswers(array $answers): void
310
    {
311
        $this->answers = [];
312
        foreach ($answers as $answer) {
313
            $this->addAnswer($answer);
314
        }
315
    }
316
317
    /**
318
     * @return ResourceRecord[]
319
     */
320
    public function getAuthoritatives(): array
321
    {
322
        return $this->authoritatives;
323
    }
324
325
    /**
326
     * @param ResourceRecord $authoritative
327
     */
328 3
    public function addAuthoritative(ResourceRecord $authoritative): void
329
    {
330 3
        $this->authoritatives[] = $authoritative;
331 3
    }
332
333
    /**
334
     * @param ResourceRecord[] $authoritatives
335
     */
336
    public function setAuthoritatives(array $authoritatives): void
337
    {
338
        $this->authoritatives = [];
339
        foreach ($authoritatives as $authoritative) {
340
            $this->addAuthoritative($authoritative);
341
        }
342
    }
343
344
    /**
345
     * @return ResourceRecord[]
346
     */
347
    public function getAdditionals(): array
348
    {
349
        return $this->additionals;
350
    }
351
352
    /**
353
     * @param ResourceRecord $additional
354
     */
355 4
    public function addAdditional(ResourceRecord $additional): void
356
    {
357 4
        $this->additionals[] = $additional;
358 4
    }
359
360
    /**
361
     * @param ResourceRecord[] $additionals
362
     */
363
    public function setAdditionals(array $additionals): void
364
    {
365
        $this->additionals = [];
366
        foreach ($additionals as $additional) {
367
            $this->addAdditional($additional);
368
        }
369
    }
370
371
    public function countQuestions(): int
372
    {
373
        return count($this->questions);
374
    }
375
376
    public function countAnswers(): int
377
    {
378
        return count($this->answers);
379
    }
380
381
    public function countAuthoritatives(): int
382
    {
383
        return count($this->authoritatives);
384
    }
385
386
    public function countAdditionals(): int
387
    {
388
        return count($this->additionals);
389
    }
390
391
    /**
392
     * @return string
393
     *
394
     * @throws UnsetValueException
395
     */
396
    public function toWire(): string
397
    {
398
        $flags = 0x0 |
399
            ($this->isResponse & 0x1) << 15 |
400
            ($this->opcode & 0xf) << 11 |
401
            ($this->isAuthoritative & 0x1) << 10 |
402
            ($this->isTruncated & 0x1) << 9 |
403
            ($this->isRecursionDesired & 0x1) << 8 |
404
            ($this->isRecursionAvailable & 0x1) << 7 |
405
            ($this->z & 0x7) << 4 |
406
            ($this->rcode & 0xf);
407
408
        $encoded = pack(
409
            'nnnnnn',
410
            $this->id,
411
            $flags,
412
            $this->countQuestions(),
413
            $this->countAnswers(),
414
            $this->countAuthoritatives(),
415
            $this->countAdditionals()
416
        );
417
418
        foreach ($this->questions as $question) {
419
            $encoded .= $question->toWire();
420
        }
421
422
        foreach ($this->answers as $answer) {
423
            $encoded .= $answer->toWire();
424
        }
425
426
        foreach ($this->authoritatives as $authoritative) {
427
            $encoded .= $authoritative->toWire();
428
        }
429
430
        foreach ($this->additionals as $additional) {
431
            $encoded .= $additional->toWire();
432
        }
433
434
        return $encoded;
435
    }
436
437
    /**
438
     * @param string $encoded
439
     *
440
     * @return Message
441
     *
442
     * @throws UnsupportedTypeException
443
     */
444 4
    public static function fromWire(string $encoded): Message
445
    {
446 4
        $message = new self();
447 4
        $offset = 0;
448 4
        $header = unpack('nid/nflags/nqdcount/nancount/nnscount/narcount', $encoded, $offset);
449 4
        $offset += 12;
450 4
        $flags = $header['flags'];
451 4
        $qdCount = $header['qdcount'];
452 4
        $anCount = $header['ancount'];
453 4
        $nsCount = $header['nscount'];
454 4
        $arCount = $header['arcount'];
455
456 4
        $message->setId($header['id']);
457 4
        $message->setResponse((bool) ($flags >> 15 & 0x1));
458 4
        $message->setOpcode($flags >> 11 & 0xf);
459 4
        $message->setAuthoritative((bool) ($flags >> 10 & 0x1));
460 4
        $message->setTruncated((bool) ($flags >> 9 & 0x1));
461 4
        $message->setRecursionDesired((bool) ($flags >> 8 & 0x1));
462 4
        $message->setRecursionAvailable((bool) ($flags >> 7 & 0x1));
463 4
        $message->setZ($flags >> 4 & 0x7);
464 4
        $message->setRcode($flags & 0xf);
465
466 4
        for ($i = 0; $i < $qdCount; ++$i) {
467 4
            $message->addQuestion(Question::fromWire($encoded, $offset));
468
        }
469
470 4
        for ($i = 0; $i < $anCount; ++$i) {
471 4
            $message->addAnswer(ResourceRecord::fromWire($encoded, $offset));
472
        }
473
474 4
        for ($i = 0; $i < $nsCount; ++$i) {
475 3
            $message->addAuthoritative(ResourceRecord::fromWire($encoded, $offset));
476
        }
477
478 4
        for ($i = 0; $i < $arCount; ++$i) {
479 4
            $message->addAdditional(ResourceRecord::fromWire($encoded, $offset));
480
        }
481
482 4
        return $message;
483
    }
484
}
485