Passed
Push — master ( 8a3b7f...1af7f7 )
by Camilo
02:34
created

Unsubscribe::createVariableHeader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4.679

Importance

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