mirror of
				https://github.com/BookStackApp/BookStack.git
				synced 2025-10-31 03:50:27 +03:00 
			
		
		
		
	Added additional exceptions to prevent such cases in the future, so that they are caught in dev ideally. Added test case specifically for reported favourite scenario.
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace BookStack\Http\Controllers;
 | |
| 
 | |
| use BookStack\Entities\Models\Entity;
 | |
| use BookStack\Entities\Queries\TopFavourites;
 | |
| use BookStack\Interfaces\Favouritable;
 | |
| use BookStack\Model;
 | |
| use Illuminate\Http\Request;
 | |
| 
 | |
| class FavouriteController extends Controller
 | |
| {
 | |
|     /**
 | |
|      * Show a listing of all favourite items for the current user.
 | |
|      */
 | |
|     public function index(Request $request)
 | |
|     {
 | |
|         $viewCount = 20;
 | |
|         $page = intval($request->get('page', 1));
 | |
|         $favourites = (new TopFavourites())->run($viewCount + 1, (($page - 1) * $viewCount));
 | |
| 
 | |
|         $hasMoreLink = ($favourites->count() > $viewCount) ? url('/favourites?page=' . ($page + 1)) : null;
 | |
| 
 | |
|         $this->setPageTitle(trans('entities.my_favourites'));
 | |
| 
 | |
|         return view('common.detailed-listing-with-more', [
 | |
|             'title'       => trans('entities.my_favourites'),
 | |
|             'entities'    => $favourites->slice(0, $viewCount),
 | |
|             'hasMoreLink' => $hasMoreLink,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 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): Entity
 | |
|     {
 | |
|         $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', 'restricted', 'owned_by']);
 | |
| 
 | |
|         $inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
 | |
|         if (is_null($modelInstance) || $inaccessibleEntity) {
 | |
|             throw new \Exception('Model instance not found');
 | |
|         }
 | |
| 
 | |
|         return $modelInstance;
 | |
|     }
 | |
| }
 |