From a8e220a803606a71d6a94464dcf6c84a793ca0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 1 Apr 2022 10:18:04 +0200 Subject: [PATCH] Ticket 765: Rewrite panier system --- app/Http/Controllers/PanierController.php | 274 ++++++++++-------- .../Bo/AjaxAddMediasBasketRequest.php | 32 ++ .../Requests/Bo/AjaxCreateBasketRequest.php | 35 +++ .../Requests/Bo/AjaxDestroyBasketRequest.php | 30 ++ .../Bo/AjaxRemoveMediasBasketRequest.php | 31 ++ .../Bo/AjaxSaveBasketPropsRequest.php | 36 +++ app/Models/Panier.php | 146 ++++++---- app/Providers/RouteServiceProvider.php | 5 + app/User.php | 2 +- .../media-manager/BasketComponent.vue | 34 ++- routes/web.php | 42 +-- 11 files changed, 455 insertions(+), 212 deletions(-) create mode 100644 app/Http/Requests/Bo/AjaxAddMediasBasketRequest.php create mode 100644 app/Http/Requests/Bo/AjaxCreateBasketRequest.php create mode 100644 app/Http/Requests/Bo/AjaxDestroyBasketRequest.php create mode 100644 app/Http/Requests/Bo/AjaxRemoveMediasBasketRequest.php create mode 100644 app/Http/Requests/Bo/AjaxSaveBasketPropsRequest.php diff --git a/app/Http/Controllers/PanierController.php b/app/Http/Controllers/PanierController.php index a1f5c8c..5ff969f 100644 --- a/app/Http/Controllers/PanierController.php +++ b/app/Http/Controllers/PanierController.php @@ -2,156 +2,176 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; +use App\Http\Requests\Bo\AjaxAddMediasBasketRequest; +use App\Http\Requests\Bo\AjaxCreateBasketRequest; +use App\Http\Requests\Bo\AjaxDestroyBasketRequest; +use App\Http\Requests\Bo\AjaxRemoveMediasBasketRequest; +use App\Http\Requests\Bo\AjaxSaveBasketPropsRequest; +use Illuminate\Support\Str; use App\Models\Panier; -use App\Models\Media; use App\Models\Format; +use App\Models\Media; class PanierController extends Controller { - /** + // * BO + + /** * Page principale des paniers * - * @return \Illuminate\Http\Response + * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory */ - public function index(Request $request) + public function index() { - $paniers = Auth::user()->paniersOwner; - return view('panier.index')->with([ - 'paniers'=> $paniers, - ]); + /** @var \App\User $user */ + $user = \auth()->user(); + /** @var \Illuminate\Database\Eloquent\Collection $paniers */ + $paniers = $user->paniersOwner; + return view('panier.index')->with([ + 'paniers' => $paniers, + ]); } - public function getBaskets(Request $request) + // * AJAX + /** + * Get user baskets + * + * @return \Illuminate\Http\JsonResponse + */ + public function getBaskets() { - return Auth::user()->paniersOwner; + /** @var \App\User $user */ + $user = \auth()->user(); + + /** @var \Illuminate\Database\Eloquent\Collection $paniers */ + $paniers = $user->paniersOwner; + + return response()->json($paniers); } - /** + /** + * Ajout de média à un panier + * + * @param AjaxAddMediasBasketRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function addMediasBasket(AjaxAddMediasBasketRequest $request) + { + /** @var \App\Models\Panier $panier */ + $panier = Panier::whereId($request->panier_id) + ->with('medias')->firstOrFail(); + + // * Sync every media to basket + $panier->medias()->sync(array_merge( + $panier->medias()->pluck('id')->all(), + $request->medias + )); + + return response()->json(); + } + + /** + * Suppression de média à un panier + * + * @param AjaxRemoveMediasBasketRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function removeMediasBasket(AjaxRemoveMediasBasketRequest $request) + { + + /** @var \App\Models\Panier $panier */ + $panier = Panier::whereId($request->panier_id) + ->with('medias')->firstOrFail(); + + /** @var \App\Models\Media $media */ + $media = Media::whereId($request->media_id)->firstOrFail(); + + $panier->medias()->detach($media); + + return response()->json(true); + } + + /** + * Ajoute un panier + * + * @param AjaxCreateBasketRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function createBasket(AjaxCreateBasketRequest $request) + { + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $panier = new Panier(); + $panier->libelle = $request->title; + $panier->uid = Str::uuid(); + $panier->owner()->associate($user); + $panier->saveOrFail(); + + return response()->json($panier); + } + + /** + * Supprimer un panier + * + * @param AjaxDestroyBasketRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function destroyBasket(AjaxDestroyBasketRequest $request) + { + /** @var \App\Models\Panier $basket */ + $basket = Panier::whereId($request->basket_id)->firstOrFail(); + + // TODO: Replace this with deleteOrFail after laravel bump. + $basket->delete(); + + return response()->json(); + } + + // * FO + + /** * Page publique d'un panier * - * @return \Illuminate\Http\Response + * @param Panier $panier + * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory */ - public function showBasket(Request $request) + public function showBasket(Panier $panier) { - $panier_uid = $request->basket_uid; - $formats = Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get(); - $panier = Panier::where('uid', $panier_uid)->first(); - if($panier && $panier->statut == 1){ - return view('panier.show')->with([ - 'panier'=> $panier, - 'formats' => $formats, - ]); - }else{ - abort(404, 'Page introuvable'); - } - } + /** @var \App\User|null $user */ + $user = auth()->user(); - /** - * Ajout de média à un panier - */ - public function addMediasBasket(Request $request) - { - $response = false; - - $mediasToAdd = $request->input('medias'); - $panierId = $request->input('panier_id'); - - $panier = Panier::where('id', $panierId)->with('medias')->first(); - if($panier){ - foreach ($mediasToAdd as $media) { - $panier->medias()->attach($media['id']); + // * Ne pas afficher le panier si il n'est pas pas publié et + // * que l'utilisateur n'est pas le propiétaire + if (!$panier->statut) { + if (!$user or \optional($panier->owner)->id !== $user->id) { + abort(404); } - $response = true; - } + } - return json_encode($response); + /** @var \Illuminate\Database\Eloquent\Collection $formats */ + $formats = Format::withoutGlobalScope('App\Scopes\SystemScope') + ->where('system', 1)->get(); + return view('panier.show')->with([ + 'panier' => $panier, + 'formats' => $formats, + ]); } - /** - * Suppression de média à un panier - */ - public function removeMediasBasket(Request $request) - { - $response = false; + /** + * Enregistre les propriétés d'un panier + * + * @param AjaxSaveBasketPropsRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function saveBasketProperty(AjaxSaveBasketPropsRequest $request) + { + /** @var \App\Models\Panier $panier */ + $panier = Panier::whereId($request->basket_id)->firstOrFail(); - $mediaToRemove = $request->input('media_id'); - $panierId = $request->input('panier_id'); - - $panier = Panier::where('id', $panierId)->with('medias')->first(); - if($panier && $mediaToRemove != ""){ - $panier->medias()->detach($mediaToRemove); - $response = true; - } - - return json_encode($response); - } - - - /** - * Ajoute un panier - */ - public function addBasket(Request $request) - { - $response = false; - $uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)); - $title = $request->input('title'); - - if($title == ""){ - $title = "Panier du ".date("d/m/Y"); - } - - $panier = new Panier(); - $panier->owner = Auth::user()->id; - $panier->libelle = $title; - $panier->uid = $uid; - if($panier->save()){ - $response = $panier; - } - - return json_encode($response); - } - - /** - * Supprimer un panier - * - */ - public function removeBasket(Request $request) - { - $response = false; - $basket_id = $request->input('basket_id'); - - - $panier = Panier::where('id', $basket_id); - if($panier){ - $panier->delete(); - $response = true; - } - return json_encode($response); - } - - /** - * enregistre les propriétés d'un panier - * - */ - public function saveBasketProperty(Request $request) - { - $response = false; - $basket_id = $request->input('basket_id'); - $libelle = $request->input('libelle'); - $description = $request->input('description'); - $statut = $request->input('statut'); - - $panier = Panier::where('id', $basket_id)->first(); - if($panier){ - $panier->libelle = $libelle; - $panier->description = $description; - $panier->statut = $statut; - $panier->save(); - $response = $panier; - } - return json_encode($response); - } + $panier->fill($request->validated()); + $panier->saveOrFail(); + return response()->json($panier); + } } diff --git a/app/Http/Requests/Bo/AjaxAddMediasBasketRequest.php b/app/Http/Requests/Bo/AjaxAddMediasBasketRequest.php new file mode 100644 index 0000000..b5c313e --- /dev/null +++ b/app/Http/Requests/Bo/AjaxAddMediasBasketRequest.php @@ -0,0 +1,32 @@ +check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'panier_id' => 'required|exists:paniers,id,deleted_at,NULL', + 'medias' => 'required|array', + 'medias.*' => 'required|exists:medias,id,deleted_at,NULL' + ]; + } +} diff --git a/app/Http/Requests/Bo/AjaxCreateBasketRequest.php b/app/Http/Requests/Bo/AjaxCreateBasketRequest.php new file mode 100644 index 0000000..ba4405a --- /dev/null +++ b/app/Http/Requests/Bo/AjaxCreateBasketRequest.php @@ -0,0 +1,35 @@ +merge([ + 'title' => $this->title ?? + sprintf('Panier du %s', Carbon::now()->format('d/m/Y')) + ]); + return auth()->check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'title' => 'required|min:1|max:255' + ]; + } +} diff --git a/app/Http/Requests/Bo/AjaxDestroyBasketRequest.php b/app/Http/Requests/Bo/AjaxDestroyBasketRequest.php new file mode 100644 index 0000000..35aa69c --- /dev/null +++ b/app/Http/Requests/Bo/AjaxDestroyBasketRequest.php @@ -0,0 +1,30 @@ +check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'basket_id' => 'required|exists:paniers,id,deleted_at,NULL' + ]; + } +} diff --git a/app/Http/Requests/Bo/AjaxRemoveMediasBasketRequest.php b/app/Http/Requests/Bo/AjaxRemoveMediasBasketRequest.php new file mode 100644 index 0000000..d0a5b27 --- /dev/null +++ b/app/Http/Requests/Bo/AjaxRemoveMediasBasketRequest.php @@ -0,0 +1,31 @@ +check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'panier_id' => 'required|exists:paniers,id,deleted_at,NULL', + 'media_id' => 'required|exists:medias,id,deleted_at,NULL' + ]; + } +} diff --git a/app/Http/Requests/Bo/AjaxSaveBasketPropsRequest.php b/app/Http/Requests/Bo/AjaxSaveBasketPropsRequest.php new file mode 100644 index 0000000..fddad47 --- /dev/null +++ b/app/Http/Requests/Bo/AjaxSaveBasketPropsRequest.php @@ -0,0 +1,36 @@ +merge([ + 'statut' => $this->statut ? true : false + ]); + return \auth()->check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'basket_id' => 'required|exists:paniers,id,deleted_at,NULL', + 'libelle' => 'required|string|min:2|max:255', + 'description' => 'nullable|string', + 'statut' => 'required|boolean' + ]; + } +} diff --git a/app/Models/Panier.php b/app/Models/Panier.php index d08a25e..19e58fa 100644 --- a/app/Models/Panier.php +++ b/app/Models/Panier.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -9,61 +10,102 @@ class Panier extends Model { use SoftDeletes; - protected $appends = array('mediacount', 'mediacover'); + /** + * The accessors to append to the model's array form. + * + * @var array + */ + protected $appends = [ + 'mediacount', 'mediacover' + ]; - /** - * Get the user that owns the panier. - */ - public function owner() - { - return $this->belongsTo('App\User', 'owner'); - } + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'description', 'libelle', 'statut' + ]; - /** - * The users that belong to the panier. - */ - public function usersFavoris() - { - return $this->belongsToMany('App\User', 'paniers_users', 'panier_id', 'user_id'); - } + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = [ + 'statut' => 'boolean' + ]; - /** - * The medias that belong to the panier. - */ - public function medias() - { - return $this->belongsToMany('App\Models\Media', 'paniers_medias', 'panier_id', 'media_id'); - } + // * RELATIONSHIPS - /** - * Get media linked - */ - public function getMediacountAttribute() - { - return $this->medias()->count(); - } + /** + * BelongsTo user relation + * Get the user that owns the panier. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function owner() + { + return $this->belongsTo(User::class, 'user_id'); + } - /** - * Get media linked - */ - public function getMediacoverAttribute() - { - $cover = ""; - $media = $this->medias()->where('typemedia_id', 1)->first(); - if($media){ - switch ($media->typemedia_id) { - case 1: - if($media->extension == "pdf" || $media->extension == "ai" || $media->extension == "psd"){ - $cover = $media->folder.$media->uid."_thumb.png"; - }else{ - $cover = $media->folder.$media->uid."_thumb.".$media->extension; - } - break; - case 2: - $cover = $media->folder.$media->uid."_thumb.".$media->extension; - break; - } - } - return $cover; - } + /** + * BelongsToMany users relation + * The users that belong to the panier. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function usersFavoris() + { + return $this->belongsToMany(User::class, 'paniers_users', 'panier_id', 'user_id'); + } + + /** + * BelongsToMany medias relation + * The medias that belong to the panier. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function medias() + { + return $this->belongsToMany(Media::class, 'paniers_medias', 'panier_id', 'media_id'); + } + + // * GETTERS + + /** + * Get mediacount attribute + * + * @return boolean + */ + public function getMediacountAttribute(): int + { + return $this->medias()->count(); + } + + /** + * Get mediacover attribute + * + * @return string + */ + public function getMediacoverAttribute(): string + { + $cover = ''; + if ($media = $this->medias()->where('typemedia_id', 1)->first()) { + switch ($media->typemedia_id) { + case 1: + if ($media->extension == "pdf" || $media->extension == "ai" || $media->extension == "psd") { + $cover = $media->folder . $media->uid . "_thumb.png"; + } else { + $cover = $media->folder . $media->uid . "_thumb." . $media->extension; + } + break; + case 2: + $cover = $media->folder . $media->uid . "_thumb." . $media->extension; + break; + } + } + return $cover; + } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 60c25ac..dbfe56f 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use App\Models\Media; +use App\Models\Panier; use Illuminate\Support\Facades\Route; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; @@ -27,6 +28,10 @@ class RouteServiceProvider extends ServiceProvider Route::bind('media', function ($value) { return Media::whereUid($value)->firstOrFail(); }); + Route::bind('basket_uuid', function ($value) { + return Panier::where('uid', $value) + ->with('owner')->firstOrFail(); + }); parent::boot(); } diff --git a/app/User.php b/app/User.php index fbbc6c9..dc78b59 100644 --- a/app/User.php +++ b/app/User.php @@ -153,7 +153,7 @@ class User extends Authenticatable */ public function paniersOwner() { - return $this->hasMany(Panier::class, 'owner')->with('medias'); + return $this->hasMany(Panier::class, 'user_id')->with('medias'); } /** diff --git a/resources/js/components/media-manager/BasketComponent.vue b/resources/js/components/media-manager/BasketComponent.vue index 8c60a1f..910eb9e 100644 --- a/resources/js/components/media-manager/BasketComponent.vue +++ b/resources/js/components/media-manager/BasketComponent.vue @@ -2,19 +2,20 @@
- + - + Aucun panier disponible +
@@ -49,8 +50,8 @@

Statut :

Créé le : {{new Date(this.selectedBasket.created_at).toLocaleDateString('fr-FR', {'hour': '2-digit', 'minute': '2-digit'})}} @@ -75,6 +76,11 @@ storeGrabbed () { return this.$store.state.grabbed; }, + basketMediaIds() { + return _.map(this.$store.state.grabbed, (media) => { + return media.id + }) + } }, mounted() { this.init(); @@ -297,7 +303,7 @@ }else{ this.$loading.show({delay:0}); axios.post('/ajax/add-media-basket', { - medias: this.storeGrabbed, + medias: this.basketMediaIds, panier_id : this.selectedBasket.id, }).then(response => { _this2.init(this.selectedBasket.id); @@ -323,6 +329,12 @@ } - diff --git a/routes/web.php b/routes/web.php index bcd3e8f..67bf92f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,20 +1,22 @@ ['auth']], function () { - // Les pages Front + // Les pages Front . Route::get('/', 'CommunController@index')->name('home'); Route::get('/gestion-des-medias', [MediaController::class, 'index'])->name('media_manager'); - Route::get('/paniers', 'PanierController@index')->name('paniers'); + Route::get('/paniers', [PanierController::class, 'index'])->name('paniers'); Route::get('/media/{media}', [MediaController::class, 'show'])->name('media.show'); - // Message de contact + // Message de contact . Route::post('/send-message', 'CommunController@sendMessage'); - // Ajax pour la gestion des dossiers + // Ajax pour la gestion des dossiers . Route::post('/ajax/load-folder', 'DossierController@loadFolder'); Route::get('/ajax-v2/load-folders', 'DossierController@loadFolders'); Route::post('/ajax/add-folder', 'DossierController@addFolder'); @@ -25,7 +27,7 @@ Route::group(['middleware' => ['auth']], function () { Route::post('/ajax/get-folder-property', 'DossierController@getFolderProperty'); Route::post('/ajax/save-folder-property', 'DossierController@saveFolderProperty'); - // Ajax pour la gestion des médias + // Ajax pour la gestion des médias . Route::post('/ajax/load-medias', 'MediaController@loadMedia'); Route::post('/ajax/move-media', 'MediaController@moveMedia'); Route::post('/ajax/remove-media', 'MediaController@removeMedia'); @@ -40,18 +42,16 @@ Route::group(['middleware' => ['auth']], function () { Route::post('/ajax/download-media', 'MediaController@downloadMedia')->name('downloadMedia'); Route::post('/ajax/get-media-others-infos', 'MediaController@getMediaOtherInfos'); - // Ajax pour la gestion des panier - Route::post('/ajax/add-media-basket', 'PanierController@addMediasBasket'); - Route::post('/ajax/remove-media-basket', 'PanierController@removeMediasBasket'); - Route::post('/ajax/load-basket', 'PanierController@loadBasket'); - Route::post('/ajax/add-basket', 'PanierController@addBasket'); + // Ajax pour la gestion des panier . + Route::post('/ajax/add-media-basket', [PanierController::class, 'addMediasBasket']); + Route::post('/ajax/remove-media-basket', [PanierController::class, 'removeMediasBasket']); + Route::post('/ajax/add-basket', [PanierController::class, 'createBasket']); Route::post('/ajax/favoris-basket', 'UserController@favorisBasket'); - Route::post('/ajax/remove-basket', 'PanierController@removeBasket'); - Route::post('/ajax/get-basket', 'PanierController@getBasket'); - Route::post('/ajax/get-baskets', 'PanierController@getBaskets'); + Route::post('/ajax/remove-basket', [PanierController::class, 'destroyBasket']); + Route::post('/ajax/get-baskets', [PanierController::class, 'getBaskets']); Route::post('/ajax/save-basket-property', 'PanierController@saveBasketProperty'); - // Back office + // Back office . Route::resource('user', 'UserController'); Route::post('/check-matricule', 'UserController@checkMatricule'); Route::get('/dossier/create-sub', 'DossierController@createSub')->name('dossier.create-sub'); @@ -71,15 +71,15 @@ Auth::routes([ 'register' => false, ]); -// Page pour déposer les médias +// Page pour déposer les médias . Route::get('/depot', 'UploadController@index'); -// Ajax pour ajouter un dossier de dépôt +// Ajax pour ajouter un dossier de dépôt . Route::post('/ajax/add-depot-folder', 'DossierController@addDepotFolder'); -// Ajax pour la gestion de l'upload de média +// Ajax pour la gestion de l'upload de média . Route::post('/ajax/upload-media', 'UploadController@storeMedia'); Route::post('/ajax-v2/upload-media', 'UploadController@storeMediaV2'); -// Les pages Front panier public -Route::get('/basket/{basket_uid}', 'PanierController@showBasket'); +// Les pages Front panier public. +Route::get('/basket/{basket_uuid}', [PanierController::class, 'showBasket']);