HeadersFrame   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 96.55%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 5
dl 0
loc 89
ccs 28
cts 29
cp 0.9655
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A serializeBody() 0 15 3
A parseBody() 0 17 4
A setData() 0 6 1
A getData() 0 4 1
1
<?php
2
declare(strict_types=1);
3
namespace Hyphper\Frame;
4
5
use Hyphper\Frame\Exception\InvalidPaddingException;
6
7
/**
8
 * The HEADERS frame carries name-value pairs. It is used to open a stream.
9
 * HEADERS frames can be sent on a stream in the "open" or "half closed
10
 * (remote)" states.
11
 *
12
 * The HeadersFrame class is actually basically a data frame in this
13
 * implementation, because of the requirement to control the sizes of frames.
14
 * A header block fragment that doesn't fit in an entire HEADERS frame needs
15
 * to be followed with CONTINUATION frames. From the perspective of the frame
16
 * building code the header block is an opaque data segment.
17
 *
18
 * @package Hyphper\Frame
19
 */
20
class HeadersFrame extends \Hyphper\Frame implements PaddingInterface, PriorityInterface
21
{
22
    use PaddingTrait, PriorityTrait;
23
24
    protected $defined_flags = [
25
        Flag::END_STREAM,
26
        Flag::END_HEADERS,
27
        Flag::PADDED,
28
        Flag::PRIORITY
29
    ];
30
31
    protected $type = 0x01;
32
33
    protected $stream_association = self::HAS_STREAM;
34
    protected $data;
35
36
37
38 7
    public function __construct(array $options = [])
39
    {
40 7
        parent::__construct($options);
41
42 7
        $this->data = $options['data'] ?? '';
43 7
    }
44
45 3
    public function serializeBody(): string
46
    {
47 3
        $padding_data = $this->serializePaddingData();
48 3
        $padding = '';
49 3
        if ($this->padding_length) {
50
            $padding = str_repeat("\0", $this->padding_length);
51
        }
52
53 3
        $priority_data = '';
54 3
        if ($this->flags->hasFlag(Flag::PRIORITY)) {
55 1
            $priority_data = $this->serializePriorityData();
56
        }
57
58 3
        return $padding_data . $priority_data . $this->data . $padding;
59
    }
60
61
    /**
62
     * Given the body of a frame, parses it into frame data. This populates
63
     * the non-header parts of the frame: that is, it does not populate the
64
     * stream ID or flags.
65
     *
66
     *
67
     * @param string $data
68
     *
69
     * @return void
70
     */
71 4
    public function parseBody(string $data)
72
    {
73 4
        $padding_data_length = $this->parsePaddingData($data);
74 4
        $data = substr($data, $padding_data_length);
75
76 4
        $priority_data_length = 0;
77 4
        if ($this->flags->hasFlag(Flag::PRIORITY)) {
78 1
            $priority_data_length = $this->parsePriorityData($data);
79
        }
80
81 4
        $this->body_len = strlen($data);
82 4
        $this->data = substr($data, $priority_data_length, strlen($data) - $this->padding_length);
83
84 4
        if ($this->padding_length && $this->padding_length >= $this->body_len) {
85 1
            throw new InvalidPaddingException('Padding is too long');
86
        }
87 3
    }
88
89
    /**
90
     * @param mixed|string $data
91
     *
92
     * @return HeadersFrame
93
     */
94 3
    public function setData($data)
95
    {
96 3
        $this->data = $data;
97
98 3
        return $this;
99
    }
100
101
    /**
102
     * @return mixed|string
103
     */
104 3
    public function getData()
105
    {
106 3
        return $this->data;
107
    }
108
}
109