|
21 | 21 | use MongoDB\BSON\UTCDateTime; |
22 | 22 |
|
23 | 23 | use function assert; |
| 24 | +use function count; |
24 | 25 | use function explode; |
25 | 26 | use function in_array; |
26 | 27 | use function is_array; |
@@ -59,8 +60,8 @@ class StreamWrapper |
59 | 60 | /** @var ReadableStream|WritableStream|null */ |
60 | 61 | private $stream; |
61 | 62 |
|
62 | | - /** @var Closure(string, string): ContextOptions|null */ |
63 | | - private static ?Closure$contextResolver = null; |
| 63 | + /** @var array<string, Closure(string, string): ContextOptions|null> */ |
| 64 | + private static array$contextResolvers = []; |
64 | 65 |
|
65 | 66 | public function __destruct() |
66 | 67 | { |
@@ -100,9 +101,9 @@ public static function register(string $protocol = 'gridfs'): void |
100 | 101 | * |
101 | 102 | * @param Closure(string, string):ContextOptions|null $resolver |
102 | 103 | */ |
103 | | - public static function setDefaultContextResolver(?Closure $resolver): void |
| 104 | + public static function setContextResolver(string$name, ?Closure $resolver): void |
104 | 105 | { |
105 | | - self::$contextResolver = $resolver; |
| 106 | + self::$contextResolvers[$name] = $resolver; |
106 | 107 | } |
107 | 108 |
|
108 | 109 | /** |
@@ -144,24 +145,34 @@ public function stream_eof(): bool |
144 | 145 | */ |
145 | 146 | public function stream_open(string $path, string $mode, int $options, ?string &$openedPath): bool |
146 | 147 | { |
147 | | - $protocol = $this->initProtocol($path); |
| 148 | + [$protocol] = explode('://', $path, 2); |
148 | 149 |
|
149 | 150 | assert(is_resource($this->context)); |
150 | 151 | $contextOptions = stream_context_get_options($this->context)[$protocol] ?? null; |
151 | 152 |
|
152 | 153 | if ($contextOptions === null) { |
153 | | - if (! isset(self::$contextResolver)) { |
| 154 | + $parts = explode('/', $path, 4); |
| 155 | + |
| 156 | + if (count($parts) < 4) { |
| 157 | + if ($options & STREAM_REPORT_ERRORS) { |
| 158 | + trigger_error(sprintf('Invalid GridFS file name: "%s"', $path), E_USER_WARNING); |
| 159 | + } |
| 160 | + |
| 161 | + return false; |
| 162 | + } |
| 163 | + |
| 164 | + if (! isset(self::$contextResolvers[$parts[2]])) { |
154 | 165 | if ($options & STREAM_REPORT_ERRORS) { |
155 | | - trigger_error(sprintf('No stream context provided for "%s" protocol. Use "%s::setDefaultContextResolver() to provide a default context."', $protocol, self::class), E_USER_WARNING); |
| 166 | + trigger_error(sprintf('Unknown GridFS Bucket "%1$s". Call $bucket->asStreamWrap(\'%1$s\') on the Bucket you want to access.', $parts[2]), E_USER_WARNING); |
156 | 167 | } |
157 | 168 |
|
158 | 169 | return false; |
159 | 170 | } |
160 | 171 |
|
161 | | - $contextOptions = (self::$contextResolver)($path, $mode); |
| 172 | + $contextOptions = self::$contextResolvers[$parts[2]]($path, $mode); |
162 | 173 | if ($contextOptions === null) { |
163 | 174 | if ($options & STREAM_REPORT_ERRORS) { |
164 | | - trigger_error(sprintf('File not found "%s" with the default GridFS resolver.', $path), E_USER_WARNING); |
| 175 | + trigger_error(sprintf('File not found "%s".', $path), E_USER_WARNING); |
165 | 176 | } |
166 | 177 |
|
167 | 178 | return false; |
@@ -325,18 +336,6 @@ private function getStatTemplate(): array |
325 | 336 | ]; |
326 | 337 | } |
327 | 338 |
|
328 | | - /** |
329 | | - * Initialize the protocol from the given path. |
330 | | - * |
331 | | - * @see StreamWrapper::stream_open() |
332 | | - */ |
333 | | - private function initProtocol(string $path): string |
334 | | - { |
335 | | - $parts = explode('://', $path, 2); |
336 | | - |
337 | | - return $parts[0] ?: 'gridfs'; |
338 | | - } |
339 | | - |
340 | 339 | /** |
341 | 340 | * Initialize the internal stream for reading. |
342 | 341 | * |
|
0 commit comments