ldc-supportweb/app/Http/Controllers/TicketController.php
2021-06-23 19:48:22 +02:00

300 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\Role;
use App\Enums\TicketStatus;
use App\Enums\TicketType;
use App\Events\NotifySubscriptions;
use App\Http\Requests\ChangeTicketStatus;
use App\Http\Requests\CreateMessage;
use App\Http\Requests\SortTickets;
use App\Http\Requests\StoreTicket;
use App\Http\Requests\UpdateTicket;
use App\Jobs\SendTicketMentionMail;
use App\Mail\NewTicket;
use App\Mail\TicketMention;
use App\Models\Message;
use App\Models\Project;
use App\Models\Ticket;
use App\Models\User;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
class TicketController extends Controller
{
public function __construct()
{
$this->authorizeResource(Ticket::class, 'ticket');
}
public function index(SortTickets $request)
{
/** @var \App\Models\User */
$user = auth()->user();
$tickets = Ticket::with('project');
if (!$user->role->equals(Role::admin())) {
$tickets = $tickets->whereHas('project', function ($q) use ($user) {
$q->whereHas('users', function ($q) use ($user) {
$q->whereId($user->id);
});
});
}
$tickets = $tickets->where('status', $request->status ? '=' : '<>', TicketStatus::archived());
if ($request->search) {
$tickets = $this->searchTicket($tickets, $request);
}
$tickets = $this->filterTickets($tickets, $request);
$tickets = $tickets->paginate();
$projects = Project::select('id', 'name')->orderBy('name')->get();
return view('ticket.index', compact('tickets', 'projects'));
}
private function filterTickets(Builder $tickets, Request $request): Builder
{
if ($request->rst) {
Session::remove('tickets.pr');
Session::remove('tickets.sort_col');
Session::remove('tickets.sort_way');
}
if ($request->prs) {
Session::remove('tickets.pr');
}
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);
}
Session::save();
if (Session::has('tickets.pr')) {
$tickets = $tickets->where('project_id', Session::get('tickets.pr'));
}
if (
Session::has('tickets.sort_col') and
Session::has('tickets.sort_way') and
in_array(Session::get('tickets.sort_col'), [
'id', 'project', 'created_at', 'created_by',
'type', 'status'
])
) {
$tickets = $tickets->orderBy(
Session::get('tickets.sort_col'),
Session::get('tickets.sort_way')
);
}
return $tickets;
}
private function searchTicket(Builder $tickets, Request $request): Builder
{
$words = explode(' ', $request->search);
return $tickets->where(function ($q) use ($words) {
foreach ($words as $word) {
if (!strlen($word)) {
continue;
}
$q = $q->where(function ($q) use ($word) {
$s = collect(TicketStatus::toArray())->filter(function (TicketStatus $t) use ($word) {
return strpos(strtolower($t->label), $word) !== false;
})->map(function (TicketStatus $ticket) {
return $ticket->value;
});
$t = collect(TicketType::toArray())->filter(function (TicketType $t) use ($word) {
return strpos(strtolower($t->label), $word) !== false;
})->map(function (TicketType $ticket) {
return $ticket->value;
});
$q->where('text', 'LIKE', "%$word%")
->orWhereIn('status', $s)
->orWhereIn('type', $t)
->orWhere('file', 'LIKE', "%$word%")
->orWhere('file2', 'LIKE', "%$word%")
->orWhereHas('user', function ($q) use ($word) {
$q->where('name', 'LIKE', "%$word%");
});
});
}
});
}
public function show(Ticket $ticket)
{
$messages = $ticket->messages()->orderBy('created_at', 'DESC')->get();
$isSubscribed = (bool)$ticket->subscriptions()->where('user_id', Auth::user()->id)->count();
return view('ticket.show', compact('ticket', 'messages', 'isSubscribed'));
}
public function create()
{
$user = Auth::user();
if ($user->role === 1) {
$projects = Project::orderBy('name')->get();
} else {
$projects = $user->projects;
}
if (!count($projects)) {
return redirect()->route('project.create')
->with('warning', 'Vous devez tout d\'abord créer un projet pour y ajouter un ticket');
}
return view('ticket.create', compact('projects'));
}
public function store(StoreTicket $request)
{
$project = Project::findOrFail($request->project_id);
$ticket = new Ticket($request->validated());
if ($request->file_ticket) {
$ticket->file = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket);
}
if ($request->file_ticket2) {
$ticket->file2 = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket2);
}
if ($request->type === TicketType::evolution()) {
$ticket->status = TicketStatus::estimateTodo();
}
$ticket->user()->associate(auth()->user());
$ticket->saveOrFail();
/** @var \App\Models\User */
$user = auth()->user();
$user->subscriptions()->toggle($ticket->id);
if (config('mail.MAIL_ADMIN')) {
Mail::to(config('mail.MAIL_ADMIN'))->send(new NewTicket($ticket));
} else {
throw new Exception('Missing MAIL_ADMIN in .env');
}
return redirect()->route('ticket.show', $ticket)->with('success', 'Ticket enregistré !');
}
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function edit(Ticket $ticket)
{
$projects = Project::all();
return view('ticket.edit', compact('ticket', 'projects'));
}
public function update(UpdateTicket $request, Ticket $ticket)
{
$project = Project::findOrFail($request->project_id);
$ticket->fill($request->validated());
if ($request->file_ticket) {
if (File::exists($ticket->file)) {
File::delete($ticket->file);
}
$ticket->file = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket);
}
if ($request->file_ticket2) {
if (File::exists($ticket->file2)) {
File::delete($ticket->file2);
}
$ticket->file2 = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket2);
}
$ticket->save();
return redirect()->route('ticket.edit', $ticket->id)->with('success', 'Modifications enregistrées !');
}
public function changeStatus(ChangeTicketStatus $request, Ticket $ticket)
{
$ticket->fill($request->validated());
$ticket->save();
return back();
}
public function createMessage(CreateMessage $request, Ticket $ticket)
{
$fileMessage = $request->file_message;
$message = new Message($request->validated());
$message->user()->associate(auth()->user());
$message->ticket()->associate($ticket);
$message->saveOrFail();
/** @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);
}
if ($request->file_message) {
$projectSlug = Str::slug($ticket->project->name);
$fileMessage = $request->file_message;
$fileName = $projectSlug . '-ticket-' . $ticket->id . '-message-' . $message->id . '.' . $fileMessage->extension();
$fileMessage->move(public_path('fichiers/' . $projectSlug . '/' . $ticket->id . '/'), $fileName);
$filePath = 'fichiers/' . $projectSlug . '/' . $ticket->id . '/' . $fileName;
$message->file = $filePath;
$message->save();
}
event(new NotifySubscriptions(
$message->ticket,
trans('Nouvelle réponse de :name :<br> :message', [
'name' => $message->user->name,
'message' => $message->message
])
));
// find @user + send mail si un seul user est trouvé
$matches = [];
\preg_match_all('/@\w*/', $message->message, $matches);
$matches = collect($matches[0] ?? [])->unique();
foreach ($matches as $pseudo_usertag) {
try {
$user = User::where('name', 'LIKE', '%' . ltrim($pseudo_usertag, '@') . '%')
->whereDoesntHave('subscriptions', function ($q) use ($ticket) {
$q->where('id', $ticket->id);
})->firstOrFail();
SendTicketMentionMail::dispatchAfterResponse(
$user,
new TicketMention($ticket, $message->message)
);
} catch (ModelNotFoundException $e) {
continue;
}
}
return back();
}
public function setToArchive(Ticket $ticket)
{
$ticket->status = TicketStatus::archived();
$ticket->saveOrFail();
return redirect()->route('ticket.index');
}
public function subscribe(Ticket $ticket)
{
User::find(Auth::user()->id)->subscriptions()->toggle($ticket->id);
return back();
}
}