Started core API route work

This commit is contained in:
Dan Brown 2019-12-28 14:58:07 +00:00
parent c055310507
commit 04137e7c98
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
8 changed files with 157 additions and 3 deletions

View File

@ -258,3 +258,6 @@ ALLOW_CONTENT_SCRIPTS=false
# Contents of the robots.txt file can be overridden, making this option obsolete.
ALLOW_ROBOTS=null
# The default and maximum item-counts for listing API requests.
API_DEFAULT_ITEM_COUNT=100
API_MAX_ITEM_COUNT=500

View File

@ -0,0 +1,82 @@
<?php namespace BookStack\Api;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
class ListingResponseBuilder
{
protected $query;
protected $fields;
/**
* ListingResponseBuilder constructor.
*/
public function __construct(Builder $query, array $fields)
{
$this->query = $query;
$this->fields = $fields;
}
/**
* Get the response from this builder.
*/
public function toResponse()
{
$total = $this->query->count();
$data = $this->fetchData();
return response()->json([
'data' => $data,
'total' => $total,
]);
}
/**
* Fetch the data to return in the response.
*/
protected function fetchData(): Collection
{
$this->applyCountAndOffset($this->query);
$this->applySorting($this->query);
// TODO - Apply filtering
return $this->query->get($this->fields);
}
/**
* Apply sorting operations to the query from given parameters
* otherwise falling back to the first given field, ascending.
*/
protected function applySorting(Builder $query)
{
$defaultSortName = $this->fields[0];
$direction = 'asc';
$sort = request()->get('sort', '');
if (strpos($sort, '-') === 0) {
$direction = 'desc';
}
$sortName = ltrim($sort, '+- ');
if (!in_array($sortName, $this->fields)) {
$sortName = $defaultSortName;
}
$query->orderBy($sortName, $direction);
}
/**
* Apply count and offset for paging, based on params from the request while falling
* back to system defined default, taking the max limit into account.
*/
protected function applyCountAndOffset(Builder $query)
{
$offset = max(0, request()->get('offset', 0));
$maxCount = config('api.max_item_count');
$count = request()->get('count', config('api.default_item_count'));
$count = max(min($maxCount, $count), 1);
$query->skip($offset)->take($count);
}
}

20
app/Config/api.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/**
* API configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// The default number of items that are returned in listing API requests.
// This count can often be overridden, up the the max option, per-request via request options.
'default_item_count' => env('API_DEFAULT_ITEM_COUNT', 100),
// The maximum number of items that can be returned in a listing API request.
'max_item_count' => env('API_MAX_ITEM_COUNT', 500),
];

View File

@ -0,0 +1,20 @@
<?php namespace BookStack\Http\Controllers\Api;
use BookStack\Api\ListingResponseBuilder;
use BookStack\Http\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
class ApiController extends Controller
{
/**
* Provide a paginated listing JSON response in a standard format
* taking into account any pagination parameters passed by the user.
*/
protected function apiListingResponse(Builder $query, array $fields): JsonResponse
{
$listing = new ListingResponseBuilder($query, $fields);
return $listing->toResponse();
}
}

View File

@ -0,0 +1,18 @@
<?php namespace BookStack\Http\Controllers\Api;
use BookStack\Entities\Book;
class BooksApiController extends ApiController
{
/**
* Get a listing of books visible to the user.
*/
public function index()
{
$books = Book::visible();
return $this->apiListingResponse($books, [
'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by',
'restricted', 'image_id',
]);
}
}

View File

@ -37,7 +37,6 @@ class Kernel extends HttpKernel
],
'api' => [
'throttle:60,1',
'bindings',
],
];

View File

@ -34,7 +34,7 @@ class RouteServiceProvider extends ServiceProvider
public function map()
{
$this->mapWebRoutes();
// $this->mapApiRoutes();
$this->mapApiRoutes();
}
/**
* Define the "web" routes for the application.
@ -63,7 +63,7 @@ class RouteServiceProvider extends ServiceProvider
{
Route::group([
'middleware' => 'api',
'namespace' => $this->namespace,
'namespace' => $this->namespace . '\Api',
'prefix' => 'api',
], function ($router) {
require base_path('routes/api.php');

12
routes/api.php Normal file
View File

@ -0,0 +1,12 @@
<?php
/**
* Routes for the BookStack API.
*
* Routes have a uri prefix of /api/.
*/
// TODO - Authenticate middleware
Route::get('books', 'BooksApiController@index');