WritableContent::createSendableMessage()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 10
c 0
b 0
f 0
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace unreal4u\MQTT\Internals;
6
7
use DomainException;
8
use OutOfRangeException;
9
use Psr\Log\LoggerInterface;
10
use unreal4u\MQTT\Exceptions\MessageTooBig;
11
use unreal4u\MQTT\Utilities;
12
13
use function base64_encode;
14
use function chr;
15
use function decbin;
16
use function get_class;
17
use function strlen;
18
19
/**
20
 * Trait WritableContent
21
 * @package unreal4u\MQTT\Internals
22
 */
23
trait WritableContent
24
{
25
    /**
26
     * @var LoggerInterface
27
     */
28
    protected $logger;
29
30
    /**
31
     * Any special flags that are set on runtime
32
     *
33
     * PUBLISH for example needs to know QoS, the retain bit and duplicate delivery settings
34
     * PUBREL, SUBSCRIBE and UNSUBSCRIBE has always bit 1 set to true
35
     *
36
     * @var int
37
     */
38
    protected $specialFlags = 0;
39
40
    /**
41
     * Returns the fixed header part needed for all methods
42
     *
43
     * This takes into account the basic control packet value, any special flags and, in the second byte, the variable
44
     * header length
45
     *
46
     * @param int $variableHeaderLength
47
     * @return string
48
     * @throws MessageTooBig
49
     */
50 3
    final public function createFixedHeader(int $variableHeaderLength): string
51
    {
52 3
        $this->logger->debug('Creating fixed header with values', [
53 3
            'controlPacketValue' => self::getControlPacketValue(),
54 3
            'specialFlags' => $this->specialFlags,
55 3
            'variableHeaderLength' => $variableHeaderLength,
56
            #'composed' => decbin(chr((self::getControlPacketValue() << 4) | $this->specialFlags)),
57
        ]);
58
59
        // Binary OR is safe to do because the first 4 bits are always 0 after shifting
60
        return
61 3
            chr((self::getControlPacketValue() << 4) | $this->specialFlags) .
62 3
            Utilities::formatRemainingLengthOutput($variableHeaderLength);
63
    }
64
65
    /**
66
     * Creates the entire message
67
     * @return string
68
     * @throws MessageTooBig
69
     */
70 2
    final public function createSendableMessage(): string
71
    {
72 2
        $variableHeader = $this->createVariableHeader();
73 2
        $this->logger->debug('Created variable header', ['variableHeader' => base64_encode($variableHeader)]);
74 2
        $payload = $this->createPayload();
75 2
        $this->logger->debug('Created payload', ['payload' => base64_encode($payload)]);
76 2
        $fixedHeader = $this->createFixedHeader(strlen($variableHeader . $payload));
77 2
        $this->logger->debug('Created fixed header', ['fixedHeader' => base64_encode($fixedHeader)]);
78
79 2
        return $fixedHeader . $variableHeader . $payload;
80
    }
81
82
    /**
83
     * Creates the variable header that each method has
84
     *
85
     * @return string
86
     */
87
    abstract public function createVariableHeader(): string;
88
89
    /**
90
     * Creates the actual payload to be sent
91
     *
92
     * @return string
93
     */
94
    abstract public function createPayload(): string;
95
96
    /**
97
     * Creates a UTF8 big-endian representation of the given string
98
     *
99
     * @param string $nonFormattedString
100
     * @return string
101
     * @throws OutOfRangeException
102
     */
103 14
    final public function createUTF8String(string $nonFormattedString): string
104
    {
105 14
        $returnString = '';
106 14
        if ($nonFormattedString !== '') {
107 13
            $returnString = Utilities::convertNumberToBinaryString(strlen($nonFormattedString)) . $nonFormattedString;
108
        }
109
110 14
        return $returnString;
111
    }
112
113
    /**
114
     * Will return an object of the type the broker has returned to us
115
     *
116
     * @param string $brokerBitStream
117
     * @param ClientInterface $client
118
     *
119
     * @return ReadableContentInterface
120
     * @throws DomainException
121
     */
122
    public function expectAnswer(string $brokerBitStream, ClientInterface $client): ReadableContentInterface
123
    {
124
        $this->logger->info('String of incoming data confirmed, returning new object', ['callee' => get_class($this)]);
125
126
        $eventManager = new EventManager($this->logger);
127
        return $eventManager->analyzeHeaders($brokerBitStream, $client);
128
    }
129
130
    /**
131
     * Gets the control packet value for this object
132
     *
133
     * @return int
134
     */
135 11
    final public static function getControlPacketValue(): int
136
    {
137 11
        return static::CONTROL_PACKET_VALUE;
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...
138
    }
139
}
140