1313
1414use Contentful \Core \Log \NullLogger ;
1515use GuzzleHttp \Client as HttpClient ;
16- use GuzzleHttp \Exception \ClientException ;
1716use Jean85 \PrettyVersions ;
18- use Psr \Http \Message \RequestInterface ;
17+ use Psr \Http \Message \ResponseInterface ;
1918use Psr \Log \LoggerInterface ;
2019use function GuzzleHttp \json_decode as guzzle_json_decode ;
2120
2221/**
2322 * Abstract client for common code for the different clients.
2423 */
25- abstract class BaseClient
24+ abstract class BaseClient implements ClientInterface
2625{
2726 /**
28- * @var HttpClient
27+ * @var Requester
2928 */
30- private $ httpClient ;
29+ private $ requester ;
3130
3231 /**
3332 * @var LoggerInterface
@@ -69,14 +68,18 @@ public function __construct(
6968 HttpClient $ httpClient = \null
7069 ) {
7170 $ this ->logger = $ logger ?: new NullLogger ();
72- $ this ->httpClient = $ httpClient ?: new HttpClient ();
71+ $ this ->requester = new Requester (
72+ $ httpClient ?: new HttpClient (),
73+ $ this ->getApi (),
74+ $ this ->getExceptionNamespace ()
75+ );
7376
7477 if ('/ ' === \mb_substr ($ host , -1 )) {
7578 $ host = \mb_substr ($ host , 0 , -1 );
7679 }
7780 $ this ->host = $ host ;
7881
79- $ this ->userAgentGenerator = new UserAgentGenerator ($ this ->getSdkName (), $ this -> getVersion ());
82+ $ this ->userAgentGenerator = new UserAgentGenerator ($ this ->getSdkName (), self :: getVersion ());
8083 $ this ->requestBuilder = new RequestBuilder (
8184 $ accessToken ,
8285 $ host ,
@@ -86,184 +89,77 @@ public function __construct(
8689 }
8790
8891 /**
89- * @return string
90- */
91- private function getVersion (): string
92- {
93- try {
94- $ version = PrettyVersions::getVersion ($ this ->getPackageName ());
95- $ shortVersion = $ version ->getShortVersion ();
96-
97- // Removes the ".x-dev" part which is inserted during development
98- if ('.x-dev ' === \mb_substr ($ shortVersion , -6 )) {
99- $ shortVersion = \mb_substr ($ shortVersion , 0 , -6 ).'-dev ' ;
100- }
101-
102- return $ shortVersion ;
103- } catch (\OutOfBoundsException $ exception ) {
104- return '0.0.0-alpha ' ;
105- }
106- }
107-
108- /**
109- * Set the application name and version.
110- * The values are used as part of the X-Contentful-User-Agent header.
111- *
112- * @param string $name
113- * @param string $version
114- *
115- * @return $this
116- */
117- public function setApplication (string $ name , string $ version = '' )
118- {
119- $ this ->userAgentGenerator ->setApplication ($ name , $ version );
120-
121- return $ this ;
122- }
123-
124- /**
125- * Set the integration name and version.
126- * The values are used as part of the X-Contentful-User-Agent header.
92+ * Make a call to the API and returns the parsed JSON.
12793 *
128- * @param string $name
129- * @param string $version
130- *
131- * @return $this
132- */
133- public function setIntegration (string $ name , string $ version = '' )
134- {
135- $ this ->userAgentGenerator ->setIntegration ($ name , $ version );
136-
137- return $ this ;
138- }
139-
140- /**
14194 * @param string $method The HTTP method
142- * @param string $path The URI path
95+ * @param string $uri The URI path
14396 * @param array $options An array of optional parameters. The following keys are accepted:
14497 * * query An array of query parameters that will be appended to the URI
14598 * * headers An array of headers that will be added to the request
14699 * * body The request body
147- * * baseUri A string that can be used to override the default client base URI
100+ * * host A string that can be used to override the default client base URI
148101 *
149102 * @throws \Exception
150103 *
151- * @return array|null
104+ * @return array
152105 */
153- protected function request (string $ method , string $ path , array $ options = [])
106+ protected function callApi (string $ method , string $ uri , array $ options = []): array
154107 {
155- $ request = $ this ->requestBuilder ->build ($ method , $ path , $ options );
108+ $ request = $ this ->requestBuilder ->build ($ method , $ uri , $ options );
156109
157- $ message = $ this ->callApi ($ request );
110+ $ message = $ this ->requester -> sendRequest ($ request );
158111 $ this ->messages [] = $ message ;
159112
160- $ logMessage = \sprintf (
161- '%s %s (%.3Fs) ' ,
162- $ request ->getMethod (),
163- (string ) $ request ->getUri (),
164- $ message ->getDuration ()
165- );
166-
167- // This is a "simple" log, for general purpose
168- $ this ->logger ->log (
169- $ message ->getLogLevel (),
170- $ logMessage
171- );
172- // This is a debug log, with all message details
173- $ this ->logger ->debug ($ logMessage , $ message ->jsonSerialize ());
113+ $ this ->logMessage ($ message );
174114
175115 $ exception = $ message ->getException ();
176116 if (\null !== $ exception ) {
177117 throw $ exception ;
178118 }
179119
180- $ response = $ message ->getResponse ();
181- $ body = $ response
182- ? (string ) $ response ->getBody ()
183- : \null;
184-
185- return $ body
186- ? guzzle_json_decode ($ body , \true)
187- : [];
120+ return $ this ->parseResponse ($ message ->getResponse ());
188121 }
189122
190123 /**
191- * Performs a query to the API, and returns a message object
192- * which contains all information needed for processing and logging.
124+ * Write information about a message object into the logger.
193125 *
194- * @param RequestInterface $request
195- *
196- * @return Message
126+ * @param Message $message
197127 */
198- private function callApi ( RequestInterface $ request ): Message
128+ private function logMessage ( Message $ message )
199129 {
200- $ startTime = \microtime (\true);
201-
202- $ exception = \null;
203- try {
204- $ response = $ this ->httpClient ->send ($ request );
205- } catch (ClientException $ exception ) {
206- $ response = $ exception ->hasResponse ()
207- ? $ exception ->getResponse ()
208- : \null;
209-
210- $ exception = $ this ->createCustomException ($ exception );
211- }
212-
213- $ duration = \microtime (\true) - $ startTime ;
214-
215- return new Message (
216- $ this ->getApi (),
217- $ duration ,
218- $ request ,
219- $ response ,
220- $ exception
130+ $ logMessage = \sprintf (
131+ '%s %s (%.3Fs) ' ,
132+ $ message ->getRequest ()->getMethod (),
133+ (string ) $ message ->getRequest ()->getUri (),
134+ $ message ->getDuration ()
221135 );
222- }
223-
224- /**
225- * Attempts to create a custom exception.
226- * It will return a default exception if no suitable class is found.
227- *
228- * @param ClientException $exception
229- *
230- * @return Exception
231- */
232- private function createCustomException (ClientException $ exception ): Exception
233- {
234- $ errorId = '' ;
235- $ response = $ exception ->getResponse ();
236- if ($ response ) {
237- $ data = guzzle_json_decode ((string ) $ response ->getBody (), \true);
238- $ errorId = (string ) $ data ['sys ' ]['id ' ];
239- }
240136
241- $ exceptionClass = $ this ->getExceptionClass ($ errorId );
137+ // This is a "simple" log, for general purpose
138+ $ this ->logger ->log (
139+ $ message ->getLogLevel (),
140+ $ logMessage
141+ );
242142
243- return new $ exceptionClass ($ exception );
143+ // This is a debug log, with all message details, useful for debugging
144+ $ this ->logger ->debug ($ logMessage , $ message ->jsonSerialize ());
244145 }
245146
246147 /**
247- * Returns the FQCN of an exception class to be used for the given API error .
148+ * Parse the body of a JSON response .
248149 *
249- * @param string $apiError
150+ * @param ResponseInterface|null $response
250151 *
251- * @return string
152+ * @return array
252153 */
253- private function getExceptionClass ( string $ apiError ): string
154+ private function parseResponse ( ResponseInterface $ response = \null ): array
254155 {
255- $ namespace = $ this ->getExceptionNamespace ();
256- if ($ namespace ) {
257- $ class = $ namespace .'\\' .$ apiError .'Exception ' ;
258-
259- if (\class_exists ($ class )) {
260- return $ class ;
261- }
262- }
263-
264- $ class = '\\Contentful \\Core \\Exception \\' .$ apiError .'Exception ' ;
156+ $ body = $ response
157+ ? (string ) $ response ->getBody ()
158+ : \null;
265159
266- return \class_exists ($ class ) ? $ class : Exception::class;
160+ return $ body
161+ ? guzzle_json_decode ($ body , \true)
162+ : [];
267163 }
268164
269165 /**
@@ -306,30 +202,64 @@ public function getHost(): string
306202 }
307203
308204 /**
309- * Returns a string representation of the API currently in use.
310- *
205+ * {@inheritdoc}
206+ */
207+ public function setApplication (string $ name , string $ version = '' )
208+ {
209+ $ this ->userAgentGenerator ->setApplication ($ name , $ version );
210+
211+ return $ this ;
212+ }
213+
214+ /**
215+ * {@inheritdoc}
216+ */
217+ public function setIntegration (string $ name , string $ version = '' )
218+ {
219+ $ this ->userAgentGenerator ->setIntegration ($ name , $ version );
220+
221+ return $ this ;
222+ }
223+
224+ /**
311225 * @return string
312226 */
313- abstract public function getApi (): string ;
227+ public static function getVersion (): string
228+ {
229+ try {
230+ $ shortVersion = PrettyVersions::getVersion (static ::getPackageName ())
231+ ->getShortVersion ()
232+ ;
233+
234+ // Removes the ".x-dev" part which is inserted during development
235+ if ('.x-dev ' === \mb_substr ($ shortVersion , -6 )) {
236+ $ shortVersion = \mb_substr ($ shortVersion , 0 , -6 ).'-dev ' ;
237+ }
238+
239+ return $ shortVersion ;
240+ } catch (\OutOfBoundsException $ exception ) {
241+ return '0.0.0-alpha ' ;
242+ }
243+ }
314244
315245 /**
316246 * Returns the packagist name of the current package.
317247 *
318248 * @return string
319249 */
320- abstract protected function getPackageName (): string ;
250+ abstract protected static function getPackageName (): string ;
321251
322252 /**
323253 * The name of the library to be used in the User-Agent header.
324254 *
325255 * @return string
326256 */
327- abstract protected function getSdkName (): string ;
257+ abstract protected static function getSdkName (): string ;
328258
329259 /**
330260 * Returns the Content-Type (MIME-Type) to be used when communication with the API.
331261 *
332262 * @return string
333263 */
334- abstract protected function getApiContentType (): string ;
264+ abstract protected static function getApiContentType (): string ;
335265}
0 commit comments