Overview

Namespaces

  • ApiAxle
    • Api
    • Shared
  • ApiAxleTest
    • Api
    • Shared
  • PHP

Classes

  • Api
  • Key
  • Keyring
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: /**
  3:  * ApiAxle (https://github.com/fillup/apiaxle-module/)
  4:  *
  5:  * @link      https://github.com/fillup/apiaxle-module for the canonical source repository
  6:  * @license   MIT
  7:  */
  8: namespace ApiAxle\Api;
  9: 
 10: use ApiAxle\Shared\Config;
 11: use ApiAxle\Shared\ItemList;
 12: use ApiAxle\Shared\Utilities;
 13: use ApiAxle\Api\Key;
 14: 
 15: /**
 16:  * ApiAxle\Api\Api class
 17:  * 
 18:  * Wraps API related calls to the ApiAxle API
 19:  * 
 20:  * @author Phillip Shipley <phillip@phillipshipley.com>
 21:  */
 22: class Api
 23: {
 24:     /**
 25:      * Configuration data
 26:      * 
 27:      * @var ApiAxle\Shared\Config
 28:      */
 29:     protected $config;
 30:     
 31:     /**
 32:      * API Name
 33:      * 
 34:      * @var string
 35:      */
 36:     protected $name;
 37:     
 38:     /**
 39:      * Optional
 40:      * 
 41:      * @var timestamp 
 42:      */
 43:     protected $createdAt;
 44:     
 45:     /**
 46:      * Optional
 47:      * 
 48:      * @var timestamp 
 49:      */
 50:     protected $updatedAt;
 51:     
 52:     /**
 53:      * (default: 0) The time in seconds that every call under this API should be cached.
 54:      * 
 55:      * @var integer 
 56:      */
 57:     protected $globalCache = 0;
 58:     
 59:     /**
 60:      * The endpoint for the API. For example; `graph.facebook.com`
 61:      * 
 62:      * @var string 
 63:      */
 64:     protected $endPoint;
 65:     
 66:     /**
 67:      * (default: http) The protocol for the API, whether or not to use SSL
 68:      * 
 69:      * @var string 
 70:      */
 71:     protected $protocol = 'http';
 72:     
 73:     /**
 74:      * (default: json) The resulting data type of the endpoint. This is 
 75:      * redundant at the moment but will eventually support both XML too.
 76:      * 
 77:      * @var string 
 78:      */
 79:     protected $apiFormat = 'json';
 80:     
 81:     /**
 82:      * (default: 2) Seconds to wait before timing out the connection
 83:      * 
 84:      * @var integer 
 85:      */
 86:     protected $endPointTimeout = '2';
 87:     
 88:     /**
 89:      * (default: 2) Max redirects that are allowed when endpoint called.
 90:      * 
 91:      * @var integer
 92:      */
 93:     protected $endPointMaxRedirects = '2';
 94:     
 95:     /**
 96:      * (optional) Regular expression used to extract API key from url. Axle will 
 97:      * use the **first** matched grouping and then apply that as the key. Using 
 98:      * the `api_key` or `apiaxle_key` will take precedence.
 99:      * 
100:      * @var string
101:      */
102:     protected $extractKeyRegex;
103:     
104:     /**
105:      * (optional) An optional path part that will always be called when the 
106:      * API is hit.
107:      * 
108:      * @var string
109:      */
110:     protected $defaultPath;
111:     
112:     /**
113:      * (default: false) Disable this API causing errors when it's hit
114:      * 
115:      * @var boolean
116:      */
117:     protected $disabled = 'false';
118:     
119:     /**
120:      * (default: true) Set to true to require that SSL certificates be valid
121:      * 
122:      * @var boolean 
123:      */
124:     protected $strictSSL = 'true';
125:     
126:     /**
127:      * Construct new Api object.
128:      * 
129:      * If a $name is provided, it will be fetched from the ApiAxle API and
130:      * properties will be set accordingly.
131:      * 
132:      * @param array $config
133:      * @param string $name
134:      */
135:     public function __construct($config=false,$name=false) 
136:     {
137:         $this->config = new Config($config);
138:         if($name){
139:             $this->get($name);
140:         }
141:     }
142:     
143:     /**
144:      * Set object properties
145:      * 
146:      * @param type $data
147:      * @return \ApiAxle\Api\Api
148:      */
149:     public function setData($data)
150:     {
151:         if(is_array($data)){
152:             $data = json_decode(json_encode($data));
153:         }
154:         
155:         /**
156:          * @todo Refactor to use setters for validation?
157:          */
158:         $this->createdAt = isset($data->createdAt) ? $data->createdAt : null;
159:         $this->updatedAt = isset($data->updatedAt) ? $data->updatedAt : null;
160:         $this->globalCache = isset($data->globalCache) ? $data->globalCache : null;
161:         $this->endPoint = isset($data->endPoint) ? $data->endPoint : null;
162:         $this->protocol = isset($data->protocol) ? $data->protocol : null;
163:         $this->apiFormat = isset($data->apiFormat) ? $data->apiFormat : null;
164:         $this->endPointTimeout = isset($data->endPointTimeout) ? $data->endPointTimeout : null;
165:         $this->endPointMaxRedirects = isset($data->endPointMaxRedirects) ? $data->endPointMaxRedirects : null;
166:         $this->extractKeyRegex = isset($data->extractKeyRegex) ? $data->extractKeyRegex : null;
167:         $this->defaultPath = isset($data->defaultPath) ? $data->defaultPath : null;
168:         $this->disabled = isset($data->disabled) ? $data->disabled : false;
169:         $this->strictSSL = isset($data->strictSSL) ? $data->strictSSL : true;
170:         
171:         return $this;
172:     }
173:     
174:     /**
175:      * Get API settings as array
176:      * 
177:      * @return array
178:      */
179:     public function getData()
180:     {
181:         $data = array(
182:             'createdAt' => $this->createdAt,
183:             'updatedAt' => $this->updatedAt,
184:             'globalCache' => $this->globalCache,
185:             'endPoint' => $this->endPoint,
186:             'protocol' => $this->protocol,
187:             'apiFormat' => $this->apiFormat,
188:             'endPointTimeout' => $this->endPointTimeout,
189:             'endPointMaxRedirects' => $this->endPointMaxRedirects,
190:             'extractKeyRegex' => $this->extractKeyRegex,
191:             'defaultPath' => $this->defaultPath,
192:             'disabled' => $this->disabled,
193:             'strictSSL' => $this->strictSSL
194:         );
195:         
196:         return $data;
197:     }
198:     
199:     /**
200:      * Set the API name
201:      * 
202:      * @param string $name
203:      */
204:     public function setName($name)
205:     {
206:         $this->name = $name;
207:     }
208:     
209:     /**
210:      * Get the API name
211:      * 
212:      * @return string
213:      */
214:     public function getName()
215:     {
216:         return $this->name;
217:     }
218:     
219:     /**
220:      * Call API to retrieve a list of available APIs
221:      * 
222:      * @return \ApiAxle\Shared\ItemList
223:      */
224:     public function getList($from=0, $to=100, $resolve='true')
225:     {
226:         $apiPath = 'apis';
227:         $params = array(
228:             'from' => $from,
229:             'to' => $to,
230:             'resolve' => $resolve
231:         );
232:         
233:         $apiList = new ItemList();
234:         $request = Utilities::callApi($apiPath, 'GET', $params, $this->getConfig());
235:         if($request){
236:             foreach($request as $name => $data){
237:                 $api = new Api($this->getConfig());
238:                 $api->setName($name);
239:                 $api->setData($data);
240:                 $apiList->addItem($api);
241:             }
242:         }
243:         
244:         return $apiList;
245:     }
246:     
247:     /**
248:      * Fetch information about the API from the server and update object
249:      * properties with information from ApiAxle
250:      * 
251:      * @param string $name
252:      * @return \ApiAxle\Api\Api
253:      */
254:     public function get($name)
255:     {
256:         if($name){
257:             $apiPath = 'api/'.$name;
258:             $request = Utilities::callApi($apiPath,'GET',null,$this->getConfig());
259:             if($request){
260:                 $this->setName($name);
261:                 $this->setData($request);
262:             }
263:         }
264:         
265:         return $this;
266:     }
267:     
268:     /**
269:      * Update the current API
270:      * 
271:      * @param array $data
272:      * @throws \ErrorException 201 - Missing API name, cant make update call
273:      */
274:     public function update($data)
275:     {
276:         if(!is_null($this->getName()) && $this->isValid()){
277:             $apiPath = 'api/'.$this->getName();
278:             $request = Utilities::callApi($apiPath,'PUT',$data,$this->getConfig());
279:             if($request){
280:                 $this->get($this->getName());
281:                 return $this;
282:             } else {
283:                 throw new \ErrorException('Unable to update API',202);
284:             }
285:         } else {
286:             throw new \ErrorException('An API name is required to update.',201);
287:         }
288:         
289:     }
290:     
291:     /**
292:      * Register a new API
293:      * 
294:      * @param string $name
295:      * @param array $data
296:      * @return \ApiAxle\Api\Api
297:      * @throws \ErrorException
298:      */
299:     public function create($name, $data)
300:     {
301:         $this->setName($name);
302:         $this->setData($data);
303:         if($this->isValid()){
304:             $apiPath = 'api/'.$this->getName();
305:             $request = Utilities::callApi($apiPath, 'POST', $data,$this->getConfig());
306:             if($request){
307:                 $this->get($name);
308:                 return $this;
309:             } else {
310:                 throw new \ErrorException('Unable to create API',203);
311:             }
312:         }
313:     }
314:     
315:     /**
316:      * Delete an API
317:      * 
318:      * @param string $name
319:      * @return boolean
320:      * @throws \Exception
321:      * @throws \ErrorException
322:      */
323:     public function delete($name=false)
324:     {
325:         if($name){
326:             $this->setName($name);
327:         }
328:         if(is_null($this->getName())){
329:             throw new \Exception('An API name is required to delete.',205);
330:         } else {
331:             $apiPath = 'api/'.$this->getName();
332:             $request = Utilities::callApi($apiPath, 'DELETE', null, $this->getConfig());
333:             if($request){
334:                 return true;
335:             } else {
336:                 throw new \ErrorException('Unable to delete API.', 206);
337:             }
338:         }
339:         
340:     }
341:     
342:     /**
343:      * Get the most used keys for this api
344:      * 
345:      * @todo Create new class to represent keycharts data
346:      * @param int $timestart
347:      * @param int $timeend
348:      * @param string $granularity Valid options: second, minute, hour, day
349:      * @param string $format_timeseries
350:      * @param string $format_timestamp Valid options: epoch_seconds, epoch_milliseconds, ISO
351:      * @return stdClass
352:      * @throws \Exception
353:      * @throws \ErrorException
354:      */
355:     public function getKeyCharts($timestart=false, $timeend=false, 
356:             $granularity='day',$format_timeseries='true',
357:             $format_timestamp='epoch_seconds')
358:     {
359:         if(is_null($this->getName())){
360:             throw new \Exception('An API name is required to get keycharts.',208);
361:         } else {
362:             
363:             $data = array(
364:                 'granularity' => $granularity,
365:                 'format_timeseries' => $format_timeseries,
366:                 'format_timestamp' => $format_timestamp,
367:             );
368:             if($timestart){
369:                 $data['from'] = $timestart;
370:             }
371:             if($timeend){
372:                 $data['to'] = $timeend;
373:             }
374:             
375:             $apiPath = 'api/'.$this->getName().'/keycharts';
376:             $request = Utilities::callApi($apiPath, 'GET', $data, $this->getConfig());
377:             if($request){
378:                 return $request;
379:             } else {
380:                 throw new \ErrorException('Unable to retrieve keycharts for API.', 207);
381:             }
382:         }
383:     }
384:     
385:     /**
386:      * Get a list of Keys with access to this API
387:      * 
388:      * Parameters $from and $to are used for paginating through results
389:      * 
390:      * @param integer $from Default is 0
391:      * @param integer $to Default is 100
392:      * @param string $resolve Wether or not get Key details. Default is 'true'
393:      * @return \ApiAxle\Shared\ItemList
394:      * @throws \Exception
395:      * @throws \ErrorException
396:      */
397:     public function getKeyList($from=0, $to=100, $resolve='true')
398:     {
399:         if(is_null($this->getName())){
400:             throw new \Exception('An API name is required to get keylist.',209);
401:         } else {
402:             $apiPath = 'api/'.$this->getName().'/keys';
403:             $data = array(
404:                 'from' => $from,
405:                 'to' => $to,
406:                 'resolve' => $resolve
407:             );
408:             $keyList = new ItemList();
409:             $request = Utilities::callApi($apiPath, 'GET', $data,$this->getConfig());
410:             if($request){
411:                 foreach($request as $item => $value){
412:                     $key = new Key($this->getConfig());
413:                     $key->setKey($item);
414:                     $key->setData($value);
415:                     $keyList->addItem($key);
416:                 }
417:                 return $keyList;
418:             } else {
419:                 throw new \ErrorException('Unable to retrieve keys for API.', 210);
420:             }
421:         }
422:     }
423:     
424:     /**
425:      * Link a Key to this Api
426:      * 
427:      * @param \ApiAxle\Api\Key $key
428:      * @return \ApiAxle\Api\Api
429:      * @throws \Exception
430:      */
431:     public function linkKey($key)
432:     {
433:         if(is_null($this->getName())){
434:             throw new \Exception('An API name is required to link a key.',211);
435:         } else {
436:             $apiPath = 'api/'.$this->getName().'/linkkey/';
437:             if(is_string($key)){
438:                 $apiPath .= $key;
439:             } elseif($key instanceof Key){
440:                 $apiPath .= $key->getKey();
441:             } else {
442:                 throw new \Exception('Key must be a string or instance of ApiAxle\Api\Key',212);
443:             }
444:             
445:             $request = Utilities::callApi($apiPath, 'PUT',null,$this->getConfig());
446:             if($request){
447:                 return $this;
448:             } else {
449:                 throw new \Exception('Unable to link key',213);
450:             }
451:         }
452:     }
453:     
454:     /**
455:      * Unlink a Key from this API
456:      * 
457:      * @param \ApiAxle\Api\Key $key
458:      * @return \ApiAxle\Api\Api
459:      * @throws \Exception
460:      */
461:     public function unLinkKey($key)
462:     {
463:         if(is_null($this->getName())){
464:             throw new \Exception('An API name is required to unlink a key.',214);
465:         } else {
466:             $apiPath = 'api/'.$this->getName().'/unlinkkey/';
467:             if(is_string($key)){
468:                 $apiPath .= $key;
469:             } elseif($key instanceof Key){
470:                 $apiPath .= $key->getKey();
471:             } else {
472:                 throw new \Exception('Key must be a string or instance of ApiAxle\Api\Key',215);
473:             }
474:             
475:             $request = Utilities::callApi($apiPath, 'PUT',null,$this->getConfig());
476:             if($request){
477:                 return $this;
478:             } else {
479:                 throw new \Exception('Unable to unlink key',216);
480:             }
481:         }
482:     }
483:     
484:     /**
485:      * Get stats for this API
486:      * 
487:      * @param integer $timestart
488:      * @param integer $timeend
489:      * @param string $granularity Options are second, minute, hour, day
490:      * @param string $format_timeseries String of either 'true' or 'false'
491:      * @param string $format_timestamp Default: epoch_seconds
492:      * @param \ApiAxle\Api\Key $forkey Limit results to a single Key
493:      * @return \stdClass Object representing results from API
494:      * @throws \Exception
495:      */
496:     public function getStats($timestart=false, $timeend=false, 
497:             $granularity='minute',$format_timeseries='true',
498:             $format_timestamp='epoch_seconds', $forkey=false)
499:     {
500:         if(is_null($this->getName())){
501:             throw new \Exception('An API name is required to get stats.',217);
502:         } else {
503:             
504:             $data = array(
505:                 'granularity' => $granularity,
506:                 'format_timeseries' => $format_timeseries,
507:                 'format_timestamp' => $format_timestamp,
508:             );
509:             if($timestart){
510:                 $data['from'] = $timestart;
511:             }
512:             if($timeend){
513:                 $data['to'] = $timeend;
514:             }
515:             
516:             if($forkey && is_string($forkey)){
517:                 $data['forkey'] = $forkey;
518:             } elseif($forkey && $forkey instanceof Key){
519:                 $data['forkey'] = $forkey->getKey();
520:             }
521:             
522:             $apiPath = 'api/'.$this->getName().'/stats';
523:             $request = Utilities::callApi($apiPath, 'GET', $data,$this->getConfig());
524:             if($request){
525:                 return $request;
526:             } else {
527:                 throw new \Exception('Unable to get stats for API',218);
528:             }
529:         }
530:     }
531:     
532:     /**
533:      * Get the most used APIs and their hit counts
534:      * 
535:      * @param string $granularity Options are second, minute, hour, day
536:      * @return \stdClass
537:      * @throws \Exception
538:      */
539:     public function getCharts($granularity='minute')
540:     {
541:         $apiPath = 'apis/charts';
542:         $data = array('granularity' => $granularity);
543:         $request = Utilities::callApi($apiPath, 'GET', $data, $this->getConfig());
544:         if($request){
545:             return $request;
546:         } else {
547:             throw new \Exception('Unable to get charts for API',219);
548:         }
549:     }
550:     
551:     /**
552:      * Get current config object
553:      * 
554:      * @return \ApiAxle\Shared\Config
555:      */
556:     public function getConfig()
557:     {
558:         return $this->config;
559:     }
560:     
561:     /**
562:      * Check if required fields are present for provisioning new API
563:      * @return boolean
564:      * @throws \Exception
565:      */
566:     public function isValid()
567:     {
568:         if(!isset($this->endPoint) || is_null($this->endPoint) || strlen($this->endPoint) < 1){
569:             throw new \Exception('Endpoint is required');
570:         } elseif(preg_match('/^http[s]{0,1}:\/\//', $this->endPoint)){
571:             throw new \Exception('Endpoint should not start with http:// or https://, use protocol to define which schema to use.',204);
572:         }
573:         
574:         return true;
575:     }
576: }
577: 
fillup/apiaxle API documentation generated by ApiGen 2.8.0