FrameParser   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 85.71%

Importance

Changes 0
Metric Value
wmc 6
lcom 1
cbo 1
dl 0
loc 75
c 0
b 0
f 0
ccs 18
cts 21
cp 0.8571
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A hasFrame() 0 14 3
A parseFrame() 0 22 3
1
<?php declare(strict_types=1);
2
3
namespace Lisachenko\Protocol\FCGI;
4
5
use Lisachenko\Protocol\FCGI;
6
7
/**
8
 * Utility class to simplify parsing of FCGI protocol data.
9
 *
10
 * @author Alexander.Lisachenko
11
 */
12
class FrameParser
13
{
14
15
    /**
16
     * Mapping of constants to the classes
17
     *
18
     * @var array
19
     */
20
    protected static $classMapping = [
21
        FCGI::BEGIN_REQUEST      => FCGI\Record\BeginRequest::class,
22
        FCGI::ABORT_REQUEST      => FCGI\Record\AbortRequest::class,
23
        FCGI::END_REQUEST        => FCGI\Record\EndRequest::class,
24
        FCGI::PARAMS             => FCGI\Record\Params::class,
25
        FCGI::STDIN              => FCGI\Record\Stdin::class,
26
        FCGI::STDOUT             => FCGI\Record\Stdout::class,
27
        FCGI::STDERR             => FCGI\Record\Stderr::class,
28
        FCGI::DATA               => FCGI\Record\Data::class,
29
        FCGI::GET_VALUES         => FCGI\Record\GetValues::class,
30
        FCGI::GET_VALUES_RESULT  => FCGI\Record\GetValuesResult::class,
31
        FCGI::UNKNOWN_TYPE       => FCGI\Record\UnknownType::class,
32
    ];
33
34
    /**
35
     * Checks if the buffer contains a valid frame to parse
36
     *
37
     * @param string $buffer Binary buffer
38
     *
39
     * @return bool
40
     */
41
    public static function hasFrame(string $buffer): bool
42 1
    {
43
        $bufferLength = strlen($buffer);
44 1
        if ($bufferLength < FCGI::HEADER_LEN) {
45 1
            return false;
46
        }
47
48
        $fastInfo = unpack(FCGI::HEADER_FORMAT, $buffer);
49 1
        if ($bufferLength < FCGI::HEADER_LEN + $fastInfo['contentLength'] + $fastInfo['paddingLength']) {
50 1
            return false;
51 1
        }
52
53
        return true;
54 1
    }
55
56
    /**
57
     * Parses a frame from the binary buffer
58
     *
59
     * @param string $buffer Binary buffer
60
     *
61
     * @return Record One of the corresponding FCGI record
62
     */
63
    public static function parseFrame(string &$buffer): Record
64 1
    {
65
        $bufferLength = strlen($buffer);
66 1
        if ($bufferLength < FCGI::HEADER_LEN) {
67 1
            throw new \RuntimeException("Not enough data in the buffer to parse");
68
        }
69
        $recordHeader = unpack(FCGI::HEADER_FORMAT, $buffer);
70 1
        $recordType   = $recordHeader['type'];
71 1
        if (!isset(self::$classMapping[$recordType])) {
72 1
            throw new \DomainException("Invalid FCGI record type {$recordType} received");
73
        }
74
75
        /** @var Record $className */
76
        $className = self::$classMapping[$recordType];
77 1
        $record    = $className::unpack($buffer);
78 1
79
80
        $offset = FCGI::HEADER_LEN + $record->getContentLength() + $record->getPaddingLength();
81 1
        $buffer = substr($buffer, $offset);
82 1
83
        return $record;
84 1
    }
85
86
}
87