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'])) { |
|
|
|
|
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'])) { |
|
|
|
|
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) { |
|
|
|
|
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
|
|
|
} |
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.