diff --git a/Dockerfile b/Dockerfile index 11c8e06e..dea80223 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM php:7.4-fpm-alpine WORKDIR /var/www/ -RUN apk add gmp-dev icu-dev +RUN apk add gmp-dev icu-dev zlib-dev libpng-dev RUN curl --silent --show-error https://getcomposer.org/installer | php # Copy any config files in diff --git a/app/Console/Commands/EmailTest.php b/app/Console/Commands/EmailTest.php index 7362e268..8684974f 100644 --- a/app/Console/Commands/EmailTest.php +++ b/app/Console/Commands/EmailTest.php @@ -17,8 +17,8 @@ class EmailTest extends Command */ public function handle() { - /** @var App\Notifications\EventHandler $eventHandler */ - $eventHandler = app(App\Notifications\EventHandler::class); + /** @var App\Notifications\NotificationEventsHandler $eventHandler */ + $eventHandler = app(App\Notifications\NotificationEventsHandler::class); $news = new App\Models\News(); $news->user_id = 1; diff --git a/app/Contracts/Notification.php b/app/Contracts/Notification.php index 563d9939..0a7a1750 100644 --- a/app/Contracts/Notification.php +++ b/app/Contracts/Notification.php @@ -2,9 +2,9 @@ namespace App\Contracts; +use App\Notifications\Channels\Discord\DiscordMessage; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Support\Facades\Log; class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue { @@ -17,14 +17,14 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho { // Look in the notifications.channels config and see where this particular // notification can go. Map it to $channels - $klass = static::class; + /*$klass = static::class; $notif_config = config('notifications.channels', []); if (!array_key_exists($klass, $notif_config)) { Log::error('Notification type '.$klass.' missing from notifications config, defaulting to mail'); return; } - $this->channels = $notif_config[$klass]; + $this->channels = $notif_config[$klass];*/ } /** @@ -34,8 +34,16 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho * * @return array */ - public function via($notifiable) + /*public function via($notifiable) { return $this->channels; + }*/ + + /** + * @return DiscordMessage|null + */ + public function toDiscordChannel($notifiable): ?DiscordMessage + { + return null; } } diff --git a/app/Contracts/Repository.php b/app/Contracts/Repository.php index 191f6f40..92c82735 100644 --- a/app/Contracts/Repository.php +++ b/app/Contracts/Repository.php @@ -2,11 +2,14 @@ namespace App\Contracts; +use Exception; use Illuminate\Validation\Validator; +use function is_array; use Prettus\Repository\Eloquent\BaseRepository; +use Prettus\Repository\Exceptions\RepositoryException; /** - * @mixin \Prettus\Repository\Eloquent\BaseRepository + * @mixin BaseRepository */ abstract class Repository extends BaseRepository { @@ -20,8 +23,8 @@ abstract class Repository extends BaseRepository { try { return $this->find($id, $columns); - } catch (\Exception $e) { - return; + } catch (Exception $e) { + return null; } } @@ -32,11 +35,7 @@ abstract class Repository extends BaseRepository */ public function validate($values) { - $validator = Validator::make( - $values, - $this->model()->rules - ); - + $validator = Validator::make($values, $this->model()->rules); if ($validator->fails()) { return $validator->messages(); } @@ -50,6 +49,8 @@ abstract class Repository extends BaseRepository * @param int $count * @param string $sort_by created_at (default) or updated_at * + * @throws RepositoryException + * * @return mixed */ public function recent($count = null, $sort_by = 'created_at') @@ -71,7 +72,7 @@ abstract class Repository extends BaseRepository return $this->scopeQuery(function ($query) use ($where, $sort_by, $order_by) { $q = $query->where($where); // See if there are multi-column sorts - if (\is_array($sort_by)) { + if (is_array($sort_by)) { foreach ($sort_by as $key => $sort) { $q = $q->orderBy($key, $sort); } @@ -98,7 +99,7 @@ abstract class Repository extends BaseRepository return $this->scopeQuery(function ($query) use ($col, $values, $sort_by, $order_by) { $q = $query->whereNotIn($col, $values); // See if there are multi-column sorts - if (\is_array($sort_by)) { + if (is_array($sort_by)) { foreach ($sort_by as $key => $sort) { $q = $q->orderBy($key, $sort); } @@ -118,7 +119,7 @@ abstract class Repository extends BaseRepository * @param array $columns * @param string $method * - * @throws \Prettus\Repository\Exceptions\RepositoryException + * @throws RepositoryException * * @return mixed */ diff --git a/app/Database/migrations/2021_06_01_141152_discord_fields.php b/app/Database/migrations/2021_06_01_141152_discord_fields.php new file mode 100644 index 00000000..f0716f0a --- /dev/null +++ b/app/Database/migrations/2021_06_01_141152_discord_fields.php @@ -0,0 +1,32 @@ +where(['key' => 'notifications.discord_api_key']) + ->delete(); + + DB::table('settings') + ->where(['key' => 'notifications.discord_public_channel_id']) + ->delete(); + + DB::table('settings') + ->where(['key' => 'notifications.discord_public_channel_id']) + ->delete(); + + // Add a field to the user to enter their own Discord ID + Schema::table('users', function (Blueprint $table) { + $table->string('discord_id') + ->default('') + ->after('rank_id'); + }); + } +} diff --git a/app/Database/seeds/settings.yml b/app/Database/seeds/settings.yml index b2478394..49e952ee 100644 --- a/app/Database/seeds/settings.yml +++ b/app/Database/seeds/settings.yml @@ -368,20 +368,20 @@ options: '' type: boolean description: 'Count transfer hours in calculations, like ranks and the total hours' -- key: notifications.discord_api_key - name: Discord API token +- key: notifications.discord_public_webhook_url + name: Discord Public Webhook URL 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' + description: The Discord Webhook URL for public notifications +- key: notifications.discord_private_webhook_url + name: Discord Private Webhook URL + group: notifications value: '' options: '' - type: 'text' - description: 'Discord public channel ID for broadcasat notifications' + type: text + description: The Discord Webhook URL for private notifications - key: 'cron.random_id' name: 'Cron Randomized ID' group: 'cron' diff --git a/app/Events/PirepStateChange.php b/app/Events/PirepStateChange.php new file mode 100644 index 00000000..a718bd02 --- /dev/null +++ b/app/Events/PirepStateChange.php @@ -0,0 +1,16 @@ +pirep = $pirep; + } +} diff --git a/app/Events/PirepStatusChange.php b/app/Events/PirepStatusChange.php new file mode 100644 index 00000000..8fa54c33 --- /dev/null +++ b/app/Events/PirepStatusChange.php @@ -0,0 +1,19 @@ +pirep = $pirep; + } +} diff --git a/app/Http/Controllers/Api/PirepController.php b/app/Http/Controllers/Api/PirepController.php index 43fe52bd..0b401ec6 100644 --- a/app/Http/Controllers/Api/PirepController.php +++ b/app/Http/Controllers/Api/PirepController.php @@ -23,10 +23,10 @@ use App\Models\Enums\PirepFieldSource; use App\Models\Enums\PirepSource; use App\Models\Pirep; use App\Models\PirepComment; -use App\Repositories\AcarsRepository; +use App\Models\PirepFare; +use App\Models\PirepFieldValue; use App\Repositories\JournalRepository; use App\Repositories\PirepRepository; -use App\Services\FareService; use App\Services\Finance\PirepFinanceService; use App\Services\PirepService; use App\Services\UserService; @@ -37,8 +37,6 @@ use Illuminate\Support\Facades\Log; class PirepController extends Controller { - private $acarsRepo; - private $fareSvc; private $financeSvc; private $journalRepo; private $pirepRepo; @@ -46,8 +44,6 @@ class PirepController extends Controller private $userSvc; /** - * @param AcarsRepository $acarsRepo - * @param FareService $fareSvc * @param PirepFinanceService $financeSvc * @param JournalRepository $journalRepo * @param PirepRepository $pirepRepo @@ -55,16 +51,12 @@ class PirepController extends Controller * @param UserService $userSvc */ public function __construct( - AcarsRepository $acarsRepo, - FareService $fareSvc, PirepFinanceService $financeSvc, JournalRepository $journalRepo, PirepRepository $pirepRepo, PirepService $pirepSvc, UserService $userSvc ) { - $this->acarsRepo = $acarsRepo; - $this->fareSvc = $fareSvc; $this->financeSvc = $financeSvc; $this->journalRepo = $journalRepo; $this->pirepRepo = $pirepRepo; @@ -101,7 +93,7 @@ class PirepController extends Controller /** * Check if a PIREP is cancelled * - * @param $pirep + * @param Pirep $pirep * * @throws \App\Exceptions\PirepCancelled */ @@ -113,50 +105,52 @@ class PirepController extends Controller } /** - * @param $pirep * @param Request $request + * + * @return PirepFieldValue[] */ - protected function updateFields($pirep, Request $request) + protected function getFields(Request $request): ?array { if (!$request->filled('fields')) { - return; + return []; } $pirep_fields = []; foreach ($request->input('fields') as $field_name => $field_value) { - $pirep_fields[] = [ + $pirep_fields[] = new PirepFieldValue([ 'name' => $field_name, 'value' => $field_value, 'source' => PirepFieldSource::ACARS, - ]; + ]); } - $this->pirepSvc->updateCustomFields($pirep->id, $pirep_fields); + return $pirep_fields; } /** * Save the fares * - * @param $pirep * @param Request $request * * @throws \Exception + * + * @return PirepFare[] */ - protected function updateFares($pirep, Request $request) + protected function getFares(Request $request): ?array { if (!$request->filled('fares')) { - return; + return []; } $fares = []; foreach ($request->post('fares') as $fare) { - $fares[] = [ + $fares[] = new PirepFare([ 'fare_id' => $fare['id'], 'count' => $fare['count'], - ]; + ]); } - $this->fareSvc->saveForPirep($pirep, $fares); + return $fares; } /** @@ -210,14 +204,13 @@ class PirepController extends Controller $attrs = $this->parsePirep($request); $attrs['source'] = PirepSource::ACARS; - $pirep = $this->pirepSvc->prefile($user, $attrs); + $fields = $this->getFields($request); + $fares = $this->getFares($request); + $pirep = $this->pirepSvc->prefile($user, $attrs, $fields, $fares); Log::info('PIREP PREFILED'); Log::info($pirep->id); - $this->updateFields($pirep, $request); - $this->updateFares($pirep, $request); - return $this->get($pirep->id); } @@ -258,9 +251,9 @@ class PirepController extends Controller } } - $pirep = $this->pirepRepo->update($attrs, $pirep_id); - $this->updateFields($pirep, $request); - $this->updateFares($pirep, $request); + $fields = $this->getFields($request); + $fares = $this->getFares($request); + $pirep = $this->pirepSvc->update($pirep_id, $attrs, $fields, $fares); event(new PirepUpdated($pirep)); @@ -303,9 +296,9 @@ class PirepController extends Controller } try { - $pirep = $this->pirepSvc->file($pirep, $attrs); - $this->updateFields($pirep, $request); - $this->updateFares($pirep, $request); + $fields = $this->getFields($request); + $fares = $this->getFares($request); + $pirep = $this->pirepSvc->file($pirep, $attrs, $fields, $fares); } catch (\Exception $e) { Log::error($e); @@ -411,7 +404,8 @@ class PirepController extends Controller $pirep = Pirep::find($pirep_id); $this->checkCancelled($pirep); - $this->updateFields($pirep, $request); + $fields = $this->getFields($request); + $this->pirepSvc->updateCustomFields($pirep_id, $fields); return new PirepFieldCollection($pirep->fields); } diff --git a/app/Listeners/PirepEventsHandler.php b/app/Listeners/PirepEventsHandler.php index 84d0d63a..3f999360 100644 --- a/app/Listeners/PirepEventsHandler.php +++ b/app/Listeners/PirepEventsHandler.php @@ -6,10 +6,7 @@ use App\Contracts\Listener; use App\Events\PirepPrefiled; /** - * Look for and run any of the award classes. Don't modify this. - * See the documentation on creating awards: - * - * @url http://docs.phpvms.net/customizing/awards + * Handler for PIREP events */ class PirepEventsHandler extends Listener { diff --git a/app/Models/Aircraft.php b/app/Models/Aircraft.php index 58c81c1f..87c0b1b9 100644 --- a/app/Models/Aircraft.php +++ b/app/Models/Aircraft.php @@ -12,6 +12,7 @@ use Carbon\Carbon; * @property int id * @property mixed subfleet_id * @property string airport_id The apt where the aircraft is + * @property string ident * @property string name * @property string icao * @property string registration @@ -71,6 +72,14 @@ class Aircraft extends Model 'zfw' => 'nullable|numeric', ]; + /** + * @return string + */ + public function getIdentAttribute(): string + { + return $this->registration.' ('.$this->icao.')'; + } + /** * See if this aircraft is active * diff --git a/app/Models/Enums/PirepStatus.php b/app/Models/Enums/PirepStatus.php index 0bef4bd7..26b4b521 100644 --- a/app/Models/Enums/PirepStatus.php +++ b/app/Models/Enums/PirepStatus.php @@ -33,7 +33,7 @@ class PirepStatus extends Enum public const LANDED = 'LAN'; public const ARRIVED = 'ONB'; // On block public const CANCELLED = 'DX'; - public const EMERG_DECENT = 'EMG'; + public const EMERG_DESCENT = 'EMG'; protected static $labels = [ self::INITIATED => 'pireps.status.initialized', @@ -58,6 +58,6 @@ class PirepStatus extends Enum self::LANDED => 'pireps.status.landed', self::ARRIVED => 'pireps.status.arrived', self::CANCELLED => 'pireps.status.cancelled', - self::EMERG_DECENT => 'pireps.status.emerg_decent', + self::EMERG_DESCENT => 'pireps.status.emerg_decent', ]; } diff --git a/app/Models/News.php b/app/Models/News.php index 1ccdb4e5..91083981 100644 --- a/app/Models/News.php +++ b/app/Models/News.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Contracts\Model; +use Illuminate\Notifications\Notifiable; /** * @property int id @@ -13,6 +14,8 @@ use App\Contracts\Model; */ class News extends Model { + use Notifiable; + public $table = 'news'; protected $fillable = [ diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index 29ee705a..9e83652a 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -3,6 +3,8 @@ namespace App\Models; use App\Contracts\Model; +use App\Events\PirepStateChange; +use App\Events\PirepStatusChange; use App\Models\Enums\AcarsType; use App\Models\Enums\PirepFieldSource; use App\Models\Enums\PirepState; @@ -10,7 +12,9 @@ use App\Models\Traits\HashIdTrait; use App\Support\Units\Distance; use App\Support\Units\Fuel; use Carbon\Carbon; +use Illuminate\Notifications\Notifiable; use Illuminate\Support\Collection; +use Kleemans\AttributeEvents; /** * @property string id @@ -44,8 +48,8 @@ use Illuminate\Support\Collection; * @property Flight|null flight * @property Collection fields * @property string status - * @property PirepState state - * @property int source + * @property int state + * @property int source * @property string source_name * @property Carbon submitted_at * @property Carbon created_at @@ -57,7 +61,9 @@ use Illuminate\Support\Collection; */ class Pirep extends Model { + use AttributeEvents; use HashIdTrait; + use Notifiable; public $table = 'pireps'; @@ -137,6 +143,14 @@ class Pirep extends Model 'route' => 'nullable', ]; + /** + * Auto-dispatch events for lifecycle state changes + */ + protected $dispatchesEvents = [ + 'status:*' => PirepStatusChange::class, + 'state:*' => PirepStateChange::class, + ]; + /* * If a PIREP is in these states, then it can't be changed. */ diff --git a/app/Models/PirepFieldValue.php b/app/Models/PirepFieldValue.php index cf885b22..0f67e4ec 100644 --- a/app/Models/PirepFieldValue.php +++ b/app/Models/PirepFieldValue.php @@ -11,6 +11,7 @@ use App\Models\Enums\PirepFieldSource; * @property string slug * @property string value * @property string source + * @property Pirep pirep * * @method static updateOrCreate(array $array, array $array1) */ diff --git a/app/Models/User.php b/app/Models/User.php index d6e321df..473e6225 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -32,6 +32,7 @@ use Laratrust\Traits\LaratrustUserTrait; * @property Rank rank * @property Journal journal * @property int rank_id + * @property string discord_id * @property int state * @property bool opt_in * @property Pirep[] pireps @@ -66,6 +67,7 @@ class User extends Authenticatable 'pilot_id', 'airline_id', 'rank_id', + 'discord_id', 'api_key', 'country', 'home_airport_id', @@ -89,6 +91,7 @@ class User extends Authenticatable */ protected $hidden = [ 'api_key', + 'discord_id', 'password', 'remember_token', ]; diff --git a/app/Notifications/Channels/Discord/Discord.php b/app/Notifications/Channels/Discord/Discord.php new file mode 100644 index 00000000..4aad7835 --- /dev/null +++ b/app/Notifications/Channels/Discord/Discord.php @@ -0,0 +1,36 @@ +httpClient = $httpClient; + } + + public function send($notifiable, Notification $notification) + { + $message = $notification->toDiscordChannel($notifiable); + if ($message === null || empty($message->webhook_url)) { + Log::debug('Discord notifications not configured, skipping'); + return; + } + + try { + $data = $message->toArray(); + $this->httpClient->post($message->webhook_url, $data); + } catch (RequestException $e) { + $response = Psr7\Message::toString($e->getResponse()); + Log::error('Error sending Discord notification: '.$e->getMessage().', '.$response); + } + } +} diff --git a/app/Notifications/Channels/Discord/DiscordMessage.php b/app/Notifications/Channels/Discord/DiscordMessage.php new file mode 100644 index 00000000..9dbebfd9 --- /dev/null +++ b/app/Notifications/Channels/Discord/DiscordMessage.php @@ -0,0 +1,140 @@ +webhook_url = $url; + return $this; + } + + /** + * Title of the notification + */ + public function title(string $title): self + { + $this->title = $title; + return $this; + } + + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * @param array|string $descriptionLines + */ + public function description($descriptionLines): self + { + if (!is_array($descriptionLines)) { + $descriptionLines = [$descriptionLines]; + } + + $this->description = implode(PHP_EOL, $descriptionLines); + return $this; + } + + /** + * Set the author information: + * [ + * 'name' => '', + * 'url' => '', + * 'icon_url' => '', + */ + public function author(array $author): self + { + $this->author = $author; + return $this; + } + + /** + * Set the fields + */ + public function fields(array $fields): self + { + $this->fields = []; + foreach ($fields as $name => $value) { + $this->fields[] = [ + 'name' => '**'.$name.'**', // bold + 'value' => $value, + 'inline' => true, + ]; + } + + return $this; + } + + public function footer(string $footer): self + { + $this->footer = $footer; + return $this; + } + + public function success(): self + { + $this->color = static::COLOR_SUCCESS; + return $this; + } + + public function warning(): self + { + $this->color = static::COLOR_WARNING; + return $this; + } + + public function error(): self + { + $this->color = static::COLOR_ERROR; + return $this; + } + + public function toArray(): array + { + return [ + 'embeds' => [ + [ + 'title' => $this->title, + 'url' => $this->url, + 'type' => 'rich', + 'description' => $this->description, + // 'color' => hexdec($this->color), + 'author' => $this->author, + 'fields' => $this->fields, + 'footer' => [ + 'text' => $this->footer ?? '', + ], + 'timestamp' => Carbon::now('UTC'), + ], + ], + ]; + } +} diff --git a/app/Notifications/Channels/MailChannel.php b/app/Notifications/Channels/MailChannel.php index ea93fef5..206ff5b2 100644 --- a/app/Notifications/Channels/MailChannel.php +++ b/app/Notifications/Channels/MailChannel.php @@ -17,7 +17,7 @@ trait MailChannel * @param string $template Markdown template to use * @param array $args Arguments to pass to the template */ - public function setMailable($subject, $template, $args) + public function setMailable(string $subject, string $template, array $args) { $this->mailSubject = $subject; $this->mailTemplate = $template; diff --git a/app/Notifications/Messages/AdminUserRegistered.php b/app/Notifications/Messages/AdminUserRegistered.php index d30f6179..b1466eb2 100644 --- a/app/Notifications/Messages/AdminUserRegistered.php +++ b/app/Notifications/Messages/AdminUserRegistered.php @@ -4,17 +4,15 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\User; +use App\Notifications\Channels\Discord\Discord; +use App\Notifications\Channels\Discord\DiscordMessage; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class AdminUserRegistered extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $user; /** @@ -34,6 +32,32 @@ class AdminUserRegistered extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail', Discord::class]; + } + + /** + * Send a Discord notification + * + * @param User $pirep + * @param mixed $user + * + * @return DiscordMessage|null + */ + public function toDiscordChannel($user): ?DiscordMessage + { + if (empty(setting('notifications.discord_private_webhook_url'))) { + return null; + } + + $dm = new DiscordMessage(); + return $dm->webhook(setting('notifications.discord_private_webhook_url')) + ->success() + ->title('New User Registered: '.$user->ident) + ->fields([]); + } + public function toArray($notifiable) { return [ diff --git a/app/Notifications/Messages/NewsAdded.php b/app/Notifications/Messages/NewsAdded.php index e154096d..4a7a1ef1 100644 --- a/app/Notifications/Messages/NewsAdded.php +++ b/app/Notifications/Messages/NewsAdded.php @@ -4,16 +4,15 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\News; +use App\Notifications\Channels\Discord\Discord; +use App\Notifications\Channels\Discord\DiscordMessage; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class NewsAdded extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; public $requires_opt_in = true; private $news; @@ -30,6 +29,34 @@ class NewsAdded extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail', Discord::class]; + } + + /** + * @param News $news + * + * @return DiscordMessage|null + */ + public function toDiscordChannel($news): ?DiscordMessage + { + if (empty(setting('notifications.discord_public_webhook_url'))) { + return null; + } + + $dm = new DiscordMessage(); + return $dm->webhook(setting('notifications.discord_public_webhook_url')) + ->success() + ->title('News: '.$news->subject) + ->author([ + 'name' => $news->user->ident.' - '.$news->user->name_private, + 'url' => '', + 'icon_url' => $news->user->resolveAvatarUrl(), + ]) + ->description($news->body); + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/Messages/PirepAccepted.php b/app/Notifications/Messages/PirepAccepted.php index fc2e571c..7b23cfd8 100644 --- a/app/Notifications/Messages/PirepAccepted.php +++ b/app/Notifications/Messages/PirepAccepted.php @@ -5,19 +5,15 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\Pirep; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; /** - * Send the PIREP accepted message to a particular user + * Send the PIREP accepted message to a particular user, can also be sent to Discord */ class PirepAccepted extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $pirep; /** @@ -38,6 +34,11 @@ class PirepAccepted extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail']; + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/Messages/PirepPrefiled.php b/app/Notifications/Messages/PirepPrefiled.php new file mode 100644 index 00000000..44faff0d --- /dev/null +++ b/app/Notifications/Messages/PirepPrefiled.php @@ -0,0 +1,102 @@ +pirep = $pirep; + } + + public function via($notifiable) + { + return [Discord::class]; + } + + /** + * Send a Discord notification + * + * @param Pirep $pirep + * + * @return DiscordMessage|null + */ + public function toDiscordChannel($pirep): ?DiscordMessage + { + if (empty(setting('notifications.discord_public_webhook_url'))) { + return null; + } + + $title = 'Flight '.$pirep->airline->code.$pirep->ident.' Prefiled'; + $fields = [ + 'Flight' => $pirep->airline->code.$pirep->ident, + 'Departure Airport' => $pirep->dpt_airport_id, + 'Arrival Airport' => $pirep->arr_airport_id, + 'Equipment' => $pirep->aircraft->ident, + 'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time), + ]; + + if ($pirep->planned_distance) { + try { + $planned_distance = new Distance( + $pirep->planned_distance, + config('phpvms.internal_units.distance') + ); + + $pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit; + $fields['Distance (Planned)'] = $pd; + } catch (NonNumericValue $e) { + } catch (NonStringUnitName $e) { + } + } + + $dm = new DiscordMessage(); + return $dm->webhook(setting('notifications.discord_public_webhook_url')) + ->success() + ->title($title) + ->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '') + ->url(route('frontend.pireps.show', [$pirep->id])) + ->author([ + 'name' => $pirep->user->ident.' - '.$pirep->user->name_private, + 'url' => route('frontend.pireps.show', [$pirep->id]), + 'icon_url' => $pirep->user->resolveAvatarUrl(), + ]) + ->fields($fields); + } + + /** + * 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, + ]; + } +} diff --git a/app/Notifications/Messages/PirepRejected.php b/app/Notifications/Messages/PirepRejected.php index 080cd6e6..69526e39 100644 --- a/app/Notifications/Messages/PirepRejected.php +++ b/app/Notifications/Messages/PirepRejected.php @@ -5,22 +5,18 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\Pirep; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class PirepRejected extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $pirep; /** * Create a new notification instance. * - * @param \App\Models\Pirep $pirep + * @param Pirep $pirep */ public function __construct(Pirep $pirep) { @@ -35,6 +31,11 @@ class PirepRejected extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail']; + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/Messages/PirepStatusChanged.php b/app/Notifications/Messages/PirepStatusChanged.php new file mode 100644 index 00000000..dbbcf8eb --- /dev/null +++ b/app/Notifications/Messages/PirepStatusChanged.php @@ -0,0 +1,141 @@ + 'is initialized', + PirepStatus::SCHEDULED => 'is scheduled', + PirepStatus::BOARDING => 'is boarding', + PirepStatus::RDY_START => 'is ready for start', + PirepStatus::PUSHBACK_TOW => 'is pushing back', + PirepStatus::DEPARTED => 'has departed', + PirepStatus::RDY_DEICE => 'is ready for de-icing', + PirepStatus::STRT_DEICE => 'is de-icing', + PirepStatus::GRND_RTRN => 'on ground return', + PirepStatus::TAXI => 'is taxiing', + PirepStatus::TAKEOFF => 'has taken off', + PirepStatus::INIT_CLIM => 'in initial climb', + PirepStatus::AIRBORNE => 'is enroute', + PirepStatus::ENROUTE => 'is enroute', + PirepStatus::DIVERTED => 'has diverted', + PirepStatus::APPROACH => 'on approach', + PirepStatus::APPROACH_ICAO => 'on approach', + PirepStatus::ON_FINAL => 'on final approach', + PirepStatus::LANDING => 'is landing', + PirepStatus::LANDED => 'has landed', + PirepStatus::ARRIVED => 'has arrived', + PirepStatus::CANCELLED => 'has cancelled', + PirepStatus::EMERG_DESCENT => 'in emergency descent', + ]; + + /** + * Create a new notification instance. + * + * @param Pirep $pirep + */ + public function __construct(Pirep $pirep) + { + parent::__construct(); + $this->pirep = $pirep; + } + + public function via($notifiable) + { + return [Discord::class]; + } + + /** + * Send a Discord notification + * + * @param Pirep $pirep + * + * @return DiscordMessage|null + */ + public function toDiscordChannel($pirep): ?DiscordMessage + { + if (empty(setting('notifications.discord_public_webhook_url'))) { + return null; + } + + $title = 'Flight '.$pirep->airline->code.$pirep->ident.' '.self::$verbs[$pirep->status]; + + $fields = [ + 'Flight' => $pirep->airline->code.$pirep->ident, + 'Departure Airport' => $pirep->dpt_airport_id, + 'Arrival Airport' => $pirep->arr_airport_id, + 'Equipment' => $pirep->aircraft->ident, + 'Flight Time' => Time::minutesToTimeString($pirep->flight_time), + ]; + + // Show the distance, but include the planned distance if it's been set + if ($pirep->distance) { + $unit = config('phpvms.internal_units.distance'); + + try { + $planned_distance = new Distance($pirep->distance, $unit); + $pd = $planned_distance[$planned_distance->unit]; + $fields['Distance'] = $pd; + + // Add the planned distance in + if ($pirep->planned_distance) { + try { + $planned_distance = new Distance($pirep->planned_distance, $unit); + $pd = $planned_distance[$planned_distance->unit]; + $fields['Distance'] .= '/'.$pd; + } catch (NonNumericValue | NonStringUnitName $e) { + } + } + + $fields['Distance'] .= ' '.$planned_distance->unit; + } catch (NonNumericValue | NonStringUnitName $e) { + } + } + + $dm = new DiscordMessage(); + return $dm->webhook(setting('notifications.discord_public_webhook_url')) + ->success() + ->title($title) + ->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '') + ->url(route('frontend.pireps.show', [$pirep->id])) + ->author([ + 'name' => $pirep->user->ident.' - '.$pirep->user->name_private, + 'url' => route('frontend.pireps.show', [$pirep->id]), + 'icon_url' => $pirep->user->resolveAvatarUrl(), + ]) + ->fields($fields); + } + + /** + * 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, + ]; + } +} diff --git a/app/Notifications/Messages/PirepSubmitted.php b/app/Notifications/Messages/PirepSubmitted.php index ad91eb6c..ef4a91b5 100644 --- a/app/Notifications/Messages/PirepSubmitted.php +++ b/app/Notifications/Messages/PirepSubmitted.php @@ -4,17 +4,19 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\Pirep; +use App\Notifications\Channels\Discord\Discord; +use App\Notifications\Channels\Discord\DiscordMessage; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; +use App\Support\Units\Distance; +use App\Support\Units\Time; use Illuminate\Contracts\Queue\ShouldQueue; +use PhpUnitsOfMeasure\Exception\NonNumericValue; +use PhpUnitsOfMeasure\Exception\NonStringUnitName; class PirepSubmitted extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $pirep; /** @@ -35,6 +37,60 @@ class PirepSubmitted extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail', Discord::class]; + } + + /** + * Send a Discord notification + * + * @param Pirep $pirep + * + * @return DiscordMessage|null + */ + public function toDiscordChannel($pirep): ?DiscordMessage + { + if (empty(setting('notifications.discord_public_webhook_url'))) { + return null; + } + + $title = 'Flight '.$pirep->airline->code.$pirep->ident.' Filed'; + $fields = [ + 'Flight' => $pirep->airline->code.$pirep->ident, + 'Departure Airport' => $pirep->dpt_airport_id, + 'Arrival Airport' => $pirep->arr_airport_id, + 'Equipment' => $pirep->aircraft->ident, + 'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time), + ]; + + if ($pirep->planned_distance) { + try { + $planned_distance = new Distance( + $pirep->planned_distance, + config('phpvms.internal_units.distance') + ); + + $pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit; + $fields['Distance (Planned)'] = $pd; + } catch (NonNumericValue | NonStringUnitName $e) { + } + } + + $dm = new DiscordMessage(); + return $dm->webhook(setting('notifications.discord_public_webhook_url')) + ->success() + ->title($title) + ->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '') + ->url(route('frontend.pireps.show', [$pirep->id])) + ->author([ + 'name' => $pirep->user->ident.' - '.$pirep->user->name_private, + 'url' => route('frontend.pireps.show', [$pirep->id]), + 'icon_url' => $pirep->user->resolveAvatarUrl(), + ]) + ->fields($fields); + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/Messages/UserPending.php b/app/Notifications/Messages/UserPending.php index 8f5839b1..7b700d67 100644 --- a/app/Notifications/Messages/UserPending.php +++ b/app/Notifications/Messages/UserPending.php @@ -5,20 +5,16 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\User; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class UserPending extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $user; /** - * @param \App\Models\User $user + * @param User $user */ public function __construct(User $user) { @@ -33,6 +29,11 @@ class UserPending extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail']; + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/Messages/UserRegistered.php b/app/Notifications/Messages/UserRegistered.php index 4faacf93..2519a18d 100644 --- a/app/Notifications/Messages/UserRegistered.php +++ b/app/Notifications/Messages/UserRegistered.php @@ -5,22 +5,18 @@ namespace App\Notifications\Messages; use App\Contracts\Notification; use App\Models\User; use App\Notifications\Channels\MailChannel; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class UserRegistered extends Notification implements ShouldQueue { - use Queueable; use MailChannel; - public $channels = ['mail']; - private $user; /** * Create a new notification instance. * - * @param \App\Models\User $user + * @param User $user */ public function __construct(User $user) { @@ -35,6 +31,11 @@ class UserRegistered extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail']; + } + public function toArray($notifiable) { return [ diff --git a/app/Notifications/Messages/UserRejected.php b/app/Notifications/Messages/UserRejected.php index e65b571d..967acf88 100644 --- a/app/Notifications/Messages/UserRejected.php +++ b/app/Notifications/Messages/UserRejected.php @@ -13,8 +13,6 @@ class UserRejected extends Notification implements ShouldQueue use Queueable; use MailChannel; - public $channels = ['mail']; - private $user; /** @@ -33,6 +31,11 @@ class UserRejected extends Notification implements ShouldQueue ); } + public function via($notifiable) + { + return ['mail']; + } + /** * Get the array representation of the notification. * diff --git a/app/Notifications/EventHandler.php b/app/Notifications/NotificationEventsHandler.php similarity index 75% rename from app/Notifications/EventHandler.php rename to app/Notifications/NotificationEventsHandler.php index e11efcb3..b1433b8f 100644 --- a/app/Notifications/EventHandler.php +++ b/app/Notifications/NotificationEventsHandler.php @@ -6,13 +6,13 @@ use App\Contracts\Listener; use App\Events\NewsAdded; use App\Events\PirepAccepted; use App\Events\PirepFiled; +use App\Events\PirepPrefiled; use App\Events\PirepRejected; +use App\Events\PirepStatusChange; use App\Events\UserRegistered; use App\Events\UserStateChanged; use App\Models\Enums\UserState; use App\Models\User; -use App\Notifications\Messages\PirepSubmitted; -use App\Notifications\Messages\UserPending; use App\Notifications\Messages\UserRejected; use App\Notifications\Notifiables\Broadcast; use Exception; @@ -23,17 +23,19 @@ use Illuminate\Support\Facades\Notification; /** * Listen for different events and map them to different notifications */ -class EventHandler extends Listener +class NotificationEventsHandler extends Listener { private static $broadcastNotifyable; public static $callbacks = [ - NewsAdded::class => 'onNewsAdded', - PirepAccepted::class => 'onPirepAccepted', - PirepFiled::class => 'onPirepFile', - PirepRejected::class => 'onPirepRejected', - UserRegistered::class => 'onUserRegister', - UserStateChanged::class => 'onUserStateChange', + NewsAdded::class => 'onNewsAdded', + PirepPrefiled::class => 'onPirepPrefile', + PirepStatusChange::class => 'onPirepStatusChange', + PirepAccepted::class => 'onPirepAccepted', + PirepFiled::class => 'onPirepFile', + PirepRejected::class => 'onPirepRejected', + UserRegistered::class => 'onUserRegister', + UserStateChanged::class => 'onUserStateChange', ]; public function __construct() @@ -56,7 +58,8 @@ class EventHandler extends Listener } try { - Notification::send([$user], $notification); + $this->notifyUser($user, $notification); + // Notification::send([$user], $notification); } catch (Exception $e) { Log::emergency('Error emailing admin ('.$user->email.'). Error='.$e->getMessage()); } @@ -117,19 +120,24 @@ class EventHandler extends Listener .$event->user->ident.' is ' .UserState::label($event->user->state).', sending active email'); - /* - * Send all of the admins a notification that a new user registered - */ - $this->notifyAdmins(new Messages\AdminUserRegistered($event->user)); - /* * Send the user a confirmation email */ if ($event->user->state === UserState::ACTIVE) { $this->notifyUser($event->user, new Messages\UserRegistered($event->user)); } elseif ($event->user->state === UserState::PENDING) { - $this->notifyUser($event->user, new UserPending($event->user)); + $this->notifyUser($event->user, new Messages\UserPending($event->user)); } + + /* + * Send all of the admins a notification that a new user registered + */ + $this->notifyAdmins(new Messages\AdminUserRegistered($event->user)); + + /** + * Discord and other notifications + */ + Notification::send([$event->user], new Messages\AdminUserRegistered($event->user)); } /** @@ -152,15 +160,34 @@ class EventHandler extends Listener } } + /** + * Prefile notification + */ + public function onPirepPrefile(PirepPrefiled $event): void + { + Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled'); + Notification::send([$event->pirep], new Messages\PirepPrefiled($event->pirep)); + } + + /** + * Status Change notification + */ + public function onPirepStatusChange(PirepStatusChange $event): void + { + Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled'); + Notification::send([$event->pirep], new Messages\PirepStatusChanged($event->pirep)); + } + /** * Notify the admins that a new PIREP has been filed * - * @param \App\Events\PirepFiled $event + * @param PirepFiled $event */ public function onPirepFile(PirepFiled $event): void { - Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed '); - $this->notifyAdmins(new PirepSubmitted($event->pirep)); + Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed'); + $this->notifyAdmins(new Messages\PirepSubmitted($event->pirep)); + Notification::send([$event->pirep], new Messages\PirepSubmitted($event->pirep)); } /** @@ -194,5 +221,6 @@ class EventHandler extends Listener { Log::info('NotificationEvents::onNewsAdded'); $this->notifyAllUsers(new Messages\NewsAdded($event->news)); + Notification::send([$event->news], new Messages\NewsAdded($event->news)); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 61465b7a..c3da1f89 100755 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -11,7 +11,7 @@ use App\Listeners\ExpenseListener; use App\Listeners\FinanceEventHandler; use App\Listeners\PirepEventsHandler; use App\Listeners\UserStateListener; -use App\Notifications\EventHandler; +use App\Notifications\NotificationEventsHandler; use Codedge\Updater\Events\UpdateAvailable; use Codedge\Updater\Events\UpdateSucceeded; use Illuminate\Auth\Events\Registered; @@ -49,7 +49,7 @@ class EventServiceProvider extends ServiceProvider protected $subscribe = [ BidEventHandler::class, FinanceEventHandler::class, - EventHandler::class, + NotificationEventsHandler::class, AwardHandler::class, PirepEventsHandler::class, ]; diff --git a/app/Services/FareService.php b/app/Services/FareService.php index 6f55e0ff..bce67ea1 100644 --- a/app/Services/FareService.php +++ b/app/Services/FareService.php @@ -292,14 +292,14 @@ class FareService extends Service /** * Save the list of fares * - * @param Pirep $pirep - * @param array $fares ['fare_id', 'count'] + * @param Pirep $pirep + * @param PirepFare[] $fares * * @throws \Exception */ public function saveForPirep(Pirep $pirep, array $fares) { - if (!$fares) { + if (!$fares || empty($fares)) { return; } @@ -308,13 +308,9 @@ class FareService extends Service // Add them in foreach ($fares as $fare) { - $fare['pirep_id'] = $pirep->id; - // other fields: ['fare_id', 'count'] - + $fare->pirep_id = $pirep->id; Log::info('Saving fare pirep='.$pirep->id.', fare='.$fare['count']); - - $field = new PirepFare($fare); - $field->save(); + $fare->save(); } } } diff --git a/app/Services/PirepService.php b/app/Services/PirepService.php index 1696645c..57baea7d 100644 --- a/app/Services/PirepService.php +++ b/app/Services/PirepService.php @@ -36,7 +36,6 @@ use App\Repositories\AircraftRepository; use App\Repositories\AirportRepository; use App\Repositories\PirepRepository; use Carbon\Carbon; -use function count; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\Log; @@ -45,16 +44,18 @@ class PirepService extends Service private $aircraftRepo; private $airportRepo; private $airportSvc; + private $fareSvc; private $geoSvc; private $pirepRepo; private $simBriefSvc; private $userSvc; /** - * @param AircraftRepository $aircraftRepo - * @param GeoService $geoSvc * @param AirportRepository $airportRepo * @param AirportService $airportSvc + * @param AircraftRepository $aircraftRepo + * @param FareService $fareSvc + * @param GeoService $geoSvc * @param PirepRepository $pirepRepo * @param SimBriefService $simBriefSvc * @param UserService $userSvc @@ -63,6 +64,7 @@ class PirepService extends Service AirportRepository $airportRepo, AirportService $airportSvc, AircraftRepository $aircraftRepo, + FareService $fareSvc, GeoService $geoSvc, PirepRepository $pirepRepo, SimBriefService $simBriefSvc, @@ -71,6 +73,7 @@ class PirepService extends Service $this->airportRepo = $airportRepo; $this->airportSvc = $airportSvc; $this->aircraftRepo = $aircraftRepo; + $this->fareSvc = $fareSvc; $this->geoSvc = $geoSvc; $this->pirepRepo = $pirepRepo; $this->simBriefSvc = $simBriefSvc; @@ -80,15 +83,17 @@ class PirepService extends Service /** * Create a prefiled PIREP * - * @param \App\Models\User $user - * @param array $attrs + * @param User $user + * @param array $attrs + * @param PirepFieldValue[] $fields + * @param PirepFare[] $fares * * @throws AirportNotFound If one of the departure or arrival airports isn't found locally * @throws \Exception * * @return \App\Models\Pirep */ - public function prefile(User $user, array $attrs): Pirep + public function prefile(User $user, array $attrs, array $fields = [], array $fares = []): Pirep { $attrs['user_id'] = $user->id; $attrs['state'] = PirepState::IN_PROGRESS; @@ -176,6 +181,7 @@ class PirepService extends Service } } + $pirep->status = PirepStatus::INITIATED; $pirep->save(); $pirep->refresh(); @@ -189,6 +195,9 @@ class PirepService extends Service } } + $this->updateCustomFields($pirep->id, $fields); + $this->fareSvc->saveForPirep($pirep, $fares); + event(new PirepPrefiled($pirep)); return $pirep; @@ -202,10 +211,10 @@ class PirepService extends Service * * @return Pirep */ - public function create(Pirep $pirep, array $field_values = []): Pirep + public function create(Pirep $pirep, array $fields = []): Pirep { - if (empty($field_values)) { - $field_values = []; + if (empty($fields)) { + $fields = []; } // Check the block times. If a block on (arrival) time isn't @@ -241,9 +250,23 @@ class PirepService extends Service $pirep->save(); $pirep->refresh(); - if (count($field_values) > 0) { - $this->updateCustomFields($pirep->id, $field_values); - } + $this->updateCustomFields($pirep->id, $fields); + + return $pirep; + } + + /** + * @param PirepFieldValue[] $fields + * @param PirepFare[] $fares + * + * @throws \Prettus\Validator\Exceptions\ValidatorException + * @throws \Exception + */ + public function update(string $pirep_id, array $attrs, array $fields = [], array $fares = []): Pirep + { + $pirep = $this->pirepRepo->update($attrs, $pirep_id); + $this->updateCustomFields($pirep_id, $fields); + $this->fareSvc->saveForPirep($pirep, $fares); return $pirep; } @@ -251,18 +274,19 @@ class PirepService extends Service /** * Finalize a PIREP (meaning it's been filed) * - * @param Pirep $pirep - * @param array $attrs - * @param array PirepFieldValue[] $field_values + * @param Pirep $pirep + * @param array $attrs + * @param PirepFieldValue[] $fields + * @param PirepFare[] $fares * * @throws \Exception * * @return Pirep */ - public function file(Pirep $pirep, array $attrs = [], array $field_values = []): Pirep + public function file(Pirep $pirep, array $attrs = [], array $fields = [], array $fares = []): Pirep { - if (empty($field_values)) { - $field_values = []; + if (empty($fields)) { + $fields = []; } // Check if the PIREP has already been submitted @@ -319,9 +343,8 @@ class PirepService extends Service $pirep->save(); $pirep->refresh(); - if (count($field_values) > 0) { - $this->updateCustomFields($pirep->id, $field_values); - } + $this->updateCustomFields($pirep->id, $fields); + $this->fareSvc->saveForPirep($pirep, $fares); return $pirep; } @@ -518,30 +541,41 @@ class PirepService extends Service */ public function delete(Pirep $pirep): void { + $user_id = $pirep->user_id; + $w = ['pirep_id' => $pirep->id]; PirepComment::where($w)->forceDelete(); PirepFare::where($w)->forceDelete(); PirepFieldValue::where($w)->forceDelete(); SimBrief::where($w)->forceDelete(); $pirep->forceDelete(); + + // Update the user's last PIREP + $last_pirep = Pirep::where(['user_id' => $user_id, 'state' => PirepState::ACCEPTED]) + ->latest('submitted_at') + ->first(); + + $user = User::find($user_id); + $user->last_pirep_id = !empty($last_pirep) ? $last_pirep->id : null; + $user->save(); } /** * Update any custom PIREP fields * - * @param $pirep_id - * @param array $field_values + * @param string $pirep_id + * @param PirepFieldValue[] $field_values */ - public function updateCustomFields($pirep_id, array $field_values) + public function updateCustomFields(string $pirep_id, array $field_values): void { + if (!$field_values || empty($field_values)) { + return; + } + foreach ($field_values as $fv) { PirepFieldValue::updateOrCreate( - ['pirep_id' => $pirep_id, - 'name' => $fv['name'], - ], - ['value' => $fv['value'], - 'source' => $fv['source'], - ] + ['pirep_id' => $pirep_id, 'name' => $fv->name], + ['value' => $fv->value, 'source' => $fv->source] ); } } @@ -554,7 +588,7 @@ class PirepService extends Service * * @return Pirep */ - public function changeState(Pirep $pirep, int $new_state) + public function changeState(Pirep $pirep, int $new_state): Pirep { Log::info('PIREP '.$pirep->id.' state change from '.$pirep->state.' to '.$new_state); diff --git a/app/Support/HttpClient.php b/app/Support/HttpClient.php index 6bb2f9d0..ddfb0793 100644 --- a/app/Support/HttpClient.php +++ b/app/Support/HttpClient.php @@ -3,6 +3,7 @@ namespace App\Support; use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\RequestOptions; /** * Helper for HTTP stuff @@ -11,9 +12,8 @@ class HttpClient { private $httpClient; - public function __construct( - GuzzleClient $httpClient - ) { + public function __construct(GuzzleClient $httpClient) + { $this->httpClient = $httpClient; } @@ -45,6 +45,29 @@ class HttpClient return $body; } + /** + * @param $uri + * @param $body + * @param array $opts + * + * @return mixed + */ + public function post($uri, $body, array $opts = []) + { + $opts = array_merge([ + 'connect_timeout' => 2, + RequestOptions::JSON => $body, + ], $opts); + + $response = $this->httpClient->post($uri, $opts); + $content_type = $response->getHeaderLine('content-type'); + if (strpos($content_type, 'application/json') !== false) { + $body = \GuzzleHttp\json_decode($body, true); + } + + return $body; + } + /** * Download a file to a given path * diff --git a/composer.json b/composer.json index d2147087..cc5ef595 100755 --- a/composer.json +++ b/composer.json @@ -67,7 +67,8 @@ "laravel/legacy-factories": "^1.1", "fakerphp/faker": "^v1.14", "wildbit/swiftmailer-postmark": "^3.3", - "queueworker/sansdaemon": "^1.2" + "queueworker/sansdaemon": "^1.2", + "jpkleemans/attribute-events": "^1.1" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.5", diff --git a/composer.lock b/composer.lock index b694faa3..605a09c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8ab12b349948ff95fed99c6e898f1a89", + "content-hash": "64f4e06461590e9a54fdc9bdc219c010", "packages": [ { "name": "akaunting/money", @@ -989,16 +989,16 @@ }, { "name": "composer/package-versions-deprecated", - "version": "1.11.99.1", + "version": "1.11.99.2", "source": { "type": "git", "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6" + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6", - "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c6522afe5540d5fc46675043d3ed5a45a740b27c", + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c", "shasum": "" }, "require": { @@ -1042,7 +1042,7 @@ "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", "support": { "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.1" + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.2" }, "funding": [ { @@ -1058,7 +1058,7 @@ "type": "tidelift" } ], - "time": "2020-11-11T10:22:58+00:00" + "time": "2021-05-24T07:46:03+00:00" }, { "name": "composer/semver", @@ -1285,16 +1285,16 @@ }, { "name": "doctrine/cache", - "version": "1.11.2", + "version": "1.11.3", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "9c53086695937c50c47936ed86d96150ffbcf60d" + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/9c53086695937c50c47936ed86d96150ffbcf60d", - "reference": "9c53086695937c50c47936ed86d96150ffbcf60d", + "url": "https://api.github.com/repos/doctrine/cache/zipball/3bb5588cec00a0268829cc4a518490df6741af9d", + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d", "shasum": "" }, "require": { @@ -1364,7 +1364,7 @@ ], "support": { "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/1.11.2" + "source": "https://github.com/doctrine/cache/tree/1.11.3" }, "funding": [ { @@ -1380,7 +1380,7 @@ "type": "tidelift" } ], - "time": "2021-05-20T14:57:29+00:00" + "time": "2021-05-25T09:01:55+00:00" }, { "name": "doctrine/dbal", @@ -1994,16 +1994,16 @@ }, { "name": "facade/flare-client-php", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "69742118c037f34ee1ef86dc605be4a105d9e984" + "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/69742118c037f34ee1ef86dc605be4a105d9e984", - "reference": "69742118c037f34ee1ef86dc605be4a105d9e984", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/47b639dc02bcfdfc4ebb83de703856fa01e35f5f", + "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f", "shasum": "" }, "require": { @@ -2047,7 +2047,7 @@ ], "support": { "issues": "https://github.com/facade/flare-client-php/issues", - "source": "https://github.com/facade/flare-client-php/tree/1.8.0" + "source": "https://github.com/facade/flare-client-php/tree/1.8.1" }, "funding": [ { @@ -2055,7 +2055,7 @@ "type": "github" } ], - "time": "2021-04-30T11:11:50+00:00" + "time": "2021-05-31T19:23:29+00:00" }, { "name": "facade/ignition", @@ -3115,6 +3115,58 @@ }, "time": "2021-01-17T21:51:00+00:00" }, + { + "name": "jpkleemans/attribute-events", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/jpkleemans/attribute-events.git", + "reference": "adfbd627d4012a6a907849c9ea510a1651e961bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jpkleemans/attribute-events/zipball/adfbd627d4012a6a907849c9ea510a1651e961bc", + "reference": "adfbd627d4012a6a907849c9ea510a1651e961bc", + "shasum": "" + }, + "require-dev": { + "illuminate/database": "^8.0", + "illuminate/events": "^8.0", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Kleemans\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan-Paul Kleemans", + "email": "jpkleemans@gmail.com" + } + ], + "description": "🔥 Fire events on attribute changes of your Eloquent model", + "homepage": "https://attribute.events/", + "keywords": [ + "attributes", + "ddd", + "domain events", + "eloquent", + "events", + "laravel", + "model events" + ], + "support": { + "issues": "https://github.com/jpkleemans/attribute-events/issues", + "source": "https://github.com/jpkleemans/attribute-events/tree/1.1.0" + }, + "time": "2020-11-21T14:52:35+00:00" + }, { "name": "justinrainbow/json-schema", "version": "5.2.10", @@ -3295,16 +3347,16 @@ }, { "name": "laravel/framework", - "version": "v8.42.1", + "version": "v8.44.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "41ec4897a70eb8729cf0ff34a8354413c54e42a6" + "reference": "7b3b27dc8911ab02a69731af2ba97b5130b2ddb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/41ec4897a70eb8729cf0ff34a8354413c54e42a6", - "reference": "41ec4897a70eb8729cf0ff34a8354413c54e42a6", + "url": "https://api.github.com/repos/laravel/framework/zipball/7b3b27dc8911ab02a69731af2ba97b5130b2ddb8", + "reference": "7b3b27dc8911ab02a69731af2ba97b5130b2ddb8", "shasum": "" }, "require": { @@ -3459,7 +3511,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-05-19T13:03:18+00:00" + "time": "2021-05-27T16:46:06+00:00" }, { "name": "laravel/helpers", @@ -3575,22 +3627,23 @@ }, { "name": "laravel/ui", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "e2478cd0342a92ec1c8c77422553bda8ee004fd0" + "reference": "07d725813350c695c779382cbd6dac0ab8665537" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/e2478cd0342a92ec1c8c77422553bda8ee004fd0", - "reference": "e2478cd0342a92ec1c8c77422553bda8ee004fd0", + "url": "https://api.github.com/repos/laravel/ui/zipball/07d725813350c695c779382cbd6dac0ab8665537", + "reference": "07d725813350c695c779382cbd6dac0ab8665537", "shasum": "" }, "require": { - "illuminate/console": "^8.0", - "illuminate/filesystem": "^8.0", - "illuminate/support": "^8.0", + "illuminate/console": "^8.42", + "illuminate/filesystem": "^8.42", + "illuminate/support": "^8.42", + "illuminate/validation": "^8.42", "php": "^7.3|^8.0" }, "type": "library", @@ -3626,9 +3679,9 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v3.2.1" + "source": "https://github.com/laravel/ui/tree/v3.3.0" }, - "time": "2021-04-27T18:17:41+00:00" + "time": "2021-05-25T16:45:33+00:00" }, { "name": "laravelcollective/html", @@ -4503,16 +4556,16 @@ }, { "name": "nesbot/carbon", - "version": "2.48.0", + "version": "2.48.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "d3c447f21072766cddec3522f9468a5849a76147" + "reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3c447f21072766cddec3522f9468a5849a76147", - "reference": "d3c447f21072766cddec3522f9468a5849a76147", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8d1f50f1436fb4b05e7127360483dd9c6e73da16", + "reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16", "shasum": "" }, "require": { @@ -4592,7 +4645,7 @@ "type": "tidelift" } ], - "time": "2021-05-07T10:08:30+00:00" + "time": "2021-05-26T22:08:38+00:00" }, { "name": "nikic/php-parser", @@ -4855,16 +4908,16 @@ }, { "name": "php-http/discovery", - "version": "1.13.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7" + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/788f72d64c43dc361e7fcc7464c3d947c64984a7", - "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7", + "url": "https://api.github.com/repos/php-http/discovery/zipball/778f722e29250c1fac0bbdef2c122fa5d038c9eb", + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb", "shasum": "" }, "require": { @@ -4881,8 +4934,7 @@ "puli/composer-plugin": "1.0.0-beta10" }, "suggest": { - "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", - "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories" }, "type": "library", "extra": { @@ -4918,9 +4970,9 @@ ], "support": { "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.13.0" + "source": "https://github.com/php-http/discovery/tree/1.14.0" }, - "time": "2020-11-27T14:49:42+00:00" + "time": "2021-06-01T14:30:21+00:00" }, { "name": "php-units-of-measure/php-units-of-measure", @@ -6390,20 +6442,21 @@ }, { "name": "symfony/console", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", + "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2", + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.15", @@ -6467,7 +6520,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.8" + "source": "https://github.com/symfony/console/tree/v5.3.0" }, "funding": [ { @@ -6483,20 +6536,20 @@ "type": "tidelift" } ], - "time": "2021-05-11T15:45:21+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/css-selector", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "5d5f97809015102116208b976eb2edb44b689560" + "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/5d5f97809015102116208b976eb2edb44b689560", - "reference": "5d5f97809015102116208b976eb2edb44b689560", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", + "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", "shasum": "" }, "require": { @@ -6532,7 +6585,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.2.9" + "source": "https://github.com/symfony/css-selector/tree/v5.3.0" }, "funding": [ { @@ -6548,7 +6601,7 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-26T17:40:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6619,16 +6672,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "1416bc16317a8188aabde251afef7618bf4687ac" + "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/1416bc16317a8188aabde251afef7618bf4687ac", - "reference": "1416bc16317a8188aabde251afef7618bf4687ac", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0e6768b8c0dcef26df087df2bbbaa143867a59b2", + "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2", "shasum": "" }, "require": { @@ -6668,7 +6721,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.2.8" + "source": "https://github.com/symfony/error-handler/tree/v5.3.0" }, "funding": [ { @@ -6684,20 +6737,20 @@ "type": "tidelift" } ], - "time": "2021-05-07T13:42:21+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.2.4", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d08d6ec121a425897951900ab692b612a61d6240" + "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d08d6ec121a425897951900ab692b612a61d6240", - "reference": "d08d6ec121a425897951900ab692b612a61d6240", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67a5f354afa8e2f231081b3fa11a5912f933c3ce", + "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce", "shasum": "" }, "require": { @@ -6753,7 +6806,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.0" }, "funding": [ { @@ -6769,7 +6822,7 @@ "type": "tidelift" } ], - "time": "2021-02-18T17:12:37+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6852,16 +6905,16 @@ }, { "name": "symfony/filesystem", - "version": "v5.2.7", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0" + "reference": "348116319d7fb7d1faa781d26a48922428013eb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/056e92acc21d977c37e6ea8e97374b2a6c8551b0", - "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2", + "reference": "348116319d7fb7d1faa781d26a48922428013eb2", "shasum": "" }, "require": { @@ -6894,7 +6947,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.7" + "source": "https://github.com/symfony/filesystem/tree/v5.3.0" }, "funding": [ { @@ -6910,20 +6963,20 @@ "type": "tidelift" } ], - "time": "2021-04-01T10:42:13+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/finder", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d" + "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", - "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", + "url": "https://api.github.com/repos/symfony/finder/zipball/0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", + "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", "shasum": "" }, "require": { @@ -6955,7 +7008,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.9" + "source": "https://github.com/symfony/finder/tree/v5.3.0" }, "funding": [ { @@ -6971,7 +7024,7 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-26T12:52:38+00:00" }, { "name": "symfony/http-client-contracts", @@ -7053,16 +7106,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.2.8", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e8fbbab7c4a71592985019477532629cb2e142dc" + "reference": "8827b90cf8806e467124ad476acd15216c2fceb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e8fbbab7c4a71592985019477532629cb2e142dc", - "reference": "e8fbbab7c4a71592985019477532629cb2e142dc", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8827b90cf8806e467124ad476acd15216c2fceb6", + "reference": "8827b90cf8806e467124ad476acd15216c2fceb6", "shasum": "" }, "require": { @@ -7106,7 +7159,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.2.8" + "source": "https://github.com/symfony/http-foundation/tree/v5.3.1" }, "funding": [ { @@ -7122,20 +7175,20 @@ "type": "tidelift" } ], - "time": "2021-05-07T13:41:16+00:00" + "time": "2021-06-02T09:32:00+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.2.9", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "eb540ef6870dbf33c92e372cfb869ebf9649e6cb" + "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/eb540ef6870dbf33c92e372cfb869ebf9649e6cb", - "reference": "eb540ef6870dbf33c92e372cfb869ebf9649e6cb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74eb022e3bac36b3d3a897951a98759f2b32b864", + "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864", "shasum": "" }, "require": { @@ -7145,7 +7198,7 @@ "symfony/error-handler": "^4.4|^5.0", "symfony/event-dispatcher": "^5.0", "symfony/http-client-contracts": "^1.1|^2", - "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-foundation": "^5.3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.15" @@ -7155,7 +7208,7 @@ "symfony/cache": "<5.0", "symfony/config": "<5.0", "symfony/console": "<4.4", - "symfony/dependency-injection": "<5.1.8", + "symfony/dependency-injection": "<5.3", "symfony/doctrine-bridge": "<5.0", "symfony/form": "<5.0", "symfony/http-client": "<5.0", @@ -7175,7 +7228,7 @@ "symfony/config": "^5.0", "symfony/console": "^4.4|^5.0", "symfony/css-selector": "^4.4|^5.0", - "symfony/dependency-injection": "^5.1.8", + "symfony/dependency-injection": "^5.3", "symfony/dom-crawler": "^4.4|^5.0", "symfony/expression-language": "^4.4|^5.0", "symfony/finder": "^4.4|^5.0", @@ -7218,7 +7271,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.2.9" + "source": "https://github.com/symfony/http-kernel/tree/v5.3.1" }, "funding": [ { @@ -7234,20 +7287,20 @@ "type": "tidelift" } ], - "time": "2021-05-19T12:23:45+00:00" + "time": "2021-06-02T10:07:12+00:00" }, { "name": "symfony/mime", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "64258e870f8cc75c3dae986201ea2df58c210b52" + "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/64258e870f8cc75c3dae986201ea2df58c210b52", - "reference": "64258e870f8cc75c3dae986201ea2df58c210b52", + "url": "https://api.github.com/repos/symfony/mime/zipball/ed710d297b181f6a7194d8172c9c2423d58e4852", + "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852", "shasum": "" }, "require": { @@ -7301,7 +7354,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.2.9" + "source": "https://github.com/symfony/mime/tree/v5.3.0" }, "funding": [ { @@ -7317,20 +7370,20 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", "shasum": "" }, "require": { @@ -7342,7 +7395,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7380,7 +7433,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" }, "funding": [ { @@ -7396,7 +7449,7 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-iconv", @@ -7480,16 +7533,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170" + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab", + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab", "shasum": "" }, "require": { @@ -7501,7 +7554,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7541,7 +7594,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0" }, "funding": [ { @@ -7557,20 +7610,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:17:38+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "af1842919c7e7364aaaa2798b29839e3ba168588" + "reference": "4a80a521d6176870b6445cfb469c130f9cae1dda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/af1842919c7e7364aaaa2798b29839e3ba168588", - "reference": "af1842919c7e7364aaaa2798b29839e3ba168588", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/4a80a521d6176870b6445cfb469c130f9cae1dda", + "reference": "4a80a521d6176870b6445cfb469c130f9cae1dda", "shasum": "" }, "require": { @@ -7582,7 +7635,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7628,7 +7681,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.23.0" }, "funding": [ { @@ -7644,20 +7697,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-24T10:04:56+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "2d63434d922daf7da8dd863e7907e67ee3031483" + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/2d63434d922daf7da8dd863e7907e67ee3031483", - "reference": "2d63434d922daf7da8dd863e7907e67ee3031483", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65", + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65", "shasum": "" }, "require": { @@ -7671,7 +7724,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7715,7 +7768,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0" }, "funding": [ { @@ -7731,20 +7784,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:27:20+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { @@ -7756,7 +7809,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7799,7 +7852,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" }, "funding": [ { @@ -7815,20 +7868,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1", "shasum": "" }, "require": { @@ -7840,7 +7893,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7879,7 +7932,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" }, "funding": [ { @@ -7895,20 +7948,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:27:20+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", "shasum": "" }, "require": { @@ -7917,7 +7970,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7955,7 +8008,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0" }, "funding": [ { @@ -7971,20 +8024,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-05-27T09:17:38+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", "shasum": "" }, "require": { @@ -7993,7 +8046,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -8034,7 +8087,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" }, "funding": [ { @@ -8050,20 +8103,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-php74", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php74.git", - "reference": "577e147350331efeb816897e004d85e6e765daaf" + "reference": "a5d80cdf049bd3b0af6da91184a2cd37533c0fd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php74/zipball/577e147350331efeb816897e004d85e6e765daaf", - "reference": "577e147350331efeb816897e004d85e6e765daaf", + "url": "https://api.github.com/repos/symfony/polyfill-php74/zipball/a5d80cdf049bd3b0af6da91184a2cd37533c0fd8", + "reference": "a5d80cdf049bd3b0af6da91184a2cd37533c0fd8", "shasum": "" }, "require": { @@ -8072,7 +8125,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -8114,7 +8167,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php74/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php74/tree/v1.23.0" }, "funding": [ { @@ -8130,20 +8183,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", "shasum": "" }, "require": { @@ -8152,7 +8205,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -8197,7 +8250,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" }, "funding": [ { @@ -8213,20 +8266,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/process", - "version": "v5.2.7", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e" + "reference": "53e36cb1c160505cdaf1ef201501669c4c317191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", - "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", + "url": "https://api.github.com/repos/symfony/process/zipball/53e36cb1c160505cdaf1ef201501669c4c317191", + "reference": "53e36cb1c160505cdaf1ef201501669c4c317191", "shasum": "" }, "require": { @@ -8259,7 +8312,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.3.0-BETA1" + "source": "https://github.com/symfony/process/tree/v5.3.0" }, "funding": [ { @@ -8275,20 +8328,20 @@ "type": "tidelift" } ], - "time": "2021-04-08T10:27:02+00:00" + "time": "2021-05-26T12:52:38+00:00" }, { "name": "symfony/property-access", - "version": "v5.2.4", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "3af8ed262bd3217512a13b023981fe68f36ad5f3" + "reference": "8988399a556cffb0fba9bb3603f8d1ba4543eceb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/3af8ed262bd3217512a13b023981fe68f36ad5f3", - "reference": "3af8ed262bd3217512a13b023981fe68f36ad5f3", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8988399a556cffb0fba9bb3603f8d1ba4543eceb", + "reference": "8988399a556cffb0fba9bb3603f8d1ba4543eceb", "shasum": "" }, "require": { @@ -8340,7 +8393,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v5.2.4" + "source": "https://github.com/symfony/property-access/tree/v5.3.0" }, "funding": [ { @@ -8356,20 +8409,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/property-info", - "version": "v5.2.8", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "cc8121baf91039648d5f8feb894dc4a9d4935cc0" + "reference": "6f8bff281f215dbf41929c7ec6f8309cdc0912cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/cc8121baf91039648d5f8feb894dc4a9d4935cc0", - "reference": "cc8121baf91039648d5f8feb894dc4a9d4935cc0", + "url": "https://api.github.com/repos/symfony/property-info/zipball/6f8bff281f215dbf41929c7ec6f8309cdc0912cf", + "reference": "6f8bff281f215dbf41929c7ec6f8309cdc0912cf", "shasum": "" }, "require": { @@ -8430,7 +8483,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v5.2.8" + "source": "https://github.com/symfony/property-info/tree/v5.3.1" }, "funding": [ { @@ -8446,20 +8499,20 @@ "type": "tidelift" } ], - "time": "2021-05-07T14:04:56+00:00" + "time": "2021-05-31T12:40:48+00:00" }, { "name": "symfony/routing", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "4a7b2bf5e1221be1902b6853743a9bb317f6925e" + "reference": "368e81376a8e049c37cb80ae87dbfbf411279199" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/4a7b2bf5e1221be1902b6853743a9bb317f6925e", - "reference": "4a7b2bf5e1221be1902b6853743a9bb317f6925e", + "url": "https://api.github.com/repos/symfony/routing/zipball/368e81376a8e049c37cb80ae87dbfbf411279199", + "reference": "368e81376a8e049c37cb80ae87dbfbf411279199", "shasum": "" }, "require": { @@ -8468,14 +8521,15 @@ "symfony/polyfill-php80": "^1.15" }, "conflict": { - "symfony/config": "<5.0", + "doctrine/annotations": "<1.12", + "symfony/config": "<5.3", "symfony/dependency-injection": "<4.4", "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4", + "doctrine/annotations": "^1.12", "psr/log": "~1.0", - "symfony/config": "^5.0", + "symfony/config": "^5.3", "symfony/dependency-injection": "^4.4|^5.0", "symfony/expression-language": "^4.4|^5.0", "symfony/http-foundation": "^4.4|^5.0", @@ -8519,7 +8573,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.2.9" + "source": "https://github.com/symfony/routing/tree/v5.3.0" }, "funding": [ { @@ -8535,37 +8589,39 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/serializer", - "version": "v5.2.9", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "b072c8faa82c641da6cc32c33f8caa7c7c4567a2" + "reference": "ebb3dc397af77a08d734eea7305e0b2ec8c5e875" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/b072c8faa82c641da6cc32c33f8caa7c7c4567a2", - "reference": "b072c8faa82c641da6cc32c33f8caa7c7c4567a2", + "url": "https://api.github.com/repos/symfony/serializer/zipball/ebb3dc397af77a08d734eea7305e0b2ec8c5e875", + "reference": "ebb3dc397af77a08d734eea7305e0b2ec8c5e875", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-php80": "^1.15" }, "conflict": { + "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/dependency-injection": "<4.4", "symfony/property-access": "<4.4", - "symfony/property-info": "<4.4", + "symfony/property-info": "<5.3", "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4", + "doctrine/annotations": "^1.12", "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", "symfony/cache": "^4.4|^5.0", "symfony/config": "^4.4|^5.0", @@ -8577,9 +8633,10 @@ "symfony/http-kernel": "^4.4|^5.0", "symfony/mime": "^4.4|^5.0", "symfony/property-access": "^4.4.9|^5.0.9", - "symfony/property-info": "^4.4|^5.0", + "symfony/property-info": "^5.3", "symfony/uid": "^5.1", "symfony/validator": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0", "symfony/var-exporter": "^4.4|^5.0", "symfony/yaml": "^4.4|^5.0" }, @@ -8618,7 +8675,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v5.2.9" + "source": "https://github.com/symfony/serializer/tree/v5.3.1" }, "funding": [ { @@ -8634,7 +8691,7 @@ "type": "tidelift" } ], - "time": "2021-05-17T19:35:40+00:00" + "time": "2021-06-02T09:36:17+00:00" }, { "name": "symfony/service-contracts", @@ -8717,16 +8774,16 @@ }, { "name": "symfony/string", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", "shasum": "" }, "require": { @@ -8780,7 +8837,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.8" + "source": "https://github.com/symfony/string/tree/v5.3.0" }, "funding": [ { @@ -8796,24 +8853,25 @@ "type": "tidelift" } ], - "time": "2021-05-10T14:56:10+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/translation", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "61af68dba333e2d376a325a29c2a3f2a605b4876" + "reference": "251de0d921c42ef0a81494d8f37405421deefdf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/61af68dba333e2d376a325a29c2a3f2a605b4876", - "reference": "61af68dba333e2d376a325a29c2a3f2a605b4876", + "url": "https://api.github.com/repos/symfony/translation/zipball/251de0d921c42ef0a81494d8f37405421deefdf6", + "reference": "251de0d921c42ef0a81494d8f37405421deefdf6", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.15", "symfony/translation-contracts": "^2.3" @@ -8836,6 +8894,7 @@ "symfony/finder": "^4.4|^5.0", "symfony/http-kernel": "^5.0", "symfony/intl": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "^1.21", "symfony/service-contracts": "^1.1.2|^2", "symfony/yaml": "^4.4|^5.0" }, @@ -8873,7 +8932,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.2.9" + "source": "https://github.com/symfony/translation/tree/v5.3.0" }, "funding": [ { @@ -8889,7 +8948,7 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-29T22:28:28+00:00" }, { "name": "symfony/translation-contracts", @@ -8971,16 +9030,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba" + "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d693200a73fae179d27f8f1b16b4faf3e8569eba", - "reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1d3953e627fe4b5f6df503f356b6545ada6351f3", + "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3", "shasum": "" }, "require": { @@ -9039,7 +9098,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.2.8" + "source": "https://github.com/symfony/var-dumper/tree/v5.3.0" }, "funding": [ { @@ -9055,20 +9114,20 @@ "type": "tidelift" } ], - "time": "2021-05-07T13:42:21+00:00" + "time": "2021-05-27T12:28:50+00:00" }, { "name": "symfony/yaml", - "version": "v5.2.9", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "d23115e4a3d50520abddccdbec9514baab1084c8" + "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d23115e4a3d50520abddccdbec9514baab1084c8", - "reference": "d23115e4a3d50520abddccdbec9514baab1084c8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", + "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", "shasum": "" }, "require": { @@ -9114,7 +9173,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.2.9" + "source": "https://github.com/symfony/yaml/tree/v5.3.0" }, "funding": [ { @@ -9130,7 +9189,7 @@ "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "theiconic/php-ga-measurement-protocol", @@ -9662,16 +9721,16 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.5.7", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "88fd9cfa144b06b2549e9d487fdaec68265e791e" + "reference": "bc99f4c52aec0636ecb3aae4576ce84c5773bae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/88fd9cfa144b06b2549e9d487fdaec68265e791e", - "reference": "88fd9cfa144b06b2549e9d487fdaec68265e791e", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/bc99f4c52aec0636ecb3aae4576ce84c5773bae2", + "reference": "bc99f4c52aec0636ecb3aae4576ce84c5773bae2", "shasum": "" }, "require": { @@ -9731,7 +9790,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.7" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.0" }, "funding": [ { @@ -9739,7 +9798,7 @@ "type": "github" } ], - "time": "2021-05-13T20:18:35+00:00" + "time": "2021-06-01T08:46:17+00:00" }, { "name": "barryvdh/laravel-ide-helper", @@ -12293,16 +12352,16 @@ }, { "name": "symfony/debug", - "version": "v4.4.22", + "version": "v4.4.25", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "45b2136377cca5f10af858968d6079a482bca473" + "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/45b2136377cca5f10af858968d6079a482bca473", - "reference": "45b2136377cca5f10af858968d6079a482bca473", + "url": "https://api.github.com/repos/symfony/debug/zipball/a8d2d5c94438548bff9f998ca874e202bb29d07f", + "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f", "shasum": "" }, "require": { @@ -12342,7 +12401,7 @@ "description": "Provides tools to ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.22" + "source": "https://github.com/symfony/debug/tree/v4.4.25" }, "funding": [ { @@ -12358,20 +12417,20 @@ "type": "tidelift" } ], - "time": "2021-04-02T07:50:12+00:00" + "time": "2021-05-26T17:39:37+00:00" }, { "name": "symfony/options-resolver", - "version": "v5.2.4", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5", + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5", "shasum": "" }, "require": { @@ -12411,7 +12470,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.2.4" + "source": "https://github.com/symfony/options-resolver/tree/v5.3.0" }, "funding": [ { @@ -12427,7 +12486,7 @@ "type": "tidelift" } ], - "time": "2021-01-27T12:56:27+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/polyfill-php70", @@ -12499,16 +12558,16 @@ }, { "name": "symfony/stopwatch", - "version": "v5.2.7", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "d99310c33e833def36419c284f60e8027d359678" + "reference": "313d02f59d6543311865007e5ff4ace05b35ee65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d99310c33e833def36419c284f60e8027d359678", - "reference": "d99310c33e833def36419c284f60e8027d359678", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/313d02f59d6543311865007e5ff4ace05b35ee65", + "reference": "313d02f59d6543311865007e5ff4ace05b35ee65", "shasum": "" }, "require": { @@ -12541,7 +12600,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.3.0-BETA1" + "source": "https://github.com/symfony/stopwatch/tree/v5.3.0" }, "funding": [ { @@ -12557,7 +12616,7 @@ "type": "tidelift" } ], - "time": "2021-03-29T15:28:41+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "theseer/tokenizer", diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 6529fcaa..1999eb73 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -26,6 +26,7 @@ services: - ./composer-lock.json:/var/www/composer-lock.json - ./env.php:/var/www/env.php - ./resources/docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf + - ./vendor/var/www/vendor depends_on: - mysql - redis diff --git a/modules/Awards/Awards/FlightRouteAwards.php b/modules/Awards/Awards/FlightRouteAwards.php index d8fd87ee..860f6beb 100644 --- a/modules/Awards/Awards/FlightRouteAwards.php +++ b/modules/Awards/Awards/FlightRouteAwards.php @@ -46,7 +46,7 @@ class FlightRouteAwards extends Award */ public function check($dptarr = null): bool { - if ($this->user->last_pirep_id === null) { + if ($this->user->last_pirep_id === null || empty($this->user->last_pirep)) { return false; } diff --git a/modules/Awards/Awards/PilotHoursAwards.php b/modules/Awards/Awards/PilotHoursAwards.php index 61ae0d7f..1399aaba 100644 --- a/modules/Awards/Awards/PilotHoursAwards.php +++ b/modules/Awards/Awards/PilotHoursAwards.php @@ -3,7 +3,7 @@ namespace Modules\Awards\Awards; use App\Contracts\Award; -use Log; +use Illuminate\Support\Facades\Log; /** * All award classes need to extend Award and implement the check() method diff --git a/resources/views/layouts/default/profile/fields.blade.php b/resources/views/layouts/default/profile/fields.blade.php index 83a72fb5..d475f3cc 100644 --- a/resources/views/layouts/default/profile/fields.blade.php +++ b/resources/views/layouts/default/profile/fields.blade.php @@ -2,7 +2,7 @@
| @lang('common.name') | +{{ __('common.name') }} |
{{ Form::text('name', null, ['class' => 'form-control']) }}
@@ -14,7 +14,7 @@
|
| @lang('common.email') | +{{ __('common.email') }} |
{{ Form::text('email', null, ['class' => 'form-control']) }}
@@ -26,7 +26,22 @@
|
| @lang('common.airline') | +Discord ID + + How to find your ID + | +
+
+ {{ Form::text('discord_id', null, ['class' => 'form-control']) }}
+
+ @if ($errors->has('discord_id'))
+ {{ $errors->first('discord_id') }} + @endif + |
+
| {{ __('common.airline') }} |
{{ Form::select('airline_id', $airlines, null , ['class' => 'form-control select2']) }}
@@ -38,7 +53,7 @@
| |
| @lang('airports.home') | +{{ __('airports.home') }} |
{{ Form::select('home_airport_id', $airports, null , ['class' => 'form-control select2']) }}
@@ -50,7 +65,7 @@
|
| @lang('common.country') | +{{ __('common.country') }} |
{{ Form::select('country', $countries, null, ['class' => 'form-control select2' ]) }}
@@ -62,7 +77,7 @@
|
| @lang('common.timezone') | +{{ __('common.timezone') }} |
{{ Form::select('timezone', $timezones, null, ['class' => 'form-control select2' ]) }}
@@ -74,9 +89,9 @@
|
| @lang('profile.changepassword') | +{{ __('profile.changepassword') }} |
- @lang('profile.newpassword'): +{{ __('profile.newpassword') }}:
{{ Form::password('password', ['class' => 'form-control']) }}
@@ -84,7 +99,7 @@
{{ $errors->first('password') }} @endif -@lang('passwords.confirm'): +{{ __('passwords.confirm') }}:
{{ Form::password('password_confirmation', ['class' => 'form-control']) }}
@@ -94,14 +109,14 @@
|
| @lang('profile.avatar') | +{{ __('profile.avatar') }} |
{{ Form::file('avatar', null) }}
- @lang('profile.avatarresize', [ + {{ __('profile.avatarresize', [ 'width' => config('phpvms.avatar.width'), - 'height' => config('phpvms.avatar.height')]) + 'height' => config('phpvms.avatar.height')]) }} @if ($errors->has('avatar')){{ $errors->first('avatar') }} @@ -130,13 +145,13 @@ @endforeach |
| @lang('profile.opt-in') | +{{ __('profile.opt-in') }} |
{{ Form::hidden('opt_in', 0, false) }}
{{ Form::checkbox('opt_in', 1, null) }}
- @lang('profile.opt-in-descrip') + {{ __('profile.opt-in-descrip') }} |
@lang('profile.apikey') (@lang('profile.dontshare')) | @lang('profile.apikey-show') | +
| Discord ID | +{{ $user->discord_id ?? '-' }} | +|
| @lang('common.timezone') | {{ $user->timezone }} | @@ -174,7 +178,7 @@ @if(!$field->private)|
| {{ $field->name }} | -{{ $field->value }} | +{{ $field->value ?? '-'}} |