- Created BookChild class to share some page/chapter logic.
- Gave entities the power to generate their own permissions and slugs.
- Moved bits out of BaseController constructor since it was overly
sticky.
- Moved slug generation logic into its own class.
- Created a facade for permissions due to high use.
- Fixed failing test issues from last commits
*/
public function removeEntity(Entity $entity)
{
+ // TODO - Rewrite to db query.
$activities = $entity->activity;
foreach ($activities as $activity) {
$activity->extra = $entity->name;
* @param Collection $books
* @param array $roles
* @param bool $deleteOld
- * @throws \Throwable
*/
protected function buildJointPermissionsForBooks($books, $roles, $deleteOld = false)
{
'Setting' => BookStack\Facades\Setting::class,
'Views' => BookStack\Facades\Views::class,
'Images' => BookStack\Facades\Images::class,
+ 'Permissions' => BookStack\Facades\Permissions::class,
],
--- /dev/null
+<?php namespace BookStack\Entities;
+
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+/**
+ * Class BookChild
+ * @property int $book_id
+ */
+class BookChild extends Entity
+{
+
+ /**
+ * Get the book this page sits in.
+ * @return BelongsTo
+ */
+ public function book(): BelongsTo
+ {
+ return $this->belongsTo(Book::class);
+ }
+
+}
\ No newline at end of file
*/
public function appendBook(Book $book)
{
- if (!$this->contains($book)) {
+ if ($this->contains($book)) {
return;
}
<?php namespace BookStack\Entities;
-class Chapter extends Entity
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class Chapter extends BookChild
{
public $searchFactor = 1.3;
return 'BookStack\\Chapter';
}
- /**
- * Get the book this chapter is within.
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function book()
- {
- return $this->belongsTo(Book::class);
- }
-
/**
* Get the pages that this chapter contains.
* @param string $dir
use BookStack\Actions\View;
use BookStack\Auth\Permissions\EntityPermission;
use BookStack\Auth\Permissions\JointPermission;
+use BookStack\Facades\Permissions;
use BookStack\Ownable;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\MorphMany;
*/
public function activity()
{
- return $this->morphMany(Activity::class, 'entity')->orderBy('created_at', 'desc');
+ return $this->morphMany(Activity::class, 'entity')
+ ->orderBy('created_at', 'desc');
}
/**
return $this->morphMany(View::class, 'viewable');
}
- public function viewCountQuery()
- {
- return $this->views()->selectRaw('viewable_id, sum(views) as view_count')->groupBy('viewable_id');
- }
-
/**
* Get the Tag models that have been user assigned to this entity.
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
return strtolower(static::getClassName());
}
+ /**
+ * Get the type of this entity.
+ */
+ public function type(): string
+ {
+ return static::getType();
+ }
+
/**
* Get an instance of an entity of the given type.
* @param $type
{
return $path;
}
+
+ /**
+ * Rebuild the permissions for this entity.
+ */
+ public function rebuildPermissions()
+ {
+ /** @noinspection PhpUnhandledExceptionInspection */
+ Permissions::buildJointPermissionsForEntity($this);
+ }
+
+ /**
+ * Generate and set a new URL slug for this model.
+ */
+ public function refreshSlug(): string
+ {
+ $generator = new SlugGenerator($this);
+ $this->slug = $generator->generate();
+ return $this->slug;
+ }
}
use BookStack\Uploads\Attachment;
-class Page extends Entity
+class Page extends BookChild
{
protected $fillable = ['name', 'html', 'priority', 'markdown'];
return $array;
}
- /**
- * Get the book this page sits in.
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function book()
- {
- return $this->belongsTo(Book::class);
- }
-
/**
* Get the parent item
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\User;
use BookStack\Entities\Book;
+use BookStack\Entities\BookChild;
use BookStack\Entities\Bookshelf;
use BookStack\Entities\Chapter;
use BookStack\Entities\Entity;
use BookStack\Exceptions\NotifyException;
use BookStack\Uploads\AttachmentService;
use DOMDocument;
-use DOMNode;
use DOMXPath;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
return $slug;
}
- /**
- * Check if a slug already exists in the database.
- * @param string $type
- * @param string $slug
- * @param bool|integer $currentId
- * @param bool|integer $bookId
- * @return bool
- */
- protected function slugExists($type, $slug, $currentId = false, $bookId = false)
- {
- $query = $this->entityProvider->get($type)->where('slug', '=', $slug);
- if (strtolower($type) === 'page' || strtolower($type) === 'chapter') {
- $query = $query->where('book_id', '=', $bookId);
- }
- if ($currentId) {
- $query = $query->where('id', '!=', $currentId);
- }
- return $query->count() > 0;
- }
/**
* Updates entity restrictions from a request
foreach ($restrictions as $action => $value) {
$entity->permissions()->create([
'role_id' => $roleId,
- 'action' => strtolower($action)
+ 'action' => strtolower($action),
]);
}
}
}
$entity->save();
- $this->permissionService->buildJointPermissionsForEntity($entity);
+ $entity->rebuildPermissions();
}
* @param array $input
* @param Book|null $book
* @return Entity
- * @throws Throwable
*/
public function createFromInput(string $type, array $input = [], Book $book = null)
{
$entityModel = $this->entityProvider->get($type)->newInstance($input);
- $entityModel->slug = $this->findSuitableSlug($type, $entityModel->name, false, $book ? $book->id : false);
$entityModel->created_by = user()->id;
$entityModel->updated_by = user()->id;
$entityModel->book_id = $book->id;
}
+ $entityModel->refreshSlug();
$entityModel->save();
if (isset($input['tags'])) {
$this->tagRepo->saveTagsToEntity($entityModel, $input['tags']);
}
- $this->permissionService->buildJointPermissionsForEntity($entityModel);
+ $entityModel->rebuildPermissions();
$this->searchService->indexEntity($entityModel);
return $entityModel;
}
/**
* Update entity details from request input.
- * Used for books and chapters
- * @param string $type
- * @param Entity $entityModel
- * @param array $input
- * @return Entity
- * @throws Throwable
+ * Used for books and chapters.
+ * TODO: Remove type param
*/
- public function updateFromInput(string $type, Entity $entityModel, array $input = [])
+ public function updateFromInput(string $type, Entity $entityModel, array $input = []): Entity
{
- if ($entityModel->name !== $input['name']) {
- $entityModel->slug = $this->findSuitableSlug($type, $input['name'], $entityModel->id);
- }
-
$entityModel->fill($input);
$entityModel->updated_by = user()->id;
+
+ if ($entityModel->isDirty('name')) {
+ $entityModel->refreshSlug();
+ }
+
$entityModel->save();
if (isset($input['tags'])) {
$this->tagRepo->saveTagsToEntity($entityModel, $input['tags']);
}
- $this->permissionService->buildJointPermissionsForEntity($entityModel);
+ $entityModel->rebuildPermissions();
$this->searchService->indexEntity($entityModel);
return $entityModel;
}
/**
* Change the book that an entity belongs to.
- * @param string $type
- * @param integer $newBookId
- * @param Entity $entity
- * @param bool $rebuildPermissions
- * @return Entity
*/
- public function changeBook($type, $newBookId, Entity $entity, $rebuildPermissions = false)
+ public function changeBook(BookChild $bookChild, int $newBookId): Entity
{
- $entity->book_id = $newBookId;
+ $bookChild->book_id = $newBookId;
+ $bookChild->refreshSlug();
+ $bookChild->save();
+
// Update related activity
- foreach ($entity->activity as $activity) {
- $activity->book_id = $newBookId;
- $activity->save();
- }
- $entity->slug = $this->findSuitableSlug($type, $entity->name, $entity->id, $newBookId);
- $entity->save();
+ $bookChild->activity()->update(['book_id' => $newBookId]);
// Update all child pages if a chapter
- if (strtolower($type) === 'chapter') {
- foreach ($entity->pages as $page) {
- $this->changeBook('page', $newBookId, $page, false);
+ if ($bookChild->isA('chapter')) {
+ foreach ($bookChild->pages as $page) {
+ $this->changeBook($page, $newBookId);
}
}
- // Update permissions if applicable
- if ($rebuildPermissions) {
- $entity->load('book');
- $this->permissionService->buildJointPermissionsForEntity($entity->book);
- }
-
- return $entity;
- }
-
- /**
- * Alias method to update the book jointPermissions in the PermissionService.
- * @param Book $book
- */
- public function buildJointPermissionsForBook(Book $book)
- {
- $this->permissionService->buildJointPermissionsForEntity($book);
- }
-
- /**
- * Format a name as a url slug.
- * @param $name
- * @return string
- */
- protected function nameToSlug($name)
- {
- $slug = preg_replace('/[\+\/\\\?\@\}\{\.\,\=\[\]\#\&\!\*\'\;\:\$\%]/', '', mb_strtolower($name));
- $slug = preg_replace('/\s{2,}/', ' ', $slug);
- $slug = str_replace(' ', '-', $slug);
- if ($slug === "") {
- $slug = substr(md5(rand(1, 500)), 0, 5);
- }
- return $slug;
+ return $bookChild;
}
/**
$shelfBooks = $bookshelf->books()->get();
$updatedBookCount = 0;
+ /** @var Book $book */
foreach ($shelfBooks as $book) {
if (!userCan('restrictions-manage', $book)) {
continue;
$book->restricted = $bookshelf->restricted;
$book->permissions()->createMany($shelfPermissions);
$book->save();
- $this->permissionService->buildJointPermissionsForEntity($book);
+ $book->rebuildPermissions();
$updatedBookCount++;
}
use DOMDocument;
use DOMElement;
use DOMXPath;
-use Illuminate\Support\Collection;
class PageRepo extends EntityRepo
{
$oldHtml = $page->html;
$oldName = $page->name;
- // Prevent slug being updated if no name change
- if ($page->name !== $input['name']) {
- $page->slug = $this->findSuitableSlug('page', $input['name'], $page->id, $book_id);
- }
-
// Save page tags if present
if (isset($input['tags'])) {
$this->tagRepo->saveTagsToEntity($page, $input['tags']);
$page->fill($input);
$page->html = $this->formatHtml($input['html']);
$page->text = $this->pageToPlainText($page);
+ $page->updated_by = $userId;
+ $page->revision_count++;
+
if (setting('app-editor') !== 'markdown') {
$page->markdown = '';
}
- $page->updated_by = $userId;
- $page->revision_count++;
+
+ if ($page->isDirty('name')) {
+ $page->refreshSlug();
+ }
+
$page->save();
// Remove all update drafts for this user & page.
}
$book->pages()->save($page);
- $page = $this->entityProvider->page->find($page->id);
- $this->permissionService->buildJointPermissionsForEntity($page);
+ $page->refresh()->rebuildPermissions();
return $page;
}
$draftPage->template = ($input['template'] === 'true');
}
- $draftPage->slug = $this->findSuitableSlug('page', $draftPage->name, false, $draftPage->book->id);
$draftPage->html = $this->formatHtml($input['html']);
$draftPage->text = $this->pageToPlainText($draftPage);
$draftPage->draft = false;
$draftPage->revision_count = 1;
-
+ $draftPage->refreshSlug();
$draftPage->save();
$this->savePageRevision($draftPage, trans('entities.pages_initial_revision'));
$this->searchService->indexEntity($draftPage);
{
$page->revision_count++;
$this->savePageRevision($page);
+
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
$page->fill($revision->toArray());
- $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
$page->text = $this->pageToPlainText($page);
$page->updated_by = user()->id;
+ $page->refreshSlug();
$page->save();
+
$this->searchService->indexEntity($page);
return $page;
}
* Change the page's parent to the given entity.
* @param Page $page
* @param Entity $parent
- * @throws \Throwable
*/
public function changePageParent(Page $page, Entity $parent)
{
$book = $parent->isA('book') ? $parent : $parent->book;
$page->chapter_id = $parent->isA('chapter') ? $parent->id : 0;
$page->save();
+
if ($page->book->id !== $book->id) {
- $page = $this->changeBook('page', $book->id, $page);
+ $page = $this->changeBook($page, $book->id);
}
+
$page->load('book');
- $this->permissionService->buildJointPermissionsForEntity($book);
+ $book->rebuildPermissions();
}
/**
--- /dev/null
+<?php namespace BookStack\Entities;
+
+class SlugGenerator
+{
+
+ protected $entity;
+
+ /**
+ * SlugGenerator constructor.
+ * @param $entity
+ */
+ public function __construct(Entity $entity)
+ {
+ $this->entity = $entity;
+ }
+
+ /**
+ * Generate a fresh slug for the given entity.
+ * The slug will generated so it does not conflict within the same parent item.
+ */
+ public function generate(): string
+ {
+ $slug = $this->formatNameAsSlug($this->entity->name);
+ while ($this->slugInUse($slug)) {
+ $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
+ }
+ return $slug;
+ }
+
+ /**
+ * Format a name as a url slug.
+ */
+ protected function formatNameAsSlug(string $name): string
+ {
+ $slug = preg_replace('/[\+\/\\\?\@\}\{\.\,\=\[\]\#\&\!\*\'\;\:\$\%]/', '', mb_strtolower($name));
+ $slug = preg_replace('/\s{2,}/', ' ', $slug);
+ $slug = str_replace(' ', '-', $slug);
+ if ($slug === "") {
+ $slug = substr(md5(rand(1, 500)), 0, 5);
+ }
+ return $slug;
+ }
+
+ /**
+ * Check if a slug is already in-use for this
+ * type of model within the same parent.
+ */
+ protected function slugInUse(string $slug): bool
+ {
+ $query = $this->entity->newQuery()->where('slug', '=', $slug);
+
+ if ($this->entity instanceof BookChild) {
+ $query->where('book_id', '=', $this->entity->book_id);
+ }
+
+ if ($this->entity->id) {
+ $query->where('id', '!=', $this->entity->id);
+ }
+
+ return $query->count() > 0;
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+<?php namespace BookStack\Facades;
+
+use Illuminate\Support\Facades\Facade;
+
+class Permissions extends Facade
+{
+ /**
+ * Get the registered name of the component.
+ *
+ * @return string
+ */
+ protected static function getFacadeAccessor()
+ {
+ return 'permissions';
+ }
+}
*/
public function index()
{
- $view = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books'));
- $sort = setting()->getUser($this->currentUser, 'books_sort', 'name');
- $order = setting()->getUser($this->currentUser, 'books_sort_order', 'asc');
+ $view = setting()->getForCurrentUser('books_view_type', config('app.views.books'));
+ $sort = setting()->getForCurrentUser('books_sort', 'name');
+ $order = setting()->getForCurrentUser('books_sort_order', 'asc');
$books = $this->bookRepo->getAllPaginated('book', 18, $sort, $order);
- $recents = $this->signedIn ? $this->bookRepo->getRecentlyViewed('book', 4, 0) : false;
+ $recents = $this->isSignedIn() ? $this->bookRepo->getRecentlyViewed('book', 4, 0) : false;
$popular = $this->bookRepo->getPopular('book', 4, 0);
$new = $this->bookRepo->getRecentlyCreated('book', 4, 0);
* @throws NotFoundException
* @throws ImageUploadException
* @throws ValidationException
- * @throws Throwable
*/
public function store(Request $request, string $shelfSlug = null)
{
* @return Factory|View
* @throws NotFoundException
*/
- public function getSortItem(string $bookSlug)
+ public function sortItem(string $bookSlug)
{
$book = $this->bookRepo->getBySlug($bookSlug);
$bookChildren = $this->bookRepo->getBookChildren($book);
// Get the books involved in the sort
$bookIdsInvolved = $bookIdsInvolved->unique()->toArray();
$booksInvolved = $this->bookRepo->getManyById('book', $bookIdsInvolved, false, true);
+
// Throw permission error if invalid ids or inaccessible books given.
if (count($bookIdsInvolved) !== count($booksInvolved)) {
$this->showPermissionError();
}
+
// Check permissions of involved books
$booksInvolved->each(function (Book $book) {
$this->checkOwnablePermission('book-update', $book);
$chapterChanged = ($mapItem->type === 'page') && intval($model->chapter_id) !== $mapItem->parentChapter;
if ($bookChanged) {
- $this->bookRepo->changeBook($mapItem->type, $mapItem->book, $model);
+ $this->bookRepo->changeBook($model, $mapItem->book);
}
if ($chapterChanged) {
$model->chapter_id = intval($mapItem->parentChapter);
// Rebuild permissions and add activity for involved books.
$booksInvolved->each(function (Book $book) {
- $this->bookRepo->buildJointPermissionsForBook($book);
+ $book->rebuildPermissions();
Activity::add($book, 'book_sort', $book->id);
});
*/
public function index()
{
- $view = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid'));
- $sort = setting()->getUser($this->currentUser, 'bookshelves_sort', 'name');
- $order = setting()->getUser($this->currentUser, 'bookshelves_sort_order', 'asc');
+ $view = setting()->getForCurrentUser('bookshelves_view_type', config('app.views.bookshelves', 'grid'));
+ $sort = setting()->getForCurrentUser('bookshelves_sort', 'name');
+ $order = setting()->getForCurrentUser('bookshelves_sort_order', 'asc');
$sortOptions = [
'name' => trans('common.sort_name'),
'created_at' => trans('common.sort_created_at'),
$shelf->books = $this->entityRepo->getBookshelfChildren($shelf);
}
- $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('bookshelf', 4, 0) : false;
+ $recents = $this->isSignedIn() ? $this->entityRepo->getRecentlyViewed('bookshelf', 4, 0) : false;
$popular = $this->entityRepo->getPopular('bookshelf', 4, 0);
$new = $this->entityRepo->getRecentlyCreated('bookshelf', 4, 0);
return redirect()->back();
}
- $this->entityRepo->changeBook('chapter', $parent->id, $chapter, true);
+ $this->entityRepo->changeBook($chapter, $parent->id);
+ $chapter->rebuildPermissions();
+
Activity::add($chapter, 'chapter_move', $chapter->book->id);
$this->showSuccessNotification( trans('entities.chapter_move_success', ['bookName' => $parent->name]));
namespace BookStack\Http\Controllers;
-use BookStack\Auth\User;
-use BookStack\Entities\Entity;
-use BookStack\Facades\Activity;
use BookStack\Ownable;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use DispatchesJobs, ValidatesRequests;
/**
- * @var User static
- */
- protected $currentUser;
-
- /**
- * @var bool
+ * Controller constructor.
*/
- protected $signedIn;
+ public function __construct()
+ {
+ //
+ }
/**
- * Controller constructor.
+ * Check if the current user is signed in.
*/
- public function __construct()
+ protected function isSignedIn(): bool
{
- $this->currentUser = user();
- $this->signedIn = auth()->check();
+ return auth()->check();
}
/**
protected function checkPermissionOrCurrentUser(string $permissionName, int $userId)
{
return $this->checkPermissionOr($permissionName, function () use ($userId) {
- return $userId === $this->currentUser->id;
+ return $userId === user()->id;
});
}
public function index()
{
$activity = Activity::latest(10);
- $draftPages = $this->signedIn ? $this->entityRepo->getUserDraftPages(6) : [];
+ $draftPages = $this->isSignedIn() ? $this->entityRepo->getUserDraftPages(6) : [];
$recentFactor = count($draftPages) > 0 ? 0.5 : 1;
- $recents = $this->signedIn ? Views::getUserRecentlyViewed(12*$recentFactor, 0) : $this->entityRepo->getRecentlyCreated('book', 12*$recentFactor);
+ $recents = $this->isSignedIn() ? Views::getUserRecentlyViewed(12*$recentFactor, 0) : $this->entityRepo->getRecentlyCreated('book', 12*$recentFactor);
$recentlyUpdatedPages = $this->entityRepo->getRecentlyUpdated('page', 12);
$homepageOptions = ['default', 'books', 'bookshelves', 'page'];
// Add required list ordering & sorting for books & shelves views.
if ($homepageOption === 'bookshelves' || $homepageOption === 'books') {
$key = $homepageOption;
- $view = setting()->getUser($this->currentUser, $key . '_view_type', config('app.views.' . $key));
- $sort = setting()->getUser($this->currentUser, $key . '_sort', 'name');
- $order = setting()->getUser($this->currentUser, $key . '_sort_order', 'asc');
+ $view = setting()->getForCurrentUser($key . '_view_type', config('app.views.' . $key));
+ $sort = setting()->getForCurrentUser($key . '_sort', 'name');
+ $order = setting()->getForCurrentUser($key . '_sort_order', 'asc');
$sortOptions = [
'name' => trans('common.sort_name'),
$this->checkOwnablePermission('page-create', $parent);
// Redirect to draft edit screen if signed in
- if ($this->signedIn) {
+ if ($this->isSignedIn()) {
$draft = $this->pageRepo->getDraftPage($book, $chapter);
return redirect($draft->getUrl());
}
$this->checkOwnablePermission('page-create', $draft->parent);
$this->setPageTitle(trans('entities.pages_edit_draft'));
- $draftsEnabled = $this->signedIn;
+ $draftsEnabled = $this->isSignedIn();
$templates = $this->pageRepo->getPageTemplates(10);
return view('pages.edit', [
}
// Check for a current draft version for this user
- $userPageDraft = $this->pageRepo->getUserPageDraft($page, $this->currentUser->id);
+ $userPageDraft = $this->pageRepo->getUserPageDraft($page, user()->id);
if ($userPageDraft !== null) {
$page->name = $userPageDraft->name;
$page->html = $userPageDraft->html;
$this->showWarningNotification( implode("\n", $warnings));
}
- $draftsEnabled = $this->signedIn;
+ $draftsEnabled = $this->isSignedIn();
$templates = $this->pageRepo->getPageTemplates(10);
return view('pages.edit', [
$page = $this->pageRepo->getById('page', $pageId, true);
$this->checkOwnablePermission('page-update', $page);
- if (!$this->signedIn) {
+ if (!$this->isSignedIn()) {
return response()->json([
'status' => 'error',
'message' => trans('errors.guests_cannot_save_drafts'),
}
// External auth id updates
- if ($this->currentUser->can('users-manage') && $request->filled('external_auth_id')) {
+ if (user()->can('users-manage') && $request->filled('external_auth_id')) {
$user->external_auth_id = $request->get('external_auth_id');
}
use BookStack\Actions\ActivityService;
use BookStack\Actions\ViewService;
+use BookStack\Auth\Permissions\PermissionService;
use BookStack\Settings\SettingService;
use BookStack\Uploads\ImageService;
use Illuminate\Support\ServiceProvider;
*/
public function register()
{
- $this->app->bind('activity', function () {
+ $this->app->singleton('activity', function () {
return $this->app->make(ActivityService::class);
});
- $this->app->bind('views', function () {
+ $this->app->singleton('views', function () {
return $this->app->make(ViewService::class);
});
- $this->app->bind('setting', function () {
+ $this->app->singleton('setting', function () {
return $this->app->make(SettingService::class);
});
- $this->app->bind('images', function () {
+ $this->app->singleton('images', function () {
return $this->app->make(ImageService::class);
});
+
+ $this->app->singleton('permissions', function () {
+ return $this->app->make(PermissionService::class);
+ });
}
}
<server name="DB_CONNECTION" value="mysql_testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="MAIL_DRIVER" value="array"/>
- <server name="LOG_CHANNEL" value="null"/>
+ <server name="LOG_CHANNEL" value="single"/>
<server name="AUTH_METHOD" value="standard"/>
<server name="DISABLE_EXTERNAL_SERVICES" value="true"/>
<server name="AVATAR_URL" value=""/>
Route::get('/{slug}/edit', 'BookController@edit');
Route::put('/{slug}', 'BookController@update');
Route::delete('/{id}', 'BookController@destroy');
- Route::get('/{slug}/sort-item', 'BookController@getSortItem');
+ Route::get('/{slug}/sort-item', 'BookController@sortItem');
Route::get('/{slug}', 'BookController@show');
Route::get('/{bookSlug}/permissions', 'BookController@showPermissions');
Route::put('/{bookSlug}/permissions', 'BookController@permissions');
public function test_draft_content_shows_if_available()
{
$addedContent = '<p>test message content</p>';
- $this->asAdmin()->visit($this->page->getUrl() . '/edit')
+ $this->asAdmin()->visit($this->page->getUrl('/edit'))
->dontSeeInField('html', $addedContent);
$newContent = $this->page->html . $addedContent;
$this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]);
- $this->asAdmin()->visit($this->page->getUrl() . '/edit')
+ $this->asAdmin()->visit($this->page->getUrl('/edit'))
->seeInField('html', $newContent);
}
public function test_draft_not_visible_by_others()
{
$addedContent = '<p>test message content</p>';
- $this->asAdmin()->visit($this->page->getUrl() . '/edit')
+ $this->asAdmin()->visit($this->page->getUrl('/edit'))
->dontSeeInField('html', $addedContent);
$newContent = $this->page->html . $addedContent;
$newUser = $this->getEditor();
$this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]);
- $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit')
+
+ $this->actingAs($newUser)->visit($this->page->getUrl('/edit'))
->dontSeeInField('html', $newContent);
}
{
$this->asAdmin();
$this->pageRepo->updatePageDraft($this->page, ['html' => 'test content']);
- $this->asAdmin()->visit($this->page->getUrl() . '/edit')
+ $this->asAdmin()->visit($this->page->getUrl('/edit'))
->see('You are currently editing a draft');
}
{
$nonEditedPage = \BookStack\Entities\Page::take(10)->get()->last();
$addedContent = '<p>test message content</p>';
- $this->asAdmin()->visit($this->page->getUrl() . '/edit')
+ $this->asAdmin()->visit($this->page->getUrl('/edit'))
->dontSeeInField('html', $addedContent);
$newContent = $this->page->html . $addedContent;
$this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]);
$this->actingAs($newUser)
- ->visit($this->page->getUrl() . '/edit')
+ ->visit($this->page->getUrl('/edit'))
->see('Admin has started editing this page');
$this->flushSession();
$this->visit($nonEditedPage->getUrl() . '/edit')
use BookStack\Entities\Book;
use BookStack\Entities\Chapter;
use BookStack\Actions\Tag;
+use BookStack\Entities\Entity;
use BookStack\Entities\Page;
use BookStack\Auth\Permissions\PermissionService;
/**
* Get an instance of a page that has many tags.
* @param \BookStack\Actions\Tag[]|bool $tags
- * @return mixed
+ * @return Entity
*/
- protected function getEntityWithTags($class, $tags = false)
+ protected function getEntityWithTags($class, $tags = false): Entity
{
$entity = $class::first();
// Set restricted permission the page
$page->restricted = true;
$page->save();
- $permissionService->buildJointPermissionsForEntity($page);
+ $page->rebuildPermissions();
$this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
$this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals([]);
*/
protected function regenEntityPermissions(Entity $entity)
{
- app(PermissionService::class)->buildJointPermissionsForEntity($entity);
+ $entity->rebuildPermissions();
$entity->load('jointPermissions');
}