authorizeResource(Ticket::class, 'ticket'); } /** * Tickets List * * @param SortTickets $request * @return \Illuminate\Http\JsonResponse|\Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory */ public function index(SortTickets $request) { // * Handle Ajax if ($request->ajax()) { $tickets = Ticket::with(['user', 'assignedUser']); if ($request->s) { $tickets = $tickets->where('text', 'LIKE', "%$request->s%") ->orWhere('id', $request->s) ->orWhereHas('user', function ($q) use ($request) { $q->where('name', 'LIKE', "%$request->s%"); }); } /** @var \Illuminate/Pagination/LengthAwarePaginator $tickets */ $tickets = $tickets->paginate(); return \response()->json($tickets->getCollection()->map(function (Ticket $ticket) { return [ 'label' => sprintf( 'Ticket %d (%s): %s', $ticket->id, $ticket->user ? $ticket->user->name : trans('Utilisateur supprimé'), Str::limit(\preg_replace('/[[:cntrl:]]+/', '', $ticket->text), 35) ), 'value' => $ticket->id ]; })); }//end if /** @var \App\Models\User */ $user = auth()->user(); $tickets = Ticket::with(['site', 'labels']); if (!$user->isAdmin()) { $tickets->whereHas('site', function ($q) use ($user) { $q->whereHas('users', function ($q) use ($user) { $q->whereId($user->id); }); }); $tickets->where('is_internal', false); } else { $tickets->has('site'); } $tickets->where( 'status', ($request->st == TicketStatus::archived()) ? '=' : '<>', TicketStatus::archived() ); $tickets = $this->searchTicket($tickets, $request); $tickets = $this->filterTickets($tickets, $request); $tickets = $tickets->paginate(); $sites = Site::select('id', 'name')->orderBy('name')->get(); $status = TicketStatus::toArray(); return view('ticket.index', compact('tickets', 'sites', 'status')); } /** * Show Ticket * * @param Request $request * @param Ticket $ticket * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory */ public function show(Request $request, Ticket $ticket) { if ($request->ajax()) { return \response()->json([ 'label' => sprintf( 'Ticket %d (%s): %s', $ticket->id, $ticket->user ? $ticket->user->email : __('Utilisateur supprimé'), Str::limit(\preg_replace('/[[:cntrl:]]+/', '', $ticket->text), 35) ), 'value' => $ticket->id ]); } /** @var \App\Models\User */ $user = auth()->user(); if (!$user->can('update', $ticket)) { abort(403); } if ($ticket->is_internal && !$user->can('changeInternalStatus', $ticket)) { abort(403); } $messages = $ticket->messages()->orderBy('created_at', 'DESC')->get(); $isSubscribed = (bool)$ticket->subscriptions()->where('user_id', $user->id)->count(); return view('ticket.show', compact('ticket', 'messages', 'isSubscribed')); } /** * Show create Form * * @return \Illuminate\Http\RedirectResponse */ public function create() { /** @var \App\Models\User */ $user = auth()->user(); if ($user->isAdmin()) { $sites = Site::orderBy('name')->get(); } else { $sites = $user->sites; } if (!count($sites)) { return redirect()->route('sites.create') ->with('warning', trans('Vous devez tout d\'abord créer un site pour y ajouter un ticket')); } return view('ticket.create', compact('sites')); } /** * Create ticket * * @param StoreTicket $request * @return \Illuminate\Http\RedirectResponse */ public function store(StoreTicket $request) { try { return DB::transaction(function () use ($request) { /** @var \App\Models\Site */ $site = Site::findOrFail($request->site_id); /** @var \App\Models\User */ $user = auth()->user(); $ticket = new Ticket($request->validated()); /** @var \Illuminate\Http\UploadedFile|null */ $fileTicket = $request->file_ticket; /** @var \Illuminate\Http\UploadedFile|null */ $fileTicket2 = $request->file_ticket2; if ($fileTicket) { $ticket->file = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket); } if ($fileTicket2) { $ticket->file2 = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket2); } $ticket->user()->associate(auth()->user()); $ticket->site()->associate($site); $ticket->saveOrFail(); if ($request->labels) { $ticket->labels()->sync($request->labels); } $user->subscriptions()->toggle($ticket->id); if (config('mail.MAIL_ADMIN')) { Mail::to(config('mail.MAIL_ADMIN'))->send(new NewTicket($ticket)); } else { throw new \ErrorException('Missing MAIL_ADMIN in .env'); } return redirect()->route('ticket.show', $ticket) ->with('success', trans('Ticket enregistré !')); }); } catch (\ErrorException $e) { report($e); Session::flash('error', trans('Une erreur est survenue')); } //end try return \back(); } /** * Show update form * * @param Ticket $ticket * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass */ public function edit(Ticket $ticket) { /** @var \App\Models\User */ $user = auth()->user(); if ($user->isAdmin()) { $sites = Site::orderBy('name')->get(); } else { $sites = $user->sites; } return view('ticket.edit', compact('ticket', 'sites')); } /** * Update Model * * @param UpdateTicket $request * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function update(UpdateTicket $request, Ticket $ticket) { $ticket->fill($request->validated()); try { return DB::transaction(function () use ($request, $ticket) { /** @var \App\Models\Site */ $site = Site::findOrFail($request->site_id); /** @var \Illuminate\Http\UploadedFile|null */ $fileTicket = $request->file_ticket; /** @var \Illuminate\Http\UploadedFile|null */ $fileTicket2 = $request->file_ticket2; if ($fileTicket) { $ticket->file = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket); } if ($fileTicket2) { $ticket->file2 = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket2); } $ticket->labels()->sync($request->labels); $ticket->site()->associate($site); $ticket->saveOrFail(); return redirect()->route('ticket.edit', $ticket->id) ->with('success', 'Modifications enregistrées !'); }); } catch (\ErrorException $e) { report($e); Session::flash('error', trans('Une erreur est survenue')); } //end try return \back(); } /** * Change ticket Status * * @param ChangeTicketStatus $request * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function changeStatus(ChangeTicketStatus $request, Ticket $ticket) { $ticket->fill($request->validated()); $ticket->saveOrFail(); return back() ->with('warning', trans('Le status à été modifié')); } /** * Add a new Message to the Ticket * * @param CreateMessage $request * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function createMessage(CreateMessage $request, Ticket $ticket) { try { return DB::transaction(function () use ($request, $ticket) { /** @var \Illuminate\Http\UploadedFile|null */ $fileMessage = $request->file_message; $message = new Message($request->validated()); $message->user()->associate(auth()->user()); $message->ticket()->associate($ticket); /** @var \App\Models\User */ $user = auth()->user(); if ($request->subscribe) { if (!$user->subscriptions()->find($ticket->id)) { $user->subscriptions()->attach($ticket->id); } } elseif ($user->subscriptions()->find($ticket->id)) { $user->subscriptions()->detach($ticket->id); } $message->saveOrFail(); if ($fileMessage) { $message->file = ToolboxHelper::storeImage($message->getTable(), $fileMessage); $message->saveOrFail(); } return back() ->with('success', trans('Votre message à été ajouté')); }); } catch (\ErrorException $e) { report($e); Session::flash('error', trans('Une erreur est survenue')); } //end try return back(); } /** * Update Message * * @param UpdateMessage $request * @param Ticket $ticket * @param Message $message * @return \Illuminate\Http\RedirectResponse * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed */ public function updateMessage(UpdateMessage $request, Ticket $ticket, Message $message) { $message->message = $request->message; $message->saveOrFail(); return back() ->with('success', trans('Votre message à bien été modifié')); } /** * Change ticket status to archived * * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function setToArchive(Ticket $ticket) { $ticket->status = TicketStatus::archived(); $ticket->saveOrFail(); return redirect()->route('ticket.index') ->with('warning', trans('Le ticket est archivé')); } /** * Subscribe to ticket * * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function subscribe(Ticket $ticket) { /** @var \App\Models\User */ $user = auth()->user(); $user->subscriptions()->toggle($ticket->id); if ($user->subscriptions()->where('ticket_id', $ticket->id)->exists()) { return back() ->with('success', trans('Vous avez été inscrit')); } return back()->with('warning', trans('Vous avez été désinscrit')); } /** * Reopen ticket * * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function reopen(Ticket $ticket) { $message = trans(':ticketName à réouvert le ticket n°:ticketNumber', [ 'ticketName' => $ticket->user->name, 'ticketNumber' => $ticket->id, ]); /** @var \App\Enums\TicketStatus */ $oldStatus = $ticket->status; $ticket->status = TicketStatus::inprogress(); $ticket->saveQuietly(); event(new TicketStatusChanged($ticket, $oldStatus, null, $message)); event(new NotifySubscriptions($ticket, $message, collect([$ticket->user]))); /** @var \App\Models\User */ $user = auth()->user(); $user->subscriptions()->toggle($ticket->id); return back()->with('warning', trans('Votre ticket à été réouvert.')); } /** * Assign ticket to user ticket * * @param AssignTicketToUserRequest $request * @param Ticket $ticket * @return \Illuminate\Http\RedirectResponse */ public function assignTo(AssignTicketToUserRequest $request, Ticket $ticket) { /** @var \App\Models\User */ $user = auth()->user(); /** @var \App\Models\User|null */ if ($assignedUser = User::whereId($request->assign)->first()) { $message = trans(':admin a assigné le ticket n°:ticketNumber à :assignedAdmin', [ 'admin' => $user->name, 'ticketNumber' => $ticket->id, 'assignedAdmin' => $assignedUser->name, ]); $ticket->assignedUser()->associate($assignedUser); } else { $message = trans( ':admin a modifié l\'assignation du ticket n°:ticketNumber, il n\'est plus assigné à quelqu\'un.', [ 'admin' => $user->name, 'ticketNumber' => $ticket->id, ] ); $ticket->assignedUser()->dissociate(); } $ticket->saveQuietly(); /** @var \App\Enums\TicketStatus */ $oldStatus = $ticket->status; event(new TicketStatusChanged($ticket, $oldStatus, null, $message)); event(new NotifySubscriptions($ticket, $message, collect([$ticket->user]))); /** @var \App\Models\User */ $user = auth()->user(); $user->subscriptions()->toggle($ticket->id); if ($assignedUser) { return back()->with('info', trans('Le ticket à été assigné à :assignedUser', [ 'assignedUser' => $assignedUser->name ])); } return back()->with('info', trans('Le ticket n\'est plus assigné à personne')); } // * PRIVATES /** * Filter Tickets request constructor * * @param Builder $tickets * @param Request $request * @return Builder */ private function filterTickets(Builder $tickets, Request $request): Builder { if ($request->rst) { Session::remove('tickets.ass'); Session::remove('tickets.st'); Session::remove('tickets.pr'); Session::remove('tickets.sort_col'); Session::remove('tickets.sort_way'); } if ($request->assr) { Session::remove('tickets.ass'); } if ($request->prs) { Session::remove('tickets.pr'); } if ($request->sts) { Session::remove('tickets.st'); } if ($request->sort_col) { Session::put('tickets.sort_col', $request->sort_col); } if ($request->sort_way) { Session::put('tickets.sort_way', $request->sort_way); } if ($request->pr) { Session::put('tickets.pr', $request->pr); } if ($request->st) { Session::put('tickets.st', $request->st); } if ($request->ass) { Session::put('tickets.ass', $request->ass); } Session::save(); if (Session::has('tickets.pr')) { $tickets->where('site_id', Session::get('tickets.pr')); } if (Session::has('tickets.ass')) { $tickets->whereHas('assignedUser', function ($q) { $q->whereId(Session::get('tickets.ass')); }); } if (Session::has('tickets.st')) { $tickets->where('status', Session::get('tickets.st')); } if ( Session::has('tickets.sort_col') and Session::has('tickets.sort_way') and in_array(Session::get('tickets.sort_col'), [ 'id', 'site_id', 'created_at', 'created_by', 'type', 'status', 'assigned_to' ]) ) { $tickets->orderBy( Session::get('tickets.sort_col'), Session::get('tickets.sort_way') ); } else { $tickets->orderBy('id', 'DESC'); } return $tickets; } /** * Search ticket sql request constructor * * @param Builder $tickets * @param Request $request * @return Builder */ private function searchTicket(Builder $tickets, Request $request): Builder { if ($request->exists('search')) { if (empty($request->search)) { Session::remove('tickets.search'); } else { Session::put('tickets.search', $request->search); } } if (!Session::has('tickets.search')) { return $tickets; } return $this->searchQuery($tickets, Session::get('tickets.search'), function ($q) { $words = explode(' ', Session::get('tickets.search')); if (\is_array($words)) { foreach ($words as $word) { if (!strlen($word)) { continue; } $s = collect(TicketStatus::toArray())->filter(function (TicketStatus $t) use ($word) { return Str::slug($t->label) === Str::slug($word); })->map(function (TicketStatus $ticket) { return $ticket->value; }); $t = collect(TicketType::toArray())->filter(function (TicketType $s) use ($word) { return Str::slug($s->label) === Str::slug($word); })->map(function (TicketType $ticket) { return $ticket->value; }); $q->orWhere('id', $word) ->orWhereIn('status', $s) ->orWhereIn('type', $t) ->orWhereHas('user', function ($q) use ($word) { $q->where('name', 'LIKE', "%$word%"); }); } //end foreach } //end if }, 'text', 'file', 'file2'); } }