Completed
Push — master ( b64fc1...5651bd )
by Raffael
16:20 queued 08:39
created

AbstractRest::decodeResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee
7
 *
8
 * @copyright   Copryright (c) 2017-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Tubee\Endpoint;
13
14
use GuzzleHttp\Client;
15
use InvalidArgumentException;
16
use Psr\Log\LoggerInterface;
17
use Tubee\AttributeMap\AttributeMapInterface;
18
use Tubee\Collection\CollectionInterface;
19
use Tubee\Endpoint\Rest\Exception as RestException;
20
use Tubee\Workflow\Factory as WorkflowFactory;
21
22
abstract class AbstractRest extends AbstractEndpoint
23
{
24
    use LoggerTrait;
25
26
    /**
27
     * Guzzle client.
28
     *
29
     * @var Client
30
     */
31
    protected $client;
32
33
    /**
34
     * Container.
35
     *
36
     * @var string
37
     */
38
    protected $container;
39
40
    /**
41
     * Access token.
42
     *
43
     * @var string
44
     */
45
    protected $access_token;
46
47
    /**
48
     * Init endpoint.
49
     */
50 9
    public function __construct(string $name, string $type, Client $client, CollectionInterface $collection, WorkflowFactory $workflow, LoggerInterface $logger, array $resource = [])
51
    {
52 9
        $this->client = $client;
53 9
        parent::__construct($name, $type, $collection, $workflow, $logger, $resource);
54 9
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 3
    public function setup(bool $simulate = false): EndpointInterface
60
    {
61 3
        if (isset($this->resource['data']['resource']['auth']) && $this->resource['data']['resource']['auth'] === 'oauth2') {
62 2
            $oauth = $this->resource['data']['resource']['oauth2'];
63
64 2
            $this->logger->debug('fetch access_token from ['.$oauth['token_endpoint'].']', [
65 2
                'category' => get_class($this),
66
            ]);
67
68 2
            $response = $this->client->post($oauth['token_endpoint'], [
69
                'form_params' => [
70 2
                    'grant_type' => 'client_credentials',
71 2
                    'client_id' => $oauth['client_id'],
72 2
                    'client_secret' => $oauth['client_secret'],
73 2
                    'scope' => $oauth['scope'],
74
                ],
75
            ]);
76
77 2
            $this->logger->debug('fetch access_token ended with status ['.$response->getStatusCode().']', [
78 2
                'category' => get_class($this),
79
            ]);
80
81 2
            $body = json_decode($response->getBody()->getContents(), true);
82
83 2
            if (isset($body['access_token'])) {
84 1
                $this->access_token = $body['access_token'];
85
            } else {
86 1
                throw new RestException\AccessTokenNotAvailable('No access_token in token_endpoint response');
87
            }
88
        }
89
90 2
        $response = $this->client->get('', $this->getRequestOptions());
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
91
92 2
        return $this;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function change(AttributeMapInterface $map, array $diff, array $object, array $endpoint_object, bool $simulate = false): ?string
99
    {
100
        $uri = $this->client->getConfig('base_uri').'/'.$this->getResourceId($object, $endpoint_object);
101
        $this->logChange($uri, $diff);
102
103
        if ($simulate === false) {
104
            $this->client->patch($uri, $this->getRequestOptions([
105
                'json' => $diff,
106
            ]));
107
        }
108
109
        return null;
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115
    public function delete(AttributeMapInterface $map, array $object, array $endpoint_object, bool $simulate = false): bool
116
    {
117
        $uri = $this->client->getConfig('base_uri').'/'.$this->getResourceId($object, $endpoint_object);
118
        $this->logDelete($uri);
119
120
        if ($simulate === false) {
121
            $response = $this->client->delete($uri, $this->getRequestOptions());
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
122
        }
123
124
        return true;
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function create(AttributeMapInterface $map, array $object, bool $simulate = false): ?string
131
    {
132
        $this->logCreate($object);
133
134
        if ($simulate === false) {
135
            $result = $this->client->post('', $this->getRequestOptions([
136
                'json' => $object,
137
            ]));
138
139
            $body = json_decode($result->getBody()->getContents(), true);
140
141
            return $this->getResourceId($body);
142
        }
143
144
        return null;
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function getDiff(AttributeMapInterface $map, array $diff): array
151
    {
152
        $result = [];
153
        foreach ($diff as $attribute => $update) {
154
            switch ($update['action']) {
155
                case AttributeMapInterface::ACTION_REPLACE:
156
                case AttributeMapInterface::ACTION_ADD:
157
                    $result[$attribute] = $update['value'];
158
159
                break;
160
                case AttributeMapInterface::ACTION_REMOVE:
161
                    $result[$attribute] = null;
162
163
                break;
164
                default:
165
                    throw new InvalidArgumentException('unknown diff action '.$update['action'].' given');
166
            }
167
        }
168
169
        return $result;
170
    }
171
172
    /**
173
     * Decode response.
174
     */
175 3
    protected function decodeResponse($response): array
176
    {
177 3
        $this->logger->debug('request to ['.$this->client->getConfig('base_uri').'] ended with code ['.$response->getStatusCode().']', [
178 3
            'category' => get_class($this),
179
        ]);
180
181 3
        return json_decode($response->getBody()->getContents(), true);
182
    }
183
184
    /**
185
     * Verify response.
186
     */
187 3
    protected function getResponse($response): array
188
    {
189 3
        $data = $this->decodeResponse($response);
190
191 3
        if (isset($this->container)) {
192 3
            if (isset($data[$this->container])) {
193 3
                $data = $data[$this->container];
194
            } else {
195
                throw new RestException\InvalidContainer('specified container '.$this->container.' does not exists in response');
196
            }
197
        }
198
199 3
        if (!is_array($data)) {
200
            throw new Exception\NotIterable('response is not iterable');
201
        }
202
203 3
        return $data;
204
    }
205
206
    /**
207
     * Get headers.
208
     */
209 5
    protected function getRequestOptions(array $options = []): array
210
    {
211 5
        if ($this->access_token) {
212 1
            return array_merge($options, [
213
                'headers' => [
214 1
                    'Accept' => 'application/json',
215 1
                    'Authorization' => "Bearer {$this->access_token}",
216
                ],
217
            ]);
218
        }
219
220 4
        return $options;
221
    }
222
223
    /**
224
     * Get identifier.
225
     */
226
    protected function getResourceId(array $object, array $endpoint_object = []): string
227
    {
228
        if (isset($object[$this->identifier])) {
229
            return $object[$this->identifier];
230
        }
231
232
        if (isset($endpoint_object[$this->identifier])) {
233
            return $endpoint_object[$this->identifier];
234
        }
235
236
        throw new RestException\IdNotFound('attribute '.$this->identifier.' is not available');
237
    }
238
}
239