ReadableContent   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 9
eloc 24
c 0
b 0
f 0
dl 0
loc 108
ccs 28
cts 28
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A instantiateObject() 0 7 1
A calculateSizeOfRemainingLengthField() 0 10 2
A checkControlPacketValue() 0 12 2
A performSpecialActions() 0 3 1
A performRemainingLengthFieldOperations() 0 20 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace unreal4u\MQTT\Internals;
6
7
use unreal4u\MQTT\Exceptions\InvalidResponseType;
8
use unreal4u\MQTT\Utilities;
9
10
use function ord;
11
use function sprintf;
12
use function strlen;
13
14
/**
15
 * Trait ReadableContent
16
 * @package unreal4u\MQTT\Internals
17
 */
18
trait ReadableContent
19
{
20
    /**
21
     * The remaining length field may be from 1 to 4 bytes long, this field will represent that offset
22
     * @var int
23
     */
24
    private $sizeOfRemainingLengthField = 1;
25
26
    /**
27
     * @param string $rawMQTTHeaders
28
     * @param ClientInterface $client
29
     * @return bool
30
     * @throws InvalidResponseType
31
     */
32 8
    final public function instantiateObject(string $rawMQTTHeaders, ClientInterface $client): bool
33
    {
34
        //var_dump(base64_encode($rawMQTTHeaders)); // Make it a bit easier to create unit tests
35 8
        $this->checkControlPacketValue(ord($rawMQTTHeaders[0]) >> 4);
36 7
        $this->fillObject($rawMQTTHeaders, $client);
37
38 7
        return true;
39
    }
40
41
    /**
42
     * Checks whether the control packet corresponds to this object
43
     *
44
     * @param int $controlPacketValue
45
     * @return bool
46
     * @throws InvalidResponseType
47
     */
48 8
    private function checkControlPacketValue(int $controlPacketValue): bool
49
    {
50
        // Check whether the first byte corresponds to the expected control packet value
51 8
        if (static::CONTROL_PACKET_VALUE !== $controlPacketValue) {
0 ignored issues
show
Bug introduced by
The constant unreal4u\MQTT\Internals\...t::CONTROL_PACKET_VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
52 1
            throw new InvalidResponseType(sprintf(
53 1
                'Value of received value does not correspond to response (Expected: %d, Actual: %d)',
54 1
                static::CONTROL_PACKET_VALUE,
55 1
                $controlPacketValue
56
            ));
57
        }
58
59 7
        return true;
60
    }
61
62
    /**
63
     * Returns the correct format for the length in bytes of the remaining bytes
64
     *
65
     * @param ClientInterface $client
66
     * @param string $rawMQTTHeaders
67
     * @return int
68
     */
69 15
    private function performRemainingLengthFieldOperations(
70
        string &$rawMQTTHeaders,
71
        ClientInterface $client
72
    ): int {
73
        // Early return: assume defaults if first digit has a value under 128, no further need for complex checks
74 15
        if (ord($rawMQTTHeaders[1]) < 128) {
75 11
            return ord($rawMQTTHeaders[1]);
76
        }
77
78
        // If we have less than 4 bytes now, we should really try to recover the rest of the remaining field data
79 4
        if (strlen($rawMQTTHeaders) < 4) {
80
            // At this point we could actually read at least 128 as a minimum, but restrict it to what we need right now
81 1
            $rawMQTTHeaders .= $client->readBrokerData(4 - strlen($rawMQTTHeaders));
82
        }
83
84 4
        $remainingBytes = Utilities::convertRemainingLengthStringToInt(substr($rawMQTTHeaders, 1, 4));
85
86
        // Estimate how much longer is the remaining length field, this will also set $this->sizeOfRemainingLengthField
87 4
        $this->calculateSizeOfRemainingLengthField($remainingBytes);
88 4
        return $remainingBytes;
89
    }
90
91
    /**
92
     * Sets the offset of the remaining length field
93
     *
94
     * @param int $size
95
     * @return int
96
     */
97 13
    private function calculateSizeOfRemainingLengthField(int $size): int
98
    {
99 13
        $blockSize = $iterations = 0;
100 13
        while ($size >= $blockSize) {
101 13
            $iterations++;
102 13
            $blockSize = 128 ** $iterations;
103
        }
104
105 13
        $this->sizeOfRemainingLengthField = $iterations;
106 13
        return $iterations;
107
    }
108
109
    /**
110
     * All classes must implement how to handle the object filling
111
     * @param string $rawMQTTHeaders
112
     * @param ClientInterface $client
113
     * @return ReadableContentInterface
114
     */
115
    abstract public function fillObject(string $rawMQTTHeaders, ClientInterface $client): ReadableContentInterface;
116
117
    /**
118
     * Any class can overwrite the default behaviour
119
     * @param ClientInterface $client
120
     * @param WritableContentInterface $originalRequest
121
     * @return bool
122
     */
123 1
    public function performSpecialActions(ClientInterface $client, WritableContentInterface $originalRequest): bool
0 ignored issues
show
Unused Code introduced by
The parameter $originalRequest is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

123
    public function performSpecialActions(ClientInterface $client, /** @scrutinizer ignore-unused */ WritableContentInterface $originalRequest): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $client is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

123
    public function performSpecialActions(/** @scrutinizer ignore-unused */ ClientInterface $client, WritableContentInterface $originalRequest): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
124
    {
125 1
        return false;
126
    }
127
}
128