Client::denormalizeObject()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
c 1
b 0
f 0
nc 8
nop 3
dl 0
loc 19
rs 9.9666
1
<?php
2
3
/*
4
 * This file is part of the CwdPowerDNS Client
5
 *
6
 * (c) 2018 cwd.at GmbH <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cwd\PowerDNSClient;
15
16
use Doctrine\Common\Annotations\AnnotationReader;
17
use Doctrine\Common\Annotations\Reader;
18
use GuzzleHttp\Psr7\Request;
19
use Http\Discovery\HttpClientDiscovery;
20
use Symfony\Component\PropertyAccess\PropertyAccessor;
21
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
22
use Symfony\Component\Serializer\Encoder\JsonEncoder;
23
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
24
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
25
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
26
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
27
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
28
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
29
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
30
use Symfony\Component\Serializer\Serializer;
31
use GuzzleHttp\Client as GuzzleClient;
32
33
class Client
34
{
35
    private $basePath = 'api/v1';
36
    private $apiKey;
37
38
    private $apiUri;
39
40
    /** @var GuzzleClient */
41
    private $client;
42
43
    /** @var Serializer */
44
    private $serializer;
45
46
    public function __construct($apiHost, $apiKey, ?GuzzleClient $client = null, Reader $annotationReader)
47
    {
48
        $this->apiKey = $apiKey;
49
        $this->apiUri = sprintf('%s/%s', $apiHost, $this->basePath);
50
        if (null === $client) {
51
            //$this->client  = new GuzzleClient(['base_uri' => $this->apiUri]);
52
            $this->client = HttpClientDiscovery::find();
0 ignored issues
show
Documentation Bug introduced by
It seems like Http\Discovery\HttpClientDiscovery::find() of type Http\Client\HttpClient is incompatible with the declared type GuzzleHttp\Client of property $client.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
53
        }
54
55
        $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader($annotationReader));
56
        $discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
57
58
        $normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter(), new PropertyAccessor(), new ReflectionExtractor(), $discriminator);
59
        $this->serializer = new Serializer([new DateTimeNormalizer(), new ArrayDenormalizer(), $normalizer], ['json' => new JsonEncoder()]);
60
    }
61
62
    /**
63
     * @param string|null     $payload
64
     * @param int|string|null $id
65
     * @param string          $endpoint
66
     * @param string|null     $hydrationClass
67
     * @param bool            $isList
68
     * @param string          $method
69
     *
70
     * @throws \Http\Client\Exception
71
     * @throws \LogicException
72
     *
73
     * @return mixed
74
     */
75
    public function call($payload = null, $uri, $hydrationClass = null, $isList = false, $method = 'GET', array $queryParams = [], $isJson = true)
76
    {
77
        $uri = rtrim(sprintf('%s/%s', $this->apiUri, $uri), '/');
78
79
        if (count($queryParams) > 0) {
80
            $uri .= '?'.http_build_query($queryParams);
81
        }
82
83
        $request = new Request($method, $uri, [
84
            'X-API-Key' => $this->apiKey,
85
            'Content-Type' => 'application/json',
86
        ], $payload);
87
88
        $response = $this->client->sendRequest($request);
89
        $responseBody = $response->getBody()->getContents();
0 ignored issues
show
Bug introduced by
The method getBody() does not exist on GuzzleHttp\Promise\PromiseInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
        $responseBody = $response->/** @scrutinizer ignore-call */ getBody()->getContents();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
91
        if (!$isJson) {
92
            return $responseBody;
93
        }
94
95
        $responseData = json_decode($responseBody);
96
97
98
        if ($response->getStatusCode() >= 300 && isset($responseData->error)) {
0 ignored issues
show
Bug introduced by
The method getStatusCode() does not exist on GuzzleHttp\Promise\PromiseInterface. Did you maybe mean getState()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
        if ($response->/** @scrutinizer ignore-call */ getStatusCode() >= 300 && isset($responseData->error)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
            throw new \LogicException(sprintf('Error on %s request %s: %s', $method, $uri, $responseData->error));
100
        }
101
        if ($response->getStatusCode() >= 300) {
102
            $message = isset($responseData->message) ?? 'Unknown';
103
            throw new \Exception(sprintf('Error on request %s: %s', $response->getStatusCode(), $message));
104
        }
105
106
        if (null !== $hydrationClass && class_exists($hydrationClass)) {
107
            return $this->denormalizeObject($hydrationClass, $responseData, $isList);
108
        }
109
        if (null !== $hydrationClass && !class_exists($hydrationClass)) {
110
            throw new \Exception(sprintf('HydrationClass (%s) does not exist', $hydrationClass));
111
        }
112
113
        return $responseData;
114
    }
115
116
    public function denormalizeObject($hydrationClass, $dataObject, $isList = false)
117
    {
118
        if (!$isList) {
119
            $dataObject = [$dataObject];
120
        }
121
122
        $result = [];
123
124
        foreach ($dataObject as $data) {
125
            $result[] = $this->serializer->denormalize($data, $hydrationClass, null, [
126
                ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => false,
127
            ]);
128
        }
129
130
        if ($isList) {
131
            return $result;
132
        }
133
134
        return current($result);
135
    }
136
137
    /**
138
     * @return Serializer
139
     */
140
    public function getSerializer(): Serializer
141
    {
142
        return $this->serializer;
143
    }
144
}
145