Failed Conditions
Branch v3.x (aec8e0)
by Chad
01:59
created

src/Client.php (4 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Chadicus\Marvel\Api;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Zend\Diactoros\Request;
10
11
/**
12
 * PHP Client for the Marvel API.
13
 */
14
class Client implements ClientInterface
15
{
16
    /**
17
     * The public api key issued by Marvel.
18
     *
19
     * @var string
20
     */
21
    private $publicApiKey;
22
23
    /**
24
     * The private api key issued by Marvel.
25
     *
26
     * @var string
27
     */
28
    private $privateApiKey;
29
30
    /**
31
     * Guzzle HTTP Client implementation.
32
     *
33
     * @var GuzzleClientInterface
34
     */
35
    private $guzzleClient;
36
37
    /**
38
     * Cache implementation.
39
     *
40
     * @var Cache\CacheInterface
41
     */
42
    private $cache;
43
44
    /**
45
     * The Marvel API url.
46
     *
47
     * @const string
48
     */
49
    const BASE_URL = 'http://gateway.marvel.com/v1/public/';
50
51
    /**
52
     * Construct a new Client.
53
     *
54
     * @param string                $privateApiKey The private api key issued by Marvel.
55
     * @param string                $publicApiKey  The public api key issued by Marvel.
56
     * @param GuzzleClientInterface $guzzleClient  Implementation of a Guzzle HTTP client.
57
     * @param Cache\CacheInterface  $cache         Implementation of Cache.
58
     */
59
    final public function __construct(
60
        string $privateApiKey,
61
        string $publicApiKey,
62
        GuzzleClientInterface $guzzleClient = null,
63
        Cache\CacheInterface $cache = null
64
    ) {
65
        $this->privateApiKey = $privateApiKey;
66
        $this->publicApiKey = $publicApiKey;
67
        $this->guzzleClient = $guzzleClient ?: new GuzzleClient();
68
        $this->cache = $cache;
69
    }
70
71
    /**
72
     * Execute a search request against the Marvel API.
73
     *
74
     * @param string $resource The API resource to search for.
75
     * @param array  $filters  Array of search criteria to use in request.
76
     *
77
     * @return ResponseInterface
78
     *
79
     * @throws \InvalidArgumentException Thrown if $resource is empty or not a string.
80
     */
81
    final public function search(string $resource, array $filters = []) : ResponseInterface
82
    {
83
        $filters['apikey'] = $this->publicApiKey;
84
        $timestamp = time();
85
        $filters['ts'] = $timestamp;
86
        $filters['hash'] = md5($timestamp . $this->privateApiKey . $this->publicApiKey);
87
        $url = self::BASE_URL . urlencode($resource) . '?' . http_build_query($filters);
88
89
        $response = $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
90
        if ($response->getStatusCode() !== 200) {
0 ignored issues
show
The method getStatusCode() does not exist on Chadicus\Marvel\Api\DataWrapperInterface. Did you maybe mean getStatus()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
91
            return null;
92
        }
93
94
        return DataWrapper::fromJson((string)$response->getBody());
0 ignored issues
show
The method getBody() does not seem to exist on object<Chadicus\Marvel\Api\DataWrapperInterface>.

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...
95
    }
96
97
    /**
98
     * Execute a GET request against the Marvel API for a single resource.
99
     *
100
     * @param string  $resource The API resource to search for.
101
     * @param integer $id       The id of the API resource.
102
     *
103
     * @return DataWrapperInterface
104
     */
105
    final public function get(string $resource, int $id) : DataWrapperInterface
106
    {
107
        $timestamp = time();
108
        $query = [
109
            'apikey' => $this->publicApiKey,
110
            'ts' => $timestamp,
111
            'hash' => md5($timestamp . $this->privateApiKey . $this->publicApiKey),
112
        ];
113
114
        $url = self::BASE_URL . urlencode($resource) . "/{$id}?" . http_build_query($query);
115
116
        $response =  $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
117
        if ($response->getStatusCode() !== 200) {
0 ignored issues
show
The method getStatusCode() does not exist on Chadicus\Marvel\Api\DataWrapperInterface. Did you maybe mean getStatus()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
118
            return null;
119
        }
120
121
        return DataWrapper::fromJson((string)$response->getBody());
0 ignored issues
show
The method getBody() does not seem to exist on object<Chadicus\Marvel\Api\DataWrapperInterface>.

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...
122
    }
123
124
    /**
125
     * Send the given API Request.
126
     *
127
     * @param RequestInterface $request The request to send.
128
     *
129
     * @return DataWrapperInterface
130
     */
131
    final private function send(RequestInterface $request) : DataWrapperInterface
132
    {
133
        $response = $this->getFromCache($request);
134
        if ($response !== null) {
135
            return $response;
136
        }
137
138
        $response = $this->guzzleClient->send($request);
139
140
        if ($this->cache !== null) {
141
            $this->cache->set($request, $response);
142
        }
143
144
        return $response;
145
    }
146
147
    /**
148
     * Retrieve the Response for the given Request from cache.
149
     *
150
     * @param RequestInterface $request The request to send.
151
     *
152
     * @return ResponseInterface|null Returns the cached Response or null if it does not exist.
153
     */
154
    final private function getFromCache(RequestInterface $request) : ResponseInterface
155
    {
156
        if ($this->cache === null) {
157
            return null;
158
        }
159
160
        return $this->cache->get($request);
161
    }
162
163
    /**
164
     * Allow calls such as $client->characters();
165
     *
166
     * @param string $name      The name of the api resource.
167
     * @param array  $arguments The parameters to pass to get() or search().
168
     *
169
     * @return Collection|EntityInterface
170
     */
171
    final public function __call(string $name, array $arguments)
172
    {
173
        $resource = strtolower($name);
174
        $parameters = array_shift($arguments);
175
        if ($parameters === null || is_array($parameters)) {
176
            return new Collection($this, $resource, $parameters ?: []);
177
        }
178
179
        $dataWrapper = $this->get($resource, $parameters);
180
        if ($dataWrapper === null) {
181
            return null;
182
        }
183
184
        $results = $dataWrapper->getData()->getResults();
185
        if (empty($results)) {
186
            return null;
187
        }
188
189
        return $results[0];
190
    }
191
}
192