mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-30 04:23:11 +03:00
Started work on the recycle bin interface
This commit is contained in:
@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class DeleteRecord extends Model
|
||||
class Deletion extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
@ -13,21 +13,21 @@ class DeleteRecord extends Model
|
||||
*/
|
||||
public function deletable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
return $this->morphTo('deletable')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* The the user that performed the deletion.
|
||||
*/
|
||||
public function deletedBy(): BelongsTo
|
||||
public function deleter(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
return $this->belongsTo(User::class, 'deleted_by');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new deletion record for the provided entity.
|
||||
*/
|
||||
public static function createForEntity(Entity $entity): DeleteRecord
|
||||
public static function createForEntity(Entity $entity): Deletion
|
||||
{
|
||||
$record = (new self())->forceFill([
|
||||
'deleted_by' => user()->id,
|
@ -204,9 +204,9 @@ class Entity extends Ownable
|
||||
/**
|
||||
* Get the related delete records for this entity.
|
||||
*/
|
||||
public function deleteRecords(): MorphMany
|
||||
public function deletions(): MorphMany
|
||||
{
|
||||
return $this->morphMany(DeleteRecord::class, 'deletable');
|
||||
return $this->morphMany(Deletion::class, 'deletable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,6 +57,7 @@ class EntityProvider
|
||||
/**
|
||||
* Fetch all core entity types as an associated array
|
||||
* with their basic names as the keys.
|
||||
* @return [string => Entity]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
|
@ -3,8 +3,9 @@
|
||||
use BookStack\Entities\Book;
|
||||
use BookStack\Entities\Bookshelf;
|
||||
use BookStack\Entities\Chapter;
|
||||
use BookStack\Entities\DeleteRecord;
|
||||
use BookStack\Entities\Deletion;
|
||||
use BookStack\Entities\Entity;
|
||||
use BookStack\Entities\EntityProvider;
|
||||
use BookStack\Entities\HasCoverImage;
|
||||
use BookStack\Entities\Page;
|
||||
use BookStack\Exceptions\NotifyException;
|
||||
@ -21,7 +22,7 @@ class TrashCan
|
||||
*/
|
||||
public function softDestroyShelf(Bookshelf $shelf)
|
||||
{
|
||||
DeleteRecord::createForEntity($shelf);
|
||||
Deletion::createForEntity($shelf);
|
||||
$shelf->delete();
|
||||
}
|
||||
|
||||
@ -31,7 +32,7 @@ class TrashCan
|
||||
*/
|
||||
public function softDestroyBook(Book $book)
|
||||
{
|
||||
DeleteRecord::createForEntity($book);
|
||||
Deletion::createForEntity($book);
|
||||
|
||||
foreach ($book->pages as $page) {
|
||||
$this->softDestroyPage($page, false);
|
||||
@ -51,7 +52,7 @@ class TrashCan
|
||||
public function softDestroyChapter(Chapter $chapter, bool $recordDelete = true)
|
||||
{
|
||||
if ($recordDelete) {
|
||||
DeleteRecord::createForEntity($chapter);
|
||||
Deletion::createForEntity($chapter);
|
||||
}
|
||||
|
||||
if (count($chapter->pages) > 0) {
|
||||
@ -70,7 +71,7 @@ class TrashCan
|
||||
public function softDestroyPage(Page $page, bool $recordDelete = true)
|
||||
{
|
||||
if ($recordDelete) {
|
||||
DeleteRecord::createForEntity($page);
|
||||
Deletion::createForEntity($page);
|
||||
}
|
||||
|
||||
// Check if set as custom homepage & remove setting if not used or throw error if active
|
||||
@ -151,6 +152,59 @@ class TrashCan
|
||||
$page->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total counts of those that have been trashed
|
||||
* but not yet fully deleted (In recycle bin).
|
||||
*/
|
||||
public function getTrashedCounts(): array
|
||||
{
|
||||
$provider = app(EntityProvider::class);
|
||||
$counts = [];
|
||||
|
||||
/** @var Entity $instance */
|
||||
foreach ($provider->all() as $key => $instance) {
|
||||
$counts[$key] = $instance->newQuery()->onlyTrashed()->count();
|
||||
}
|
||||
|
||||
return $counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all items that have pending deletions.
|
||||
*/
|
||||
public function destroyFromAllDeletions()
|
||||
{
|
||||
$deletions = Deletion::all();
|
||||
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) {
|
||||
$this->destroyEntity($deletion->deletable);
|
||||
}
|
||||
$deletion->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the given entity.
|
||||
*/
|
||||
protected function destroyEntity(Entity $entity)
|
||||
{
|
||||
if ($entity->isA('page')) {
|
||||
return $this->destroyPage($entity);
|
||||
}
|
||||
if ($entity->isA('chapter')) {
|
||||
return $this->destroyChapter($entity);
|
||||
}
|
||||
if ($entity->isA('book')) {
|
||||
return $this->destroyBook($entity);
|
||||
}
|
||||
if ($entity->isA('shelf')) {
|
||||
return $this->destroyShelf($entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update entity relations to remove or update outstanding connections.
|
||||
*/
|
||||
@ -163,7 +217,7 @@ class TrashCan
|
||||
$entity->comments()->delete();
|
||||
$entity->jointPermissions()->delete();
|
||||
$entity->searchTerms()->delete();
|
||||
$entity->deleteRecords()->delete();
|
||||
$entity->deletions()->delete();
|
||||
|
||||
if ($entity instanceof HasCoverImage && $entity->cover) {
|
||||
$imageService = app()->make(ImageService::class);
|
||||
|
@ -14,7 +14,6 @@ class HomeController extends Controller
|
||||
|
||||
/**
|
||||
* Display the homepage.
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
@ -22,9 +21,12 @@ class HomeController extends Controller
|
||||
$draftPages = [];
|
||||
|
||||
if ($this->isSignedIn()) {
|
||||
$draftPages = Page::visible()->where('draft', '=', true)
|
||||
$draftPages = Page::visible()
|
||||
->where('draft', '=', true)
|
||||
->where('created_by', '=', user()->id)
|
||||
->orderBy('updated_at', 'desc')->take(6)->get();
|
||||
->orderBy('updated_at', 'desc')
|
||||
->take(6)
|
||||
->get();
|
||||
}
|
||||
|
||||
$recentFactor = count($draftPages) > 0 ? 0.5 : 1;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace BookStack\Http\Controllers;
|
||||
|
||||
use BookStack\Entities\Managers\TrashCan;
|
||||
use BookStack\Notifications\TestEmail;
|
||||
use BookStack\Uploads\ImageService;
|
||||
use Illuminate\Http\Request;
|
||||
@ -19,7 +20,13 @@ class MaintenanceController extends Controller
|
||||
// Get application version
|
||||
$version = trim(file_get_contents(base_path('version')));
|
||||
|
||||
return view('settings.maintenance', ['version' => $version]);
|
||||
// Recycle bin details
|
||||
$recycleStats = (new TrashCan())->getTrashedCounts();
|
||||
|
||||
return view('settings.maintenance', [
|
||||
'version' => $version,
|
||||
'recycleStats' => $recycleStats,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
35
app/Http/Controllers/RecycleBinController.php
Normal file
35
app/Http/Controllers/RecycleBinController.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use BookStack\Entities\Deletion;
|
||||
use BookStack\Entities\Managers\TrashCan;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RecycleBinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the top-level listing for the recycle bin.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->checkPermission('settings-manage');
|
||||
$this->checkPermission('restrictions-manage-all');
|
||||
|
||||
$deletions = Deletion::query()->with(['deletable', 'deleter'])->paginate(10);
|
||||
|
||||
return view('settings.recycle-bin', [
|
||||
'deletions' => $deletions,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty out the recycle bin.
|
||||
*/
|
||||
public function empty()
|
||||
{
|
||||
$this->checkPermission('settings-manage');
|
||||
$this->checkPermission('restrictions-manage-all');
|
||||
|
||||
(new TrashCan())->destroyFromAllDeletions();
|
||||
return redirect('/settings/recycle-bin');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user