Completed
Pull Request — master (#12)
by Frederik
01:58
created

ResourceStream   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 75.47%

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 0
dl 0
loc 172
ccs 40
cts 53
cp 0.7547
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A __toString() 0 5 1
A close() 0 4 1
A detach() 0 4 1
A getSize() 0 4 1
A tell() 0 4 1
A eof() 0 4 1
A isSeekable() 0 9 3
A seek() 0 4 1
A rewind() 0 4 1
A isWritable() 0 9 4
A write() 0 4 1
A isReadable() 0 4 1
A read() 0 4 1
A getContents() 0 4 1
A getMetadata() 0 17 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Stream;
5
6
use Genkgo\Mail\StreamInterface;
7
8
/**
9
 * Class ResourceStream
10
 * @package Genkgo\Mail\Stream
11
 */
12
final class ResourceStream implements StreamInterface
13
{
14
15
    /**
16
     * @var resource
17
     */
18
    private $resource;
19
20
    /**
21
     * ResourceStream constructor.
22
     * @param $resource
23
     */
24 57
    public function __construct($resource)
25
    {
26 57
        if (!is_resource($resource)) {
27
            throw new \InvalidArgumentException('Argument 0 must be a resource');
28
        }
29
30 57
        rewind($resource);
31 57
        $this->resource = $resource;
32 57
    }
33
34
    /**
35
     * @return string
36
     */
37 15
    public function __toString(): string
38
    {
39 15
        rewind($this->resource);
40 15
        return stream_get_contents($this->resource);
41
    }
42
43
    /**
44
     *
45
     */
46
    public function close(): void
47
    {
48
        fclose($this->resource);
49
    }
50
51
    /**
52
     * @return mixed
53
     */
54 51
    public function detach()
55
    {
56 51
        return $this->resource;
57
    }
58
59
    /**
60
     * @return int|null
61
     */
62 4
    public function getSize(): ?int
63
    {
64 4
        return fstat($this->resource)['size'];
65
    }
66
67
    /**
68
     * @return int
69
     * @throws \RuntimeException
70
     */
71 3
    public function tell(): int
72
    {
73 3
        return ftell($this->resource);
74
    }
75
76
    /**
77
     * @return bool
78
     */
79 5
    public function eof(): bool
80
    {
81 5
        return feof($this->resource);
82
    }
83
84
    /**
85
     * @return bool
86
     */
87
    public function isSeekable(): bool
88
    {
89
        $metaData = stream_get_meta_data($this->resource);
90
        if (!$metaData || !isset($metaData['seekable'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metaData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91
            return false;
92
        }
93
94
        return $metaData['seekable'];
95
    }
96
97
    /**
98
     * @param int $offset
99
     * @param int $whence
100
     * @return int
101
     */
102 1
    public function seek(int $offset, int $whence = SEEK_SET): int
103
    {
104 1
        return fseek($this->resource, $offset, $whence);
105
    }
106
107
    /**
108
     * @return bool
109
     */
110 3
    public function rewind(): bool
111
    {
112 3
        return rewind($this->resource);
113
    }
114
115
    /**
116
     * @return bool
117
     */
118 1
    public function isWritable(): bool
119
    {
120 1
        $metaData = stream_get_meta_data($this->resource);
121 1
        if (!$metaData || !isset($metaData['uri'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metaData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
122
            return false;
123
        }
124
125 1
        return is_writable($metaData['uri']) || $metaData['uri'] === 'php://memory';
126
    }
127
128
    /**
129
     * @param $string
130
     * @return int
131
     */
132 1
    public function write($string): int
133
    {
134 1
        return fwrite($this->resource, $string);
135
    }
136
137
    /**
138
     * @return bool
139
     */
140
    public function isReadable(): bool
141
    {
142
        return true;
143
    }
144
145
    /**
146
     * @param int $length
147
     * @return string
148
     */
149 9
    public function read(int $length): string
150
    {
151 9
        return fread($this->resource, $length);
152
    }
153
154
    /**
155
     * @return string
156
     */
157 8
    public function getContents(): string
158
    {
159 8
        return stream_get_contents($this->resource);
160
    }
161
162
    /**
163
     * @param array $keys
164
     * @return array
165
     */
166 11
    public function getMetadata(array $keys = []): array
167
    {
168 11
        $metaData = stream_get_meta_data($this->resource);
169 11
        if (!$metaData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metaData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
170
            return [];
171
        }
172
173 11
        $keys = array_map('strtolower', $keys);
174
175 11
        return array_filter(
176 11
            $metaData,
177 11
            function ($key) use ($keys) {
178 11
                return in_array(strtolower($key), $keys);
179 11
            },
180 11
            ARRAY_FILTER_USE_KEY
181
        );
182
    }
183
}