Passed
Push — master ( 588318...10921e )
by Pierre
02:55
created

Input::openStream()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

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