1: <?php
2:
3: namespace billythekid;
4:
5: use GuzzleHttp\Client;
6:
7: /**
8: * Class PunkApi
9: * Wrapper class for querying the PunkAPI https://punkapi.com
10: * Docs: https://punkapi.com/documentation
11: *
12: * @package billythekid
13: */
14: class PunkApi
15: {
16: /**
17: * @var string
18: */
19: private $apiKey;
20: /**
21: * @var string
22: */
23: private $apiRoot = 'https://punkapi.com/api/v1/beers';
24: /**
25: * @var array
26: */
27: private $params = [];
28: /**
29: * @var array
30: */
31: private $allowedParams = [
32: 'abv_gt', //number Returns all beers with ABV greater than the supplied number
33: 'abv_lt', //number Returns all beers with ABV less than the supplied number
34: 'ibu_gt', //number Returns all beers with IBU greater than the supplied number
35: 'ibu_lt', //number Returns all beers with IBU less than the supplied number
36: 'ebc_gt', //number Returns all beers with EBC greater than the supplied number
37: 'ebc_lt', //number Returns all beers with EBC less than the supplied number
38: 'beer_name', //string Returns all beers matching the supplied name (this will match partial strings as well so e.g punk will return Punk IPA)
39: 'yeast', //string Returns all beers matching the supplied yeast name, this also matches partial strings
40: 'brewed_before', //date Returns all beers brewed before this date, the date format is mm-yyyy e.g 10-2011
41: 'brewed_after', //date Returns all beers brewed after this date, the date format is mm-yyyy e.g 10-2011
42: 'hops', //string Returns all beers matching the supplied hops name, this also matches partial strings
43: 'malt', //string Returns all beers matching the supplied malt name, this also matches partial strings
44: 'food', //string Returns all beers matching the supplied food string, this also matches partial strings
45: 'page', //number Return the beers from the page given (responses are paginated)
46: 'per_page', //number Change the number of beers returned per page (default - 25)
47: 'ids', //string A list of ID numbers, separated by a pipe | (PunkAPI v2)
48: ];
49:
50: /**
51: * PunkApi constructor.
52: *
53: * @param $apiKey
54: */
55: public function __construct($apiKey = 'v2')
56: {
57: if($apiKey === 'v2')
58: {
59: $this->apiRoot = 'https://api.punkapi.com/v2/beers';
60: }
61: $this->apiKey = $apiKey;
62: $this->client = new Client;
63: }
64:
65: /**
66: * Static constructor, not really needed since PHP 5.4 but it's nice to have, right?
67: *
68: * @param $apiKey
69: * @return PunkApi
70: */
71: public static function create($apiKey)
72: {
73: return new self($apiKey);
74: }
75:
76: /**
77: * Returns the URL that would be hit at the current state of this object.
78: *
79: * @return string
80: */
81: public function getEndpoint()
82: {
83: return rtrim($this->apiRoot . '?' . http_build_query($this->params), '?');
84: }
85:
86: /**
87: * Queries the PunkAPI with the current parameters of this object.
88: *
89: * @return array of beer \StdClass objects
90: * @throws \InvalidArgumentException (via GuzzleHttp\json_decode()
91: */
92: public function getBeers()
93: {
94: $response = $this->client->get($this->getEndpoint(),
95: [
96: 'auth' => [$this->apiKey, $this->apiKey],
97: ]
98: );
99:
100: return \GuzzleHttp\json_decode($response->getBody());
101: }
102:
103: /**
104: * Empties the parameters of this object.
105: *
106: * @return $this
107: */
108: public function clearParams()
109: {
110: $this->params = [];
111:
112: return $this;
113: }
114:
115: /**
116: * Adds parameter options to this object.
117: *
118: * @param array $params
119: * @return $this
120: */
121: public function addParams(Array $params)
122: {
123: $this->params = array_merge($this->params, $this->cleanParams($params));
124:
125: return $this;
126: }
127:
128: /**
129: * Removes given parameters from this object.
130: *
131: * @param array ...$badParams
132: * @return $this
133: */
134: public function removeParams(...$badParams)
135: {
136: $this->params = array_filter($this->params,
137: function ($paramName) use ($badParams)
138: {
139: return (!in_array($paramName, $badParams));
140: },
141: ARRAY_FILTER_USE_KEY
142: );
143:
144: return $this;
145: }
146:
147: /**
148: * Get a random beer from the API
149: *
150: * @return \StdClass beer object
151: */
152: public function getRandomBeer()
153: {
154: $response = $this->client->get($this->apiRoot . '/random',
155: [
156: 'auth' => [$this->apiKey, $this->apiKey],
157: ]
158: );
159:
160: return \GuzzleHttp\json_decode($response->getBody());
161: }
162:
163: /**
164: * Get a beer from the API by it's ID number
165: *
166: * @return \StdClass beer object
167: */
168: public function getBeerById($beerId)
169: {
170: $response = $this->client->get($this->apiRoot . '/' . $beerId,
171: [
172: 'auth' => [$this->apiKey, $this->apiKey],
173: ]
174: );
175:
176: return \GuzzleHttp\json_decode($response->getBody());
177: }
178:
179: /**
180: * Set the parameters to return the given page of results
181: *
182: * @param $pageNumber
183: * @return $this
184: */
185: public function page($pageNumber)
186: {
187: $this->addParams(['page' => $pageNumber]);
188:
189: return $this;
190: }
191:
192: /**
193: * Set the number of beers to return per page
194: *
195: * @param $number
196: * @return $this
197: */
198: public function perPage($number)
199: {
200: $this->addParams(['per_page', $number]);
201:
202: return $this;
203: }
204:
205: /**
206: * Sets the abv_gt parameter to the given number.
207: *
208: * @param $number
209: * @return $this
210: */
211: public function abvAbove($number)
212: {
213: $this->addParams(['abv_gt' => $number]);
214:
215: return $this;
216: }
217:
218: /**
219: * Sets the abv_lt parameter to the given number.
220: *
221: * @param $number
222: * @return $this
223: */
224: public function abvBelow($number)
225: {
226: $this->addParams(['abv_lt' => $number]);
227:
228: return $this;
229: }
230:
231: /**
232: * Sets the ibu_gt parameter to the given number.
233: *
234: * @param $number
235: * @return $this
236: */
237: public function ibuAbove($number)
238: {
239: $this->addParams(['ibu_gt' => $number]);
240:
241: return $this;
242: }
243:
244: /**
245: * Sets the ibu_lt parameter to the given number.
246: *
247: * @param $number
248: * @return $this
249: */
250: public function ibuBelow($number)
251: {
252: $this->addParams(['ibu_lt' => $number]);
253:
254: return $this;
255: }
256:
257: /**
258: * Sets the ebc_gt parameter to the given number.
259: *
260: * @param $number
261: * @return $this
262: */
263: public function ebcAbove($number)
264: {
265: $this->addParams(['ebc_gt' => $number]);
266:
267: return $this;
268: }
269:
270: /**
271: * Sets the ebc_lt parameter to the given number.
272: *
273: * @param $number
274: * @return $this
275: */
276: public function ebcBelow($number)
277: {
278: $this->addParams(['ebc_lt' => $number]);
279:
280: return $this;
281: }
282:
283: /**
284: * Sets the beer_name parameter to the given beer name.
285: *
286: * @param $beerName
287: * @return $this
288: */
289: public function named($beerName)
290: {
291: $this->addParams(['beer_name' => $beerName]);
292:
293: return $this;
294: }
295:
296: /**
297: * Sets the yeast parameter to the given yeast name
298: *
299: * @param $yeastName
300: * @return $this
301: */
302: public function yeast($yeastName)
303: {
304: $this->addParams(['yeast' => $yeastName]);
305:
306: return $this;
307: }
308:
309: /**
310: * Sets the hops parameter to the given hops name
311: *
312: * @param $hopsName
313: * @return $this
314: */
315: public function hops($hopsName)
316: {
317: $this->addParams(['hops' => $hopsName]);
318:
319: return $this;
320: }
321:
322: /**
323: * Sets the malt parameter to the given malt name
324: *
325: * @param $maltName
326: * @return $this
327: */
328: public function malt($maltName)
329: {
330: $this->addParams(['malt' => $maltName]);
331:
332: return $this;
333: }
334:
335: /**
336: * Sets the brewed_before parameter to the given date
337: *
338: * @param $date
339: * @return $this
340: */
341: public function brewedBefore($date)
342: {
343: $this->addParams(['brewed_before' => $date]);
344:
345: return $this;
346: }
347:
348: /**
349: * Sets the brewed_after parameter to the given date
350: * @param $date
351: * @return $this
352: */
353: public function brewedAfter($date)
354: {
355: $this->addParams(['brewed_after' => $date]);
356:
357: return $this;
358: }
359:
360: /**
361: * Sets the food parameter to the given food name
362: *
363: * @param $foodName
364: * @return $this
365: */
366: public function food($foodName)
367: {
368: $this->addParams(['food' => $foodName]);
369:
370: return $this;
371: }
372:
373: /**
374: * Sets the ids paramater to the given ids
375: * @param mixed $ids (array of ID numbers or piped string)
376: * @return $this
377: */
378: public function ids($ids)
379: {
380: if (is_array($ids))
381: {
382: $ids = join("|",$ids);
383: }
384:
385: $this->addParams(['ids' => $ids]);
386:
387: return $this;
388: }
389:
390: /**
391: * Helper method, parameter validation-ish.
392: *
393: * @param $params
394: * @return array
395: */
396: private function cleanParams($params)
397: {
398:
399: return array_filter(
400: $params,
401: function ($key)
402: {
403: return in_array($key, $this->allowedParams);
404: },
405: ARRAY_FILTER_USE_KEY
406: );
407: }
408:
409: }
410: