Issues (49)

src/Webservice/WebserviceClient.php (2 issues)

1
<?php
2
3
namespace Vox\Webservice;
4
5
use GuzzleHttp\ClientInterface;
6
use GuzzleHttp\Psr7\Request;
7
use GuzzleHttp\Psr7\Response;
8
use function GuzzleHttp\Psr7\stream_for;
9
use Metadata\MetadataFactoryInterface;
10
use RuntimeException;
11
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
12
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
13
use Vox\Webservice\Exception\WebserviceResponseException;
14
use Vox\Webservice\Mapping\Resource;
15
use Vox\Webservice\Metadata\TransferMetadata;
16
17
/**
18
 * the webservice client does the actual work of consuming and publishing data to the external webservices
19
 *
20
 * @author Jhonatan Teixeira <[email protected]>
21
 */
22
class WebserviceClient implements WebserviceClientInterface
23
{
24
    /**
25
     * @var ClientRegistryInterface
26
     */
27
    private $clientRegistry;
28
29
    /**
30
     * @var MetadataFactoryInterface
31
     */
32
    private $metadataFactory;
33
34
    /**
35
     * @var DenormalizerInterface
36
     */
37
    private $denormalizer;
38
39
    /**
40
     * @var NormalizerInterface
41
     */
42
    private $normalizer;
43
44 36
    public function __construct(
45
        ClientRegistryInterface $clientRegistry,
46
        MetadataFactoryInterface $metadataFactory,
47
        DenormalizerInterface $denormalizer,
48
        NormalizerInterface $normalizer
49
    ) {
50 36
        $this->clientRegistry  = $clientRegistry;
51 36
        $this->metadataFactory = $metadataFactory;
52 36
        $this->denormalizer    = $denormalizer;
53 36
        $this->normalizer      = $normalizer;
54 36
    }
55
56 10
    public function cGet(string $transferName, array $filters = []): TransferCollection
57
    {
58 10
        $resource = $this->getResource($transferName);
59 10
        $client   = $this->getClient($transferName);
60 10
        $options  = ['headers' => ['Content-Type' => 'application/json']];
61
62 10
        if (!empty($filters)) {
63 6
            $options['query'] = $filters;
64
        }
65
66 10
        $response = $client->request('GET', $resource->route, $options);
67
68 10
        if ($response->getStatusCode() >= 300) {
69 3
            throw new WebserviceResponseException($response, new Request('GET', $resource->route, $options));
70
        }
71
72 7
        return new TransferCollection($transferName, $this->denormalizer, $response);
73
    }
74
75 2
    public function delete(string $transferName, $id)
76
    {
77 2
        $resource = $this->getResource($transferName);
78 2
        $client   = $this->getClient($transferName);
79 2
        $route    = sprintf('%s/%s', $resource->route, $id);
80 2
        $response = $client->request('DELETE', $route);
81
82 2
        if ($response->getStatusCode() >= 300) {
83
            throw new WebserviceResponseException($response, new Request('DELETE', $route));
84
        }
85 2
    }
86
87 16
    public function get(string $transferName, $id)
88
    {
89 16
        $resource = $this->getResource($transferName);
90 16
        $client   = $this->getClient($transferName);
91 16
        $route    = sprintf('%s/%s', $resource->route, $id);
92 16
        $response = $client->request('GET', $route, ['headers' => ['Content-Type' => 'application/json']]);
93
94 16
        if ($response->getStatusCode() >= 300) {
95
            throw new WebserviceResponseException($response, new Request('GET', $route));
96
        }
97
98 16
        $contents = $response->getBody()->getContents();
99
        
100 16
        if ($contents) {
101 16
            return $this->denormalizer->denormalize(json_decode($contents, true), $transferName);
102
        }
103
    }
104
105 9
    public function post($transfer)
106
    {
107 9
        $data = $this->normalizer->normalize($transfer, 'json');
108
109 9
        $resource = $this->getResource(get_class($transfer));
110 9
        $client   = $this->getClient(get_class($transfer));
111 9
        $response = $client->request('POST', $resource->route, ['json' => $data]);
112
113 9
        if ($response->getStatusCode() >= 300) {
114 2
            throw new WebserviceResponseException($response, new Request('POST', $resource->route, ['json' => $data]));
115
        }
116
117 8
        $contents = $response->getBody()->getContents();
118 8
        $this->denormalizer->denormalize(json_decode($contents, true), $transfer);
119 8
    }
120
121 4
    public function put($transfer)
122
    {
123 4
        $data     = $this->normalizer->normalize($transfer, 'json');
124 4
        $metadata = $this->getMetadata(get_class($transfer));
125 4
        $resource = $this->getResource(get_class($transfer));
126 4
        $client   = $this->getClient(get_class($transfer));
127
128 4
        if (empty($metadata->id)) {
129
            throw new RuntimeException('no id mapped for class ' . get_class($transfer));
130
        }
131
132 4
        $route    = sprintf('%s/%s', $resource->route, $metadata->id->getValue($transfer));
133 4
        $response = $client->request('PUT', $route, ['json' => $data]);
134
135 4
        if ($response->getStatusCode() >= 300) {
136
            throw new WebserviceResponseException($response, new Request('PUT', $route, ['json' => $data]));
137
        }
138
139 4
        $this->denormalizer->denormalize(json_decode($response->getBody()->getContents(), true), $transfer);
140 4
    }
141
142 4
    public function getByCriteria(CriteriaInterface $criteria, string $transferName)
143
    {
144 4
        $client   = $this->getClient($transferName);
145
146 4
        $request = $criteria->createRequest($this->getMetadata($transferName));
147
148 4
        $response = $client->send($request);
149
150 4
        if ($response->getStatusCode() >= 300) {
151 2
            throw new WebserviceResponseException($response, $request);
152
        }
153
154 2
        if ($criteria->getOperationType() == CriteriaInterface::OPERATION_TYPE_ITEM) {
155 1
            $contents = $response->getBody()->getContents();
156 1
            return $this->denormalizer->denormalize(json_decode($contents, true), $transferName);
157
        }
158
159 1
        if ($criteria->getOperationType() == CriteriaInterface::OPERATION_TYPE_COLLECTION) {
160 1
            return new TransferCollection($transferName, $this->denormalizer, $response);
161
        }
162
    }
163
164 31
    private function getClient(string $transferName, Resource $resource = null): ClientInterface
165
    {
166 31
        if (null === $resource) {
167 31
            $resource = $this->getResource($transferName);
168
        }
169
170 31
        return  $this->clientRegistry->get($resource->client);
171
    }
172
173 31
    private function getResource(string $transferName): Resource
174
    {
175 31
        return $this->getMetadata($transferName)->getAnnotation(Resource::class, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getMetadat...\Resource::class, true) could return the type null which is incompatible with the type-hinted return Vox\Webservice\Mapping\Resource. Consider adding an additional type-check to rule them out.
Loading history...
176
    }
177
178 31
    private function getMetadata(string $transferName): TransferMetadata
179
    {
180 31
        return $this->metadataFactory->getMetadataForClass($transferName);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->metadataFa...ForClass($transferName) returns the type null|Metadata\ClassHierarchyMetadata which is incompatible with the type-hinted return Vox\Webservice\Metadata\TransferMetadata.
Loading history...
181
    }
182
}
183