Completed
Push — master ( 4ca550...f445a9 )
by Camilo
02:08
created

Unsubscribe::setPacketIdentifier()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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