Upgrade to 3.1.0
This commit is contained in:
@@ -22,25 +22,106 @@ class Api
|
||||
{
|
||||
use Properties;
|
||||
|
||||
/**
|
||||
* Authentication callback
|
||||
*
|
||||
* @var Closure
|
||||
*/
|
||||
protected $authentication;
|
||||
|
||||
/**
|
||||
* Debugging flag
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $debug = false;
|
||||
|
||||
/**
|
||||
* Collection definition
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $collections = [];
|
||||
|
||||
/**
|
||||
* Injected data/dependencies
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Model definitions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $models = [];
|
||||
|
||||
/**
|
||||
* The current route
|
||||
*
|
||||
* @var Route
|
||||
*/
|
||||
protected $route;
|
||||
|
||||
/**
|
||||
* The Router instance
|
||||
*
|
||||
* @var Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Route definition
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $routes = [];
|
||||
|
||||
/**
|
||||
* Request data
|
||||
* [query, body, files]
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requestData = [];
|
||||
|
||||
/**
|
||||
* The applied request method
|
||||
* (GET, POST, PATCH, etc.)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $requestMethod;
|
||||
|
||||
public function __call($method, $args)
|
||||
/**
|
||||
* Magic accessor for any given data
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $method, array $args = [])
|
||||
{
|
||||
return $this->data($method, ...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new API instance
|
||||
*
|
||||
* @param array $props
|
||||
*/
|
||||
public function __construct(array $props)
|
||||
{
|
||||
$this->setProperties($props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the authentication method
|
||||
* if set
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
if ($auth = $this->authentication()) {
|
||||
@@ -50,11 +131,25 @@ class Api
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authentication callback
|
||||
*
|
||||
* @return Closure|null
|
||||
*/
|
||||
public function authentication()
|
||||
{
|
||||
return $this->authentication;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an API call for the given path,
|
||||
* request method and optional request data
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @param array $requestData
|
||||
* @return mixed
|
||||
*/
|
||||
public function call(string $path = null, string $method = 'GET', array $requestData = [])
|
||||
{
|
||||
$path = rtrim($path, '/');
|
||||
@@ -62,15 +157,15 @@ class Api
|
||||
$this->setRequestMethod($method);
|
||||
$this->setRequestData($requestData);
|
||||
|
||||
$router = new Router($this->routes());
|
||||
$result = $router->find($path, $method);
|
||||
$auth = $result->attributes()['auth'] ?? true;
|
||||
$this->router = new Router($this->routes());
|
||||
$this->route = $this->router->find($path, $method);
|
||||
$auth = $this->route->attributes()['auth'] ?? true;
|
||||
|
||||
if ($auth !== false) {
|
||||
$this->authenticate();
|
||||
}
|
||||
|
||||
$output = $result->action()->call($this, ...$result->arguments());
|
||||
$output = $this->route->action()->call($this, ...$this->route->arguments());
|
||||
|
||||
if (is_object($output) === true) {
|
||||
return $this->resolve($output)->toResponse();
|
||||
@@ -79,6 +174,13 @@ class Api
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter and getter for an API collection
|
||||
*
|
||||
* @param string $name
|
||||
* @param array|null $collection
|
||||
* @return Collection
|
||||
*/
|
||||
public function collection(string $name, $collection = null)
|
||||
{
|
||||
if (isset($this->collections[$name]) === false) {
|
||||
@@ -88,11 +190,24 @@ class Api
|
||||
return new Collection($this, $collection, $this->collections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collections definition
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function collections(): array
|
||||
{
|
||||
return $this->collections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the injected data array
|
||||
* or certain parts of it by key
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed ...$args
|
||||
* @return mixed
|
||||
*/
|
||||
public function data($key = null, ...$args)
|
||||
{
|
||||
if ($key === null) {
|
||||
@@ -111,11 +226,34 @@ class Api
|
||||
return $this->data[$key];
|
||||
}
|
||||
|
||||
public function hasData($key): bool
|
||||
/**
|
||||
* Returns the debugging flag
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function debug(): bool
|
||||
{
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if injected data exists for the given key
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasData(string $key): bool
|
||||
{
|
||||
return isset($this->data[$key]) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an API model instance by name
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $object
|
||||
* @return Model
|
||||
*/
|
||||
public function model(string $name, $object = null)
|
||||
{
|
||||
if (isset($this->models[$name]) === false) {
|
||||
@@ -125,12 +263,27 @@ class Api
|
||||
return new Model($this, $object, $this->models[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all model definitions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function models(): array
|
||||
{
|
||||
return $this->models;
|
||||
}
|
||||
|
||||
public function requestData($type = null, $key = null, $default = null)
|
||||
/**
|
||||
* Getter for request data
|
||||
* Can either get all the data
|
||||
* or certain parts of it.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestData(string $type = null, string $key = null, $default = null)
|
||||
{
|
||||
if ($type === null) {
|
||||
return $this->requestData;
|
||||
@@ -146,31 +299,71 @@ class Api
|
||||
return $data[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request body if available
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestBody(string $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('body', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the files from the request if available
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestFiles(string $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('files', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all headers from the request if available
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestHeaders(string $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('headers', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function requestMethod(): string
|
||||
{
|
||||
return $this->requestMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request query if available
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestQuery(string $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('query', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a Kirby object into an
|
||||
* API model or collection representation
|
||||
*
|
||||
* @param mixed $object
|
||||
* @return Model|Collection
|
||||
*/
|
||||
public function resolve($object)
|
||||
{
|
||||
if (is_a($object, 'Kirby\Api\Model') === true || is_a($object, 'Kirby\Api\Collection') === true) {
|
||||
@@ -202,17 +395,34 @@ class Api
|
||||
throw new NotFoundException(sprintf('The object "%s" cannot be resolved', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all defined routes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function routes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the authentication callback
|
||||
*
|
||||
* @param Closure $authentication
|
||||
* @return self
|
||||
*/
|
||||
protected function setAuthentication(Closure $authentication = null)
|
||||
{
|
||||
$this->authentication = $authentication;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the collections definition
|
||||
*
|
||||
* @param array $collections
|
||||
* @return self
|
||||
*/
|
||||
protected function setCollections(array $collections = null)
|
||||
{
|
||||
if ($collections !== null) {
|
||||
@@ -221,18 +431,36 @@ class Api
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the injected data
|
||||
*
|
||||
* @param array $data
|
||||
* @return self
|
||||
*/
|
||||
protected function setData(array $data = null)
|
||||
{
|
||||
$this->data = $data ?? [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the debug flag
|
||||
*
|
||||
* @param boolean $debug
|
||||
* @return self
|
||||
*/
|
||||
protected function setDebug(bool $debug = false)
|
||||
{
|
||||
$this->debug = $debug;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the model definitions
|
||||
*
|
||||
* @param array $models
|
||||
* @return self
|
||||
*/
|
||||
protected function setModels(array $models = null)
|
||||
{
|
||||
if ($models !== null) {
|
||||
@@ -242,6 +470,12 @@ class Api
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the request data
|
||||
*
|
||||
* @param array $requestData
|
||||
* @return self
|
||||
*/
|
||||
protected function setRequestData(array $requestData = null)
|
||||
{
|
||||
$defaults = [
|
||||
@@ -254,25 +488,48 @@ class Api
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the request method
|
||||
*
|
||||
* @param string $requestMethod
|
||||
* @return self
|
||||
*/
|
||||
protected function setRequestMethod(string $requestMethod = null)
|
||||
{
|
||||
$this->requestMethod = $requestMethod;
|
||||
$this->requestMethod = $requestMethod ?? 'GET';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the route definitions
|
||||
*
|
||||
* @param array $routes
|
||||
* @return self
|
||||
*/
|
||||
protected function setRoutes(array $routes = null)
|
||||
{
|
||||
$this->routes = $routes ?? [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the API call
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @param array $requestData
|
||||
* @return mixed
|
||||
*/
|
||||
public function render(string $path, $method = 'GET', array $requestData = [])
|
||||
{
|
||||
try {
|
||||
$result = $this->call($path, $method, $requestData);
|
||||
} catch (Throwable $e) {
|
||||
if (is_a($e, 'Kirby\Exception\Exception') === true) {
|
||||
$result = ['status' => 'error'] + $e->toArray();
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'route' => $this->route->pattern()
|
||||
] + $e->toArray();
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
@@ -280,7 +537,8 @@ class Api
|
||||
'message' => $e->getMessage(),
|
||||
'file' => ltrim($e->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null),
|
||||
'line' => $e->getLine(),
|
||||
'code' => empty($e->getCode()) === false ? $e->getCode() : 500
|
||||
'code' => empty($e->getCode()) === false ? $e->getCode() : 500,
|
||||
'route' => $this->route->pattern()
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -338,6 +596,13 @@ class Api
|
||||
return Response::json($result, 200, $pretty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload helper method
|
||||
*
|
||||
* @param Closure $callback
|
||||
* @param boolean $single
|
||||
* @return array
|
||||
*/
|
||||
public function upload(Closure $callback, $single = false): array
|
||||
{
|
||||
$trials = 0;
|
||||
|
Reference in New Issue
Block a user