Initial API setup

This commit is contained in:
Matthew Ross 2016-04-21 18:08:59 -04:00
parent 72c0c37672
commit 0b0a4e9d69
11 changed files with 215 additions and 0 deletions

9
src/api/.htaccess Normal file
View File

@ -0,0 +1,9 @@
RewriteEngine On
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^recipes.db$ %{ENV_BASE}index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ %{ENV:BASE}index.php [QSA,L]

50
src/api/app-setup.php Normal file
View File

@ -0,0 +1,50 @@
<?php
$container = $app->getContainer();
// Inject a Monolog logger into the dependency container
$container['logger'] = function($c) {
$logger = new Monolog\Logger('API');
$fileHandler = new Monolog\Handler\StreamHandler('logs/api.log');
$logger->pushHandler($fileHandler);
return $logger;
};
// Replace notFoundHandler to use an API response
$container['notFoundHandler'] = function($c) {
return function($request, $response) use ($c) {
return $c['response']
->withHeader('Content-Type', 'application/json')
->write('{ message: "Matching API call not found." }');
};
};
// Replace the errorHandler to use an API response
$container['errorHandler'] = function ($c) {
return function ($request, $response, $exception) use ($c) {
$c['logger']->addError('Server error', $exception->getTrace());
return $c['response']->withStatus(500)
->withHeader('Content-Type', 'application/json')
->write('{ message: "Internal Server Error", error: "' .
$exception->getMessage() . '" }');
};
};
// Routes ending in '/' use route without '/'
$app->add(function($request, $response, $next) {
$uri = $request->getUri();
$path = $uri->getPath();
if (strlen($path) > 1 && substr($path, -1) === '/') {
$path = substr($path, 0, -1);
}
if ($uri->getPath() !== $path) {
return $next($request->withUri($uri->withPath($path)), $response);
}
return $next($request, $response);
});

View File

@ -0,0 +1,26 @@
<?php
class ApiJson {
public $status = 'failure';
public $data = [];
public $alerts = [];
function setSuccess() {
$this->status = 'success';
}
function setFailure() {
$this->status = 'failure';
}
function addData($obj) {
$this->data[] = $obj;
}
function addAlert($type, $text) {
$this->alerts[] = [
'type' => $type,
'text' => $text
];
}
}

View File

@ -0,0 +1,15 @@
<?php
abstract class BaseController {
protected $apiJson;
protected $logger;
public function __construct($container) {
$this->apiJson = new ApiJson();
$this->logger = $container->get('logger');
}
public function jsonResponse($response) {
return $response->withJson($this->apiJson);
}
}

View File

@ -0,0 +1,24 @@
<?php
use RedBeanPHP\R;
class Boards extends BaseController {
public function getAllBoards($request, $response, $args) {
$boardBeans = R::findAll('board');
if (count($boardBeans)) {
$this->apiJson->setSuccess();
foreach($boardBeans as $bean) {
$this->apiJson->addData(Board::fromBean($bean));
}
} else {
$this->logger->addInfo('No boards in database.');
$this->apiJson->addAlert('info', 'No boards in database.');
}
return $this->jsonResponse($response);
}
}

View File

@ -0,0 +1,21 @@
<?php
class Invalid extends BaseController {
public function noApi($request, $response, $args) {
$this->apiJson->addAlert('error',
'No API functionality at this endpoint.');
$apiReturn = new stdClass();
$apiReturn->status = 'One of "success" or "failure".';
$apiReturn->data = 'An array of data (JSON objects and/or arrays).';
$apiReturn->alerts = 'An array of alerts, with "type" of "success", "error", "warn", or "info" and a "text" message.';
$this->apiJson->addData($apiReturn);
$this->logger->addInfo('Invalid Endpoint: ', [$this->apiJson]);
return $this->jsonResponse($response);
}
}

16
src/api/index.php Normal file
View File

@ -0,0 +1,16 @@
<?php
require './vendor/autoload.php';
use RedBeanPHP\R;
R::setup('sqlite:taskboard');
$app = new Slim\App();
require 'app-setup.php';
$app->get('/', 'Invalid:noApi');
$app->get('/boards', 'Boards:getAllBoards');
$app->run();
R::close();

View File

@ -0,0 +1,30 @@
<?php
use RedBeanPHP\R;
abstract class BaseModel {
protected $logger;
protected $bean;
public function __construct($type, $id) {
global $app;
$container = $app->getContainer();
$this->logger = $container->get('logger');
$this->bean = R::load($type, $id);
}
public abstract function updateBean();
public abstract function loadFromBean($bean);
public function save() {
$this->updateBean();
R::store($this->bean);
$this->loadFromBean($this->bean);
}
public function delete() {
$this->updateBean();
R::trash($this->bean);
}
}

24
src/api/models/Board.php Normal file
View File

@ -0,0 +1,24 @@
<?php
class Board extends BaseModel {
public function __construct($id = 0, $internal = false) {
parent::__construct('board', $id);
if ($internal) {
return;
}
$this->loadFromBean($this->bean);
}
public static function fromBean($bean) {
}
public function updateBean() {
}
public function loadFromBean() {
}
}

View File