Passed
Push — master ( 49fa37...dabd6a )
by Camilo
02:32
created

UnSubscribe::loop()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 0
cts 12
cp 0
rs 9.3142
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 2
crap 12
1
<?php
2
3
declare(strict_types=1);
4
5
namespace unreal4u\MQTT\Protocol;
6
7
use unreal4u\MQTT\Application\EmptyReadableResponse;
8
use unreal4u\MQTT\Internals\ClientInterface;
9
use unreal4u\MQTT\Internals\EventManager;
10
use unreal4u\MQTT\Internals\ProtocolBase;
11
use unreal4u\MQTT\Internals\ReadableContentInterface;
12
use unreal4u\MQTT\Internals\WritableContent;
13
use unreal4u\MQTT\Internals\WritableContentInterface;
14
use unreal4u\MQTT\Protocol\Subscribe\Topic;
15
use unreal4u\MQTT\Utilities;
16
17
final class UnSubscribe extends ProtocolBase implements WritableContentInterface
18
{
19
    use WritableContent;
20
21
    const CONTROL_PACKET_VALUE = 10;
22
23
    private $packetIdentifier = 0;
24
25
    /**
26
     * An array of topics on which to subscribe to
27
     * @var Topic[]
28
     */
29
    private $topics = [];
30
31
    /**
32
     * @return string
33
     * @throws \OutOfRangeException
34
     * @throws \Exception
35
     */
36
    public function createVariableHeader(): string
37
    {
38
        // Subscribe must always send a 2 flag
39
        $this->specialFlags = 2;
40
41
        // Assign a packet identifier automatically if none has been assigned yet
42
        if ($this->packetIdentifier === 0) {
43
            $this->setPacketIdentifier(random_int(0, 65535));
44
        }
45
46
        return Utilities::convertNumberToBinaryString($this->packetIdentifier);
47
    }
48
49
    public function createPayload(): string
50
    {
51
        $output = '';
52
        foreach ($this->topics as $topic) {
53
            // chr on QoS level is safe because it will create an 8-bit flag where the first 6 are only 0's
54
            $output .= $this->createUTF8String($topic->getTopicName()) . \chr($topic->getTopicQoSLevel());
55
        }
56
        return $output;
57
    }
58
59
    /**
60
     * When the Server receives a SUBSCRIBE Packet from a Client, the Server MUST respond with a SUBACK Packet
61
     *
62
     * This can however not be in the same order, as we may be able to receive PUBLISH packets before getting a SUBACK
63
     * back
64
     *
65
     * @see http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718134 (MQTT-3.8.4-1)
66
     * @return bool
67
     */
68
    public function shouldExpectAnswer(): bool
69
    {
70
        return true;
71
    }
72
73
    /**
74
     * SUBSCRIBE Control Packets MUST contain a non-zero 16-bit Packet Identifier
75
     *
76
     * @param int $packetIdentifier
77
     * @return Subscribe
78
     * @throws \OutOfRangeException
79
     */
80
    public function setPacketIdentifier(int $packetIdentifier): self
81
    {
82
        if ($packetIdentifier > 65535 || $packetIdentifier < 1) {
83
            throw new \OutOfRangeException('Packet identifier must fit within 2 bytes');
84
        }
85
86
        $this->packetIdentifier = $packetIdentifier;
87
        $this->logger->debug('Setting packet identifier', ['current' => $this->packetIdentifier]);
88
89
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type unreal4u\MQTT\Protocol\UnSubscribe which is incompatible with the documented return type unreal4u\MQTT\Protocol\Subscribe.
Loading history...
90
    }
91
92
    public function getPacketIdentifier(): int
93
    {
94
        return $this->packetIdentifier;
95
    }
96
97
    /**
98
     * A subscription is based on filters, this function allows us to pass on filters
99
     *
100
     * @param Topic[] $topics
101
     * @return Subscribe
102
     */
103
    public function addTopics(Topic ...$topics): self
104
    {
105
        $this->topics = $topics;
106
        $this->logger->debug('Topics added', ['totalTopics', count($this->topics)]);
107
108
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type unreal4u\MQTT\Protocol\UnSubscribe which is incompatible with the documented return type unreal4u\MQTT\Protocol\Subscribe.
Loading history...
109
    }
110
}
111