MarkerFramePicker   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 2
dl 0
loc 118
ccs 37
cts 37
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A resolveStartOfFrame() 0 19 4
A doHandleData() 0 17 4
A doCreateFrame() 0 9 3
A findMarker() 0 6 2
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2017, Efimov Evgenij <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
namespace AsyncSockets\Frame;
11
12
/**
13
 * Class MarkerFramePicker
14
 */
15
class MarkerFramePicker extends AbstractFramePicker
16
{
17
    /**
18
     * Frame start byte sequence or null
19
     *
20
     * @var string|null
21
     */
22
    private $startMarker;
23
24
    /**
25
     * Frame end marker
26
     *
27
     * @var string
28
     */
29
    private $endMarker;
30
31
    /**
32
     * Offset to search for end marker during data handling
33
     *
34
     * @var int
35
     */
36
    private $startPos;
37
38
    /**
39
     * bool
40
     *
41
     * @var bool
42
     */
43
    private $isCaseSensitive;
44
45
    /**
46
     * MarkerFramePicker constructor.
47
     *
48
     * @param null|string $startMarker Start marker
49
     * @param string      $endMarker End marker
50
     * @param bool        $isCaseSensitive True, if case is important
51
     */
52 30
    public function __construct($startMarker, $endMarker, $isCaseSensitive = true)
53
    {
54 30
        parent::__construct();
55 30
        $this->startMarker     = $startMarker;
56 30
        $this->endMarker       = $endMarker;
57 30
        $this->isCaseSensitive = $isCaseSensitive;
58 30
    }
59
60
    /**
61
     * Find start of data in frame
62
     *
63
     * @param string $buffer Collected data for frame
64
     *
65
     * @return bool True if start of frame is found
66
     */
67 29
    protected function resolveStartOfFrame($buffer)
68
    {
69 29
        if ($this->startPos !== null) {
70 7
            return true;
71
        }
72
73 29
        if ($this->startMarker === null) {
74 4
            $this->startPos = 0;
75 4
            return true;
76
        }
77
78 25
        $pos = $this->findMarker($buffer, $this->startMarker);
79 25
        if ($pos !== false) {
80 19
            $this->startPos = $pos;
0 ignored issues
show
Documentation Bug introduced by
It seems like $pos can also be of type boolean. However, the property $startPos is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
81 19
            return true;
82
        }
83
84 8
        return false;
85
    }
86
87
    /** {@inheritdoc} */
88 29
    protected function doHandleData($chunk, $remoteAddress, &$buffer)
89
    {
90 29
        $buffer .= $chunk;
91 29
        if (!$this->resolveStartOfFrame($buffer)) {
92 8
            return '';
93
        }
94
95 23
        $pos = $this->findMarker($buffer, $this->endMarker, $this->startPos + strlen($this->startMarker));
96 23
        if ($pos === false) {
97 12
            return '';
98
        }
99
100 17
        $this->setFinished(true);
101 17
        $result = substr($buffer, $pos + strlen($this->endMarker));
102 17
        $buffer = substr($buffer, $this->startPos, $pos + strlen($this->endMarker) - $this->startPos);
103 17
        return $result !== false ? $result : '';
104
    }
105
106
    /** {@inheritdoc} */
107 29
    protected function doCreateFrame($buffer, $remoteAddress)
108
    {
109 29
        if ($this->isEof()) {
110 17
            return new Frame($buffer, $remoteAddress);
111
        }
112
113 12
        $data = $this->startPos === null ? '' : substr($buffer, $this->startPos);
114 12
        return new Frame($data, $remoteAddress);
115
    }
116
117
    /**
118
     * Performs strpos or stripos according to case sensibility
119
     *
120
     * @param string $haystack Where find text
121
     * @param string $needle What to find
122
     * @param int    $offset Start offset in $haystack
123
     *
124
     * @return bool|int
125
     */
126 29
    protected function findMarker($haystack, $needle, $offset = 0)
127
    {
128 29
        return $this->isCaseSensitive ?
129 29
            strpos($haystack, $needle, $offset) :
130 29
            stripos($haystack, $needle, $offset);
131
    }
132
}
133