diff --git a/app/Events/UserStateChanged.php b/app/Events/UserStateChanged.php index 7fa78985..ef251e00 100644 --- a/app/Events/UserStateChanged.php +++ b/app/Events/UserStateChanged.php @@ -7,14 +7,19 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; +/** + * Event triggered when a user's state changes + * @package App\Events + */ class UserStateChanged { use Dispatchable, InteractsWithSockets, SerializesModels; - public $user; + public $old_state, $user; - public function __construct(User $user) + public function __construct(User $user, $old_state) { + $this->old_state = $old_state; $this->user = $user; } } diff --git a/app/Events/UserStatsChanged.php b/app/Events/UserStatsChanged.php new file mode 100644 index 00000000..9c5cf973 --- /dev/null +++ b/app/Events/UserStatsChanged.php @@ -0,0 +1,29 @@ +user = $user; + $this->stat_name = $stat_name; + $this->old_value = $old_value; + } +} diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index ab987ca4..16cdb09e 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -2,26 +2,29 @@ namespace App\Http\Controllers\Admin; +use DB; +use Hash; +use Log; +use Flash; +use Response; +use Jackiedo\Timezonelist\Facades\Timezonelist; +use Illuminate\Http\Request; + use App\Http\Requests\CreateUserRequest; use App\Http\Requests\UpdateUserRequest; use App\Repositories\UserRepository; -use DB; -use Hash; -use Illuminate\Http\Request; -use Flash; -use Jackiedo\Timezonelist\Facades\Timezonelist; -use Response; +use App\Services\UserService; use App\Models\Airport; use App\Models\Airline; use App\Models\Rank; use App\Models\Role; - class UserController extends BaseController { /** @var UserRepository */ - private $userRepo; + private $userRepo, + $userSvc; /** * UserController constructor. @@ -29,18 +32,18 @@ class UserController extends BaseController * @param UserRepository $userRepo */ public function __construct( - UserRepository $userRepo + UserRepository $userRepo, + UserService $userSvc ) { + $this->userSvc = $userSvc; $this->userRepo = $userRepo; } public function index(Request $request) { - $users = $this->userRepo->searchCriteria($request, false)->paginate(); - /*$this->userRepo->pushCriteria(new RequestCriteria($request)); - $users = $this->userRepo + $users = $this->userRepo->searchCriteria($request, false) ->orderBy('created_at', 'desc') - ->paginate();*/ + ->paginate(); return view('admin.users.index', [ 'users' => $users, @@ -146,8 +149,15 @@ class UserController extends BaseController $req_data['password'] = Hash::make($req_data['password']); } + $original_user_state = $user->state; + $user = $this->userRepo->update($req_data, $id); + if($original_user_state !== $user->state) { + $this->userSvc->changeUserState($user, $original_user_state); + } + + # Delete all of the roles and then re-attach the valid ones DB::table('role_user')->where('user_id',$id)->delete(); foreach ($request->input('roles') as $key => $value) { $user->attachRole($value); diff --git a/app/Listeners/EmailEventListener.php b/app/Listeners/EmailEventListener.php index c61f2471..a652d5ef 100644 --- a/app/Listeners/EmailEventListener.php +++ b/app/Listeners/EmailEventListener.php @@ -2,6 +2,7 @@ namespace App\Listeners; +use App\Events\UserStateChanged; use Log; use Illuminate\Support\Facades\Mail; @@ -34,10 +35,45 @@ class EmailEventListener . ', sending active email'); if($event->user->state === PilotState::ACTIVE) { - Mail::to($event->user->email)->send(new \App\Mail\UserRegistered($event->user)); + $email = new \App\Mail\UserRegistered( + $event->user, + 'Welcome to ' . config('app.name') . '!' + ); + + Mail::to($event->user->email)->send($email); } else if($event->user->state === PilotState::PENDING) { Mail::to($event->user->email)->send(new \App\Mail\UserPending($event->user)); } } + /** + * When a user's state changes, send an email out + * @param UserStateChanged $event + */ + public function onUserStateChange(UserStateChanged $event) + { + if ($event->old_state === PilotState::PENDING) { + if ($event->user->state === PilotState::ACTIVE) + { + $email = new \App\Mail\UserRegistered( + $event->user, + 'Your registration has been accepted!' + ); + + Mail::to($event->user->email)->send($email); + } + + else if ($event->user->state === PilotState::REJECTED) + { + $email = new \App\Mail\UserRejected($event->user); + Mail::to($event->user->email)->send($email); + } + } + + # TODO: Other state transitions + elseif ($event->old_state === PilotState::ACTIVE) + { + + } + } } diff --git a/app/Mail/UserPending.php b/app/Mail/UserPending.php index fc6adf8a..5b93d803 100644 --- a/app/Mail/UserPending.php +++ b/app/Mail/UserPending.php @@ -3,30 +3,27 @@ namespace App\Mail; use App\Models\User; -use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; +use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; -use Illuminate\Contracts\Queue\ShouldQueue; class UserPending extends Mailable { use Queueable, SerializesModels; - private $user; + private $subject, + $user; - public function __construct(User $user) + public function __construct(User $user, $subject=null) { + $this->subject = $subject ?: 'Your registration is pending!'; $this->user = $user; } - /** - * Build the message. - * - * @return $this - */ public function build() { return $this->markdown('emails.user.pending') + ->subject($this->subject) ->with(['user' => $this->user]); } } diff --git a/app/Mail/UserRegistered.php b/app/Mail/UserRegistered.php index 9f0b2474..8d2b1560 100644 --- a/app/Mail/UserRegistered.php +++ b/app/Mail/UserRegistered.php @@ -12,23 +12,19 @@ class UserRegistered extends Mailable { use Queueable, SerializesModels; - private $user; + private $subject, + $user; - public function __construct(User $user) + public function __construct(User $user, $subject=null) { + $this->subject = $subject; $this->user = $user; } - /** - * Build the message. - * - * @return $this - */ public function build() { return $this->markdown('emails.user.registered') - ->with([ - 'user' => $this->user, - ]); + ->subject($this->subject) + ->with(['user' => $this->user]); } } diff --git a/app/Mail/UserRejected.php b/app/Mail/UserRejected.php new file mode 100644 index 00000000..316702d3 --- /dev/null +++ b/app/Mail/UserRejected.php @@ -0,0 +1,29 @@ +subject = $subject ?: 'Your registration has been denied'; + $this->user = $user; + } + + public function build() + { + return $this->markdown('emails.user.rejected') + ->subject($this->subject) + ->with(['user' => $this->user]); + } +} diff --git a/app/Models/Enums/EnumBase.php b/app/Models/Enums/EnumBase.php index 0f4c0e27..e09ce685 100644 --- a/app/Models/Enums/EnumBase.php +++ b/app/Models/Enums/EnumBase.php @@ -12,7 +12,6 @@ namespace App\Models\Enums; /** * Class EnumBase * @package App\Models\Enums - * TODO: Implement lang translations for enum labels */ class EnumBase { @@ -29,4 +28,17 @@ class EnumBase return trans(static::$labels[$value]); } } + + /** + * Return all of the (translated) labels + */ + public static function labels() + { + $labels = []; + foreach(static::$labels as $key => $label) { + $labels[$key] = trans($label); + } + + return $labels; + } } diff --git a/app/Models/User.php b/app/Models/User.php index c0ccc21a..5b602a02 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -57,6 +57,10 @@ class User extends Authenticatable 'balance' => 'double', ]; + public static $rules = [ + + ]; + public function getPilotIdAttribute($value) { $length = setting('pilots.id_length'); diff --git a/app/Services/PIREPService.php b/app/Services/PIREPService.php index 8fc36e95..a4d2770d 100644 --- a/app/Services/PIREPService.php +++ b/app/Services/PIREPService.php @@ -10,7 +10,7 @@ use App\Models\PirepFieldValues; use App\Events\PirepAccepted; use App\Events\PirepFiled; use App\Events\PirepRejected; -use App\Events\UserStateChanged; +use App\Events\UserStatsChanged; use App\Repositories\PirepRepository; use Log; @@ -202,6 +202,6 @@ class PIREPService extends BaseService $pilot->last_pirep_id = $pirep->id; $pilot->save(); - event(new UserStateChanged($pilot)); + event(new UserStatsChanged($pilot)); } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 5c758b25..7fb153b2 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -2,23 +2,20 @@ namespace App\Services; -use App\Events\UserRegistered; use App\Facades\Utils; -use App\Models\Enums\PilotState; use App\Models\User; use App\Models\Rank; use App\Models\Role; - +use App\Events\UserRegistered; use App\Events\UserStateChanged; - -use Illuminate\Support\Facades\Cache; -use Illuminate\Support\Facades\Hash; +use App\Events\UserStatsChanged; +use App\Models\Enums\PilotState; class UserService extends BaseService { - /** - * Register a pilot + * Register a pilot. Also attaches the initial roles + * required, and then triggers the UserRegistered event * @param User $user * @return mixed */ @@ -37,7 +34,7 @@ class UserService extends BaseService $role = Role::where('name', 'user')->first(); $user->attachRole($role); - # Let's check their rank + # Let's check their rank and where they should start $this->calculatePilotRank($user); $user->refresh(); @@ -47,35 +44,76 @@ class UserService extends BaseService return $user; } + /** + * Change the user's state. PENDING to ACCEPTED, etc + * Send out an email + * @param User $user + * @param $old_state + * @return User + */ + public function changeUserState(User $user, $old_state): User + { + if($user->state === $old_state) { + return; + } + + Log::info('User ' . $user->pilot_id . ' state changing from ' + . PilotState::label($old_state) . ' to ' + . PilotState::label($user->state)); + + event(new UserStateChanged($user, $old_state)); + } + + /** + * Adjust the number of flights a user has. Triggers + * UserStatsChanged event + * @param User $user + * @param int $count + * @return User + */ public function adjustFlightCount(User $user, int $count): User { $user->refresh(); + $old_value = $user->flights; $user->flights += $count; $user->save(); - event(new UserStateChanged($user)); + event(new UserStatsChanged($user, 'flights', $old_value)); return $user; } + /** + * Update a user's flight times + * @param User $user + * @param int $minutes + * @return User + */ public function adjustFlightTime(User $user, int $minutes): User { $user->refresh(); $user->flight_time += $minutes; $user->save(); - event(new UserStateChanged($user)); - return $user; } + + /** + * See if a pilot's rank has change. Triggers the UserStatsChanged event + * @param User $user + * @return User + */ public function calculatePilotRank(User $user): User { $user->refresh(); + $old_rank = $user->rank; + $original_rank_id = $user->rank_id; $pilot_hours = Utils::minutesToHours($user->flight_time); # TODO: Cache - $ranks = Rank::where('auto_promote', true)->orderBy('hours', 'asc')->get(); + $ranks = Rank::where('auto_promote', true) + ->orderBy('hours', 'asc')->get(); foreach ($ranks as $rank) { if($rank->hours > $pilot_hours) { @@ -85,10 +123,23 @@ class UserService extends BaseService } } - $user->save(); - - event(new UserStateChanged($user)); + // Only trigger the event/update if there's been a change + if($user->rank_id !== $original_rank_id) { + $user->save(); + $user->refresh(); + event(new UserStatsChanged($user, 'rank', $old_rank)); + } return $user; } + + /** + * Recount/update all of the stats for a user + * @param User $user + * @return User + */ + public function recalculateStats(User $user): User + { + return $user; + } } diff --git a/resources/views/admin/users/fields.blade.php b/resources/views/admin/users/fields.blade.php index ec846561..a8c19507 100644 --- a/resources/views/admin/users/fields.blade.php +++ b/resources/views/admin/users/fields.blade.php @@ -50,10 +50,9 @@
- {!! Form::label('active', 'Active:') !!} + {!! Form::label('state', 'State:') !!}
diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php index a6de4a69..b290cdbb 100644 --- a/resources/views/admin/users/index.blade.php +++ b/resources/views/admin/users/index.blade.php @@ -3,7 +3,7 @@ @section('title', 'Users') @section('actions')
  • - {!! PilotState::label(PilotState::PENDING) !!} + {!! PilotState::label(PilotState::PENDING) !!}
  • @endsection diff --git a/resources/views/emails/user/pending.blade.php b/resources/views/emails/user/pending.blade.php index 4c46d36b..e5614b95 100644 --- a/resources/views/emails/user/pending.blade.php +++ b/resources/views/emails/user/pending.blade.php @@ -4,5 +4,5 @@ You will be notified as soon as your account is approved! Thanks,
    -{{ config('app.name') }} +Management, {{ config('app.name') }} @endcomponent diff --git a/resources/views/emails/user/registered.blade.php b/resources/views/emails/user/registered.blade.php index 2e00c8db..7b291eeb 100644 --- a/resources/views/emails/user/registered.blade.php +++ b/resources/views/emails/user/registered.blade.php @@ -8,5 +8,5 @@ Visit your account now! @endcomponent Thanks,
    -{{ config('app.name') }} +Management, {{ config('app.name') }} @endcomponent diff --git a/resources/views/emails/user/rejected.blade.php b/resources/views/emails/user/rejected.blade.php new file mode 100644 index 00000000..cf77cf7b --- /dev/null +++ b/resources/views/emails/user/rejected.blade.php @@ -0,0 +1,9 @@ +@component('mail::message') +# Hi {!! $user->name !!}, + +Your registration to our airline was denied. Please contact +an administrator with any questions you may have. + +Thanks,
    +Management, {{ config('app.name') }} +@endcomponent