Completed
Push — master ( 3a6032...111f4c )
by Andrea Marco
21:34 queued 11:35
created

AbstractApi::toJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Cerbero\FluentApi;
4
5
use BadMethodCallException;
6
use Cerbero\FluentApi\Clients\AsyncClientInterface;
7
use Cerbero\FluentApi\Clients\ClientInterface;
8
use Cerbero\FluentApi\Clients\GuzzleAdapter;
9
use Cerbero\FluentApi\Inflectors\Psr4ResourceInflector;
10
use Cerbero\FluentApi\Inflectors\ResourceInflectorInterface;
11
use Cerbero\FluentApi\Requests\Request;
12
use Closure;
13
use Exception;
14
use GuzzleHttp\Client;
15
16
/**
17
 * Abstract implementation of an API start point.
18
 *
19
 * @author    Andrea Marco Sartori
20
 */
21
abstract class AbstractApi extends VersionableRequestMaker
22
{
23
    /**
24
     * The HTTP client.
25
     *
26
     * @author  Andrea Marco Sartori
27
     * @var     Cerbero\FluentApi\Clients\ClientInterface
28
     */
29
    protected $client;
30
31
    /**
32
     * The resource inflector.
33
     *
34
     * @author  Andrea Marco Sartori
35
     * @var     Cerbero\FluentApi\Inflectors\ResourceInflectorInterface
36
     */
37
    protected $inflector;
38
39
    /**
40
     * The latest resource invoked.
41
     *
42
     * @var Cerbero\FluentApi\AbstractResource|null
43
     */
44
    protected $resource;
45
46
    /**
47
     * Set the dependencies.
48
     *
49
     * @author    Andrea Marco Sartori
50
     * @param    string|null    $version
51
     * @param    Cerbero\FluentApi\Clients\ClientInterface|null    $client
52
     * @param    Cerbero\FluentApi\Inflectors\ResourceInflectorInterface|null    $inflector
53
     * @return    void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
54
     */
55
    public function __construct(
56
        $version = null,
57
        ClientInterface $client = null,
58
        ResourceInflectorInterface $inflector = null
59
    ) {
60
        $client    = $client    ?: $this->defaultClient();
61
        $inflector = $inflector ?: $this->defaultInflector();
62
63
        $this->setVersion($version)->setClient($client)->setInflector($inflector);
64
    }
65
66
    /**
67
     * Dynamically resolve resources.
68
     *
69
     * @author    Andrea Marco Sartori
70
     * @param    string    $name
71
     * @param    array    $parameters
72
     * @return    $this
73
     */
74
    public function __call($name, array $parameters)
75
    {
76
        $class = $this->inflectResource($name);
77
78
        $this->resource = new $class(...$parameters);
79
80
        $this->request = $this->resource->fillRequest($this->getRequest());
81
82
        return $this;
83
    }
84
85
    /**
86
     * Retrieve the base URL.
87
     *
88
     * @author    Andrea Marco Sartori
89
     * @return    string
90
     */
91
    abstract public function getUrl();
92
93
    /**
94
     * Retrieve the resource to call by inflecting the given name.
95
     *
96
     * @author    Andrea Marco Sartori
97
     * @param    string    $name
98
     * @return    Cerbero\FluentApi\Resources\ResourceInterface
99
     */
100
    protected function inflectResource($name)
101
    {
102
        $target = $this->resource ?: $this;
103
104
        $resource = $this->getInflector()->baseNamespace(get_class($target))
105
                                         ->version($target->getVersion())
106
                                         ->inflect($name);
107
108
        if (class_exists($resource)) {
109
            return $resource;
110
        }
111
112
        throw new BadMethodCallException("The resource [$resource] does not exist.");
113
    }
114
115
    /**
116
     * Retrieve the resource inflector.
117
     *
118
     * @return    Cerbero\FluentApi\Inflectors\ResourceInflectorInterface
119
     */
120
    public function getInflector()
121
    {
122
        return $this->inflector ?: $this->defaultInflector();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->inflector ?: $this->defaultInflector(); of type Cerbero\FluentApi\Cerber...s\Psr4ResourceInflector adds the type Cerbero\FluentApi\Inflectors\Psr4ResourceInflector to the return on line 122 which is incompatible with the return type documented by Cerbero\FluentApi\AbstractApi::getInflector of type Cerbero\FluentApi\Cerber...ourceInflectorInterface.
Loading history...
123
    }
124
125
    /**
126
     * Retrieve the default inflector.
127
     *
128
     * @author    Andrea Marco Sartori
129
     * @return    Cerbero\FluentApi\Inflectors\ResourceInflectorInterface
130
     */
131
    protected function defaultInflector()
132
    {
133
        return new Psr4ResourceInflector;
134
    }
135
136
    /**
137
     * Set the resource inflector.
138
     *
139
     * @author    Andrea Marco Sartori
140
     * @param    Cerbero\FluentApi\Inflectors\ResourceInflectorInterface    $inflector
141
     * @return    $this
142
     */
143
    public function setInflector(ResourceInflectorInterface $inflector)
144
    {
145
        $this->inflector = $inflector;
0 ignored issues
show
Documentation Bug introduced by
It seems like $inflector of type object<Cerbero\FluentApi...urceInflectorInterface> is incompatible with the declared type object<Cerbero\FluentApi...urceInflectorInterface> of property $inflector.

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...
146
147
        return $this;
148
    }
149
150
    /**
151
     * Perform a synchronous call to the eventual endpoint.
152
     *
153
     * @return    Psr\Http\Message\ResponseInterface
154
     */
155
    public function call()
156
    {
157
        return $this->performCall();
158
    }
159
160
    /**
161
     * Perform an HTTP call by using the client.
162
     *
163
     * @param    Closure|null    $success
164
     * @param    Closure|null    $failure
165
     * @return    mixed
166
     */
167
    private function performCall(Closure $success = null, Closure $failure = null)
168
    {
169
        $parameters = [
170
            $this->request->verb(), $this->request->endpoint(), $this->request->options(),
171
        ];
172
173
        if ($success) {
174
            array_push($parameters, $success, $failure);
175
        }
176
177
        return call_user_func_array(
178
            [$this->getClient(), $success ? 'then' : 'call'], $parameters
179
        );
180
    }
181
182
    /**
183
     * Perform an asynchronous call to the eventual endpoint.
184
     *
185
     * @param    Closure    $success
186
     * @param    Closure|null    $failure
187
     * @return    mixed
188
     */
189
    public function then(Closure $success, Closure $failure = null)
190
    {
191
        if (! $this->getClient() instanceof AsyncClientInterface) {
192
            throw new Exception("The set client can't perform asynchronous calls.");
193
        }
194
195
        return $this->performCall($success, $failure);
196
    }
197
198
    /**
199
     * Retrieve the body of the response as a JSON object.
200
     *
201
     * @return    \StdClass
202
     */
203
    public function toJson()
204
    {
205
        return $this->decodeBody();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->decodeBody(); of type stdClass|array adds the type array to the return on line 205 which is incompatible with the return type documented by Cerbero\FluentApi\AbstractApi::toJson of type stdClass.
Loading history...
206
    }
207
208
    /**
209
     * Retrieve the decoded response body.
210
     *
211
     * @param    boolean    $toArray
212
     * @return    \StdClass|array
213
     */
214
    private function decodeBody($toArray = false)
215
    {
216
        $body = $this->call()->getBody()->getContents();
217
218
        return json_decode($body, $toArray);
219
    }
220
221
    /**
222
     * Retrieve the body of the response as an array.
223
     *
224
     * @return    array
225
     */
226
    public function toArray()
227
    {
228
        return $this->decodeBody(true);
229
    }
230
231
    /**
232
     * Retrieve the request to pass through resources.
233
     *
234
     * @return    Cerbero\FluentApi\Requests\Request
235
     */
236
    public function getRequest()
237
    {
238
        return $this->request ?: new Request($this->getUrl());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request ?: new \C...quest($this->getUrl()); of type Cerbero\FluentApi\Cerber...entApi\Requests\Request adds the type Cerbero\FluentApi\Requests\Request to the return on line 238 which is incompatible with the return type declared by the abstract method Cerbero\FluentApi\Versio...equestMaker::getRequest of type Cerbero\FluentApi\Cerber...entApi\Requests\Request.
Loading history...
239
    }
240
241
    /**
242
     * Set the HTTP client.
243
     *
244
     * @author    Andrea Marco Sartori
245
     * @param    Cerbero\FluentApi\Clients\ClientInterface    $client
246
     * @return    $this
247
     */
248
    public function setClient(ClientInterface $client)
249
    {
250
        $this->client = $client;
0 ignored issues
show
Documentation Bug introduced by
It seems like $client of type object<Cerbero\FluentApi\Clients\ClientInterface> is incompatible with the declared type object<Cerbero\FluentApi...lients\ClientInterface> 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...
251
252
        return $this;
253
    }
254
255
    /**
256
     * Retrieve the HTTP client.
257
     *
258
     * @author    Andrea Marco Sartori
259
     * @return    Cerbero\FluentApi\Clients\ClientInterface
260
     */
261
    public function getClient()
262
    {
263
        return $this->client;
264
    }
265
266
    /**
267
     * Retrieve the default HTTP client to use if none is provided.
268
     *
269
     * @author    Andrea Marco Sartori
270
     * @return    Cerbero\FluentApi\Clients\ClientInterface
271
     */
272
    protected function defaultClient()
273
    {
274
        return new GuzzleAdapter(new Client);
275
    }
276
}
277