# 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
\ No newline at end of file
--- /dev/null
+<?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);
+ }
+}
--- /dev/null
+<?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),
+
+];
--- /dev/null
+<?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();
+ }
+}
\ No newline at end of file
--- /dev/null
+<?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',
+ ]);
+ }
+}
\ No newline at end of file
],
'api' => [
'throttle:60,1',
- 'bindings',
],
];
public function map()
{
$this->mapWebRoutes();
-// $this->mapApiRoutes();
+ $this->mapApiRoutes();
}
/**
* Define the "web" routes for the application.
{
Route::group([
'middleware' => 'api',
- 'namespace' => $this->namespace,
+ 'namespace' => $this->namespace . '\Api',
'prefix' => 'api',
], function ($router) {
require base_path('routes/api.php');
--- /dev/null
+<?php
+
+/**
+ * Routes for the BookStack API.
+ *
+ * Routes have a uri prefix of /api/.
+ */
+
+
+// TODO - Authenticate middleware
+
+Route::get('books', 'BooksApiController@index');
\ No newline at end of file