Skip to content

Instantly share code, notes, and snippets.

@ssddanbrown
Created January 21, 2023 23:06
Show Gist options
  • Save ssddanbrown/78553a39d36187476283a00fd67ed3dc to your computer and use it in GitHub Desktop.
Save ssddanbrown/78553a39d36187476283a00fd67ed3dc to your computer and use it in GitHub Desktop.
bookstack autosort tagged books

This is a hack to BookStack, using the theme system, to enable auto-sorting of book chapters and pages upon page or chapter create/update. It sorts by name, ascending, with chapters first. By default it will run for any book with an Autosort tag assigned.

Setup

This uses the logical theme system.

  1. Within the BookStack install folder, you should have a themes folder.
  2. Create a themes/custom/functions.php file with the contents of the functions.php file example below.
  3. Customize the tag name, if desired, by teaking the string at around line 45. Set this to empty to run for all books.
  4. Add APP_THEME=custom to your .env file.

Note

This can slow down page & chapter create & update system events. These customizations are not officially supported any may break upon, or conflict with, future updates. Quickly tested on BookStack v22.11.1.

<?php
use BookStack\Actions\ActivityType;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
/**
* Auto-sort the contents of the given book.
* This sorts in name order, ascending, with chapters first.
*/
function autoSortBook(Book $book) {
$chapters = $book->chapters()->orderBy('name', 'asc')->get(['id', 'priority']);
$pages = $book->pages()->orderBy('name', 'asc')
->where('draft', '=', false)
->get(['id', 'priority']);
$chapterCount = $chapters->count();
foreach ($chapters as $index => $chapter) {
$chapter->priority = $index;
$chapter->save();
}
foreach ($pages as $index => $page) {
$page->priority = $chapterCount + $index;
$page->save();
}
}
// Listen to the activity logged theme event to run our custom logic
Theme::listen(ThemeEvents::ACTIVITY_LOGGED, function (string $type, $detail) {
// The activity events we're triggering sort upon.
$sortActivityTypes = [
ActivityType::PAGE_CREATE,
ActivityType::PAGE_UPDATE,
ActivityType::CHAPTER_CREATE,
ActivityType::CHAPTER_UPDATE,
];
// The name of the book-level tag which indicates auto-sort should run.
// Set to empty string ('') to run for all books.
$tagName = 'autosort';
// If it's one of our activity types, correctly tagged, run the auto-sort logic
if (in_array($type, $sortActivityTypes) && ($detail instanceof Page || $detail instanceof Chapter)) {
$book = $detail->book;
if (empty($tagName) || $book->tags()->where('name', '=', $tagName)->exists()) {
autoSortBook($detail->book);
}
}
});
@ssddanbrown
Copy link
Author

ssddanbrown commented Jun 27, 2024

@mschoon85 Happy to consider it, which is why it remains open at BookStackApp/BookStack#2065, but there's little demand for extra added complication & maintenance so not something I'd jump to right now.

I did add this to the hacks site here: https://www.bookstackapp.com/hacks/autosort-tagged-books/
If needed, there is an option there to request an update for the latest BookStack version via our hack update service.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment