391 Notification refactorings (#441)

* Refactor notifications to allow easier plugins

* Notification refactoring

* Formatting

* Move news to NewsService; cleanup of events

* More refactoring; added send email out for news item and the template

* Formatting

* Formatting
This commit is contained in:
Nabeel S
2019-11-20 10:16:01 -05:00
committed by GitHub
parent 02973a0f22
commit ea3ab21beb
66 changed files with 754 additions and 718 deletions

View File

@@ -5,13 +5,11 @@ namespace App\Bootstrap;
use Illuminate\Contracts\Config\Repository as RepositoryContract; use Illuminate\Contracts\Config\Repository as RepositoryContract;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
/**
* Class LoadConfiguration
*/
class LoadConfiguration extends \Illuminate\Foundation\Bootstrap\LoadConfiguration class LoadConfiguration extends \Illuminate\Foundation\Bootstrap\LoadConfiguration
{ {
/** /**
* Load the configuration items from all of the files. * Load the configuration items from all of the files. This reads the config.php from
* that's sitting in the root, and then recursively merges it with the current configs
* *
* @param \Illuminate\Contracts\Foundation\Application $app * @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Contracts\Config\Repository $repository * @param \Illuminate\Contracts\Config\Repository $repository

View File

@@ -6,7 +6,8 @@ use App\Facades\Utils;
use App\Models\Award as AwardModel; use App\Models\Award as AwardModel;
use App\Models\User; use App\Models\User;
use App\Models\UserAward; use App\Models\UserAward;
use Log; use Exception;
use Illuminate\Support\Facades\Log;
/** /**
* Base class for the Awards, you need to extend this, and implement: * Base class for the Awards, you need to extend this, and implement:
@@ -38,12 +39,6 @@ abstract class Award
protected $award; protected $award;
protected $user; protected $user;
/**
* AwardInterface constructor.
*
* @param AwardModel $award
* @param User $user
*/
public function __construct(AwardModel $award = null, User $user = null) public function __construct(AwardModel $award = null, User $user = null)
{ {
$this->award = $award; $this->award = $award;
@@ -73,7 +68,7 @@ abstract class Award
* *
* @return bool|UserAward * @return bool|UserAward
*/ */
final protected function addAward() protected function addAward()
{ {
$w = [ $w = [
'user_id' => $this->user->id, 'user_id' => $this->user->id,
@@ -90,7 +85,7 @@ abstract class Award
try { try {
$award->save(); $award->save();
} catch (\Exception $e) { } catch (Exception $e) {
Log::error( Log::error(
'Error saving award: '.$e->getMessage(), 'Error saving award: '.$e->getMessage(),
$e->getTrace() $e->getTrace()

View File

@@ -2,9 +2,21 @@
namespace App\Contracts; namespace App\Contracts;
/** use Illuminate\Contracts\Events\Dispatcher;
* Class Listener
*/
abstract class Listener abstract class Listener
{ {
public static $callbacks = [];
/**
* Sets up any callbacks that are defined in the child class
*
* @param $events
*/
public function subscribe(Dispatcher $events): void
{
foreach (static::$callbacks as $klass => $cb) {
$events->listen($klass, get_class($this).'@'.$cb);
}
}
} }

View File

@@ -20,7 +20,7 @@ awards:
name: Pilot 50 flights name: Pilot 50 flights
description: When a pilot has 50 flights, give this award description: When a pilot has 50 flights, give this award
image_url: image_url:
ref_model: App\Awards\PilotFlightAwards ref_model: Modules\Awards\Awards\PilotFlightAwards
ref_model_params: 50 ref_model_params: 50
created_at: now created_at: now
updated_at: now updated_at: now

View File

@@ -222,3 +222,17 @@
options: '' options: ''
type: boolean type: boolean
description: 'Count transfer hours in calculations, like ranks and the total hours' description: 'Count transfer hours in calculations, like ranks and the total hours'
- key: notifications.discord_api_key
name: Discord API token
group: notifications
value: ''
options: ''
type: text
description: Discord API token for notifications
- key: 'notifications.discord_public_channel_id'
name: 'Discord Public Channel ID'
group: 'notifications'
value: ''
options: ''
type: 'text'
description: 'Discord public channel ID for broadcasat notifications'

12
app/Events/BaseEvent.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BaseEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
}

View File

@@ -2,20 +2,6 @@
namespace App\Events; namespace App\Events;
use Illuminate\Foundation\Events\Dispatchable; class CronHourly extends BaseEvent
use Illuminate\Queue\SerializesModels;
/**
* This event is dispatched when the hourly cron is run
*/
class CronHourly
{ {
use Dispatchable, SerializesModels;
/**
* CronHourly constructor.
*/
public function __construct()
{
}
} }

View File

@@ -2,21 +2,10 @@
namespace App\Events; namespace App\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** /**
* This event is dispatched when the monthly cron is run * This event is dispatched when the monthly cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronMonthly class CronMonthly extends BaseEvent
{ {
use Dispatchable, SerializesModels;
/**
* CronMonthly constructor.
*/
public function __construct()
{
}
} }

View File

@@ -2,21 +2,10 @@
namespace App\Events; namespace App\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** /**
* This event is dispatched when the daily cron is run * This event is dispatched when the daily cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronNightly class CronNightly extends BaseEvent
{ {
use Dispatchable, SerializesModels;
/**
* CronNightly constructor.
*/
public function __construct()
{
}
} }

View File

@@ -2,20 +2,12 @@
namespace App\Events; namespace App\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** /**
* This event is dispatched when the weekly cron is run * This event is dispatched when the weekly cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronWeekly class CronWeekly extends BaseEvent
{ {
use Dispatchable, SerializesModels;
/**
* CronWeekly constructor.
*/
public function __construct() public function __construct()
{ {
} }

View File

@@ -3,8 +3,6 @@
namespace App\Events; namespace App\Events;
use App\Models\Pirep; use App\Models\Pirep;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** /**
* This event is dispatched when the expenses for a flight report * This event is dispatched when the expenses for a flight report
@@ -27,9 +25,8 @@ use Illuminate\Queue\SerializesModels;
* *
* The event will have a copy of the PIREP model, if it's applicable * The event will have a copy of the PIREP model, if it's applicable
*/ */
class Expenses class Expenses extends BaseEvent
{ {
use Dispatchable, SerializesModels;
public $pirep; public $pirep;
/** /**

15
app/Events/NewsAdded.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
namespace App\Events;
use App\Models\News;
class NewsAdded extends BaseEvent
{
public $news;
public function __construct(News $news)
{
$this->news = $news;
}
}

View File

@@ -3,24 +3,11 @@
namespace App\Events; namespace App\Events;
use App\Models\Pirep; use App\Models\Pirep;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class PirepAccepted extends BaseEvent
* Class PirepAccepted
*/
class PirepAccepted
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $pirep; public $pirep;
/**
* PirepAccepted constructor.
*
* @param Pirep $pirep
*/
public function __construct(Pirep $pirep) public function __construct(Pirep $pirep)
{ {
$this->pirep = $pirep; $this->pirep = $pirep;

View File

@@ -3,13 +3,9 @@
namespace App\Events; namespace App\Events;
use App\Models\Pirep; use App\Models\Pirep;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PirepFiled class PirepFiled extends BaseEvent
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $pirep; public $pirep;
public function __construct(Pirep $pirep) public function __construct(Pirep $pirep)

View File

@@ -3,24 +3,11 @@
namespace App\Events; namespace App\Events;
use App\Models\Pirep; use App\Models\Pirep;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class PirepRejected extends BaseEvent
* Class PirepRejected
*/
class PirepRejected
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $pirep; public $pirep;
/**
* PirepRejected constructor.
*
* @param Pirep $pirep
*/
public function __construct(Pirep $pirep) public function __construct(Pirep $pirep)
{ {
$this->pirep = $pirep; $this->pirep = $pirep;

View File

@@ -3,24 +3,11 @@
namespace App\Events; namespace App\Events;
use App\Models\User; use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class TestEvent extends BaseEvent
* Class TestEvent
*/
class TestEvent
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user; public $user;
/**
* Create a new event instance.
*
* @param User $user
*/
public function __construct(User $user) public function __construct(User $user)
{ {
$this->user = $user; $this->user = $user;

View File

@@ -3,24 +3,11 @@
namespace App\Events; namespace App\Events;
use App\Models\User; use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class UserAccepted extends BaseEvent
* Class UserAccepted
*/
class UserAccepted
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user; public $user;
/**
* UserAccepted constructor.
*
* @param User $user
*/
public function __construct(User $user) public function __construct(User $user)
{ {
$this->user = $user; $this->user = $user;

View File

@@ -3,24 +3,11 @@
namespace App\Events; namespace App\Events;
use App\Models\User; use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class UserRegistered extends BaseEvent
* Class UserRegistered
*/
class UserRegistered
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user; public $user;
/**
* UserRegistered constructor.
*
* @param User $user
*/
public function __construct(User $user) public function __construct(User $user)
{ {
$this->user = $user; $this->user = $user;

View File

@@ -3,26 +3,15 @@
namespace App\Events; namespace App\Events;
use App\Models\User; use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** /**
* Event triggered when a user's state changes * Event triggered when a user's state changes
*/ */
class UserStateChanged class UserStateChanged extends BaseEvent
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $old_state; public $old_state;
public $user; public $user;
/**
* UserStateChanged constructor.
*
* @param User $user
* @param $old_state
*/
public function __construct(User $user, $old_state) public function __construct(User $user, $old_state)
{ {
$this->old_state = $old_state; $this->old_state = $old_state;

View File

@@ -3,26 +3,18 @@
namespace App\Events; namespace App\Events;
use App\Models\User; use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/** class UserStatsChanged extends BaseEvent
* Class UserStatsChanged
*/
class UserStatsChanged
{ {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $stat_name; public $stat_name;
public $old_value; public $old_value;
public $user; public $user;
/* /*
* When a user's stats change. Stats changed match the field name: * When a user's stats change. Stats changed match the field name:
* airport * airport
* flights * flights
* rank * rank
*/ */
public function __construct(User $user, $stat_name, $old_value) public function __construct(User $user, $stat_name, $old_value)
{ {

View File

@@ -4,9 +4,9 @@ namespace App\Http\Controllers\Admin;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Repositories\KvpRepository; use App\Repositories\KvpRepository;
use App\Repositories\NewsRepository;
use App\Repositories\PirepRepository; use App\Repositories\PirepRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Services\NewsService;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -15,7 +15,7 @@ use Laracasts\Flash\Flash;
class DashboardController extends Controller class DashboardController extends Controller
{ {
private $kvpRepo; private $kvpRepo;
private $newsRepo; private $newsSvc;
private $pirepRepo; private $pirepRepo;
private $userRepo; private $userRepo;
@@ -23,20 +23,20 @@ class DashboardController extends Controller
* DashboardController constructor. * DashboardController constructor.
* *
* @param KvpRepository $kvpRepo * @param KvpRepository $kvpRepo
* @param NewsRepository $newsRepo
* @param PirepRepository $pirepRepo * @param PirepRepository $pirepRepo
* @param UserRepository $userRepo * @param UserRepository $userRepo
* @param $newsSvc
*/ */
public function __construct( public function __construct(
KvpRepository $kvpRepo, KvpRepository $kvpRepo,
NewsRepository $newsRepo, NewsService $newsSvc,
PirepRepository $pirepRepo, PirepRepository $pirepRepo,
UserRepository $userRepo UserRepository $userRepo
) { ) {
$this->kvpRepo = $kvpRepo; $this->kvpRepo = $kvpRepo;
$this->newsRepo = $newsRepo;
$this->pirepRepo = $pirepRepo; $this->pirepRepo = $pirepRepo;
$this->userRepo = $userRepo; $this->userRepo = $userRepo;
$this->newsSvc = $newsSvc;
} }
/** /**
@@ -93,10 +93,10 @@ class DashboardController extends Controller
$attrs = $request->post(); $attrs = $request->post();
$attrs['user_id'] = Auth::user()->id; $attrs['user_id'] = Auth::user()->id;
$this->newsRepo->create($attrs); $this->newsSvc->addNews($attrs);
} elseif ($request->isMethod('delete')) { } elseif ($request->isMethod('delete')) {
$news_id = $request->input('news_id'); $id = $request->input('news_id');
$this->newsRepo->delete($news_id); $this->newsSvc->deleteNews($id);
} }
return view('admin.dashboard.news', [ return view('admin.dashboard.news', [

View File

@@ -4,14 +4,19 @@ namespace App\Listeners;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\PirepAccepted; use App\Events\PirepAccepted;
use App\Events\PirepRejected;
use App\Services\BidService; use App\Services\BidService;
use Illuminate\Contracts\Events\Dispatcher;
/** /**
* Do stuff with bids - like if a PIREP is accepted, then remove the bid * Do stuff with bids - like if a PIREP is accepted, then remove the bid
*/ */
class BidEvents extends Listener class BidEventHandler extends Listener
{ {
public static $callbacks = [
PirepAccepted::class => 'onPirepAccept',
PirepRejected::class => 'onPirepReject',
];
private $bidSvc; private $bidSvc;
public function __construct(BidService $bidSvc) public function __construct(BidService $bidSvc)
@@ -19,17 +24,6 @@ class BidEvents extends Listener
$this->bidSvc = $bidSvc; $this->bidSvc = $bidSvc;
} }
/**
* @param $events
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
PirepAccepted::class,
'App\Listeners\BidEvents@onPirepAccept'
);
}
/** /**
* When a PIREP is accepted, remove any bids * When a PIREP is accepted, remove any bids
* *
@@ -43,4 +37,18 @@ class BidEvents extends Listener
{ {
$this->bidSvc->removeBidForPirep($event->pirep); $this->bidSvc->removeBidForPirep($event->pirep);
} }
/**
* When a PIREP is accepted, remove any bids
*
* @param PirepRejected $event
*
* @throws \UnexpectedValueException
* @throws \InvalidArgumentException
* @throws \Exception
*/
public function onPirepReject(PirepRejected $event): void
{
$this->bidSvc->removeBidForPirep($event->pirep);
}
} }

View File

@@ -5,9 +5,6 @@ namespace App\Listeners;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\Expenses; use App\Events\Expenses;
/**
* Class ExpenseListener
*/
class ExpenseListener extends Listener class ExpenseListener extends Listener
{ {
/** /**

View File

@@ -6,41 +6,23 @@ use App\Contracts\Listener;
use App\Events\PirepAccepted; use App\Events\PirepAccepted;
use App\Events\PirepRejected; use App\Events\PirepRejected;
use App\Services\Finance\PirepFinanceService; use App\Services\Finance\PirepFinanceService;
use Illuminate\Contracts\Events\Dispatcher;
/** /**
* Subscribe for events that we do some financial processing for * Subscribe for events that we do some financial processing for
* This includes when a PIREP is accepted, or rejected * This includes when a PIREP is accepted, or rejected
*/ */
class FinanceEvents extends Listener class FinanceEventHandler extends Listener
{ {
private $financeSvc; private $financeSvc;
/** public static $callbacks = [
* FinanceEvents constructor. PirepAccepted::class => 'onPirepAccept',
* PirepRejected::class => 'onPirepReject',
* @param PirepFinanceService $financeSvc ];
*/
public function __construct(
PirepFinanceService $financeSvc
) {
$this->financeSvc = $financeSvc;
}
/** public function __construct(PirepFinanceService $financeSvc)
* @param $events
*/
public function subscribe(Dispatcher $events): void
{ {
$events->listen( $this->financeSvc = $financeSvc;
PirepAccepted::class,
'App\Listeners\FinanceEvents@onPirepAccept'
);
$events->listen(
PirepRejected::class,
'App\Listeners\FinanceEvents@onPirepReject'
);
} }
/** /**

View File

@@ -7,7 +7,7 @@ use App\Events\PirepFiled;
use App\Events\UserStateChanged; use App\Events\UserStateChanged;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
class SetUserActive extends Listener class UserStateListener extends Listener
{ {
public function handle(PirepFiled $event): void public function handle(PirepFiled $event): void
{ {

View File

@@ -4,6 +4,10 @@ namespace App\Models;
use App\Contracts\Model; use App\Contracts\Model;
/**
* @property string subject
* @property string body
*/
class News extends Model class News extends Model
{ {
public $table = 'news'; public $table = 'news';

View File

@@ -1,61 +0,0 @@
<?php
namespace App\Notifications\Admin;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRegistered extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address'))
->markdown('mail.admin.user.registered')
->subject('A new user registered')
->with(['user' => $this->user]);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;
class BaseNotification extends Notification implements ShouldQueue
{
use Queueable;
public $channels = [];
public function __construct()
{
// Look in the notifications.channels config and see where this particular
// notification can go. Map it to $channels
$klass = get_class($this);
$notif_config = config('notifications.channels', []);
if (!array_key_exists($klass, $notif_config)) {
Log::error('Notification type '.$klass.' missing from notifications config');
return;
}
$this->channels = $notif_config[$klass];
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return $this->channels;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Notifications\Channels;
use Illuminate\Notifications\Messages\MailMessage;
trait MailChannel
{
private $mailSubject;
private $mailTemplate;
private $mailTemplateArgs;
/**
* Set the arguments for the toMail() method
*
* @param string $subject Email subject
* @param string $template Markdown template to use
* @param array $args Arguments to pass to the template
*/
public function setMailable($subject, $template, $args)
{
$this->mailSubject = $subject;
$this->mailTemplate = $template;
$this->mailTemplateArgs = $args;
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject($this->mailSubject)
->markdown($this->mailTemplate, $this->mailTemplateArgs);
}
}

View File

@@ -1,8 +1,9 @@
<?php <?php
namespace App\Listeners; namespace App\Notifications;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\NewsAdded;
use App\Events\PirepAccepted; use App\Events\PirepAccepted;
use App\Events\PirepFiled; use App\Events\PirepFiled;
use App\Events\PirepRejected; use App\Events\PirepRejected;
@@ -10,26 +11,32 @@ use App\Events\UserRegistered;
use App\Events\UserStateChanged; use App\Events\UserStateChanged;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\User; use App\Models\User;
use App\Notifications\PirepSubmitted; use App\Notifications\Messages\PirepSubmitted;
use Illuminate\Contracts\Events\Dispatcher; use App\Notifications\Messages\UserPending;
use App\Notifications\Messages\UserRejected;
use App\Notifications\Notifiables\Broadcast;
use Exception;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
/** /**
* Handle sending emails on different events * Listen for different events and map them to different notifications
*/ */
class NotificationEvents extends Listener class EventHandler extends Listener
{ {
/** private static $broadcastNotifyable;
* @param Dispatcher $events
*/ public static $callbacks = [
public function subscribe(Dispatcher $events): void PirepAccepted::class => 'onPirepAccepted',
PirepFiled::class => 'onPirepFile',
PirepRejected::class => 'onPirepRejected',
UserRegistered::class => 'onUserRegister',
UserStateChanged::class => 'onUserStateChange',
];
public function __construct()
{ {
$events->listen(UserRegistered::class, 'App\Listeners\NotificationEvents@onUserRegister'); static::$broadcastNotifyable = app(Broadcast::class);
$events->listen(UserStateChanged::class, 'App\Listeners\NotificationEvents@onUserStateChange');
$events->listen(PirepFiled::class, 'App\Listeners\NotificationEvents@onPirepFile');
$events->listen(PirepAccepted::class, 'App\Listeners\NotificationEvents@onPirepAccepted');
$events->listen(PirepRejected::class, 'App\Listeners\NotificationEvents@onPirepRejected');
} }
/** /**
@@ -43,7 +50,7 @@ class NotificationEvents extends Listener
try { try {
Notification::send($admin_users, $notification); Notification::send($admin_users, $notification);
} catch (\Exception $e) { } catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage()); Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
} }
} }
@@ -56,7 +63,23 @@ class NotificationEvents extends Listener
{ {
try { try {
$user->notify($notification); $user->notify($notification);
} catch (\Exception $e) { } catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
}
}
/**
* Send a notification to all users
*
* @param $notification
*/
protected function notifyAllUsers($notification)
{
$users = User::all()->get();
try {
Notification::send($users, $notification);
} catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage()); Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
} }
} }
@@ -70,21 +93,20 @@ class NotificationEvents extends Listener
{ {
Log::info('NotificationEvents::onUserRegister: ' Log::info('NotificationEvents::onUserRegister: '
.$event->user->ident.' is ' .$event->user->ident.' is '
.UserState::label($event->user->state) .UserState::label($event->user->state).', sending active email');
.', sending active email');
/* /*
* Send all of the admins a notification that a new user registered * Send all of the admins a notification that a new user registered
*/ */
$this->notifyAdmins(new \App\Notifications\Admin\UserRegistered($event->user)); $this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/* /*
* Send the user a confirmation email * Send the user a confirmation email
*/ */
if ($event->user->state === UserState::ACTIVE) { if ($event->user->state === UserState::ACTIVE) {
$this->notifyUser($event->user, new \App\Notifications\UserRegistered($event->user)); $this->notifyUser($event->user, new Messages\UserRegistered($event->user));
} elseif ($event->user->state === UserState::PENDING) { } elseif ($event->user->state === UserState::PENDING) {
$this->notifyUser($event->user, new \App\Notifications\UserPending($event->user)); $this->notifyUser($event->user, new UserPending($event->user));
} }
} }
@@ -99,9 +121,9 @@ class NotificationEvents extends Listener
if ($event->old_state === UserState::PENDING) { if ($event->old_state === UserState::PENDING) {
if ($event->user->state === UserState::ACTIVE) { if ($event->user->state === UserState::ACTIVE) {
$this->notifyUser($event->user, new \App\Notifications\UserRegistered($event->user)); $this->notifyUser($event->user, new Messages\UserRegistered($event->user));
} elseif ($event->user->state === UserState::REJECTED) { } elseif ($event->user->state === UserState::REJECTED) {
$this->notifyUser($event->user, new \App\Notifications\UserRejected($event->user)); $this->notifyUser($event->user, new UserRejected($event->user));
} }
} elseif ($event->old_state === UserState::ACTIVE) { } elseif ($event->old_state === UserState::ACTIVE) {
Log::info('User state change from active to ??'); Log::info('User state change from active to ??');
@@ -127,7 +149,7 @@ class NotificationEvents extends Listener
public function onPirepAccepted(PirepAccepted $event): void public function onPirepAccepted(PirepAccepted $event): void
{ {
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted'); Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new \App\Notifications\PirepAccepted($event->pirep)); $this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
} }
/** /**
@@ -138,6 +160,17 @@ class NotificationEvents extends Listener
public function onPirepRejected(PirepRejected $event): void public function onPirepRejected(PirepRejected $event): void
{ {
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected'); Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new \App\Notifications\PirepRejected($event->pirep)); $this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
/**
* Notify all users of a news event
*
* @param \App\Events\NewsAdded $event
*/
public function onNewsAdded(NewsAdded $event): void
{
Log::info('NotificationEvents::onNewsAdded');
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
} }
} }

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class AdminUserRegistered extends BaseNotification
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'A new user registered',
'notifications.mail.admin.user.registered',
['user' => $user]
);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Notifications\Messages;
use App\Models\News;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class NewsAdded extends BaseNotification
{
use MailChannel;
private $news;
public function __construct(News $news)
{
parent::__construct();
$this->news = $news;
$this->setMailable(
$news->subject,
'notifications.mail.news',
['news' => $news]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'news_id' => $this->news->id,
];
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
/**
* Send the PIREP accepted message to a particular user
*/
class PirepAccepted extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'PIREP Accepted!',
'notifications.mail.pirep.accepted',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class PirepRejected extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'PIREP Rejected!',
'notifications.mail.pirep.rejected',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class PirepSubmitted extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserPending extends BaseNotification
{
use MailChannel;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
$this->setMailable(
'Your registration is pending',
'notifications.mail.user.pending',
['user' => $this->user]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserRegistered extends BaseNotification
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'Welcome to '.config('app.name').'!',
'notifications.mail.user.registered',
['user' => $this->user]
);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserRejected extends BaseNotification
{
use MailChannel;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'Your registration has been denied',
'notifications.mail.user.rejected',
['user' => $this->user]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,6 +1,6 @@
<?php <?php
namespace App\Notifications; namespace App\Notifications\Notifiables;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Notifications\Notifiables;
use Illuminate\Notifications\Notifiable;
/**
* These are notifications that get broadcasted, not to a single person
* (e.g, on Discord, Slack or Telegram or something)
*
* $notifyable = app(Broadcast::class);
* $notifyable->notify($eventclass);
*/
class Broadcast
{
use Notifiable;
/**
* Routing for Discord - the public channel ID that's used
*/
public function routeNotificationForDiscord()
{
return setting('notifications.discord_public_channel_id');
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepAccepted extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('PIREP Accepted!')
->markdown('mail.pirep.accepted', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepRejected extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('PIREP Rejected!')
->markdown('mail.pirep.rejected', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepSubmitted extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('New PIREP Submitted')
->markdown('mail.admin.pirep.submitted', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,65 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserPending extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Your registration is pending')
->markdown('mail.user.pending', ['user' => $this->user]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,60 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRegistered extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Welcome to '.config('app.name').'!')
->markdown('mail.user.registered', ['user' => $this->user]);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,65 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRejected extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Your registration has been denied')
->markdown('mail.user.rejected', ['user' => $this->user]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -6,11 +6,11 @@ use App\Events\Expenses;
use App\Events\PirepFiled; use App\Events\PirepFiled;
use App\Events\UserStatsChanged; use App\Events\UserStatsChanged;
use App\Listeners\AwardListener; use App\Listeners\AwardListener;
use App\Listeners\BidEvents; use App\Listeners\BidEventHandler;
use App\Listeners\ExpenseListener; use App\Listeners\ExpenseListener;
use App\Listeners\FinanceEvents; use App\Listeners\FinanceEventHandler;
use App\Listeners\NotificationEvents; use App\Listeners\UserStateListener;
use App\Listeners\SetUserActive; use App\Notifications\EventHandler;
use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -23,7 +23,7 @@ class EventServiceProvider extends ServiceProvider
], ],
PirepFiled::class => [ PirepFiled::class => [
SetUserActive::class, UserStateListener::class,
], ],
Registered::class => [ Registered::class => [
@@ -36,8 +36,8 @@ class EventServiceProvider extends ServiceProvider
]; ];
protected $subscribe = [ protected $subscribe = [
BidEvents::class, BidEventHandler::class,
FinanceEvents::class, FinanceEventHandler::class,
NotificationEvents::class, EventHandler::class,
]; ];
} }

View File

@@ -4,6 +4,7 @@ namespace App\Services;
use App\Contracts\Service; use App\Contracts\Service;
use App\Support\ClassLoader; use App\Support\ClassLoader;
use function get_class;
use Nwidart\Modules\Facades\Module; use Nwidart\Modules\Facades\Module;
class AwardService extends Service class AwardService extends Service
@@ -18,9 +19,9 @@ class AwardService extends Service
$awards = []; $awards = [];
$formatted_awards = []; $formatted_awards = [];
// Find the awards in the app/Awards directory // Find the awards in the modules/Awards directory
$classes = ClassLoader::getClassesInPath(app_path('/Awards')); // $classes = ClassLoader::getClassesInPath(module_path('Awards'));
$awards = array_merge($awards, $classes); // $awards = array_merge($awards, $classes);
// Look throughout all the other modules, in the module/{MODULE}/Awards directory // Look throughout all the other modules, in the module/{MODULE}/Awards directory
foreach (Module::all() as $module) { foreach (Module::all() as $module) {
@@ -33,7 +34,7 @@ class AwardService extends Service
} }
foreach ($awards as $award) { foreach ($awards as $award) {
$formatted_awards[\get_class($award)] = $award; $formatted_awards[get_class($award)] = $award;
} }
return $formatted_awards; return $formatted_awards;

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Services;
use App\Contracts\Service;
use App\Events\NewsAdded;
use App\Repositories\NewsRepository;
class NewsService extends Service
{
private $newsRepo;
public function __construct(NewsRepository $newsRepo)
{
$this->newsRepo = $newsRepo;
}
/**
* Add a news item
*
* @param array $attrs
*
* @throws \Prettus\Validator\Exceptions\ValidatorException
*
* @return mixed
*/
public function addNews(array $attrs)
{
$news = $this->newsRepo->create($attrs);
event(new NewsAdded($news));
return $news;
}
/**
* Delete something from the news items
*
* @param int $id ID of the news row to delete
*/
public function deleteNews($id)
{
$this->newsRepo->delete($id);
}
}

View File

@@ -1,6 +1,6 @@
<?php <?php
use App\Notifications\Backups; use App\Notifications\Notifiables\Backups;
use Spatie\Backup\Notifications\Notifications\BackupHasFailed; use Spatie\Backup\Notifications\Notifications\BackupHasFailed;
use Spatie\Backup\Notifications\Notifications\BackupWasSuccessful; use Spatie\Backup\Notifications\Notifications\BackupWasSuccessful;
use Spatie\Backup\Notifications\Notifications\CleanupHasFailed; use Spatie\Backup\Notifications\Notifications\CleanupHasFailed;

26
config/notifications.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
use App\Notifications\Messages\AdminUserRegistered;
use App\Notifications\Messages\NewsAdded;
use App\Notifications\Messages\PirepAccepted;
use App\Notifications\Messages\PirepRejected;
use App\Notifications\Messages\PirepSubmitted;
use App\Notifications\Messages\UserPending;
use App\Notifications\Messages\UserRegistered;
use App\Notifications\Messages\UserRejected;
return [
/*
* The channels that notifications are sent on
*/
'channels' => [
AdminUserRegistered::class => ['mail'],
NewsAdded::class => ['mail'],
PirepAccepted::class => ['mail'],
PirepRejected::class => ['mail'],
PirepSubmitted::class => ['mail'],
UserPending::class => ['mail'],
UserRegistered::class => ['mail'],
UserRejected::class => ['mail'],
],
];

1
modules/.gitignore vendored
View File

@@ -3,6 +3,7 @@
/* /*
/*/ /*/
!.gitignore !.gitignore
!/Awards
!/Installer !/Installer
!/Sample !/Sample
!/Vacentral !/Vacentral

View File

@@ -1,12 +1,14 @@
<?php <?php
namespace App\Awards; namespace Modules\Awards\Awards;
use App\Contracts\Award; use App\Contracts\Award;
/** /**
* Simple example of an awards class, where you can apply an award when a user * Simple example of an awards class, where you can apply an award when a user
* has 100 flights. All award classes need to extend the AwardInterface * has 100 flights. All award classes need to extend Award and implement the check() method
*
* See: http://docs.phpvms.net/customizing/awards
*/ */
class PilotFlightAwards extends Award class PilotFlightAwards extends Award
{ {

View File

@@ -0,0 +1,12 @@
{
"name": "Awards",
"alias": "awards",
"description": "",
"keywords": [],
"active": 1,
"order": 0,
"providers": [],
"aliases": {},
"files": [],
"requires": []
}

View File

@@ -0,0 +1,12 @@
@component('mail::message')
# {{ $news->subject }}
$news->body
@component('mail::button', ['url' => route('frontend.pireps.show', [$pirep->id])])
View PIREP
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent

View File

@@ -34,7 +34,7 @@ class AwardsTest extends TestCase
{ {
// Create one award that's given out with one flight // Create one award that's given out with one flight
$award = factory(App\Models\Award::class)->create([ $award = factory(App\Models\Award::class)->create([
'ref_model' => App\Awards\PilotFlightAwards::class, 'ref_model' => Modules\Awards\Awards\PilotFlightAwards::class,
'ref_model_params' => 1, 'ref_model_params' => 1,
]); ]);

View File

@@ -6,11 +6,13 @@ use App\Models\Enums\AcarsType;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\User; use App\Models\User;
use App\Notifications\Messages\PirepAccepted;
use App\Repositories\SettingRepository; use App\Repositories\SettingRepository;
use App\Services\BidService; use App\Services\BidService;
use App\Services\FlightService; use App\Services\FlightService;
use App\Services\PirepService; use App\Services\PirepService;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Notification;
class PIREPTest extends TestCase class PIREPTest extends TestCase
{ {
@@ -81,7 +83,6 @@ class PIREPTest extends TestCase
* Now set the PIREP state to ACCEPTED * Now set the PIREP state to ACCEPTED
*/ */
$new_pirep_count = $pirep->pilot->flights + 1; $new_pirep_count = $pirep->pilot->flights + 1;
$original_flight_time = $pirep->pilot->flight_time;
$new_flight_time = $pirep->pilot->flight_time + $pirep->flight_time; $new_flight_time = $pirep->pilot->flight_time + $pirep->flight_time;
$this->pirepSvc->changeState($pirep, PirepState::ACCEPTED); $this->pirepSvc->changeState($pirep, PirepState::ACCEPTED);
@@ -96,6 +97,9 @@ class PIREPTest extends TestCase
$this->get('/api/fleet/aircraft/'.$pirep->aircraft_id, [], $user) $this->get('/api/fleet/aircraft/'.$pirep->aircraft_id, [], $user)
->assertJson(['data' => ['airport_id' => $pirep->arr_airport_id]]); ->assertJson(['data' => ['airport_id' => $pirep->arr_airport_id]]);
// Make sure a notification was sent out to both the user and the admin(s)
Notification::assertSentTo([$user], PirepAccepted::class);
// Try cancelling it // Try cancelling it
$uri = '/api/pireps/'.$pirep->id.'/cancel'; $uri = '/api/pireps/'.$pirep->id.'/cancel';
$response = $this->put($uri, [], [], $user); $response = $this->put($uri, [], [], $user);

View File

@@ -8,7 +8,7 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification;
use Tests\CreatesApplication; use Tests\CreatesApplication;
use Tests\TestData; use Tests\TestData;
@@ -46,7 +46,7 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
ThrottleRequests::class ThrottleRequests::class
); );
Mail::fake(); Notification::fake();
Artisan::call('database:create', ['--reset' => true]); Artisan::call('database:create', ['--reset' => true]);
Artisan::call('migrate:refresh', ['--env' => 'testing']); Artisan::call('migrate:refresh', ['--env' => 'testing']);