1: <?php
2: namespace Worldline\Connect\Sdk\Communication;
3:
4: use UnexpectedValueException;
5: use Worldline\Connect\Sdk\Domain\DataObject;
6:
7: /**
8: * Class ResponseFactory
9: *
10: * @package Worldline\Connect\Sdk\Communication
11: */
12: class ResponseFactory
13: {
14: const MIME_APPLICATION_JSON = 'application/json';
15:
16: /**
17: * @param ConnectionResponse $response
18: * @param ResponseClassMap $responseClassMap
19: *
20: * @return DataObject|null
21: */
22: public function createResponse(ConnectionResponse $response, ResponseClassMap $responseClassMap): ?DataObject
23: {
24: try {
25: return $this->getResponseObject($response, $responseClassMap);
26: } catch (UnexpectedValueException $e) {
27: throw new InvalidResponseException($response, $e->getMessage());
28: }
29: }
30:
31: /**
32: * @param ConnectionResponse $response
33: * @param ResponseClassMap $responseClassMap
34: *
35: * @return DataObject|null
36: */
37: protected function getResponseObject(ConnectionResponse $response, ResponseClassMap $responseClassMap): ?DataObject
38: {
39: $httpStatusCode = $response->getHttpStatusCode();
40: if (!$httpStatusCode) {
41: throw new UnexpectedValueException('HTTP status code is missing');
42: }
43: $contentType = $response->getHeaderValue('Content-Type');
44: if (!$contentType && $httpStatusCode !== 204) {
45: throw new UnexpectedValueException('Content type is missing or empty');
46: }
47: if (!$this->isJsonContentType($contentType) && $httpStatusCode !== 204) {
48: throw new UnexpectedValueException(
49: "Invalid content type; got '$contentType', expected '" . static::MIME_APPLICATION_JSON . "'"
50: );
51: }
52: $responseClassName = $responseClassMap->getResponseClassName($httpStatusCode);
53: if (empty($responseClassName)) {
54: if ($httpStatusCode < 400) {
55: return null;
56: }
57: throw new UnexpectedValueException('No default error response class name defined');
58: }
59: if (!class_exists($responseClassName)) {
60: throw new UnexpectedValueException("class '$responseClassName' does not exist");
61: }
62: $responseObject = new $responseClassName();
63: if (!$responseObject instanceof DataObject) {
64: throw new UnexpectedValueException("class '$responseClassName' is not a 'DataObject'");
65: }
66: return $responseObject->fromJson($response->getBody());
67: }
68:
69: private function isJsonContentType(string $contentType): bool
70: {
71: return $contentType === static::MIME_APPLICATION_JSON
72: || substr($contentType, 0, strlen(static::MIME_APPLICATION_JSON)) === static::MIME_APPLICATION_JSON;
73: }
74: }
75: