2018-09-10 07:40:26 -07:00
< ? php
namespace App\Listeners ;
2023-04-19 12:31:12 -07:00
use App\Events\CheckoutableCheckedOut ;
2024-10-16 15:27:34 -07:00
use App\Mail\CheckinAccessoryMail ;
2024-10-16 15:44:45 -07:00
use App\Mail\CheckinLicenseMail ;
2024-10-16 15:27:34 -07:00
use App\Mail\CheckoutAccessoryMail ;
2024-10-15 12:49:52 -07:00
use App\Mail\CheckoutAssetMail ;
2024-10-15 14:01:28 -07:00
use App\Mail\CheckinAssetMail ;
2024-10-16 15:53:05 -07:00
use App\Mail\CheckoutConsumableMail ;
2024-10-16 15:38:49 -07:00
use App\Mail\CheckoutLicenseMail ;
2018-09-10 07:40:26 -07:00
use App\Models\Accessory ;
use App\Models\Asset ;
use App\Models\CheckoutAcceptance ;
2023-04-18 13:07:55 -07:00
use App\Models\Component ;
2018-09-10 07:40:26 -07:00
use App\Models\Consumable ;
use App\Models\LicenseSeat ;
2024-11-04 15:13:10 -08:00
use App\Models\Location ;
2018-09-10 07:40:26 -07:00
use App\Models\Setting ;
2024-10-17 12:39:48 -07:00
use App\Models\User ;
2018-09-10 07:40:26 -07:00
use App\Notifications\CheckinAccessoryNotification ;
2024-10-16 16:46:52 -07:00
use App\Notifications\CheckinAssetNotification ;
2018-09-10 07:40:26 -07:00
use App\Notifications\CheckinLicenseSeatNotification ;
use App\Notifications\CheckoutAccessoryNotification ;
use App\Notifications\CheckoutAssetNotification ;
use App\Notifications\CheckoutConsumableNotification ;
use App\Notifications\CheckoutLicenseSeatNotification ;
2023-10-10 15:06:08 -07:00
use GuzzleHttp\Exception\ClientException ;
2024-10-15 12:49:52 -07:00
use Illuminate\Support\Facades\Mail ;
2018-09-10 07:40:26 -07:00
use Illuminate\Support\Facades\Notification ;
2022-09-15 13:18:42 -07:00
use Exception ;
2024-05-29 04:38:15 -07:00
use Illuminate\Support\Facades\Log ;
2024-11-13 14:29:01 -08:00
use Illuminate\Support\Str ;
2024-10-30 10:40:23 -07:00
use Osama\LaravelTeamsNotification\TeamsNotification ;
2018-09-10 07:40:26 -07:00
class CheckoutableListener
{
2023-04-18 13:07:55 -07:00
private array $skipNotificationsFor = [
Component :: class ,
];
2018-09-10 07:40:26 -07:00
/**
2023-04-19 17:22:56 -07:00
* Notify the user and post to webhook about the checked out checkoutable
* and add a record to the checkout_requests table .
2018-09-10 07:40:26 -07:00
*/
2021-06-10 13:15:52 -07:00
public function onCheckedOut ( $event )
{
2025-01-09 12:51:54 -08:00
if ( $this -> shouldNotSendAnyNotifications ( $event -> checkoutable )) {
2023-04-18 13:07:55 -07:00
return ;
}
2018-09-10 07:40:26 -07:00
/**
* Make a checkout acceptance and attach it in the notification
*/
2024-10-23 14:44:45 -07:00
$settings = Setting :: getSettings ();
2023-10-10 15:18:37 -07:00
$acceptance = $this -> getCheckoutAcceptance ( $event );
2024-10-23 14:54:21 -07:00
$adminCcEmailsArray = [];
2025-01-09 12:51:54 -08:00
if ( $settings -> admin_cc_email !== '' ) {
2024-10-23 14:54:21 -07:00
$adminCcEmail = $settings -> admin_cc_email ;
$adminCcEmailsArray = array_map ( 'trim' , explode ( ',' , $adminCcEmail ));
}
2024-10-24 22:53:53 -07:00
$ccEmails = array_filter ( $adminCcEmailsArray );
2024-10-16 15:27:34 -07:00
$mailable = $this -> getCheckoutMailType ( $event , $acceptance );
2024-11-04 16:32:46 -08:00
$notifiable = $this -> getNotifiables ( $event );
2024-11-04 15:13:10 -08:00
2025-01-09 12:51:54 -08:00
if ( $event -> checkedOutTo -> locale ) {
2024-11-04 15:13:10 -08:00
$mailable -> locale ( $event -> checkedOutTo -> locale );
}
2024-09-18 15:23:44 -07:00
// Send email notifications
2022-09-15 13:18:42 -07:00
try {
2024-10-22 11:49:06 -07:00
/**
* Send an email if any of the following conditions are met :
* 1. The asset requires acceptance
* 2. The item has a EULA
* 3. The item should send an email at check - in / check - out
*/
2024-10-31 12:50:13 -07:00
2025-01-09 12:51:54 -08:00
if ( $event -> checkoutable -> requireAcceptance () || $event -> checkoutable -> getEula () ||
$this -> checkoutableShouldSendEmail ( $event )) {
Log :: info ( 'Sending checkout email, Locale: ' . ( $event -> checkedOutTo -> locale ? ? 'default' ));
if ( ! empty ( $notifiable )) {
Mail :: to ( $notifiable ) -> cc ( $ccEmails ) -> send ( $mailable );
} elseif ( ! empty ( $ccEmails )) {
Mail :: cc ( $ccEmails ) -> send ( $mailable );
2024-11-04 15:13:10 -08:00
}
2025-01-09 12:51:54 -08:00
Log :: info ( 'Checkout Mail sent.' );
}
2024-11-04 15:13:10 -08:00
} catch ( ClientException $e ) {
Log :: debug ( " Exception caught during checkout email: " . $e -> getMessage ());
} catch ( Exception $e ) {
Log :: debug ( " Exception caught during checkout email: " . $e -> getMessage ());
}
2024-10-16 12:51:19 -07:00
// Send Webhook notification
2025-01-09 12:51:54 -08:00
try {
if ( $this -> shouldSendWebhookNotification ()) {
if ( $this -> newMicrosoftTeamsWebhookEnabled ()) {
$message = $this -> getCheckoutNotification ( $event ) -> toMicrosoftTeams ();
$notification = new TeamsNotification ( Setting :: getSettings () -> webhook_endpoint );
$notification -> success () -> sendMessage ( $message [ 0 ], $message [ 1 ]); // Send the message to Microsoft Teams
} else {
Notification :: route ( $this -> webhookSelected (), Setting :: getSettings () -> webhook_endpoint )
-> notify ( $this -> getCheckoutNotification ( $event , $acceptance ));
2024-10-16 12:51:19 -07:00
}
2025-01-09 12:51:54 -08:00
}
2023-10-10 15:18:55 -07:00
} catch ( ClientException $e ) {
2025-01-09 12:55:25 -08:00
Log :: error ( " ClientException caught during checkin notification: " . $e -> getMessage ());
2025-01-09 12:51:54 -08:00
return redirect () -> back () -> with ( 'error' , ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed: Check to make sure your URL is still valid.' );
2023-10-10 15:18:55 -07:00
} catch ( Exception $e ) {
2025-01-09 12:51:54 -08:00
Log :: error ( ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed:' , [
'error' => $e -> getMessage (),
'webhook_endpoint' => Setting :: getSettings () -> webhook_endpoint ,
'event' => $event ,
]);
return redirect () -> back () -> with ( 'error' , ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed: Check to make sure your URL is still valid.' );
2019-01-22 14:02:08 -08:00
}
2018-09-10 07:40:26 -07:00
}
2024-09-18 15:23:44 -07:00
2025-01-09 12:51:54 -08:00
2018-09-10 07:40:26 -07:00
/**
2023-04-05 12:39:41 -07:00
* Notify the user and post to webhook about the checked in checkoutable
2018-09-10 07:40:26 -07:00
*/
2021-06-10 13:15:52 -07:00
public function onCheckedIn ( $event )
{
2024-05-29 04:38:15 -07:00
Log :: debug ( 'onCheckedIn in the Checkoutable listener fired' );
2020-09-11 16:10:18 -07:00
2023-04-18 13:07:55 -07:00
if ( $this -> shouldNotSendAnyNotifications ( $event -> checkoutable )) {
return ;
}
2018-09-10 07:40:26 -07:00
/**
* Send the appropriate notification
*/
2023-09-13 15:35:10 -07:00
if ( $event -> checkedOutTo && $event -> checkoutable ){
$acceptances = CheckoutAcceptance :: where ( 'checkoutable_id' , $event -> checkoutable -> id )
-> where ( 'assigned_to_id' , $event -> checkedOutTo -> id )
-> get ();
2021-09-07 10:01:32 -07:00
2023-09-13 15:35:10 -07:00
foreach ( $acceptances as $acceptance ){
if ( $acceptance -> isPending ()){
$acceptance -> delete ();
}
2021-09-07 10:01:32 -07:00
}
}
2024-10-23 14:44:45 -07:00
$settings = Setting :: getSettings ();
2024-10-23 14:54:21 -07:00
$adminCcEmailsArray = [];
if ( $settings -> admin_cc_email !== '' ) {
$adminCcEmail = $settings -> admin_cc_email ;
$adminCcEmailsArray = array_map ( 'trim' , explode ( ',' , $adminCcEmail ));
}
2024-10-24 22:53:53 -07:00
$ccEmails = array_filter ( $adminCcEmailsArray );
2024-10-16 15:27:34 -07:00
$mailable = $this -> getCheckinMailType ( $event );
2024-11-04 16:32:46 -08:00
$notifiable = $this -> getNotifiables ( $event );
2025-01-07 10:51:48 -08:00
if ( $event -> checkedOutTo -> locale ){
2024-11-04 15:13:10 -08:00
$mailable -> locale ( $event -> checkedOutTo -> locale );
}
2024-09-18 15:23:44 -07:00
// Send email notifications
2022-09-15 13:18:42 -07:00
try {
2024-10-22 11:49:06 -07:00
/**
* Send an email if any of the following conditions are met :
* 1. The asset requires acceptance
* 2. The item has a EULA
* 3. The item should send an email at check - in / check - out
*/
if ( $event -> checkoutable -> requireAcceptance () || $event -> checkoutable -> getEula () ||
2024-11-13 13:07:28 -08:00
$this -> checkoutableShouldSendEmail ( $event )) {
2024-11-13 12:19:16 -08:00
Log :: info ( 'Sending checkin email, Locale: ' . ( $event -> checkedOutTo -> locale ? ? 'default' ));
2024-11-04 15:13:10 -08:00
if ( ! empty ( $notifiable )) {
2024-10-31 12:50:13 -07:00
Mail :: to ( $notifiable ) -> cc ( $ccEmails ) -> send ( $mailable );
2024-11-04 15:13:10 -08:00
} elseif ( ! empty ( $ccEmails )){
2024-10-31 12:50:13 -07:00
Mail :: cc ( $ccEmails ) -> send ( $mailable );
}
2024-11-13 12:19:16 -08:00
Log :: info ( 'Checkin Mail sent.' );
2024-10-22 11:49:06 -07:00
}
2024-11-04 15:13:10 -08:00
} catch ( ClientException $e ) {
Log :: debug ( " Exception caught during checkin email: " . $e -> getMessage ());
} catch ( Exception $e ) {
Log :: debug ( " Exception caught during checkin email: " . $e -> getMessage ());
}
2024-10-31 12:50:13 -07:00
2024-11-04 15:13:10 -08:00
// Send Webhook notification
try {
2024-09-18 15:23:44 -07:00
if ( $this -> shouldSendWebhookNotification ()) {
2024-11-13 14:29:01 -08:00
if ( $this -> newMicrosoftTeamsWebhookEnabled ()) {
2025-01-09 12:51:54 -08:00
$message = $this -> getCheckinNotification ( $event ) -> toMicrosoftTeams ();
$notification = new TeamsNotification ( Setting :: getSettings () -> webhook_endpoint );
$notification -> success () -> sendMessage ( $message [ 0 ], $message [ 1 ]); // Send the message to Microsoft Teams
} else {
Notification :: route ( $this -> webhookSelected (), Setting :: getSettings () -> webhook_endpoint )
-> notify ( $this -> getCheckinNotification ( $event ));
2024-01-23 11:10:04 -08:00
}
2025-01-09 12:51:54 -08:00
}
2023-10-10 15:18:55 -07:00
} catch ( ClientException $e ) {
2025-01-09 12:55:25 -08:00
Log :: error ( " ClientException caught during checkin notification: " . $e -> getMessage ());
2025-01-09 12:51:54 -08:00
return redirect () -> back () -> with ( 'error' , ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed: Check to make sure the URL is still valid.' );
2023-10-10 15:18:55 -07:00
} catch ( Exception $e ) {
2025-01-09 12:51:54 -08:00
Log :: error ( ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed:' , [
'error' => $e -> getMessage (),
'webhook_endpoint' => Setting :: getSettings () -> webhook_endpoint ,
'event' => $event ,
]);
return redirect () -> back () -> with ( 'error' , ucfirst ( Setting :: getSettings () -> webhook_selected ) . ' webhook notification failed: Check to make sure the URL is still valid.' );
2019-01-22 14:02:08 -08:00
}
2018-09-10 07:40:26 -07:00
}
/**
* Generates a checkout acceptance
* @ param Event $event
* @ return mixed
*/
2021-06-10 13:15:52 -07:00
private function getCheckoutAcceptance ( $event )
{
2024-08-07 14:53:06 -07:00
$checkedOutToType = get_class ( $event -> checkedOutTo );
if ( $checkedOutToType != " App \ Models \ User " ) {
return null ;
}
if ( ! $event -> checkoutable -> requireAcceptance ()) {
2018-09-10 07:40:26 -07:00
return null ;
}
$acceptance = new CheckoutAcceptance ;
$acceptance -> checkoutable () -> associate ( $event -> checkoutable );
$acceptance -> assignedTo () -> associate ( $event -> checkedOutTo );
$acceptance -> save ();
return $acceptance ;
}
/**
* Get the appropriate notification for the event
*
* @ param CheckoutableCheckedIn $event
* @ return Notification
*/
2021-06-10 13:15:52 -07:00
private function getCheckinNotification ( $event )
{
2018-09-10 07:40:26 -07:00
$notificationClass = null ;
switch ( get_class ( $event -> checkoutable )) {
case Accessory :: class :
$notificationClass = CheckinAccessoryNotification :: class ;
break ;
case Asset :: class :
$notificationClass = CheckinAssetNotification :: class ;
break ;
case LicenseSeat :: class :
$notificationClass = CheckinLicenseSeatNotification :: class ;
break ;
}
2020-09-11 16:10:18 -07:00
2024-05-29 04:38:15 -07:00
Log :: debug ( 'Notification class: ' . $notificationClass );
2021-06-10 13:15:52 -07:00
2018-09-10 07:40:26 -07:00
return new $notificationClass ( $event -> checkoutable , $event -> checkedOutTo , $event -> checkedInBy , $event -> note );
}
/**
* Get the appropriate notification for the event
*
2023-04-19 12:31:12 -07:00
* @ param CheckoutableCheckedOut $event
* @ param CheckoutAcceptance | null $acceptance
2018-09-10 07:40:26 -07:00
* @ return Notification
*/
2023-03-23 17:03:48 -07:00
private function getCheckoutNotification ( $event , $acceptance = null )
2021-06-10 13:15:52 -07:00
{
2018-09-10 07:40:26 -07:00
$notificationClass = null ;
2024-10-16 15:53:05 -07:00
switch ( get_class ( $event -> checkoutable )) {
case Accessory :: class :
2018-09-10 07:40:26 -07:00
$notificationClass = CheckoutAccessoryNotification :: class ;
break ;
2024-10-16 15:53:05 -07:00
case Asset :: class :
2018-09-10 07:40:26 -07:00
$notificationClass = CheckoutAssetNotification :: class ;
break ;
2024-10-16 15:53:05 -07:00
case Consumable :: class :
2018-09-10 07:40:26 -07:00
$notificationClass = CheckoutConsumableNotification :: class ;
2024-10-16 12:51:19 -07:00
break ;
2024-10-16 15:53:05 -07:00
case LicenseSeat :: class :
2018-09-10 07:40:26 -07:00
$notificationClass = CheckoutLicenseSeatNotification :: class ;
2024-01-23 13:05:39 -08:00
break ;
2018-09-10 07:40:26 -07:00
}
2024-10-16 15:53:05 -07:00
2018-09-10 07:40:26 -07:00
return new $notificationClass ( $event -> checkoutable , $event -> checkedOutTo , $event -> checkedOutBy , $acceptance , $event -> note );
}
2024-10-16 15:27:34 -07:00
private function getCheckoutMailType ( $event , $acceptance ){
$lookup = [
Accessory :: class => CheckoutAccessoryMail :: class ,
Asset :: class => CheckoutAssetMail :: class ,
2024-10-16 15:38:49 -07:00
LicenseSeat :: class => CheckoutLicenseMail :: class ,
2024-10-16 15:53:05 -07:00
Consumable :: class => CheckoutConsumableMail :: class ,
2024-10-16 15:27:34 -07:00
];
$mailable = $lookup [ get_class ( $event -> checkoutable )];
2024-12-11 16:14:06 -08:00
return new $mailable ( $event -> checkoutable , $event -> checkedOutTo , $event -> checkedOutBy , $acceptance , $event -> note );
2024-10-16 15:27:34 -07:00
}
private function getCheckinMailType ( $event ){
$lookup = [
Accessory :: class => CheckinAccessoryMail :: class ,
Asset :: class => CheckinAssetMail :: class ,
2024-10-16 15:44:45 -07:00
LicenseSeat :: class => CheckinLicenseMail :: class ,
2024-10-16 15:27:34 -07:00
];
2024-10-16 15:53:05 -07:00
2024-10-16 15:27:34 -07:00
$mailable = $lookup [ get_class ( $event -> checkoutable )];
return new $mailable ( $event -> checkoutable , $event -> checkedOutTo , $event -> checkedInBy , $event -> note );
}
2024-11-04 16:32:46 -08:00
private function getNotifiables ( $event ){
if ( $event -> checkedOutTo instanceof Asset ){
$event -> checkedOutTo -> load ( 'assignedTo' );
return $event -> checkedOutTo -> assignedto ? -> email ? ? '' ;
}
else if ( $event -> checkedOutTo instanceof Location ) {
return $event -> checkedOutTo -> manager ? -> email ? ? '' ;
}
else {
2024-11-20 08:29:28 -08:00
return $event -> checkedOutTo ? -> email ? ? '' ;
2024-11-04 16:32:46 -08:00
}
}
2024-12-02 10:19:24 -08:00
private function webhookSelected (){
if ( Setting :: getSettings () -> webhook_selected === 'slack' || Setting :: getSettings () -> webhook_selected === 'general' ){
return 'slack' ;
}
return Setting :: getSettings () -> webhook_selected ;
}
2018-09-10 07:40:26 -07:00
/**
* Register the listeners for the subscriber .
*
* @ param Illuminate\Events\Dispatcher $events
*/
public function subscribe ( $events )
{
$events -> listen (
2021-06-10 13:16:56 -07:00
\App\Events\CheckoutableCheckedIn :: class ,
2018-09-10 07:40:26 -07:00
'App\Listeners\CheckoutableListener@onCheckedIn'
);
$events -> listen (
2021-06-10 13:16:56 -07:00
\App\Events\CheckoutableCheckedOut :: class ,
2018-09-10 07:40:26 -07:00
'App\Listeners\CheckoutableListener@onCheckedOut'
);
}
2023-04-05 12:36:24 -07:00
2023-04-18 13:07:55 -07:00
private function shouldNotSendAnyNotifications ( $checkoutable ) : bool
{
return in_array ( get_class ( $checkoutable ), $this -> skipNotificationsFor );
}
2023-04-05 12:36:24 -07:00
private function shouldSendWebhookNotification () : bool
{
return Setting :: getSettings () && Setting :: getSettings () -> webhook_endpoint ;
}
2024-11-13 13:07:28 -08:00
private function checkoutableShouldSendEmail ( $event ) : bool
{
if ( $event -> checkoutable instanceof LicenseSeat ){
return $event -> checkoutable -> license -> checkin_email ();
}
return ( method_exists ( $event -> checkoutable , 'checkin_email' ) && $event -> checkoutable -> checkin_email ());
}
2024-11-13 14:29:01 -08:00
private function newMicrosoftTeamsWebhookEnabled () : bool
{
return Setting :: getSettings () -> webhook_selected === 'microsoft' && Str :: contains ( Setting :: getSettings () -> webhook_endpoint , 'workflows' );
}
2021-06-10 13:15:52 -07:00
}