ResourceStream   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 33
c 2
b 0
f 0
dl 0
loc 86
ccs 34
cts 34
cp 1
rs 10
wmc 14

4 Methods

Rating   Name   Duplication   Size   Complexity  
A read() 0 23 5
A __construct() 0 12 2
A close() 0 9 3
A write() 0 13 4
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of mracine/php-streams.
4
 *
5
 * (c) Matthieu Racine <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace mracine\Streams;
11
12
use mracine\Streams\Stream;
13
use mracine\Streams\Exception\StreamException;
14
use mracine\Streams\Exception\TimeoutException;
15
16
/**
17
 * class ResourceStream
18
 *
19
 * Stream using a resource (socket, file, pipe etc.)
20
 *
21
 * @since 0.1
22
 */
23
24
class ResourceStream implements Stream
25
{
26
    /**
27
     * @var resource|null $stream null if stream has been closed
28
     */
29
    protected $stream;
30
31
    /**
32
     * Constructs a stream from a resource
33
     *
34
     * @since 0.1
35
     * @param resource $stream the PHP resource (PHP refuse resource type hinting)
36
     * @throws  InvalidArgumentException when $stream is not a resource
37 8
     */
38
    public function __construct($stream)
39 8
    {
40 5
        if (false === is_resource($stream)) {
41 5
            throw new \InvalidArgumentException(
42 5
                sprintf(
43 5
                    'Argument must be a valid resource type. %s given.',
44
                    gettype($stream)
45
                )
46
            );
47
        }
48 3
        // // TODO  : Should we verify the resource type ?
49 3
        $this->stream = $stream;
50
    }
51
52
    /**
53
     * {@inheritDoc}
54 6
     */
55
    public function read(int $length) : string
56 6
    {
57 1
        if (is_null($this->stream)) {
58
            throw new StreamException(sprintf("Cannot read from closed (null) stream"));
59 5
        }
60 2
        if ($length<=0) {
61
            throw new \InvalidArgumentException("Cannot read zero ot negative count of bytes from a stream");
62
        }
63 3
64
        $result = @fread($this->stream, $length);
65 3
        if (false === $result) {
66 1
            throw new StreamException(sprintf("Error reading %d bytes", $length));
67
        }
68
        
69 2
        $streamInfos = stream_get_meta_data($this->stream);
70
        if (true === $streamInfos['timed_out']) {
71
            // TODO: How to test timeout ???
72
            // @codeCoverageIgnoreStart
73
            throw new TimeoutException(sprintf("Timeout reading %d bytes", $length));
74
            // @codeCoverageIgnoreEnd
75 3
        }
76
77 3
        return $result;
78 1
    }
79
80 2
    /**
81 2
     * {@inheritDoc}
82
     */
83 2
    public function write(string $string, $length = null) : int
84 2
    {
85 1
        if (is_null($this->stream)) {
86
            throw new StreamException(sprintf("Cannot write to closed (null) stream"));
87 1
        }
88
        if (is_null($length)) {
89
            $length = strlen($string);
90
        }
91
        $result = @fwrite($this->stream, $string, $length);
92
        if (false === $result) {
93 3
            throw new StreamException(sprintf("Error writing %d bytes", $length));
94
        }
95 3
        return $result;
96 3
    }
97 3
98 3
    /**
99
     * {@inheritDoc}
100 3
     */
101 1
    public function close()
102
    {
103 3
        $hasBeenClosed = false;
104
        if (!is_null($this->stream)) {
105
            $hasBeenClosed = @fclose($this->stream);
106
            $this->stream = null;
107
        }
108
        if (false === $hasBeenClosed) {
109
            throw new StreamException("Error closing stream");
110
        }
111
    }
112
}
113