Hacks & Customizations
These hacks are unsupported customizations meant as unofficial workarounds.
They can cause instability, introduce issues and may conflict with future updates. Apply at your own risk!

Autosort Tagged Books

  • Author: @ssddanbrown
  • Created: 23rd Jan 2023
  • Updated: 23rd Jan 2023
  • Last Tested On: v22.11.1

This is a hack to BookStack 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.

Options

Customize the tag name, if desired, by tweaking the string at around line 45. Set this to empty to run for all books.

Code

functions.php
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?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);
        }
    }

});

Request an Update

Hack not working on the latest version of BookStack?
You can request this hack to be updated & tested for a small one-time fee.
This helps keeps these hacks updated & maintained in a sustainable manner.


Latest Hacks