Last active
September 16, 2017 07:12
-
-
Save Radiergummi/3c402345f249a22b75a8afa240a1fba5 to your computer and use it in GitHub Desktop.
CraftCMS API Wrapper class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Craft; | |
use Closure; | |
use function array_merge; | |
/** | |
* API endpoints wrapper | |
* | |
* @package config\api | |
*/ | |
class Api { | |
/** | |
* current API version. will be false if there's no version. | |
* | |
* @var int|bool | |
*/ | |
protected $version; | |
/** | |
* API URI prefix | |
* | |
* @var string | |
*/ | |
protected $baseURI; | |
/** | |
* API endpoints | |
* | |
* @var array | |
*/ | |
protected $endpoints = []; | |
/** | |
* holds the endpoint defaults | |
* | |
* @var array | |
*/ | |
protected $defaults = []; | |
/** | |
* Api constructor | |
* | |
* @param string $baseURI API base URI prefix | |
* @param int|null $version Current API version. Omit to skip versioning. | |
*/ | |
public function __construct( string $baseURI = 'api', int $version = null ) { | |
$this->baseURI = $baseURI; | |
$this->version = $version ?? false; | |
} | |
/** | |
* adds an endpoint to the API | |
* | |
* @param string $uri relative endpoint URI to add | |
* @param Closure $handler handler this endpoint will call | |
* | |
* @return void | |
*/ | |
public function addEndpoint( string $uri, Closure $handler ) { | |
$this->endpoints[ $this->buildEndpointURI( $uri ) ] = $handler; | |
} | |
/** | |
* builds an endpoint URI | |
* | |
* @param string $uri relative URI to prepend the base URI prefix and version, if set | |
* | |
* @return string | |
*/ | |
protected function buildEndpointURI( string $uri ): string { | |
$uri = ltrim($uri, '/'); | |
if ( $this->version ) { | |
return "{$this->baseURI}/v{$this->version}/$uri"; | |
} | |
return "{$this->baseURI}/$uri"; | |
} | |
/** | |
* Adds a collection. This will call a callback with a new Api instance as its call context | |
* and merged with the existing endpoints later on. | |
* Collections can be nested, too. | |
* | |
* @param string $uri URI for all members of the group | |
* @param \Closure $endpointsCallback callback which makes changes to the collection | |
* | |
* @return void | |
*/ | |
public function addCollection( string $uri, Closure $endpointsCallback ) { | |
// create a new Api instance with the given URI as its base URI | |
$collection = new self( $this->buildEndpointURI( $uri ) ); | |
// call the endpoints callback with the collection passed as context. | |
// this means all methods need to be called on "$this" or use the arguments | |
$endpointsCallback->call( $collection, $collection, $this ); | |
// merge the resulting endpoints | |
$this->endpoints = array_merge( $this->getEndpoints(), $collection->getEndpoints() ); | |
} | |
/** | |
* retrieves the API endpoints | |
* | |
* @return array | |
*/ | |
public function getEndpoints(): array { | |
return $this->endpoints; | |
} | |
/** | |
* removes an endpoint | |
* | |
* @param string $uri relative endpoint URI to remove. Will be run through buildEndpointURI | |
* | |
* @return void | |
*/ | |
public function removeEndpoint( string $uri ) { | |
unset( $this->endpoints[ $this->buildEndpointURI( $uri ) ] ); | |
} | |
/** | |
* retrieves the Api version | |
* | |
* @return int | |
*/ | |
public function getVersion(): int { | |
return $this->version; | |
} | |
/** | |
* retrieves the API URI prefix | |
* | |
* @return string | |
*/ | |
public function getBaseURI(): string { | |
return $this->baseURI; | |
} | |
/** | |
* converts the API definitions into an array consumable by the elementAPI plugin | |
* | |
* @return array | |
*/ | |
public function toArray() { | |
return [ | |
'defaults' => $this->getDefaults(), | |
'endpoints' => $this->getEndpoints() | |
]; | |
} | |
/** | |
* retrieves the default endpoint settings | |
* | |
* @return array | |
*/ | |
public function getDefaults(): array { | |
return $this->defaults; | |
} | |
/** | |
* sets the default endpoint settings | |
* | |
* @param array $defaults default settings to apply for this configuration. Will be ignored if set | |
* on a collection. | |
*/ | |
public function setDefaults( array $defaults ) { | |
$this->defaults = $defaults; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Craft; | |
$myApi = new Api('api', 1); | |
// endpoint for /api/v1/news | |
$myApi->addEndpoint( 'news.json', function() { | |
return [ | |
'elementType' => Entry::class, | |
'criteria' => ['section' => 'news'], | |
'transformer' => function(Entry $entry) { | |
return [ | |
'title' => $entry->title, | |
'url' => $entry->url, | |
'jsonUrl' => UrlHelper::url("news/{$entry->id}.json"), | |
'summary' => $entry->summary, | |
]; | |
}, | |
]; | |
} ); | |
// collection for /api/v1/receipts/ | |
$myApi->addCollection( 'receipts', function( Api $collection, Api $api ) { | |
// endpoint for /api/v1/receipts/:id.json | |
$this->addEndpoint( '<entryId:\d+>.json', function() { /* ... */ } ); | |
// collection for /api/v1/receipts/ingredients/ | |
$this->addCollection( 'ingredients', function() { | |
// endpoint for /api/v1/receipts/ingredients/:id.json | |
$this->addEndpoint( '<entryId:\d+.json', function() { /* ... */ } ); | |
} ); | |
} ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment