Passed
Push — master ( 11b97c...bafc8d )
by Alexander
44s queued 10s
created

RestRepository::formatResponseExceptionMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Indigerd\Repository\Rest;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\BadResponseException;
7
use Indigerd\Hydrator\Hydrator;
8
use Indigerd\Repository\Rest\Exception\ClientException;
9
use Indigerd\Repository\Rest\Exception\ServerException;
10
11
class RestRepository
12
{
13
    /**
14
     * @var Hydrator
15
     */
16
    protected $hydrator;
17
18
    /**
19
     * @var Hydrator
20
     */
21
    protected $collectionHydrator;
22
23
    /**
24
     * @var Client
25
     */
26
    protected $client;
27
28
    /**
29
     * @var string
30
     */
31
    protected $modelClass;
32
33
    /**
34
     * @var string
35
     */
36
    protected $collectionClass;
37
38
    protected $endpoint;
39
40
    /**
41
     * @var array
42
     */
43
    protected $headers;
44
45
    /**
46
     * RestRepository constructor.
47
     * @param Hydrator $hydrator
48
     * @param Hydrator $collectionHydrator
49
     * @param Client $client
50
     * @param string $modelClass
51
     * @param string $collectionClass
52
     * @param string $endpoint
53
     */
54
    public function __construct(
55
        Hydrator $hydrator,
56
        Hydrator $collectionHydrator,
57
        Client $client,
58
        string $modelClass,
59
        string $collectionClass,
60
        string $endpoint
61
    ) {
62
        $this->hydrator = $hydrator;
63
        $this->collectionHydrator = $collectionHydrator;
64
        $this->client = $client;
65
        $this->modelClass = $modelClass;
66
        $this->collectionClass = $collectionClass;
67
        $this->endpoint = $endpoint;
68
    }
69
70
    /**
71
     * @param string $id
72
     * @param string $token
73
     * @return object|null
74
     */
75
    public function findOne(string $id, string $token = ''): ?object
76
    {
77
        $url = \rtrim($this->endpoint, '/') . '/' . $id;
78
        $this->addToken($token);
79
        $response = $this->request('get', $url);
80
        return $this->hydrator->hydrate($this->modelClass, $response['body']);
81
    }
82
83
    /**
84
     * @param array $params
85
     * @param string $token
86
     * @return Collection
87
     */
88
    public function findAll(array $params = [], string $token = ''): Collection
89
    {
90
        $url = \rtrim($this->endpoint, '/');
91
        $this->addToken($token);
92
        $response = $this->request('get', $url, $params);
93
94
        return $this->collectionHydrator->hydrate(
95
            $this->collectionClass,
96
            ['items' => $response['body']] + $this->generateHeaders($response['headers'])
97
        );
98
    }
99
100
    /**
101
     * @param string $header
102
     * @param string $value
103
     * @return $this
104
     */
105
    protected function addHeader(string $header, string $value)
106
    {
107
        $this->headers[$header] = $value;
108
        return $this;
109
    }
110
111
    /**
112
     * @param string $token
113
     */
114
    protected function addToken(string $token)
115
    {
116
        if (!empty($token)) {
117
            $this->addHeader('Authorization', $token);
118
        }
119
    }
120
121
    /**
122
     * @param string $method
123
     * @param string $url
124
     * @param array $params
125
     * @return array
126
     */
127
    protected function request(string $method, string $url, array $params = []): array
128
    {
129
        $this->addHeader('Accept', 'application/json');
130
        $params['headers'] = $this->headers;
131
132
        try {
133
            /** @var \Psr\Http\Message\ResponseInterface $userRequest */
134
            $userRequest = $this->client->{$method}($url, $params);
135
        } catch (\GuzzleHttp\Exception\ClientException $e) {
136
            $message = $this->formatResponseExceptionMessage($e);
137
            throw new ClientException($e->getResponse()->getStatusCode(), $message);
138
        } catch (\GuzzleHttp\Exception\ServerException $e) {
139
            $message = $this->formatResponseExceptionMessage($e);
140
            throw new ServerException($message, $e->getResponse()->getStatusCode());
141
        } catch (\Exception $e) {
142
            $message = \sprintf('Failed to to perform request to service (%s).', $e->getMessage());
143
            throw new ServerException($message, $e->getCode());
144
        }
145
146
        $data = \json_decode($userRequest->getBody()->getContents(), true);
147
148
        return [
149
            'headers' => $userRequest->getHeaders(),
150
            'body' => $data
151
        ];
152
    }
153
154
    /**
155
     * @param BadResponseException $e
156
     * @return string
157
     */
158
    private function formatResponseExceptionMessage(BadResponseException $e): string
159
    {
160
        $message = \sprintf(
161
            'Service responded with error (%s - %s).',
162
            $e->getResponse()->getStatusCode(),
163
            $e->getResponse()->getReasonPhrase()
164
        );
165
        $message .= "\n" . $e->getResponse()->getBody()->getContents();
166
167
        return $message;
168
    }
169
    
170
     /**
171
     * @param array $response
172
     * @return array
173
     */
174
    public function generateHeaders(array $response): array
175
    {
176
        $headers = [];
177
        foreach ($this->headers as $header => $value) {
178
            if (isset($response[$header][0])) {
179
                $headers[$value] = $response[$header];
180
            }
181
        }
182
        return $headers;
183
    }
184
}
185