]> BookStack Code Mirror - bookstack/commitdiff
Started core API route work
authorDan Brown <redacted>
Sat, 28 Dec 2019 14:58:07 +0000 (14:58 +0000)
committerDan Brown <redacted>
Sat, 28 Dec 2019 14:58:07 +0000 (14:58 +0000)
.env.example.complete
app/Api/ListingResponseBuilder.php [new file with mode: 0644]
app/Config/api.php [new file with mode: 0644]
app/Http/Controllers/Api/ApiController.php [new file with mode: 0644]
app/Http/Controllers/Api/BooksApiController.php [new file with mode: 0644]
app/Http/Kernel.php
app/Providers/RouteServiceProvider.php
routes/api.php [new file with mode: 0644]

index a13c8b7d086ee2f8b37ee27a1bf5ed97bd486b3c..716d614a33074cbe3add5f7e36082fb7459a577c 100644 (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
 
 # 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
diff --git a/app/Api/ListingResponseBuilder.php b/app/Api/ListingResponseBuilder.php
new file mode 100644 (file)
index 0000000..279fabd
--- /dev/null
@@ -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);
+    }
+}
diff --git a/app/Config/api.php b/app/Config/api.php
new file mode 100644 (file)
index 0000000..dd54b29
--- /dev/null
@@ -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),
+
+];
diff --git a/app/Http/Controllers/Api/ApiController.php b/app/Http/Controllers/Api/ApiController.php
new file mode 100644 (file)
index 0000000..4971c0c
--- /dev/null
@@ -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();
+    }
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/Api/BooksApiController.php b/app/Http/Controllers/Api/BooksApiController.php
new file mode 100644 (file)
index 0000000..d23aaf0
--- /dev/null
@@ -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',
+        ]);
+    }
+}
\ No newline at end of file
index f9752da09d6492430dd2fe2f4c131dcac301aedf..cd3fc83ec36a6f70871e43bc497428a2805a12bf 100644 (file)
@@ -37,7 +37,6 @@ class Kernel extends HttpKernel
         ],
         'api' => [
             'throttle:60,1',
         ],
         'api' => [
             'throttle:60,1',
-            'bindings',
         ],
     ];
 
         ],
     ];
 
index c4c39d5345fa74b80631c7e737e4f928407f32a9..a37780e52eb1c25eaef4355afc3b497e786d9f6a 100644 (file)
@@ -34,7 +34,7 @@ class RouteServiceProvider extends ServiceProvider
     public function map()
     {
         $this->mapWebRoutes();
     public function map()
     {
         $this->mapWebRoutes();
-//        $this->mapApiRoutes();
+        $this->mapApiRoutes();
     }
     /**
      * Define the "web" routes for the application.
     }
     /**
      * Define the "web" routes for the application.
@@ -63,7 +63,7 @@ class RouteServiceProvider extends ServiceProvider
     {
         Route::group([
             'middleware' => 'api',
     {
         Route::group([
             'middleware' => 'api',
-            'namespace' => $this->namespace,
+            'namespace' => $this->namespace . '\Api',
             'prefix' => 'api',
         ], function ($router) {
             require base_path('routes/api.php');
             'prefix' => 'api',
         ], function ($router) {
             require base_path('routes/api.php');
diff --git a/routes/api.php b/routes/api.php
new file mode 100644 (file)
index 0000000..0604ffd
--- /dev/null
@@ -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');
\ No newline at end of file