1 | <?php
|
---|
2 |
|
---|
3 | declare(strict_types=1);
|
---|
4 |
|
---|
5 | namespace GuzzleHttp\Psr7;
|
---|
6 |
|
---|
7 | use Psr\Http\Message\StreamInterface;
|
---|
8 |
|
---|
9 | /**
|
---|
10 | * Stream decorator trait
|
---|
11 | *
|
---|
12 | * @property StreamInterface $stream
|
---|
13 | */
|
---|
14 | trait StreamDecoratorTrait
|
---|
15 | {
|
---|
16 | /**
|
---|
17 | * @param StreamInterface $stream Stream to decorate
|
---|
18 | */
|
---|
19 | public function __construct(StreamInterface $stream)
|
---|
20 | {
|
---|
21 | $this->stream = $stream;
|
---|
22 | }
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * Magic method used to create a new stream if streams are not added in
|
---|
26 | * the constructor of a decorator (e.g., LazyOpenStream).
|
---|
27 | *
|
---|
28 | * @return StreamInterface
|
---|
29 | */
|
---|
30 | public function __get(string $name)
|
---|
31 | {
|
---|
32 | if ($name === 'stream') {
|
---|
33 | $this->stream = $this->createStream();
|
---|
34 |
|
---|
35 | return $this->stream;
|
---|
36 | }
|
---|
37 |
|
---|
38 | throw new \UnexpectedValueException("$name not found on class");
|
---|
39 | }
|
---|
40 |
|
---|
41 | public function __toString(): string
|
---|
42 | {
|
---|
43 | try {
|
---|
44 | if ($this->isSeekable()) {
|
---|
45 | $this->seek(0);
|
---|
46 | }
|
---|
47 |
|
---|
48 | return $this->getContents();
|
---|
49 | } catch (\Throwable $e) {
|
---|
50 | if (\PHP_VERSION_ID >= 70400) {
|
---|
51 | throw $e;
|
---|
52 | }
|
---|
53 | trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
|
---|
54 |
|
---|
55 | return '';
|
---|
56 | }
|
---|
57 | }
|
---|
58 |
|
---|
59 | public function getContents(): string
|
---|
60 | {
|
---|
61 | return Utils::copyToString($this);
|
---|
62 | }
|
---|
63 |
|
---|
64 | /**
|
---|
65 | * Allow decorators to implement custom methods
|
---|
66 | *
|
---|
67 | * @return mixed
|
---|
68 | */
|
---|
69 | public function __call(string $method, array $args)
|
---|
70 | {
|
---|
71 | /** @var callable $callable */
|
---|
72 | $callable = [$this->stream, $method];
|
---|
73 | $result = ($callable)(...$args);
|
---|
74 |
|
---|
75 | // Always return the wrapped object if the result is a return $this
|
---|
76 | return $result === $this->stream ? $this : $result;
|
---|
77 | }
|
---|
78 |
|
---|
79 | public function close(): void
|
---|
80 | {
|
---|
81 | $this->stream->close();
|
---|
82 | }
|
---|
83 |
|
---|
84 | /**
|
---|
85 | * @return mixed
|
---|
86 | */
|
---|
87 | public function getMetadata($key = null)
|
---|
88 | {
|
---|
89 | return $this->stream->getMetadata($key);
|
---|
90 | }
|
---|
91 |
|
---|
92 | public function detach()
|
---|
93 | {
|
---|
94 | return $this->stream->detach();
|
---|
95 | }
|
---|
96 |
|
---|
97 | public function getSize(): ?int
|
---|
98 | {
|
---|
99 | return $this->stream->getSize();
|
---|
100 | }
|
---|
101 |
|
---|
102 | public function eof(): bool
|
---|
103 | {
|
---|
104 | return $this->stream->eof();
|
---|
105 | }
|
---|
106 |
|
---|
107 | public function tell(): int
|
---|
108 | {
|
---|
109 | return $this->stream->tell();
|
---|
110 | }
|
---|
111 |
|
---|
112 | public function isReadable(): bool
|
---|
113 | {
|
---|
114 | return $this->stream->isReadable();
|
---|
115 | }
|
---|
116 |
|
---|
117 | public function isWritable(): bool
|
---|
118 | {
|
---|
119 | return $this->stream->isWritable();
|
---|
120 | }
|
---|
121 |
|
---|
122 | public function isSeekable(): bool
|
---|
123 | {
|
---|
124 | return $this->stream->isSeekable();
|
---|
125 | }
|
---|
126 |
|
---|
127 | public function rewind(): void
|
---|
128 | {
|
---|
129 | $this->seek(0);
|
---|
130 | }
|
---|
131 |
|
---|
132 | public function seek($offset, $whence = SEEK_SET): void
|
---|
133 | {
|
---|
134 | $this->stream->seek($offset, $whence);
|
---|
135 | }
|
---|
136 |
|
---|
137 | public function read($length): string
|
---|
138 | {
|
---|
139 | return $this->stream->read($length);
|
---|
140 | }
|
---|
141 |
|
---|
142 | public function write($string): int
|
---|
143 | {
|
---|
144 | return $this->stream->write($string);
|
---|
145 | }
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Implement in subclasses to dynamically create streams when requested.
|
---|
149 | *
|
---|
150 | * @throws \BadMethodCallException
|
---|
151 | */
|
---|
152 | protected function createStream(): StreamInterface
|
---|
153 | {
|
---|
154 | throw new \BadMethodCallException('Not implemented');
|
---|
155 | }
|
---|
156 | }
|
---|