Added Email Capability
This commit is contained in:
+1
-4
@@ -9,11 +9,8 @@ use Illuminate\Console\Command;
|
||||
|
||||
#[Signature('app:recalculate-achivements')]
|
||||
#[Description('Recalculate achievements for all users')]
|
||||
class RecalculateAchivements extends Command
|
||||
class RecalculateAchievements extends Command
|
||||
{
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$users = User::all();
|
||||
@@ -37,6 +37,8 @@ class UpdateAlliances extends Command
|
||||
|
||||
Airline::whereInternalName($change['airline'])->update(['alliance' => $allianceId]);
|
||||
}
|
||||
|
||||
Alliance::recalculateChallengeThresholds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ class UserProfileController extends Controller
|
||||
$aircraftFamilies = match($achievement->internal_name){
|
||||
'aircraft.all_boeing_7x7' => Aircraft::BOEING_FAMILIES,
|
||||
'aircraft.all_airbus_a3xx' => Aircraft::AIRBUS_FAMILIES,
|
||||
'aircraft.all_boeing_737' => Aircraft::BOEING_737_VARIANTS,
|
||||
default => [],
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,22 @@ class Aircraft extends Model
|
||||
'787' => ['B788', 'B789', 'B78X'],
|
||||
];
|
||||
|
||||
public const array BOEING_737_VARIANTS = [
|
||||
'737-100' => ['B731'],
|
||||
'737-200' => ['B732'],
|
||||
'737-300' => ['B733'],
|
||||
'737-400' => ['B734'],
|
||||
'737-500' => ['B735'],
|
||||
'737-600' => ['B736'],
|
||||
'737-700' => ['B737', 'E737'],
|
||||
'737-800' => ['B738', 'P8'],
|
||||
'737-900' => ['B739'],
|
||||
'737 Max 7' => ['B37M'],
|
||||
'737 Max 8' => ['B38M'],
|
||||
'737 Max 9' => ['B39M'],
|
||||
'737 Max 10' => ['B3XM']
|
||||
];
|
||||
|
||||
public const array AIRBUS_FAMILIES = [
|
||||
'A300' => ['A30B', 'A300', 'A306'],
|
||||
'A310' => ['A310', 'A312', 'A313'],
|
||||
|
||||
@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Alliance extends Model
|
||||
{
|
||||
|
||||
protected $table = 'alliances';
|
||||
|
||||
protected $fillable = [
|
||||
@@ -18,8 +19,25 @@ class Alliance extends Model
|
||||
'internal_name' => 'string',
|
||||
];
|
||||
|
||||
const ALLIANCE_CHALLENGES = [
|
||||
'star_alliance' => 'airlines_alliances.all_star_alliance',
|
||||
'oneworld' => 'airlines_alliances.all_oneworld',
|
||||
'vanilla_alliance' => 'airlines_alliances.all_vanilla_alliance',
|
||||
'skyteam' => 'airlines_alliances.all_skyteam',
|
||||
];
|
||||
|
||||
public function airlines(): HasMany
|
||||
{
|
||||
return $this->hasMany(Airline::class);
|
||||
}
|
||||
|
||||
public static function recalculateChallengeThresholds() : void {
|
||||
$alliances = Alliance::all();
|
||||
foreach ($alliances as $alliance) {
|
||||
$airlineCount = $alliance->airlines()->count();
|
||||
$challenge = self::ALLIANCE_CHALLENGES[$alliance->internal_name];
|
||||
Achievement::where('internal_name', $challenge)->update(['threshold' => $airlineCount]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -13,11 +13,14 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use App\Traits\HasAchievements;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use NotificationChannels\WebPush\HasPushSubscriptions;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
use App\Notifications\ResetPasswordNotification;
|
||||
|
||||
|
||||
#[Fillable(['name', 'email', 'password', 'distance_unit', 'settings'])]
|
||||
#[Hidden(['password', 'remember_token'])]
|
||||
@@ -35,6 +38,22 @@ class User extends Authenticatable
|
||||
|
||||
protected $appends = ['resolved_settings'];
|
||||
|
||||
public function calculateAchievementsAndClearCache(): void
|
||||
{
|
||||
$this->clearCache();
|
||||
$this->calculateAchievements();
|
||||
}
|
||||
|
||||
public function clearCache(): void
|
||||
{
|
||||
Cache::forget("user_flights_{$this->id}");
|
||||
|
||||
$this
|
||||
->followers()
|
||||
->get()
|
||||
->each(fn ($follower) => Cache::forget("user_following_flights_{$follower->id}"));
|
||||
}
|
||||
|
||||
public function achievements(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserAchievement::class);
|
||||
@@ -83,6 +102,11 @@ class User extends Authenticatable
|
||||
});
|
||||
}
|
||||
|
||||
public function sendPasswordResetNotification($token): void
|
||||
{
|
||||
$this->notify(new ResetPasswordNotification($token));
|
||||
}
|
||||
|
||||
public function resolveRouteBinding($value, $field = null): ?User
|
||||
{
|
||||
return $this->where('name', 'ilike', $value)->firstOrFail();
|
||||
@@ -129,8 +153,8 @@ class User extends Authenticatable
|
||||
$today = now('UTC')->toDateString();
|
||||
|
||||
return match ($filter) {
|
||||
'departed' => $collection->filter(fn($f) => $f->departure_date <= $today)->values(),
|
||||
'upcoming' => $collection->filter(fn($f) => $f->departure_date > $today)->values(),
|
||||
'departed' => $collection->filter(fn($f) => Carbon::parse($f->departure_date)->toDateString() <= $today)->values(),
|
||||
'upcoming' => $collection->filter(fn($f) => Carbon::parse($f->departure_date)->toDateString() > $today)->values(),
|
||||
default => $collection,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
|
||||
class ResetPasswordNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $token;
|
||||
|
||||
public function __construct($token)
|
||||
{
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$url = url(route('password.reset', [
|
||||
'token' => $this->token,
|
||||
'email' => $notifiable->getEmailForPasswordReset(),
|
||||
], false));
|
||||
|
||||
return (new MailMessage)
|
||||
->theme('flightsgoneby')
|
||||
->subject(Lang::get('Reset your password'))
|
||||
->line(Lang::get('You are receiving this email because we received a password reset request for your account.'))
|
||||
->action(Lang::get('Reset Password'), $url)
|
||||
->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))
|
||||
->line(Lang::get('If you did not request a password reset, no further action is required.'));
|
||||
}
|
||||
}
|
||||
@@ -11,25 +11,12 @@ use Illuminate\Support\Facades\Cache;
|
||||
class FlightObserver
|
||||
{
|
||||
|
||||
protected function clearCache(UserFlight $flight): void
|
||||
{
|
||||
Cache::forget("user_flights_{$flight->user->id}");
|
||||
|
||||
$flight
|
||||
->user
|
||||
->followers()
|
||||
->get()
|
||||
->each(fn ($follower) => Cache::forget("user_following_flights_{$follower->id}"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recalculate after a flight is created.
|
||||
*/
|
||||
public function created(UserFlight $flight): void
|
||||
{
|
||||
$flight->user->calculateAchievements();
|
||||
$this->clearCache($flight);
|
||||
$flight->user->calculateAchievementsAndClearCache();
|
||||
new FollowerNotificationService()->notifyFlightEvent($flight, FlightNotificationType::forCreation($flight));
|
||||
}
|
||||
|
||||
@@ -41,8 +28,7 @@ class FlightObserver
|
||||
public function updated(UserFlight $flight): void
|
||||
{
|
||||
\Log::info('Observer fired for flight ' . $flight->id);
|
||||
$flight->user->calculateAchievements();
|
||||
$this->clearCache($flight);
|
||||
$flight->user->calculateAchievementsAndClearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,9 +37,7 @@ class FlightObserver
|
||||
*/
|
||||
public function deleted(UserFlight $flight): void
|
||||
{
|
||||
$flight->user->calculateAchievements();
|
||||
$this->clearCache($flight);
|
||||
|
||||
$flight->user->calculateAchievementsAndClearCache();
|
||||
if ($flight->departure_date->isFuture()) {
|
||||
new FollowerNotificationService()->notifyFlightEvent($flight, FlightNotificationType::Cancelled);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -29,6 +30,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
if(!app()->isProduction()){
|
||||
Mail::alwaysTo(config('app.test_email'));
|
||||
}
|
||||
Vite::prefetch(concurrency: 3);
|
||||
UserFlight::observe(FlightObserver::class);
|
||||
Airline::observe(AirlineObserver::class);
|
||||
|
||||
@@ -99,9 +99,9 @@ class AircraftChecker extends BaseChecker
|
||||
|
||||
$flownBoeingFamilies = collect(Aircraft::BOEING_FAMILIES)
|
||||
->filter(fn($designators) =>
|
||||
$flightsWithAircraft->contains(
|
||||
fn(UserFlight $f) => in_array($f->aircraft->designator, $designators)
|
||||
)
|
||||
$flightsWithAircraft->contains(
|
||||
fn(UserFlight $f) => in_array($f->aircraft->designator, $designators)
|
||||
)
|
||||
)
|
||||
->count();
|
||||
|
||||
@@ -109,14 +109,24 @@ class AircraftChecker extends BaseChecker
|
||||
|
||||
// --- Airbus A3xx families ---
|
||||
|
||||
$flownAirbusFamilie = collect(Aircraft::AIRBUS_FAMILIES)
|
||||
$flownAirbusFamilies = collect(Aircraft::AIRBUS_FAMILIES)
|
||||
->filter(fn($designators) =>
|
||||
$flightsWithAircraft->contains(
|
||||
fn(UserFlight $f) => in_array($f->aircraft->designator, $designators)
|
||||
)
|
||||
$flightsWithAircraft->contains(
|
||||
fn(UserFlight $f) => in_array($f->aircraft->designator, $designators)
|
||||
)
|
||||
)
|
||||
->count();
|
||||
|
||||
$this->awardProgress($flownAirbusFamilie, 'aircraft.all_airbus_a3xx');
|
||||
$this->awardProgress($flownAirbusFamilies, 'aircraft.all_airbus_a3xx');
|
||||
|
||||
$flown737Variants = collect(Aircraft::BOEING_737_VARIANTS)
|
||||
->filter(fn($designators) =>
|
||||
$flightsWithAircraft->contains(
|
||||
fn(UserFlight $f) => in_array($f->aircraft->designator, $designators)
|
||||
)
|
||||
)
|
||||
->count();
|
||||
$this->awardProgress($flown737Variants, 'aircraft.all_boeing_737');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user