Skip to content
Merged
6 changes: 4 additions & 2 deletions app/App/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function index(
: $this->queries->books->visibleForList()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
$favourites = $topFavourites->run(6);
$recentlyUpdatedPages = $this->queries->pages->visibleForList()
->where('draft', false)
->where('entity_page_data.draft', false)
->orderBy('updated_at', 'desc')
->take($favourites->count() > 0 ? 5 : 10)
->get();
Expand Down Expand Up @@ -102,7 +102,9 @@ public function index(
$homepageSetting = setting('app-homepage', '0:');
$id = intval(explode(':', $homepageSetting)[0]);
/** @var Page $customHomepage */
$customHomepage = $this->queries->pages->start()->where('draft', '=', false)->findOrFail($id);
$customHomepage = $this->queries->pages->start()
->where('entity_page_data.draft', '=', false)
->findOrFail($id);
$pageContent = new PageContent($customHomepage);
$customHomepage->html = $pageContent->render(false);

Expand Down
2 changes: 2 additions & 0 deletions app/Config/setting-defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'page-draft-color-dark' => '#a66ce8',
'app-custom-head' => false,
'registration-enabled' => false,
'default_page_cover_image' => ENV('DEFAULT_PAGE_COVER_IMAGE', 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='),

// User-level default settings
'user' => [
Expand All @@ -41,6 +42,7 @@
'bookshelves_view_type' => env('APP_VIEWS_BOOKSHELVES', 'grid'),
'bookshelf_view_type' => env('APP_VIEWS_BOOKSHELF', 'grid'),
'books_view_type' => env('APP_VIEWS_BOOKS', 'grid'),
'pages_view_type' => env('APP_VIEWS_BOOKS', 'grid'),
'notifications#comment-mentions' => true,
],

Expand Down
3 changes: 3 additions & 0 deletions app/Entities/Controllers/ChapterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ public function store(Request $request, string $bookSlug)
*/
public function show(string $bookSlug, string $chapterSlug)
{
$view = setting()->getForCurrentUser(key: 'pages_view_type');
try {
$chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-view', $chapter);
} catch (NotFoundException $exception) {
$chapter = $this->entityQueries->findVisibleByOldSlugs('chapter', $chapterSlug, $bookSlug);
if (is_null($chapter)) {
Expand All @@ -105,6 +107,7 @@ public function show(string $bookSlug, string $chapterSlug)
'next' => $nextPreviousLocator->getNext(),
'previous' => $nextPreviousLocator->getPrevious(),
'referenceCount' => $this->referenceFetcher->getReferenceCountToEntity($chapter),
'view' => $view,
]);
}

Expand Down
6 changes: 6 additions & 0 deletions app/Entities/Controllers/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ public function update(Request $request, string $bookSlug, string $pageSlug)
$page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission(Permission::PageUpdate, $page);

if ($request->has('image_reset')) {
$request['image'] = null;
} elseif (array_key_exists('image', $request->all()) && is_null($request['image'])) {
unset($request['image']);
}

$this->pageRepo->update($page, $request->all());

return redirect($page->getUrl());
Expand Down
2 changes: 2 additions & 0 deletions app/Entities/Models/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
* @property int|null $updated_by
* @property int|null $owned_by
* @property Collection $tags
* @property string $description
* @property string $description_html
*
* @method static Entity|Builder visible()
* @method static Builder withLastView()
Expand Down
9 changes: 9 additions & 0 deletions app/Entities/Models/EntityContainerData.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ class EntityContainerData extends Model
public $timestamps = false;
protected $primaryKey = 'entity_id';
public $incrementing = false;
protected $fillable = [
'entity_id',
'entity_type',
'description',
'description_html',
'default_template_id',
'image_id',
'sort_rule_id',
];

public static array $fields = [
'description',
Expand Down
1 change: 1 addition & 0 deletions app/Entities/Models/EntityPageData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ class EntityPageData extends Model
'html',
'text',
'markdown',
'image_id'
];
}
34 changes: 31 additions & 3 deletions app/Entities/Models/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

namespace BookStack\Entities\Models;

use BookStack\Entities\Tools\EntityCover;
use BookStack\Entities\Tools\EntityDefaultTemplate;
use BookStack\Entities\Tools\EntityHtmlDescription;
use BookStack\Uploads\Image;
use BookStack\Entities\Tools\PageContent;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Uploads\Attachment;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
Expand All @@ -23,22 +28,25 @@
* @property bool $draft
* @property int $revision_count
* @property string $editor
* @property Image|null $cover
* @property Chapter $chapter
* @property Collection $attachments
* @property Collection $revisions
* @property PageRevision $currentRevision
*/
class Page extends BookChild
class Page extends BookChild implements HasDescriptionInterface, HasCoverInterface
{
use HasFactory;

// use ContainerTrait;

public string $textField = 'text';
public string $htmlField = 'html';
protected $hidden = ['html', 'markdown', 'text', 'pivot', 'deleted_at', 'entity_id', 'entity_type'];
protected $hidden = ['html', 'markdown', 'text', 'pivot', 'deleted_at', 'entity_id', 'entity_type'];
protected $fillable = ['name', 'priority'];

protected $casts = [
'draft' => 'boolean',
'draft' => 'boolean',
'template' => 'boolean',
];

Expand Down Expand Up @@ -145,6 +153,26 @@ public function forJsonDisplay(): self
return $refreshed;
}


public function descriptionInfo(): EntityHtmlDescription
{
return new EntityHtmlDescription($this);
}

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

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

public function coverImageTypeKey(): string
{
return 'cover_page';
}
/**
* @return HasOne<EntityPageData, $this>
*/
Expand Down
48 changes: 34 additions & 14 deletions app/Entities/Queries/PageQueries.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@
class PageQueries implements ProvidesEntityQueries
{
protected static array $contentAttributes = [
'name', 'id', 'slug', 'book_id', 'chapter_id', 'draft',
'template', 'html', 'markdown', 'text', 'created_at', 'updated_at', 'priority',
'created_by', 'updated_by', 'owned_by',
'entities.name as name', 'entities.id as id', 'entities.slug as slug', 'entities.book_id as book_id',
'entities.chapter_id as chapter_id', 'entity_page_data.draft as draft',
'entity_page_data.template as template', 'entity_page_data.html as html', 'entity_page_data.markdown as markdown',
'entity_page_data.text as text', 'entities.created_at as created_at', 'entities.updated_at as updated_at',
'entities.priority as priority', 'entities.created_by as created_by', 'entities.updated_by as updated_by',
'entities.owned_by as owned_by',
];
protected static array $listAttributes = [
'name', 'id', 'slug', 'book_id', 'chapter_id', 'draft',
'template', 'text', 'created_at', 'updated_at', 'priority', 'owned_by',
'entities.name as name', 'entities.id as id', 'entities.slug as slug', 'entities.book_id as book_id',
'entities.chapter_id as chapter_id', 'entity_page_data.draft as draft',
'entity_page_data.template as template', 'entity_page_data.text as text', 'entities.created_at as created_at',
'entities.updated_at as updated_at', 'entities.priority as priority', 'entities.owned_by as owned_by',
];

/**
Expand Down Expand Up @@ -79,7 +84,12 @@ public function visibleForList(): Builder
{
return $this->start()
->scopes('visible')
->select($this->mergeBookSlugForSelect(static::$listAttributes));
->select(array_merge(
$this->mergeBookSlugForSelect(static::$listAttributes),
[
'entity_page_data.image_id',
]
));
}

/**
Expand All @@ -92,30 +102,35 @@ public function visibleForContent(): Builder

public function visibleForChapterList(int $chapterId): Builder
{
return $this->visibleForList()
->where('chapter_id', '=', $chapterId)
->orderBy('draft', 'desc')
->orderBy('priority', 'asc');
return $this->visibleForListWithCover()
->where('entities.chapter_id', '=', $chapterId)
->orderBy('entity_page_data.draft', 'desc')
->orderBy('entities.priority', 'asc');
}

public function visibleWithContents(): Builder
{
return $this->start()
->scopes('visible')
->select($this->mergeBookSlugForSelect(static::$contentAttributes));
->select(array_merge(
$this->mergeBookSlugForSelect(static::$contentAttributes),
[
'entity_page_data.image_id',
]
));
}

public function currentUserDraftsForList(): Builder
{
return $this->visibleForList()
->where('draft', '=', true)
->where('created_by', '=', user()->id);
->where('entity_page_data.draft', '=', true)
->where('entities.created_by', '=', user()->id);
}

public function visibleTemplates(bool $includeContents = false): Builder
{
$base = $includeContents ? $this->visibleWithContents() : $this->visibleForList();
return $base->where('template', '=', true);
return $base->where('entity_page_data.template', '=', true);
}

protected function mergeBookSlugForSelect(array $columns): array
Expand All @@ -127,4 +142,9 @@ protected function mergeBookSlugForSelect(array $columns): array
->whereColumn('books.id', '=', 'entities.book_id');
}]);
}

public function visibleForListWithCover(): Builder
{
return $this->visibleForList()->with('cover');
}
}
8 changes: 8 additions & 0 deletions app/Entities/Repos/PageRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ public function publishDraft(Page $draft, array $input): Page
$draft->priority = $this->getNewPriority($draft);
$this->updateTemplateStatusAndContentFromInput($draft, $input);

if (array_key_exists('image', $input)) {
$this->baseRepo->updateCoverImage($draft, $input['image'], $input['image'] === null);
}

$draft = $this->baseRepo->update($draft, $input);
$draft->rebuildPermissions();

Expand Down Expand Up @@ -142,6 +146,10 @@ public function update(Page $page, array $input): Page
$this->revisionRepo->storeNewForPage($page, $summary);
}

if (array_key_exists('image', $input)) {
$this->baseRepo->updateCoverImage($page, $input['image'], $input['image'] === null);
}

Activity::add(ActivityType::PAGE_UPDATE, $page);
$this->baseRepo->sortParent($page);

Expand Down
4 changes: 2 additions & 2 deletions app/Entities/Tools/BookContents.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function __construct(
public function getLastPriority(): int
{
$maxPage = $this->book->pages()
->where('draft', '=', false)
->where('entity_page_data.draft', '=', false)
->whereDoesntHave('chapter')
->max('priority');

Expand Down Expand Up @@ -97,7 +97,7 @@ protected function getPages(bool $showDrafts = false, bool $getPageContent = fal
}

if (!$showDrafts) {
$query->where('draft', '=', false);
$query->where('entity_page_data.draft', '=', false);
}

return $query->where('book_id', '=', $this->book->id)->get();
Expand Down
3 changes: 1 addition & 2 deletions app/Entities/Tools/Cloner.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ protected function createBookClone(Book $original, string $newName): Book

// Clone book
$copyBook = $this->bookRepo->create($bookDetails);
$this->referenceChangeContext->add($original, $copyBook);

// Clone contents
$directChildren = $original->getDirectVisibleChildren();
Expand All @@ -127,8 +128,6 @@ protected function createBookClone(Book $original, string $newName): Book
}
}

$this->referenceChangeContext->add($original, $copyBook);

return $copyBook;
}

Expand Down
4 changes: 3 additions & 1 deletion app/Entities/Tools/EntityCover.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Page;
use BookStack\Uploads\Image;
use Exception;
use Illuminate\Database\Eloquent\Builder;

class EntityCover
{
public function __construct(
protected Book|Bookshelf $entity,
protected Book|Bookshelf|Page $entity,
) {
}

Expand All @@ -33,6 +34,7 @@ public function exists(): bool
*/
public function getImage(): Image|null
{

if ($this->entity->image_id === null) {
return null;
}
Expand Down
3 changes: 2 additions & 1 deletion app/Entities/Tools/EntityHtmlDescription.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use BookStack\Util\HtmlContentFilter;

class EntityHtmlDescription
Expand All @@ -13,7 +14,7 @@ class EntityHtmlDescription
protected string $plain = '';

public function __construct(
protected Book|Chapter|Bookshelf $entity,
protected Book|Chapter|Bookshelf|Page $entity,
) {
$this->html = $this->entity->description_html ?? '';
$this->plain = $this->entity->description ?? '';
Expand Down
6 changes: 3 additions & 3 deletions app/Permissions/PermissionApplicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ public function restrictEntityQuery(Builder $query): Builder
public function restrictDraftsOnPageQuery(Builder $query): Builder
{
return $query->where(function (Builder $query) {
$query->where('draft', '=', false)
$query->where('entity_page_data.draft', '=', false)
->orWhere(function (Builder $query) {
$query->where('draft', '=', true)
->where('owned_by', '=', $this->currentUser()->id);
$query->where('entity_page_data.draft', '=', true)
->where('entities.owned_by', '=', $this->currentUser()->id);
});
});
}
Expand Down
Loading
Loading