5 // You can either provide them as environment variables
6 // or hard-code them in the empty strings below.
7 $apiUrl = getenv('BS_URL') ?: ''; // http://bookstack.local/
8 $clientId = getenv('BS_TOKEN_ID') ?: '';
9 $clientSecret = getenv('BS_TOKEN_SECRET') ?: '';
11 // Export Format & Location
12 // Can be provided as a arguments when calling the script
13 // or be hard-coded as strings below.
14 $exportFormat = $argv[1] ?? 'pdf';
15 $exportLocation = $argv[2] ?? './';
20 $books = getAllBooks();
21 $outDir = realpath($exportLocation);
23 $extensionByFormat = [
29 foreach ($books as $book) {
31 $extension = $extensionByFormat[$exportFormat] ?? $exportFormat;
32 $content = apiGet("api/books/{$id}/export/{$exportFormat}");
33 $outPath = $outDir . "/{$book['slug']}.{$extension}";
34 file_put_contents($outPath, $content);
38 * Get all books from the system API.
40 function getAllBooks() {
47 $endpoint = 'api/books?' . http_build_query(['count' => $count, 'offset' => $offset]);
48 $resp = apiGetJson($endpoint);
50 // Only set total on first request, due to API bug:
51 // https://github.com/BookStackApp/BookStack/issues/2043
53 $total = $resp['total'] ?? 0;
56 $newBooks = $resp['data'] ?? [];
57 array_push($allBooks, ...$newBooks);
59 } while ($offset < $total);
65 * Make a simple GET HTTP request to the API.
67 function apiGet(string $endpoint): string {
68 global $apiUrl, $clientId, $clientSecret;
69 $url = rtrim($apiUrl, '/') . '/' . ltrim($endpoint, '/');
70 $opts = ['http' => ['header' => "Authorization: Token {$clientId}:{$clientSecret}"]];
71 $context = stream_context_create($opts);
72 return file_get_contents($url, false, $context);
76 * Make a simple GET HTTP request to the API &
77 * decode the JSON response to an array.
79 function apiGetJson(string $endpoint): array {
80 $data = apiGet($endpoint);
81 return json_decode($data, true);
85 * DEBUG: Dump out the given variables and exit.
87 function dd(...$args) {
88 foreach ($args as $arg) {