Failed Conditions
Pull Request — master (#26)
by Chad
02:04
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 DominionEnterprises\Util;
6
use GuzzleHttp\Client as GuzzleClient;
7
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Zend\Diactoros\Request;
11
12
/**
13
 * PHP Client for the Marvel API.
14
 */
15
class Client implements ClientInterface
16
{
17
    /**
18
     * The public api key issued by Marvel.
19
     *
20
     * @var string
21
     */
22
    private $publicApiKey;
23
24
    /**
25
     * The private api key issued by Marvel.
26
     *
27
     * @var string
28
     */
29
    private $privateApiKey;
30
31
    /**
32
     * Guzzle HTTP Client implementation.
33
     *
34
     * @var GuzzleClientInterface
35
     */
36
    private $guzzleClient;
37
38
    /**
39
     * Cache implementation.
40
     *
41
     * @var Cache\CacheInterface
42
     */
43
    private $cache;
44
45
    /**
46
     * The Marvel API url.
47
     *
48
     * @const string
49
     */
50
    const BASE_URL = 'http://gateway.marvel.com/v1/public/';
51
52
    /**
53
     * Construct a new Client.
54
     *
55
     * @param string               $privateApiKey The private api key issued by Marvel.
56
     * @param string               $publicApiKey  The public api key issued by Marvel.
57
     * @param ClientInterface      $guzzleClient  Implementation of a Guzzle HTTP client.
58
     * @param Cache\CacheInterface $cache         Implementation of Cache.
59
     */
60
    final public function __construct(
0 ignored issues
show
Expected type hint "ClientInterface"; found "GuzzleClientInterface" for $guzzleClient
Loading history...
61
        $privateApiKey,
62
        $publicApiKey,
63
        GuzzleClientInterface $guzzleClient = null,
64
        Cache\CacheInterface $cache = null
65
    ) {
66
        Util::throwIfNotType(['string' => [$privateApiKey, $publicApiKey]], true);
67
68
        $this->privateApiKey = $privateApiKey;
69
        $this->publicApiKey = $publicApiKey;
70
        $this->guzzleClient = $guzzleClient ?: new GuzzleClient();
71
        $this->cache = $cache;
72
    }
73
74
    /**
75
     * Execute a search request against the Marvel API.
76
     *
77
     * @param string $resource The API resource to search for.
78
     * @param array  $filters  Array of search criteria to use in request.
79
     *
80
     * @return ResponseInterface
81
     *
82
     * @throws \InvalidArgumentException Thrown if $resource is empty or not a string.
83
     */
84
    final public function search($resource, array $filters = [])
85
    {
86
        if (!is_string($resource) || trim($resource) == '') {
87
            throw new \InvalidArgumentException('$resource must be a non-empty string');
88
        }
89
90
        $filters['apikey'] = $this->publicApiKey;
91
        $timestamp = time();
92
        $filters['ts'] = $timestamp;
93
        $filters['hash'] = md5($timestamp . $this->privateApiKey . $this->publicApiKey);
94
        $url = self::BASE_URL . urlencode($resource) . '?' . http_build_query($filters);
95
96
        return $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
97
    }
98
99
    /**
100
     * Execute a GET request against the Marvel API for a single resource.
101
     *
102
     * @param string  $resource The API resource to search for.
103
     * @param integer $id       The id of the API resource.
104
     *
105
     * @return ResponseInterface
106
     */
107
    final public function get($resource, $id)
108
    {
109
        Util::throwIfNotType(['string' => [$resource], 'int' => [$id]], true);
110
111
        $timestamp = time();
112
        $query = [
113
            'apikey' => $this->publicApiKey,
114
            'ts' => $timestamp,
115
            'hash' => md5($timestamp . $this->privateApiKey . $this->publicApiKey),
116
        ];
117
118
        $url = self::BASE_URL . urlencode($resource) . "/{$id}?" . http_build_query($query);
119
120
        return $this->send(new Request($url, 'GET', 'php://temp', ['Accept' =>  'application/json']));
121
    }
122
123
    /**
124
     * Send the given API Request.
125
     *
126
     * @param RequestInterface $request The request to send.
127
     *
128
     * @return ResponseInterface
129
     */
130
    final private function send(RequestInterface $request)
131
    {
132
        $response = $this->getFromCache($request);
133
        if ($response !== null) {
134
            return $response;
135
        }
136
137
        $response = $this->guzzleClient->send($request);
138
139
        if ($this->cache !== null) {
140
            $this->cache->set($request, $response);
141
        }
142
143
        return $response;
144
    }
145
146
    /**
147
     * Retrieve the Response for the given Request from cache.
148
     *
149
     * @param RequestInterface $request The request to send.
150
     *
151
     * @return ResponseInterface|null Returns the cached Response or null if it does not exist.
152
     */
153
    final private function getFromCache(RequestInterface $request)
154
    {
155
        if ($this->cache === null) {
156
            return null;
157
        }
158
159
        return $this->cache->get($request);
160
    }
161
162
    /**
163
     * Allow calls such as $client->characters();
164
     *
165
     * @param string $name      The name of the api resource.
166
     * @param array  $arguments The parameters to pass to get() or search().
167
     *
168
     * @return Collection|EntityInterface
169
     */
170
    final public function __call($name, array $arguments)
171
    {
172
        $resource = strtolower($name);
173
        $parameters = array_shift($arguments);
174
        if ($parameters === null || is_array($parameters)) {
175
            return new Collection($this, $resource, $parameters ?: []);
176
        }
177
178
        $response = $this->get($resource, $parameters);
179
        if ($response->getStatusCode() !== 200) {
180
            return null;
181
        }
182
183
        $json = (string)$response->getBody();
184
        $dataWrapper = new DataWrapper(json_decode($json, true));
185
        $results = $dataWrapper->getData()->getResults();
186
        if (empty($results)) {
187
            return null;
188
        }
189
190
        return $results[0];
191
    }
192
}
193