Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/Access/Mfa/MfaSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class MfaSession
*/
public function isRequiredForUser(User $user): bool
{
// TODO - Test both these cases
return $user->mfaValues()->exists() || $this->userRoleEnforcesMfa($user);
}

Expand Down
6 changes: 2 additions & 4 deletions app/Console/Commands/UpdateUrlCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ public function handle(Connection $db): int

$columnsToUpdateByTable = [
'attachments' => ['path'],
'pages' => ['html', 'text', 'markdown'],
'chapters' => ['description_html'],
'books' => ['description_html'],
'bookshelves' => ['description_html'],
'entity_page_data' => ['html', 'text', 'markdown'],
'entity_container_data' => ['description_html'],
'page_revisions' => ['html', 'text', 'markdown'],
'images' => ['url'],
'settings' => ['value'],
Expand Down
7 changes: 4 additions & 3 deletions app/Entities/Controllers/BookApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,10 @@ protected function forJsonDisplay(Book $book): Book
$book = clone $book;
$book->unsetRelations()->refresh();

$book->load(['tags', 'cover']);
$book->makeVisible('description_html')
->setAttribute('description_html', $book->descriptionHtml());
$book->load(['tags']);
$book->makeVisible(['cover', 'description_html'])
->setAttribute('description_html', $book->descriptionInfo()->getHtml())
->setAttribute('cover', $book->coverInfo()->getImage());

return $book;
}
Expand Down
7 changes: 4 additions & 3 deletions app/Entities/Controllers/BookshelfApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ protected function forJsonDisplay(Bookshelf $shelf): Bookshelf
$shelf = clone $shelf;
$shelf->unsetRelations()->refresh();

$shelf->load(['tags', 'cover']);
$shelf->makeVisible('description_html')
->setAttribute('description_html', $shelf->descriptionHtml());
$shelf->load(['tags']);
$shelf->makeVisible(['cover', 'description_html'])
->setAttribute('description_html', $shelf->descriptionInfo()->getHtml())
->setAttribute('cover', $shelf->coverInfo()->getImage());

return $shelf;
}
Expand Down
1 change: 1 addition & 0 deletions app/Entities/Controllers/BookshelfController.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public function show(Request $request, ActivityQueries $activities, string $slug
]);

$sort = $listOptions->getSort();

$sortedVisibleShelfBooks = $shelf->visibleBooks()
->reorder($sort === 'default' ? 'order' : $sort, $listOptions->getOrder())
->get()
Expand Down
4 changes: 2 additions & 2 deletions app/Entities/Controllers/ChapterApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function update(Request $request, string $id)
$chapter = $this->queries->findVisibleByIdOrFail(intval($id));
$this->checkOwnablePermission(Permission::ChapterUpdate, $chapter);

if ($request->has('book_id') && $chapter->book_id !== intval($requestData['book_id'])) {
if ($request->has('book_id') && $chapter->book_id !== (intval($requestData['book_id']) ?: null)) {
$this->checkOwnablePermission(Permission::ChapterDelete, $chapter);

try {
Expand Down Expand Up @@ -144,7 +144,7 @@ protected function forJsonDisplay(Chapter $chapter): Chapter

$chapter->load(['tags']);
$chapter->makeVisible('description_html');
$chapter->setAttribute('description_html', $chapter->descriptionHtml());
$chapter->setAttribute('description_html', $chapter->descriptionInfo()->getHtml());

/** @var Book $book */
$book = $chapter->book()->first();
Expand Down
2 changes: 1 addition & 1 deletion app/Entities/Controllers/ChapterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public function update(Request $request, string $bookSlug, string $chapterSlug)
$chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission(Permission::ChapterUpdate, $chapter);

$this->chapterRepo->update($chapter, $validated);
$chapter = $this->chapterRepo->update($chapter, $validated);

return redirect($chapter->getUrl());
}
Expand Down
1 change: 1 addition & 0 deletions app/Entities/Controllers/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public function store(Request $request, string $bookSlug, int $pageId)
$this->validate($request, [
'name' => ['required', 'string', 'max:255'],
]);

$draftPage = $this->queries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission(Permission::PageCreate, $draftPage->getParent());

Expand Down
20 changes: 20 additions & 0 deletions app/Entities/EntityExistsRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace BookStack\Entities;

use Illuminate\Validation\Rules\Exists;

class EntityExistsRule implements \Stringable
{
public function __construct(
protected string $type,
) {
}

public function __toString()
{
$existsRule = (new Exists('entities', 'id'))
->where('type', $this->type);
return $existsRule->__toString();
}
}
91 changes: 33 additions & 58 deletions app/Entities/Models/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

namespace BookStack\Entities\Models;

use BookStack\Entities\Tools\EntityCover;
use BookStack\Entities\Tools\EntityDefaultTemplate;
use BookStack\Sorting\SortRule;
use BookStack\Uploads\Image;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
Expand All @@ -15,26 +16,25 @@
* Class Book.
*
* @property string $description
* @property string $description_html
* @property int $image_id
* @property ?int $default_template_id
* @property ?int $sort_rule_id
* @property Image|null $cover
* @property \Illuminate\Database\Eloquent\Collection $chapters
* @property \Illuminate\Database\Eloquent\Collection $pages
* @property \Illuminate\Database\Eloquent\Collection $directPages
* @property \Illuminate\Database\Eloquent\Collection $shelves
* @property ?Page $defaultTemplate
* @property ?SortRule $sortRule
* @property ?SortRule $sortRule
*/
class Book extends Entity implements CoverImageInterface, HtmlDescriptionInterface
class Book extends Entity implements HasDescriptionInterface, HasCoverInterface, HasDefaultTemplateInterface
{
use HasFactory;
use HtmlDescriptionTrait;
use ContainerTrait;

public float $searchFactor = 1.2;

protected $hidden = ['pivot', 'deleted_at', 'description_html', 'entity_id', 'entity_type', 'chapter_id', 'book_id', 'priority'];
protected $fillable = ['name'];
protected $hidden = ['pivot', 'image_id', 'deleted_at', 'description_html'];

/**
* Get the url for this book.
Expand All @@ -44,55 +44,6 @@ public function getUrl(string $path = ''): string
return url('/books/' . implode('/', [urlencode($this->slug), trim($path, '/')]));
}

/**
* Returns book cover image, if book cover not exists return default cover image.
*/
public function getBookCover(int $width = 440, int $height = 250): string
{
$default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
if (!$this->image_id || !$this->cover) {
return $default;
}

try {
return $this->cover->getThumb($width, $height, false) ?? $default;
} catch (Exception $err) {
return $default;
}
}

/**
* Get the cover image of the book.
*/
public function cover(): BelongsTo
{
return $this->belongsTo(Image::class, 'image_id');
}

/**
* Get the type of the image model that is used when storing a cover image.
*/
public function coverImageTypeKey(): string
{
return 'cover_book';
}

/**
* Get the Page that is used as default template for newly created pages within this Book.
*/
public function defaultTemplate(): BelongsTo
{
return $this->belongsTo(Page::class, 'default_template_id');
}

/**
* Get the sort set assigned to this book, if existing.
*/
public function sortRule(): BelongsTo
{
return $this->belongsTo(SortRule::class);
}

/**
* Get all pages within this book.
* @return HasMany<Page, $this>
Expand All @@ -107,7 +58,7 @@ public function pages(): HasMany
*/
public function directPages(): HasMany
{
return $this->pages()->where('chapter_id', '=', '0');
return $this->pages()->whereNull('chapter_id');
}

/**
Expand All @@ -116,7 +67,8 @@ public function directPages(): HasMany
*/
public function chapters(): HasMany
{
return $this->hasMany(Chapter::class);
return $this->hasMany(Chapter::class)
->where('type', '=', 'chapter');
}

/**
Expand All @@ -137,4 +89,27 @@ public function getDirectVisibleChildren(): Collection

return $pages->concat($chapters)->sortBy('priority')->sortByDesc('draft');
}

public function defaultTemplate(): EntityDefaultTemplate
{
return new EntityDefaultTemplate($this);
}

public function cover(): BelongsTo
{
return $this->belongsTo(Image::class, 'image_id');
}

public function coverInfo(): EntityCover
{
return new EntityCover($this);
}

/**
* Get the sort rule assigned to this container, if existing.
*/
public function sortRule(): BelongsTo
{
return $this->belongsTo(SortRule::class);
}
}
5 changes: 2 additions & 3 deletions app/Entities/Models/BookChild.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace BookStack\Entities\Models;

use BookStack\References\ReferenceUpdater;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
Expand All @@ -27,13 +26,13 @@ public function book(): BelongsTo
/**
* Change the book that this entity belongs to.
*/
public function changeBook(int $newBookId): Entity
public function changeBook(int $newBookId): self
{
$oldUrl = $this->getUrl();
$this->book_id = $newBookId;
$this->unsetRelation('book');
$this->refreshSlug();
$this->save();
$this->refresh();

if ($oldUrl !== $this->getUrl()) {
app()->make(ReferenceUpdater::class)->updateEntityReferences($this, $oldUrl);
Expand Down
Loading