1616use Geocoder \Exception \InvalidServerResponse ;
1717use Geocoder \Exception \QuotaExceeded ;
1818use Geocoder \Provider \AbstractProvider ;
19- use Http \Discovery \MessageFactoryDiscovery ;
19+ use Http \Discovery \Psr17Factory ;
2020use Http \Message \MessageFactory ;
2121use Psr \Http \Client \ClientInterface ;
22+ use Psr \Http \Message \RequestFactoryInterface ;
2223use Psr \Http \Message \RequestInterface ;
24+ use Psr \Http \Message \ResponseFactoryInterface ;
25+ use Psr \Http \Message \ResponseInterface ;
26+ use Psr \Http \Message \StreamFactoryInterface ;
27+ use Psr \Http \Message \StreamInterface ;
28+ use Psr \Http \Message \UriInterface ;
2329
2430/**
2531 * @author William Durand <william.durand1@gmail.com>
@@ -33,14 +39,17 @@ abstract class AbstractHttpProvider extends AbstractProvider
3339 private $ client ;
3440
3541 /**
36- * @var MessageFactory
42+ * @var RequestFactoryInterface&StreamFactoryInterface)| MessageFactory
3743 */
3844 private $ messageFactory ;
3945
40- public function __construct (ClientInterface $ client , MessageFactory $ factory = null )
46+ /**
47+ * @param Psr17Factory|MessageFactory|null $factory Passing a MessageFactory is @deprecated
48+ */
49+ public function __construct (ClientInterface $ client , MessageFactory |Psr17Factory $ factory = null )
4150 {
4251 $ this ->client = $ client ;
43- $ this ->messageFactory = $ factory ?: MessageFactoryDiscovery:: find ( );
52+ $ this ->messageFactory = $ factory ?? ( $ client instanceof RequestFactoryInterface && $ client instanceof StreamFactoryInterface ? $ client : new Psr17Factory () );
4453 }
4554
4655 /**
@@ -57,7 +66,35 @@ protected function getUrlContents(string $url): string
5766
5867 protected function getRequest (string $ url ): RequestInterface
5968 {
60- return $ this ->getMessageFactory ()->createRequest ('GET ' , $ url );
69+ return $ this ->createRequest ('GET ' , $ url );
70+ }
71+
72+ /**
73+ * @param array<string,string|string[]> $headers
74+ */
75+ protected function createRequest (string $ method , string $ uri , array $ headers = [], string $ body = null ): RequestInterface
76+ {
77+ if ($ this ->messageFactory instanceof MessageFactory) {
78+ return $ this ->messageFactory ->createRequest ($ method , $ uri , $ headers , $ body );
79+ }
80+
81+ $ request = $ this ->messageFactory ->createRequest ($ method , $ uri );
82+
83+ foreach ($ headers as $ name => $ value ) {
84+ $ request = $ request ->withAddedHeader ($ name , $ value );
85+ }
86+
87+ if (null === $ body ) {
88+ return $ request ;
89+ }
90+
91+ $ stream = $ this ->messageFactory ->createStream ($ body );
92+
93+ if ($ stream ->isSeekable ()) {
94+ $ stream ->seek (0 );
95+ }
96+
97+ return $ request ->withBody ($ stream );
6198 }
6299
63100 /**
@@ -94,8 +131,93 @@ protected function getHttpClient(): ClientInterface
94131 return $ this ->client ;
95132 }
96133
134+ /**
135+ * @deprecated Use createRequest instead
136+ */
97137 protected function getMessageFactory (): MessageFactory
98138 {
99- return $ this ->messageFactory ;
139+ if ($ this ->messageFactory instanceof MessageFactory) {
140+ return $ this ->messageFactory ;
141+ }
142+
143+ $ factory = $ this ->messageFactory instanceof ResponseFactoryInterface ? $ this ->messageFactory : new Psr17Factory ();
144+
145+ return new class ($ factory ) implements MessageFactory {
146+ public function __construct (
147+ /**
148+ * @param RequestFactoryInterface&ResponseFactoryInterface&StreamFactoryInterface $factory
149+ */
150+ private RequestFactoryInterface |ResponseFactoryInterface |StreamFactoryInterface $ factory ,
151+ ) {
152+ }
153+
154+ /**
155+ * @param string $method
156+ * @param string|UriInterface $uri
157+ * @param array<string,string|string[]> $headers
158+ * @param resource|string|StreamInterface|null $body
159+ * @param string $protocolVersion
160+ */
161+ public function createRequest ($ method , $ uri , array $ headers = [], $ body = null , $ protocolVersion = '1.1 ' ): RequestInterface
162+ {
163+ $ request = $ this ->factory ->createRequest ($ method , $ uri );
164+
165+ foreach ($ headers as $ name => $ value ) {
166+ $ request = $ request ->withAddedHeader ($ name , $ value );
167+ }
168+
169+ if (null !== $ body ) {
170+ $ request = $ request ->withBody ($ this ->createStream ($ body ));
171+ }
172+
173+ return $ request ->withProtocolVersion ($ protocolVersion );
174+ }
175+
176+ /**
177+ * @param int $statusCode
178+ * @param string|null $reasonPhrase
179+ * @param array<string,string|string[]> $headers
180+ * @param resource|string|StreamInterface|null $body
181+ * @param string $protocolVersion
182+ */
183+ public function createResponse ($ statusCode = 200 , $ reasonPhrase = null , array $ headers = [], $ body = null , $ protocolVersion = '1.1 ' ): ResponseInterface
184+ {
185+ $ response = $ this ->factory ->createResponse ($ statusCode , $ reasonPhrase );
186+
187+ foreach ($ headers as $ name => $ value ) {
188+ $ response = $ response ->withAddedHeader ($ name , $ value );
189+ }
190+
191+ if (null !== $ body ) {
192+ $ response = $ response ->withBody ($ this ->createStream ($ body ));
193+ }
194+
195+ return $ response ->withProtocolVersion ($ protocolVersion );
196+ }
197+
198+ /**
199+ * @param string|resource|StreamInterface|null $body
200+ */
201+ private function createStream ($ body = '' ): StreamInterface
202+ {
203+ if ($ body instanceof StreamInterface) {
204+ return $ body ;
205+ }
206+
207+ if (\is_string ($ body ?? '' )) {
208+ $ stream = $ this ->factory ->createStream ($ body ?? '' );
209+ } elseif (\is_resource ($ body )) {
210+ $ stream = $ this ->factory ->createStreamFromResource ($ body );
211+ } else {
212+ throw new \InvalidArgumentException (sprintf ('"%s()" expects string, resource or StreamInterface, "%s" given. ' , __METHOD__ , get_debug_type ($ body )));
213+ }
214+
215+ if ($ stream ->isSeekable ()) {
216+ $ stream ->seek (0 );
217+ }
218+
219+ return $ stream ;
220+ }
221+ };
100222 }
101223}
0 commit comments