Upgrade notification system on tickets

This commit is contained in:
Jérémy Munsch 2021-07-21 09:44:29 +02:00
parent 0afc9b71d3
commit 62d2c0acf5
9 changed files with 163 additions and 56 deletions

View file

@ -6,6 +6,7 @@ use App\Models\Ticket;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
class NotifySubscriptions
{
@ -19,14 +20,18 @@ class NotifySubscriptions
/** @var string */
public $corpsMaj;
/** @var Collection */
public $ignoreUsers;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Ticket $ticket, string $corpsMaj)
public function __construct(Ticket $ticket, string $corpsMaj, Collection $ignoreUsers = null)
{
$this->ticket = $ticket;
$this->corpsMaj = $corpsMaj;
$this->ignoreUsers = $ignoreUsers;
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace App\Events;
use App\Models\Ticket;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NotifyTicketCreator
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;
/** @var Ticket */
public $ticket;
/** @var string */
public $corpsMaj;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Ticket $ticket, string $corpsMaj)
{
$this->ticket = $ticket;
$this->corpsMaj = $corpsMaj;
}
}

View file

@ -2,22 +2,28 @@
namespace App\Events;
use App\Models\Ticket;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class TicketStatusChanged
{
use Dispatchable, InteractsWithSockets, SerializesModels;
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;
public $ticket, $status;
/** @var Ticket */
public $ticket;
public $status;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($ticket, $status)
public function __construct(Ticket $ticket, $status)
{
$this->ticket = $ticket;
$this->status = $status;

View file

@ -5,21 +5,17 @@ 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;
@ -237,11 +233,11 @@ class TicketController extends Controller
$message = new Message($request->validated());
$message->user()->associate(auth()->user());
$message->ticket()->associate($ticket);
$message->saveOrFail();
/** @var \App\Models\User */
$user = auth()->user();
// Toggle auth user subscription
if ($request->subscribe) {
if (!$user->subscriptions()->find($ticket->id)) {
$user->subscriptions()->attach($ticket->id);
@ -257,35 +253,9 @@ class TicketController extends Controller
$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;
}
}
$message->saveOrFail();
return back();
}

View file

@ -7,16 +7,6 @@ use App\Models\Message;
class AddStatusMessages
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*

View file

@ -0,0 +1,26 @@
<?php
namespace App\Listeners;
use App\Events\NotifyTicketCreator;
use App\Mail\TicketUpdate;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
class SendNotificationMailToTicketCreator
{
/**
* Handle the event.
*
* @param NotifyTicketCreator $event
* @return void
*/
public function handle(NotifyTicketCreator $event)
{
$ticket = $event->ticket;
Mail::to($ticket->user->email)
->send(new TicketUpdate($ticket, $event->corpsMaj));
}
}

View file

@ -4,13 +4,12 @@ namespace App\Listeners;
use App\Events\NotifySubscriptions;
use App\Mail\TicketUpdate;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
class SendNotificationMail
class SendSubscriptionsNotificationsMail
{
/**
* Handle the event.
@ -20,9 +19,15 @@ class SendNotificationMail
*/
public function handle(NotifySubscriptions $event)
{
$ignoreConnectedUserEmail = Auth::user()->email ?? '';
$ignoreUsers = $event->ignoreUsers ?? collect();
foreach ($event->ticket->subscriptions as $sub) {
if (Auth::user() and $sub->email !== Auth::user()->email) {
Mail::to($sub->email)->send(new TicketUpdate($event->ticket, $event->corpsMaj));
if (
$sub->email !== $ignoreConnectedUserEmail and
!$ignoreUsers->contains('email', $sub->email)
) {
Mail::to($sub->email)
->send(new TicketUpdate($event->ticket, $event->corpsMaj));
}
}
}

View file

@ -2,10 +2,14 @@
namespace App\Models;
use App\Enums\TicketType;
use App\Enums\Role;
use App\Events\NotifySubscriptions;
use App\Events\NotifyTicketCreator;
use App\Jobs\SendTicketMentionMail;
use App\Mail\TicketMention;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\UploadedFile;
class Message extends Model
@ -16,6 +20,65 @@ class Message extends Model
'message'
];
protected static function booted()
{
static::created(function (Message $message) {
$ticket = $message->ticket;
if ($message->user) {
$ticket->load('user');
if ($ticket->user !== $message->user) {
event(new NotifyTicketCreator(
$ticket,
trans('Nouvelle réponse de :name :<br> :message sur votre ticket', [
'name' => $message->user->name,
'message' => $message->message
])
));
}
// find @user + send mail si un seul user est trouvé
$usersNotified = collect([]);
$matches = [];
$ticket->load('project');
\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, '@') . '%')
->where('email', '!=', $ticket->user->email)
->where(function ($q) use ($ticket) {
$q->whereHas('projects', function ($q) use ($ticket) {
$q->where('id', $ticket->project->id);
})->orWhere('role', Role::admin()->value);
})->firstOrFail();
$usersNotified->add($user);
SendTicketMentionMail::dispatchAfterResponse(
$user,
new TicketMention($ticket, $message->message)
);
} catch (ModelNotFoundException $e) {
continue;
}
}
event(new NotifySubscriptions(
$message->ticket,
trans('Nouvelle réponse de :name :<br> :message', [
'name' => $message->user->name,
'message' => $message->message
]),
$usersNotified
));
} else {
event(new NotifyTicketCreator(
$ticket,
trans('Votre ticket : :message', [
'message' => $message->message
])
));
}
});
}
public function ticket()
{
return $this->belongsTo(Ticket::class, 'ticket_id');

View file

@ -2,13 +2,20 @@
namespace App\Providers;
use App\Events\NotifySubscriptions;
use App\Events\NotifyTicketCreator;
use App\Events\TicketStatusChanged;
use App\Listeners\AddStatusMessages;
use App\Listeners\SendNotificationMail;
use App\Listeners\SendNotificationMailToTicketCreator;
use App\Listeners\SendSubscriptionsNotificationsMail;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
@ -18,11 +25,14 @@ class EventServiceProvider extends ServiceProvider
Registered::class => [
SendEmailVerificationNotification::class,
],
'App\Events\TicketStatusChanged' => [
'App\Listeners\AddStatusMessages',
TicketStatusChanged::class => [
AddStatusMessages::class
],
'App\Events\NotifySubscriptions' => [
'App\Listeners\SendNotificationMail'
NotifySubscriptions::class => [
SendSubscriptionsNotificationsMail::class
],
NotifyTicketCreator::class => [
SendNotificationMailToTicketCreator::class
],
];