Input   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Test Coverage

Coverage 89.74%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 43
c 3
b 0
f 0
dl 0
loc 160
ccs 35
cts 39
cp 0.8974
rs 10
wmc 14

9 Methods

Rating   Name   Duplication   Size   Complexity  
A value() 0 16 2
A getStreamName() 0 3 1
A getStreamHandler() 0 4 1
A setMaxLength() 0 4 1
A __construct() 0 9 2
A streamable() 0 3 1
A getMaxLength() 0 3 1
A openStream() 0 9 3
A closeStream() 0 6 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Component\Console;
6
7
class Input
8
{
9
10
    const STREAM_STDIN = 'php://stdin';
11
    const STREAM_MEMORY = 'php://memory';
12
    const STREAM_TEMP = 'php://temp';
13
    const STREAM_MODE_READ = 'r';
14
    const STREAM_MODE_APPEND = 'r+';
15
    const STREAM_MODE_WRITE = 'w';
16
    const STREAM_MODE_WRITE_APPEND = 'w+';
17
    const DEBUGER = 'phpdbg';
18
19
    /**
20
     * streamName
21
     *
22
     * @var string
23
     */
24
    protected $streamName;
25
26
    /**
27
     * streamMode
28
     *
29
     * @var string
30
     */
31
    protected $streamMode;
32
33
    /**
34
     * $streamHandler
35
     *
36
     * @var resource
37
     */
38
    protected $streamHandler;
39
40
    /**
41
     * $maxLength
42
     *
43
     * @var int
44
     */
45
    protected $maxLength;
46
47
    /**
48
     * instanciate
49
     *
50
     * @param string $streamName
51
     */
52 6
    public function __construct(
53
        string $streamName = self::STREAM_STDIN,
54
        string $streamMode = self::STREAM_MODE_WRITE_APPEND
55
    ) {
56 6
        $this->streamName = (php_sapi_name() == self::DEBUGER)
57 6
            ? self::STREAM_MEMORY
58
            : $streamName;
59 6
        $this->streamMode = $streamMode;
60 6
        $this->setMaxLength(1);
61
    }
62
63
    /**
64
     * return the input value
65
     *
66
     * @param string $forcedValue
67
     * @return string
68
     */
69 1
    public function value(string $forcedValue = ''): string
70
    {
71 1
        $handle = $this->getStreamHandler();
72
        //readline_callback_handler_install('', function () { });
73 1
        if (!empty($forcedValue)) {
74 1
            $this->setMaxLength(strlen($forcedValue));
75 1
            rewind($handle);
76 1
            fwrite($handle, $forcedValue);
77
        }
78 1
        $value = stream_get_contents(
79 1
            $handle,
80 1
            $this->getMaxLength(),
81
            0
82
        );
83 1
        $this->closeStream();
84 1
        return $value;
85
    }
86
87
    /**
88
     * set stream max length
89
     *
90
     * @return Input
91
     */
92 6
    public function setMaxLength(int $len): Input
93
    {
94 6
        $this->maxLength = $len;
95 6
        return $this;
96
    }
97
98
    /**
99
     * returns stream handler
100
     *
101
     * @return int
102
     */
103 1
    protected function getMaxLength(): int
104
    {
105 1
        return $this->maxLength;
106
    }
107
108
    /**
109
     * returns stream handler
110
     *
111
     * @return resource | null
112
     */
113 1
    protected function getStreamHandler()
114
    {
115 1
        $this->openStream();
116 1
        return $this->streamHandler;
117
    }
118
119
    /**
120
     * returns stream name
121
     *
122
     * @return string
123
     */
124 1
    protected function getStreamName(): string
125
    {
126 1
        return $this->streamName;
127
    }
128
129
    /**
130
     * return false if streamHandler is not a resource
131
     *
132
     * @return boolean
133
     */
134
    protected function streamable(): bool
135
    {
136
        return is_resource($this->streamHandler);
137
    }
138
139
    /**
140
     * open resource
141
     *
142
     * @return Input
143
     * @throws Exception
144
     */
145 1
    protected function openStream(): Input
146
    {
147 1
        if (false === $this->streamable()) {
148 1
            $this->streamHandler = fopen($this->getStreamName(), $this->streamMode, false);
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($this->getStreamNa...his->streamMode, false) can also be of type false. However, the property $streamHandler is declared as type resource. 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...
149
        }
150 1
        if (false === $this->streamable()) {
151
            throw new \Exception('Cant open input stream handle');
152
        }
153 1
        return $this;
154
    }
155
156
    /**
157
     * close resource
158
     *
159
     * @return Input
160
     */
161 1
    protected function closeStream(): Input
162
    {
163 1
        if ($this->streamable()) {
164 1
            fclose($this->streamHandler);
165
        }
166 1
        return $this;
167
    }
168
}
169