mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-05 01:24:38 +08:00
Started addition of favourite system
This commit is contained in:
17
app/Actions/Favourite.php
Normal file
17
app/Actions/Favourite.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php namespace BookStack\Actions;
|
||||
|
||||
use BookStack\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class Favourite extends Model
|
||||
{
|
||||
protected $fillable = ['user_id'];
|
||||
|
||||
/**
|
||||
* Get the related model that can be favourited.
|
||||
*/
|
||||
public function favouritable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php namespace BookStack\Actions;
|
||||
|
||||
use BookStack\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class View extends Model
|
||||
{
|
||||
@ -9,9 +10,8 @@ class View extends Model
|
||||
|
||||
/**
|
||||
* Get all owning viewable models.
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function viewable()
|
||||
public function viewable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use BookStack\Actions\Activity;
|
||||
use BookStack\Actions\Comment;
|
||||
use BookStack\Actions\Favourite;
|
||||
use BookStack\Actions\Tag;
|
||||
use BookStack\Actions\View;
|
||||
use BookStack\Auth\Permissions\EntityPermission;
|
||||
@ -9,6 +10,7 @@ use BookStack\Auth\Permissions\JointPermission;
|
||||
use BookStack\Entities\Tools\SearchIndex;
|
||||
use BookStack\Entities\Tools\SlugGenerator;
|
||||
use BookStack\Facades\Permissions;
|
||||
use BookStack\Interfaces\Favouritable;
|
||||
use BookStack\Interfaces\Sluggable;
|
||||
use BookStack\Model;
|
||||
use BookStack\Traits\HasCreatorAndUpdater;
|
||||
@ -38,7 +40,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static Builder withLastView()
|
||||
* @method static Builder withViewCount()
|
||||
*/
|
||||
abstract class Entity extends Model implements Sluggable
|
||||
abstract class Entity extends Model implements Sluggable, Favouritable
|
||||
{
|
||||
use SoftDeletes;
|
||||
use HasCreatorAndUpdater;
|
||||
@ -297,4 +299,22 @@ abstract class Entity extends Model implements Sluggable
|
||||
$this->slug = app(SlugGenerator::class)->generate($this);
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function favourites(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Favourite::class, 'favouritable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the entity is a favourite of the current user.
|
||||
*/
|
||||
public function isFavourite(): bool
|
||||
{
|
||||
return $this->favourites()
|
||||
->where('user_id', '=', user()->id)
|
||||
->exists();
|
||||
}
|
||||
}
|
||||
|
76
app/Http/Controllers/FavouriteController.php
Normal file
76
app/Http/Controllers/FavouriteController.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers;
|
||||
|
||||
use BookStack\Entities\Models\Entity;
|
||||
use BookStack\Interfaces\Favouritable;
|
||||
use BookStack\Model;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FavouriteController extends Controller
|
||||
{
|
||||
/**
|
||||
* Add a new item as a favourite.
|
||||
*/
|
||||
public function add(Request $request)
|
||||
{
|
||||
$favouritable = $this->getValidatedModelFromRequest($request);
|
||||
$favouritable->favourites()->firstOrCreate([
|
||||
'user_id' => user()->id,
|
||||
]);
|
||||
|
||||
$this->showSuccessNotification(trans('activities.favourite_add_notification', [
|
||||
'name' => $favouritable->name,
|
||||
]));
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item as a favourite.
|
||||
*/
|
||||
public function remove(Request $request)
|
||||
{
|
||||
$favouritable = $this->getValidatedModelFromRequest($request);
|
||||
$favouritable->favourites()->where([
|
||||
'user_id' => user()->id,
|
||||
])->delete();
|
||||
|
||||
$this->showSuccessNotification(trans('activities.favourite_remove_notification', [
|
||||
'name' => $favouritable->name,
|
||||
]));
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getValidatedModelFromRequest(Request $request): Favouritable
|
||||
{
|
||||
$modelInfo = $this->validate($request, [
|
||||
'type' => 'required|string',
|
||||
'id' => 'required|integer',
|
||||
]);
|
||||
|
||||
if (!class_exists($modelInfo['type'])) {
|
||||
throw new \Exception('Model not found');
|
||||
}
|
||||
|
||||
/** @var Model $model */
|
||||
$model = new $modelInfo['type'];
|
||||
if (! $model instanceof Favouritable) {
|
||||
throw new \Exception('Model not favouritable');
|
||||
}
|
||||
|
||||
$modelInstance = $model->newQuery()
|
||||
->where('id', '=', $modelInfo['id'])
|
||||
->first(['id', 'name']);
|
||||
|
||||
$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
|
||||
if (is_null($modelInstance) || $inaccessibleEntity) {
|
||||
throw new \Exception('Model instance not found');
|
||||
}
|
||||
|
||||
return $modelInstance;
|
||||
}
|
||||
}
|
11
app/Interfaces/Favouritable.php
Normal file
11
app/Interfaces/Favouritable.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php namespace BookStack\Interfaces;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
|
||||
interface Favouritable
|
||||
{
|
||||
/**
|
||||
* Get the related favourite instances.
|
||||
*/
|
||||
public function favourites(): MorphMany;
|
||||
}
|
Reference in New Issue
Block a user