mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-01-03 23:42:28 +03:00
Added per-item recycle-bin delete and restore
This commit is contained in:
@@ -287,6 +287,22 @@ class Entity extends Ownable
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent entity if existing.
|
||||
* This is the "static" parent and does not include dynamic
|
||||
* relations such as shelves to books.
|
||||
*/
|
||||
public function getParent(): ?Entity
|
||||
{
|
||||
if ($this->isA('page')) {
|
||||
return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book->withTrashed()->first();
|
||||
}
|
||||
if ($this->isA('chapter')) {
|
||||
return $this->book->withTrashed()->first();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the permissions for this entity.
|
||||
*/
|
||||
|
||||
@@ -180,24 +180,91 @@ class TrashCan
|
||||
|
||||
/**
|
||||
* Destroy all items that have pending deletions.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroyFromAllDeletions(): int
|
||||
{
|
||||
$deletions = Deletion::all();
|
||||
$deleteCount = 0;
|
||||
foreach ($deletions as $deletion) {
|
||||
// For each one we load in the relation since it may have already
|
||||
// been deleted as part of another deletion in this loop.
|
||||
$entity = $deletion->deletable()->first();
|
||||
if ($entity) {
|
||||
$count = $this->destroyEntity($deletion->deletable);
|
||||
$deleteCount += $count;
|
||||
}
|
||||
$deletion->delete();
|
||||
$deleteCount += $this->destroyFromDeletion($deletion);
|
||||
}
|
||||
return $deleteCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an element from the given deletion model.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroyFromDeletion(Deletion $deletion): int
|
||||
{
|
||||
// We directly load the deletable element here just to ensure it still
|
||||
// exists in the event it has already been destroyed during this request.
|
||||
$entity = $deletion->deletable()->first();
|
||||
$count = 0;
|
||||
if ($entity) {
|
||||
$count = $this->destroyEntity($deletion->deletable);
|
||||
}
|
||||
$deletion->delete();
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the content within the given deletion.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function restoreFromDeletion(Deletion $deletion): int
|
||||
{
|
||||
$shouldRestore = true;
|
||||
$restoreCount = 0;
|
||||
$parent = $deletion->deletable->getParent();
|
||||
|
||||
if ($parent && $parent->trashed()) {
|
||||
$shouldRestore = false;
|
||||
}
|
||||
|
||||
if ($shouldRestore) {
|
||||
$restoreCount = $this->restoreEntity($deletion->deletable);
|
||||
}
|
||||
|
||||
$deletion->delete();
|
||||
return $restoreCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore an entity so it is essentially un-deleted.
|
||||
* Deletions on restored child elements will be removed during this restoration.
|
||||
*/
|
||||
protected function restoreEntity(Entity $entity): int
|
||||
{
|
||||
$count = 1;
|
||||
$entity->restore();
|
||||
|
||||
if ($entity->isA('chapter') || $entity->isA('book')) {
|
||||
foreach ($entity->pages()->withTrashed()->withCount('deletions')->get() as $page) {
|
||||
if ($page->deletions_count > 0) {
|
||||
$page->deletions()->delete();
|
||||
}
|
||||
|
||||
$page->restore();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->isA('book')) {
|
||||
foreach ($entity->chapters()->withTrashed()->withCount('deletions')->get() as $chapter) {
|
||||
if ($chapter->deletions_count === 0) {
|
||||
$chapter->deletions()->delete();
|
||||
}
|
||||
|
||||
$chapter->restore();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the given entity.
|
||||
*/
|
||||
|
||||
@@ -49,14 +49,6 @@ class Page extends BookChild
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent item
|
||||
*/
|
||||
public function parent(): Entity
|
||||
{
|
||||
return $this->chapter_id ? $this->chapter : $this->book;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chapter that this page is in, If applicable.
|
||||
* @return BelongsTo
|
||||
|
||||
@@ -321,7 +321,7 @@ class PageRepo
|
||||
*/
|
||||
public function copy(Page $page, string $parentIdentifier = null, string $newName = null): Page
|
||||
{
|
||||
$parent = $parentIdentifier ? $this->findParentByIdentifier($parentIdentifier) : $page->parent();
|
||||
$parent = $parentIdentifier ? $this->findParentByIdentifier($parentIdentifier) : $page->getParent();
|
||||
if ($parent === null) {
|
||||
throw new MoveOperationException('Book or chapter to move page into not found');
|
||||
}
|
||||
@@ -440,8 +440,9 @@ class PageRepo
|
||||
*/
|
||||
protected function getNewPriority(Page $page): int
|
||||
{
|
||||
if ($page->parent() instanceof Chapter) {
|
||||
$lastPage = $page->parent()->pages('desc')->first();
|
||||
$parent = $page->getParent();
|
||||
if ($parent instanceof Chapter) {
|
||||
$lastPage = $parent->pages('desc')->first();
|
||||
return $lastPage ? $lastPage->priority + 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user