Failed Conditions
Push — v3.x ( 1f61fa...b0fa1f )
by Chad
02:14
created

src/Client.php (1 issue)

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;
6
use Psr\SimpleCache\CacheInterface;
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 default ttl for cached responses (24 hours).
18
     *
19
     * @link http://developer.marvel.com/documentation/attribution Marvel's rules for caching.
20
     *
21
     * @const integer
22
     */
23
    const MAX_TTL = 86400;
24
25
    /**
26
     * The public api key issued by Marvel.
27
     *
28
     * @var string
29
     */
30
    private $publicApiKey;
31
32
    /**
33
     * The private api key issued by Marvel.
34
     *
35
     * @var string
36
     */
37
    private $privateApiKey;
38
39
    /**
40
     * Guzzle HTTP Client implementation.
41
     *
42
     * @var GuzzleClientInterface
43
     */
44
    private $guzzleClient;
45
46
    /**
47
     * Cache implementation.
48
     *
49
     * @var CacheInterface
50
     */
51
    private $cache;
52
53
    /**
54
     * The Marvel API url.
55
     *
56
     * @const string
57
     */
58
    const BASE_URL = 'http://gateway.marvel.com/v1/public/';
59
60
    /**
61
     * Construct a new Client.
62
     *
63
     * @param string                     $privateApiKey The private api key issued by Marvel.
64
     * @param string                     $publicApiKey  The public api key issued by Marvel.
65
     * @param GuzzleHttp\ClientInterface $guzzleClient  Implementation of a Guzzle HTTP client.
66
     * @param CacheInterface             $cache         Implementation of Cache.
67
     */
68
    final public function __construct(
69
        string $privateApiKey,
70
        string $publicApiKey,
71
        GuzzleHttp\ClientInterface $guzzleClient = null,
72
        CacheInterface $cache = null
73
    ) {
74
        $this->privateApiKey = $privateApiKey;
75
        $this->publicApiKey = $publicApiKey;
76
        $this->guzzleClient = $guzzleClient ?: new GuzzleHttp\Client();
0 ignored issues
show
Documentation Bug introduced by
It seems like $guzzleClient ?: new \GuzzleHttp\Client() of type object<GuzzleHttp\ClientInterface> is incompatible with the declared type object<Chadicus\Marvel\Api\GuzzleClientInterface> of property $guzzleClient.

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...
77
        $this->cache = $cache ?: new Cache\NullCache();
78
    }
79
80
    /**
81
     * Execute a search request against the Marvel API.
82
     *
83
     * @param string $resource The API resource to search for.
84
     * @param array  $filters  Array of search criteria to use in request.
85
     *
86
     * @return DataWrapperInterface|null
87
     *
88
     * @throws \InvalidArgumentException Thrown if $resource is empty or not a string.
89
     */
90
    final public function search(string $resource, array $filters = [])
91
    {
92
        $filters['apikey'] = $this->publicApiKey;
93
        $timestamp = time();
94
        $filters['ts'] = $timestamp;
95
        $filters['hash'] = md5($timestamp . $this->privateApiKey . $this->publicApiKey);
96
        $url = self::BASE_URL . urlencode($resource) . '?' . http_build_query($filters);
97
98
        $response = $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
99
        if ($response->getStatusCode() !== 200) {
100
            return null;
101
        }
102
103
        return DataWrapper::fromJson((string)$response->getBody());
104
    }
105
106
    /**
107
     * Execute a GET request against the Marvel API for a single resource.
108
     *
109
     * @param string  $resource The API resource to search for.
110
     * @param integer $id       The id of the API resource.
111
     *
112
     * @return DataWrapperInterface|null
113
     */
114
    final public function get(string $resource, int $id)
115
    {
116
        $timestamp = time();
117
        $query = [
118
            'apikey' => $this->publicApiKey,
119
            'ts' => $timestamp,
120
            'hash' => md5($timestamp . $this->privateApiKey . $this->publicApiKey),
121
        ];
122
123
        $url = self::BASE_URL . urlencode($resource) . "/{$id}?" . http_build_query($query);
124
125
        $response =  $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
126
        if ($response->getStatusCode() !== 200) {
127
            return null;
128
        }
129
130
        return DataWrapper::fromJson((string)$response->getBody());
131
    }
132
133
    /**
134
     * Send the given API Request.
135
     *
136
     * @param RequestInterface $request The request to send.
137
     *
138
     * @return ResponseInterface
139
     */
140
    final private function send(RequestInterface $request) : ResponseInterface
141
    {
142
        $key = (string)$request->getUri();
143
        $response = $this->cache->get($key);
144
        if ($response !== null) {
145
            return $response;
146
        }
147
148
        $response = $this->guzzleClient->send($request);
149
        $this->cache->set($key, $response, self::MAX_TTL);
150
        return $response;
151
    }
152
153
    /**
154
     * Allow calls such as $client->characters();
155
     *
156
     * @param string $name      The name of the api resource.
157
     * @param array  $arguments The parameters to pass to get() or search().
158
     *
159
     * @return Collection|EntityInterface
160
     */
161
    final public function __call(string $name, array $arguments)
162
    {
163
        $resource = strtolower($name);
164
        $parameters = array_shift($arguments);
165
        if ($parameters === null || is_array($parameters)) {
166
            return new Collection($this, $resource, $parameters ?: []);
167
        }
168
169
        $dataWrapper = $this->get($resource, $parameters);
170
        if ($dataWrapper === null) {
171
            return null;
172
        }
173
174
        $results = $dataWrapper->getData()->getResults();
175
        if (empty($results)) {
176
            return null;
177
        }
178
179
        return $results[0];
180
    }
181
}
182