]> BookStack Code Mirror - bookstack/commitdiff
Added book-export endpoints to the API
authorDan Brown <redacted>
Fri, 10 Apr 2020 15:05:17 +0000 (16:05 +0100)
committerDan Brown <redacted>
Fri, 10 Apr 2020 15:05:17 +0000 (16:05 +0100)
app/Api/ApiDocsGenerator.php
app/Http/Controllers/Api/BooksExportApiController.php [new file with mode: 0644]
resources/views/api-docs/index.blade.php
routes/api.php
tests/Api/BooksApiTest.php

index a0c45608aede96881f7005ee4b1abdf9a292b0a2..ddba24bdb65d6ec8dc1474e3d50996c546623228 100644 (file)
@@ -3,6 +3,7 @@
 use BookStack\Http\Controllers\Api\ApiController;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Route;
+use Illuminate\Support\Str;
 use ReflectionClass;
 use ReflectionException;
 use ReflectionMethod;
@@ -117,6 +118,7 @@ class ApiDocsGenerator
                 'method' => $route->methods[0],
                 'controller' => $controller,
                 'controller_method' => $controllerMethod,
+                'controller_method_kebab' => Str::kebab($controllerMethod),
                 'base_model' => $baseModelName,
             ];
         });
diff --git a/app/Http/Controllers/Api/BooksExportApiController.php b/app/Http/Controllers/Api/BooksExportApiController.php
new file mode 100644 (file)
index 0000000..605f8f4
--- /dev/null
@@ -0,0 +1,55 @@
+<?php namespace BookStack\Http\Controllers\Api;
+
+use BookStack\Entities\Book;
+use BookStack\Entities\ExportService;
+use BookStack\Entities\Repos\BookRepo;
+use Throwable;
+
+class BooksExportApiController extends ApiController
+{
+
+    protected $bookRepo;
+    protected $exportService;
+
+    /**
+     * BookExportController constructor.
+     */
+    public function __construct(BookRepo $bookRepo, ExportService $exportService)
+    {
+        $this->bookRepo = $bookRepo;
+        $this->exportService = $exportService;
+        parent::__construct();
+    }
+
+    /**
+     * Export a book as a PDF file.
+     * @throws Throwable
+     */
+    public function exportPdf(int $id)
+    {
+        $book = Book::visible()->findOrFail($id);
+        $pdfContent = $this->exportService->bookToPdf($book);
+        return $this->downloadResponse($pdfContent, $book->slug . '.pdf');
+    }
+
+    /**
+     * Export a book as a contained HTML file.
+     * @throws Throwable
+     */
+    public function exportHtml(int $id)
+    {
+        $book = Book::visible()->findOrFail($id);
+        $htmlContent = $this->exportService->bookToContainedHtml($book);
+        return $this->downloadResponse($htmlContent, $book->slug . '.html');
+    }
+
+    /**
+     * Export a book as a plain text file.
+     */
+    public function exportPlainText(int $id)
+    {
+        $book = Book::visible()->findOrFail($id);
+        $textContent = $this->exportService->bookToPlainText($book);
+        return $this->downloadResponse($textContent, $book->slug . '.txt');
+    }
+}
index ab4db89e8d606ea9a93b06b7544a348f53245664..e92b505cf3792c4b74d002b0b92f384c39ec609b 100644 (file)
@@ -26,7 +26,7 @@
                                     <span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
                                 </a>
                                 <a href="#{{ $endpoint['name'] }}" class="text-mono">
-                                    {{ $endpoint['controller_method'] }}
+                                    {{ $endpoint['controller_method_kebab'] }}
                                 </a>
                             </div>
                         @endforeach
                         <h1 class="list-heading text-capitals">{{ $model }}</h1>
 
                         @foreach($endpoints as $endpoint)
-                            <h6 class="text-uppercase text-muted float right">{{ $endpoint['controller_method'] }}</h6>
+                            <h6 class="text-uppercase text-muted float right">{{ $endpoint['controller_method_kebab'] }}</h6>
                             <h5 id="{{ $endpoint['name'] }}" class="text-mono mb-m">
                                 <span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
                                 {{ url($endpoint['uri']) }}
index 7ca5e66fc1688a3e711897e148f343287829a4b9..f9c27b62f29581770b65c0a704ebaf31a8f66324 100644 (file)
@@ -15,6 +15,10 @@ Route::get('books/{id}', 'BooksApiController@read');
 Route::put('books/{id}', 'BooksApiController@update');
 Route::delete('books/{id}', 'BooksApiController@delete');
 
+Route::get('books/{id}/export/html', 'BooksExportApiController@exportHtml');
+Route::get('books/{id}/export/pdf', 'BooksExportApiController@exportPdf');
+Route::get('books/{id}/export/plaintext', 'BooksExportApiController@exportPlainText');
+
 Route::get('shelves', 'BookshelfApiController@list');
 Route::post('shelves', 'BookshelfApiController@create');
 Route::get('shelves/{id}', 'BookshelfApiController@read');
index 6f8753fb05ce0cd16a73aeb7b9a5245a9784d2fa..3fd763ec625969872d9fa5a5f27f27e6002ad80e 100644 (file)
@@ -105,4 +105,36 @@ class BooksApiTest extends TestCase
         $resp->assertStatus(204);
         $this->assertActivityExists('book_delete');
     }
+
+    public function test_export_html_endpoint()
+    {
+        $this->actingAsApiEditor();
+        $book = Book::visible()->first();
+
+        $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/html");
+        $resp->assertStatus(200);
+        $resp->assertSee($book->name);
+        $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
+    }
+
+    public function test_export_plain_text_endpoint()
+    {
+        $this->actingAsApiEditor();
+        $book = Book::visible()->first();
+
+        $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/plaintext");
+        $resp->assertStatus(200);
+        $resp->assertSee($book->name);
+        $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"');
+    }
+
+    public function test_export_pdf_endpoint()
+    {
+        $this->actingAsApiEditor();
+        $book = Book::visible()->first();
+
+        $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/pdf");
+        $resp->assertStatus(200);
+        $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
+    }
 }
\ No newline at end of file