diff --git a/app/Console/Commands/TestReminders.php b/app/Console/Commands/TestReminders.php new file mode 100644 index 00000000000..f3eddded985 --- /dev/null +++ b/app/Console/Commands/TestReminders.php @@ -0,0 +1,53 @@ +with('userNotificationChannel') + ->get(); + + foreach ($scheduledReminders as $scheduledReminder) { + if ($scheduledReminder->userNotificationChannel->type == UserNotificationChannel::TYPE_EMAIL) { + SendEmailNotification::dispatch($scheduledReminder)->onQueue('low'); + } + + (new RescheduleContactReminder)->execute([ + 'scheduled_contact_reminder_id' => $scheduledReminder->id, + ]); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d8bc1d29f0c..5986a66994c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -3,6 +3,7 @@ namespace App\Console; use Illuminate\Console\Scheduling\Schedule; +use App\Jobs\ProcessScheduledContactReminders; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel @@ -15,7 +16,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - // $schedule->command('inspire')->hourly(); + $schedule->job(new ProcessScheduledContactReminders)->everyMinute(); } /** diff --git a/app/Jobs/Notifications/SendEmailNotification.php b/app/Jobs/Notifications/SendEmailNotification.php new file mode 100644 index 00000000000..cee9d0da97f --- /dev/null +++ b/app/Jobs/Notifications/SendEmailNotification.php @@ -0,0 +1,57 @@ +scheduledReminder = $scheduledReminder; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $emailAddress = $this->scheduledReminder->userNotificationChannel->content; + $user = $this->scheduledReminder->userNotificationChannel->user; + + Mail::to($emailAddress) + ->queue((new SendReminder($this->scheduledReminder, $user)) + ->onQueue('low') + ); + + $this->scheduledReminder->triggered_at = Carbon::now(); + $this->scheduledReminder->save(); + + UserNotificationSent::create([ + 'user_notification_channel_id' => $this->scheduledReminder->userNotificationChannel->id, + 'sent_at' => Carbon::now(), + 'subject_line' => $this->scheduledReminder->reminder->label, + ]); + } +} diff --git a/app/Jobs/ProcessScheduledContactReminders.php b/app/Jobs/ProcessScheduledContactReminders.php new file mode 100644 index 00000000000..b7d97fac6f0 --- /dev/null +++ b/app/Jobs/ProcessScheduledContactReminders.php @@ -0,0 +1,57 @@ +second = 0; + + $scheduledReminders = ScheduledContactReminder::where('scheduled_at', '<=', $currentDate) + ->where('triggered_at', null) + ->with('userNotificationChannel') + ->get(); + + foreach ($scheduledReminders as $scheduledReminder) { + if ($scheduledReminder->userNotificationChannel->type == UserNotificationChannel::TYPE_EMAIL) { + SendEmailNotification::dispatch($scheduledReminder)->onQueue('low'); + } + + (new RescheduleContactReminder)->execute([ + 'scheduled_contact_reminder_id' => $scheduledReminder->id, + ]); + } + } +} diff --git a/app/Mail/SendReminder.php b/app/Mail/SendReminder.php new file mode 100644 index 00000000000..2d9d341a4ce --- /dev/null +++ b/app/Mail/SendReminder.php @@ -0,0 +1,49 @@ +scheduledContactReminder = $contactReminder; + $this->user = $user; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $contact = $this->scheduledContactReminder->reminder->contact; + $contactName = NameHelper::formatContactName($this->user, $contact); + + $reason = $this->scheduledContactReminder->reminder->label; + + return $this->subject(trans('email.notification_reminder_email', ['name' => $contactName])) + ->markdown('emails.notifications.reminder', [ + 'name' => $this->user->name, + 'reason' => $reason, + 'contactName' => $contactName, + ]); + } +} diff --git a/app/Models/ScheduledContactReminder.php b/app/Models/ScheduledContactReminder.php index 6906db6f198..94133a4cf5b 100644 --- a/app/Models/ScheduledContactReminder.php +++ b/app/Models/ScheduledContactReminder.php @@ -19,8 +19,9 @@ class ScheduledContactReminder extends Model */ protected $fillable = [ 'contact_reminder_id', + 'user_notification_channel_id', + 'scheduled_at', 'triggered_at', - 'triggered', ]; /** @@ -29,18 +30,10 @@ class ScheduledContactReminder extends Model * @var array */ protected $dates = [ + 'scheduled_at', 'triggered_at', ]; - /** - * The attributes that should be cast to native types. - * - * @var array - */ - protected $casts = [ - 'triggered' => 'boolean', - ]; - /** * Get the contact reminder associated with the scheduled contact reminder. * @@ -52,12 +45,12 @@ public function reminder() } /** - * Get the user associated with the scheduled contact reminder. + * Get the user notification channel associated with the scheduled contact reminder. * * @return BelongsTo */ - public function user() + public function userNotificationChannel() { - return $this->belongsTo(User::class); + return $this->belongsTo(UserNotificationChannel::class); } } diff --git a/app/Services/Account/ManageUsers/AcceptInvitation.php b/app/Services/Account/ManageUsers/AcceptInvitation.php index 96e22edbe63..5337049c375 100644 --- a/app/Services/Account/ManageUsers/AcceptInvitation.php +++ b/app/Services/Account/ManageUsers/AcceptInvitation.php @@ -7,6 +7,8 @@ use App\Services\BaseService; use App\Interfaces\ServiceInterface; use Illuminate\Support\Facades\Hash; +use App\Models\UserNotificationChannel; +use App\Services\User\NotificationChannels\CreateUserNotificationChannel; class AcceptInvitation extends BaseService implements ServiceInterface { @@ -41,6 +43,7 @@ public function execute(array $data): User $this->validateRules($data); $this->findUserByInvitationCode(); $this->updateUser(); + $this->createNotificationChannel(); return $this->user; } @@ -60,6 +63,24 @@ private function updateUser(): void $this->user->invitation_accepted_at = Carbon::now(); $this->user->email_verified_at = Carbon::now(); $this->user->password = Hash::make($this->data['password']); + $this->user->timezone = 'UTC'; $this->user->save(); } + + private function createNotificationChannel(): void + { + $channel = (new CreateUserNotificationChannel)->execute([ + 'account_id' => $this->user->account_id, + 'author_id' => $this->user->id, + 'label' => trans('app.notification_channel_email'), + 'type' => UserNotificationChannel::TYPE_EMAIL, + 'content' => $this->user->email, + 'verify_email' => false, + 'preferred_time' => '09:00', + ]); + + $channel->verified_at = Carbon::now(); + $channel->active = true; + $channel->save(); + } } diff --git a/app/Services/Contact/ManageReminder/CreateReminder.php b/app/Services/Contact/ManageReminder/CreateReminder.php index dbbbc2b71c2..19f1d961b9a 100644 --- a/app/Services/Contact/ManageReminder/CreateReminder.php +++ b/app/Services/Contact/ManageReminder/CreateReminder.php @@ -72,6 +72,10 @@ public function execute(array $data): ContactReminder $this->contact->last_updated_at = Carbon::now(); $this->contact->save(); + (new ScheduleContactReminder)->execute([ + 'contact_reminder_id' => $this->reminder->id, + ]); + $this->log(); return $this->reminder; diff --git a/app/Services/Contact/ManageReminder/RescheduleContactReminder.php b/app/Services/Contact/ManageReminder/RescheduleContactReminder.php new file mode 100644 index 00000000000..f2428d38779 --- /dev/null +++ b/app/Services/Contact/ManageReminder/RescheduleContactReminder.php @@ -0,0 +1,75 @@ + 'required|integer|exists:scheduled_contact_reminders,id', + ]; + } + + /** + * Schedule another occurence of the scheduled contact reminder, as the + * previous iteration has been sent. + * Before sending this occurence, we need to make the user notification + * channel is still active. + * + * @param array $data + * @return void + */ + public function execute(array $data): void + { + $this->validateRules($data); + $this->data = $data; + + $this->scheduledContactReminder = ScheduledContactReminder::with('reminder') + ->findOrFail($this->data['scheduled_contact_reminder_id']); + + if (! $this->scheduledContactReminder->userNotificationChannel->active) { + return; + } + + if ($this->scheduledContactReminder->reminder->type !== ContactReminder::TYPE_ONE_TIME) { + $this->schedule(); + } + } + + private function schedule(): void + { + if ($this->scheduledContactReminder->reminder->type === ContactReminder::TYPE_RECURRING_DAY) { + $this->upcomingDate = $this->scheduledContactReminder->scheduled_at->addDay(); + } + + if ($this->scheduledContactReminder->reminder->type === ContactReminder::TYPE_RECURRING_MONTH) { + $this->upcomingDate = $this->scheduledContactReminder->scheduled_at->addMonth(); + } + + if ($this->scheduledContactReminder->reminder->type === ContactReminder::TYPE_RECURRING_YEAR) { + $this->upcomingDate = $this->scheduledContactReminder->scheduled_at->addYear(); + } + + ScheduledContactReminder::create([ + 'contact_reminder_id' => $this->scheduledContactReminder->contact_reminder_id, + 'user_notification_channel_id' => $this->scheduledContactReminder->user_notification_channel_id, + 'scheduled_at' => $this->upcomingDate, + ]); + } +} diff --git a/app/Services/Contact/ManageReminder/ScheduleContactReminder.php b/app/Services/Contact/ManageReminder/ScheduleContactReminder.php index 204c1bd8d71..20bfc54fd20 100644 --- a/app/Services/Contact/ManageReminder/ScheduleContactReminder.php +++ b/app/Services/Contact/ManageReminder/ScheduleContactReminder.php @@ -11,7 +11,6 @@ class ScheduleContactReminder extends BaseService implements ServiceInterface { private ContactReminder $contactReminder; - private ScheduledContactReminder $scheduledContactReminder; private array $data; private Carbon $upcomingDate; @@ -29,24 +28,29 @@ public function rules(): array /** * Schedule a contact reminder. + * For each user in the vault, a scheduled reminder is created. * This service SHOULD NOT BE CALLED FROM THE CLIENTS, ever. * It is called by other services. - * For each user in the vault, a scheduled reminder is created. * * @param array $data - * @return ScheduledContactReminder + * @return void */ - public function execute(array $data): ScheduledContactReminder + public function execute(array $data): void { $this->validateRules($data); $this->data = $data; $this->getDate(); $this->schedule(); - - return $this->scheduledContactReminder; } + /** + * A ContactReminder can be either a complete date, or only a day/month. + * If it is only a day/month, we need to add a fake year so we can still + * manipulate the date as a Carbon object. + * + * @return void + */ private function getDate(): void { $this->contactReminder = ContactReminder::findOrFail($this->data['contact_reminder_id']); @@ -63,13 +67,29 @@ private function schedule(): void // is the date in the past? if so, we need to schedule the reminder // for next year if ($this->upcomingDate->isPast()) { - $this->upcomingDate->year = Carbon::now()->addYear()->year; + $this->upcomingDate->year = Carbon::now()->year; + if ($this->upcomingDate->isPast()) { + $this->upcomingDate->year = Carbon::now()->addYear()->year; + } } - $this->scheduledContactReminder = ScheduledContactReminder::create([ - 'contact_id' => $this->contactReminder->id, - 'contact_reminder_id' => $this->contactReminder->id, - 'triggered_at' => $this->upcomingDate, - ]); + $users = $this->contactReminder->contact->vault->users; + + foreach ($users as $user) { + // we'll loop through all the user notification channels of this user + // and schedule the reminder for each of them + $notificationChannels = $user->notificationChannels; + foreach ($notificationChannels as $channel) { + $this->upcomingDate->shiftTimezone($user->timezone); + $this->upcomingDate->hour = $channel->preferred_time->hour; + $this->upcomingDate->minute = $channel->preferred_time->minute; + + $this->scheduledContactReminder = ScheduledContactReminder::create([ + 'contact_reminder_id' => $this->contactReminder->id, + 'user_notification_channel_id' => $channel->id, + 'scheduled_at' => $this->upcomingDate->tz('UTC'), + ]); + } + } } } diff --git a/app/Services/User/NotificationChannels/ScheduleAllContactRemindersForNotificationChannel.php b/app/Services/User/NotificationChannels/ScheduleAllContactRemindersForNotificationChannel.php new file mode 100644 index 00000000000..b79853f1ee1 --- /dev/null +++ b/app/Services/User/NotificationChannels/ScheduleAllContactRemindersForNotificationChannel.php @@ -0,0 +1,110 @@ + 'required|integer|exists:accounts,id', + 'author_id' => 'required|integer|exists:users,id', + 'user_notification_channel_id' => 'required|integer|exists:user_notification_channels,id', + ]; + } + + /** + * Get the permissions that apply to the user calling the service. + * + * @return array + */ + public function permissions(): array + { + return [ + 'author_must_belong_to_account', + ]; + } + + /** + * Schedule all the contact reminders of the given user for a given user + * notification channel. + * This is useful when we create a new user notification channel, or when + * we activate a formerly inactive user notification channel. + * + * @param array $data + * @return UserNotificationChannel + */ + public function execute(array $data): UserNotificationChannel + { + $this->data = $data; + $this->validate(); + $this->schedule(); + + return $this->userNotificationChannel; + } + + private function validate(): void + { + $this->validateRules($this->data); + + $this->userNotificationChannel = UserNotificationChannel::where('user_id', $this->data['author_id']) + ->findOrFail($this->data['user_notification_channel_id']); + } + + private function schedule(): void + { + $vaults = Vault::where('account_id', $this->data['account_id']) + ->pluck('id')->toArray(); + + $contactReminders = DB::table('contact_reminders') + ->join('contacts', 'contacts.id', '=', 'contact_reminders.contact_id') + ->join('vaults', 'vaults.id', '=', 'contacts.vault_id') + ->whereIn('vaults.id', $vaults) + ->select('contact_reminders.id as id', 'contact_reminders.day as day', 'contact_reminders.year as year', 'contact_reminders.month as month') + ->get(); + + foreach ($contactReminders as $contactReminder) { + if (! $contactReminder->year) { + $upcomingDate = Carbon::parse('1900-'.$contactReminder->month.'-'.$contactReminder->day); + } else { + $upcomingDate = Carbon::parse($contactReminder->year.'-'.$contactReminder->month.'-'.$contactReminder->day); + } + + if ($upcomingDate->isPast()) { + $upcomingDate->year = Carbon::now()->year; + + if ($upcomingDate->isPast()) { + $upcomingDate->year = Carbon::now()->addYear()->year; + } + } + + $upcomingDate->shiftTimezone($this->userNotificationChannel->user->timezone); + $upcomingDate->hour = $this->userNotificationChannel->preferred_time->hour; + $upcomingDate->minute = $this->userNotificationChannel->preferred_time->minute; + + ScheduledContactReminder::create([ + 'contact_reminder_id' => $contactReminder->id, + 'user_notification_channel_id' => $this->userNotificationChannel->id, + 'scheduled_at' => $upcomingDate->tz('UTC'), + ]); + } + } +} diff --git a/app/Services/User/NotificationChannels/ToggleUserNotificationChannel.php b/app/Services/User/NotificationChannels/ToggleUserNotificationChannel.php index e4da110a82c..dc1000a23c5 100644 --- a/app/Services/User/NotificationChannels/ToggleUserNotificationChannel.php +++ b/app/Services/User/NotificationChannels/ToggleUserNotificationChannel.php @@ -5,6 +5,7 @@ use App\Models\User; use App\Jobs\CreateAuditLog; use App\Services\BaseService; +use Illuminate\Support\Facades\DB; use App\Interfaces\ServiceInterface; use App\Models\UserNotificationChannel; @@ -50,6 +51,7 @@ public function execute(array $data): UserNotificationChannel $this->data = $data; $this->validate(); $this->toggle(); + $this->updateScheduledReminders(); $this->log(); return $this->userNotificationChannel; @@ -68,6 +70,39 @@ private function toggle(): void $this->userNotificationChannel->save(); } + /** + * If the notification channel is deactivated, we need to delete all the + * upcoming scheduled reminders for that channel. + * If the notification channel is reactivated, we need to reschedule all + * the contact reminders for this channel specifically. + * + * @return void + */ + private function updateScheduledReminders(): void + { + if ($this->userNotificationChannel->active) { + $this->rescheduledReminders(); + } else { + $this->deleteScheduledReminders(); + } + } + + private function deleteScheduledReminders(): void + { + DB::table('scheduled_contact_reminders') + ->where('user_notification_channel_id', $this->userNotificationChannel->id) + ->delete(); + } + + private function rescheduledReminders(): void + { + (new ScheduleAllContactRemindersForNotificationChannel)->execute([ + 'account_id' => $this->data['account_id'], + 'author_id' => $this->data['author_id'], + 'user_notification_channel_id' => $this->userNotificationChannel->id, + ]); + } + private function log(): void { CreateAuditLog::dispatch([ diff --git a/composer.json b/composer.json index 510a0f9c0a8..53a657a2526 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "http-interop/http-factory-guzzle": "^1.2", "inertiajs/inertia-laravel": "^0.5.4", "itsgoingd/clockwork": "^5.1", + "laravel-notification-channels/telegram": "^2.0", "laravel/framework": "^9.0", "laravel/sanctum": "^2.6", "laravel/scout": "^9.4", diff --git a/composer.lock b/composer.lock index 1020309d4e9..2c2a2e99f85 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": "3aaa80dbc1bcc6f98742e0a8c7e7ef73", + "content-hash": "27f4516f8ab2dc8146c82669bbb4a96f", "packages": [ { "name": "asm89/stack-cors", @@ -356,16 +356,16 @@ }, { "name": "doctrine/lexer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c" + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c", - "reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", "shasum": "" }, "require": { @@ -373,7 +373,7 @@ }, "require-dev": { "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "1.3", + "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", "vimeo/psalm": "^4.11" }, @@ -412,7 +412,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.2" + "source": "https://github.com/doctrine/lexer/tree/1.2.3" }, "funding": [ { @@ -428,7 +428,7 @@ "type": "tidelift" } ], - "time": "2022-01-12T08:27:12+00:00" + "time": "2022-02-28T11:07:21+00:00" }, { "name": "dragonmantank/cron-expression", @@ -1289,18 +1289,84 @@ ], "time": "2022-02-13T22:57:42+00:00" }, + { + "name": "laravel-notification-channels/telegram", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/laravel-notification-channels/telegram.git", + "reference": "63f6727c3f9953e11ee9a690c29ce0db456d69a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel-notification-channels/telegram/zipball/63f6727c3f9953e11ee9a690c29ce0db456d69a1", + "reference": "63f6727c3f9953e11ee9a690c29ce0db456d69a1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^7.0", + "illuminate/contracts": "8.45 - 9", + "illuminate/notifications": "8.45 - 9", + "illuminate/support": "8.45 - 9", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.4", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NotificationChannels\\Telegram\\TelegramServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "NotificationChannels\\Telegram\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Irfaq Syed", + "email": "github@lukonet.net", + "homepage": "https://lukonet.com", + "role": "Developer" + } + ], + "description": "Telegram Notifications Channel for Laravel", + "homepage": "https://github.com/laravel-notification-channels/telegram", + "keywords": [ + "laravel", + "notification", + "telegram", + "telegram notification", + "telegram notifications channel" + ], + "support": { + "issues": "https://github.com/laravel-notification-channels/telegram/issues", + "source": "https://github.com/laravel-notification-channels/telegram/tree/2.0.0" + }, + "time": "2022-02-10T19:29:50+00:00" + }, { "name": "laravel/framework", - "version": "v9.2.0", + "version": "v9.4.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "13372872bed31ae75df8709b9de5cde01d50646e" + "reference": "29f0aaade82eadd20ef881b4efb88b0dad4e9a5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/13372872bed31ae75df8709b9de5cde01d50646e", - "reference": "13372872bed31ae75df8709b9de5cde01d50646e", + "url": "https://api.github.com/repos/laravel/framework/zipball/29f0aaade82eadd20ef881b4efb88b0dad4e9a5b", + "reference": "29f0aaade82eadd20ef881b4efb88b0dad4e9a5b", "shasum": "" }, "require": { @@ -1386,7 +1452,7 @@ "mockery/mockery": "^1.4.4", "orchestra/testbench-core": "^7.1", "pda/pheanstalk": "^4.0", - "phpstan/phpstan": "^1.0", + "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^9.5.8", "predis/predis": "^1.1.9", "symfony/cache": "^6.0" @@ -1466,7 +1532,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-02-22T15:30:23+00:00" + "time": "2022-03-08T16:17:00+00:00" }, { "name": "laravel/sanctum", @@ -1733,16 +1799,16 @@ }, { "name": "league/commonmark", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "13d7751377732637814f0cda0e3f6d3243f9f769" + "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/13d7751377732637814f0cda0e3f6d3243f9f769", - "reference": "13d7751377732637814f0cda0e3f6d3243f9f769", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", + "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", "shasum": "" }, "require": { @@ -1833,7 +1899,7 @@ "type": "tidelift" } ], - "time": "2022-02-13T15:00:57+00:00" + "time": "2022-02-26T21:24:45+00:00" }, { "name": "league/config", @@ -1919,16 +1985,16 @@ }, { "name": "league/flysystem", - "version": "3.0.9", + "version": "3.0.12", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "fb0801a60b7f9ea4188f01c25cb48aed26db7fb6" + "reference": "4744d96fb2456d9808be3ad596a2520b902996e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/fb0801a60b7f9ea4188f01c25cb48aed26db7fb6", - "reference": "fb0801a60b7f9ea4188f01c25cb48aed26db7fb6", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4744d96fb2456d9808be3ad596a2520b902996e2", + "reference": "4744d96fb2456d9808be3ad596a2520b902996e2", "shasum": "" }, "require": { @@ -1936,6 +2002,7 @@ "php": "^8.0.2" }, "conflict": { + "aws/aws-sdk-php": "3.209.31 || 3.210.0", "guzzlehttp/guzzle": "<7.0", "guzzlehttp/ringphp": "<1.1.1", "symfony/http-client": "<5.2" @@ -1988,7 +2055,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.0.9" + "source": "https://github.com/thephpleague/flysystem/tree/3.0.12" }, "funding": [ { @@ -2004,7 +2071,7 @@ "type": "tidelift" } ], - "time": "2022-02-22T07:37:40+00:00" + "time": "2022-03-12T19:32:12+00:00" }, { "name": "league/mime-type-detection", @@ -3354,16 +3421,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.1", + "version": "v0.11.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "570292577277f06f590635381a7f761a6cf4f026" + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/570292577277f06f590635381a7f761a6cf4f026", - "reference": "570292577277f06f590635381a7f761a6cf4f026", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/7f7da640d68b9c9fec819caae7c744a213df6514", + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514", "shasum": "" }, "require": { @@ -3374,6 +3441,9 @@ "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, "require-dev": { "bamarni/composer-bin-plugin": "^1.2", "hoa/console": "3.17.05.02" @@ -3423,9 +3493,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.1" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.2" }, - "time": "2022-01-03T13:58:38+00:00" + "time": "2022-02-28T15:28:54+00:00" }, { "name": "ralouphie/getallheaders", @@ -3615,12 +3685,12 @@ } }, "autoload": { - "psr-4": { - "Ramsey\\Uuid\\": "src/" - }, "files": [ "src/functions.php" - ] + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3650,16 +3720,16 @@ }, { "name": "symfony/console", - "version": "v6.0.3", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "22e8efd019c3270c4f79376234a3f8752cd25490" + "reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/22e8efd019c3270c4f79376234a3f8752cd25490", - "reference": "22e8efd019c3270c4f79376234a3f8752cd25490", + "url": "https://api.github.com/repos/symfony/console/zipball/3bebf4108b9e07492a2a4057d207aa5a77d146b1", + "reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1", "shasum": "" }, "require": { @@ -3725,7 +3795,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.3" + "source": "https://github.com/symfony/console/tree/v6.0.5" }, "funding": [ { @@ -3741,7 +3811,7 @@ "type": "tidelift" } ], - "time": "2022-01-26T17:23:29+00:00" + "time": "2022-02-25T10:48:52+00:00" }, { "name": "symfony/css-selector", @@ -4171,16 +4241,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.0.3", + "version": "v6.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ad157299ced81a637fade1efcadd688d6deba5c1" + "reference": "a000fcf2298a1bc79a1dcff22608792506534719" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ad157299ced81a637fade1efcadd688d6deba5c1", - "reference": "ad157299ced81a637fade1efcadd688d6deba5c1", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a000fcf2298a1bc79a1dcff22608792506534719", + "reference": "a000fcf2298a1bc79a1dcff22608792506534719", "shasum": "" }, "require": { @@ -4223,7 +4293,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.0.3" + "source": "https://github.com/symfony/http-foundation/tree/v6.0.6" }, "funding": [ { @@ -4239,20 +4309,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-03-05T21:04:00+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.4", + "version": "v6.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "9dce179ce52b0f4f669c07fd5e465e5d809a5d3b" + "reference": "f9e49ad9fe16895b24cd7a09dc28d3364282e21a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9dce179ce52b0f4f669c07fd5e465e5d809a5d3b", - "reference": "9dce179ce52b0f4f669c07fd5e465e5d809a5d3b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9e49ad9fe16895b24cd7a09dc28d3364282e21a", + "reference": "f9e49ad9fe16895b24cd7a09dc28d3364282e21a", "shasum": "" }, "require": { @@ -4332,7 +4402,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/v6.0.4" + "source": "https://github.com/symfony/http-kernel/tree/v6.0.6" }, "funding": [ { @@ -4348,20 +4418,20 @@ "type": "tidelift" } ], - "time": "2022-01-29T18:12:46+00:00" + "time": "2022-03-05T21:19:20+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.3", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "d958befe7dbee9d2b2157ef6dfa9b103efa94f82" + "reference": "0f4772db6521a1beb44529aa2c0c1e56f671be8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/d958befe7dbee9d2b2157ef6dfa9b103efa94f82", - "reference": "d958befe7dbee9d2b2157ef6dfa9b103efa94f82", + "url": "https://api.github.com/repos/symfony/mailer/zipball/0f4772db6521a1beb44529aa2c0c1e56f671be8f", + "reference": "0f4772db6521a1beb44529aa2c0c1e56f671be8f", "shasum": "" }, "require": { @@ -4406,7 +4476,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.3" + "source": "https://github.com/symfony/mailer/tree/v6.0.5" }, "funding": [ { @@ -4422,7 +4492,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-02-25T10:48:52+00:00" }, { "name": "symfony/mime", @@ -4574,7 +4644,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -4606,12 +4676,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4636,7 +4706,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" }, "funding": [ { @@ -4656,7 +4726,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -4717,7 +4787,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" }, "funding": [ { @@ -4737,7 +4807,7 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -4804,7 +4874,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0" }, "funding": [ { @@ -4824,7 +4894,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -4888,7 +4958,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" }, "funding": [ { @@ -4908,7 +4978,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -4971,7 +5041,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" }, "funding": [ { @@ -4991,7 +5061,7 @@ }, { "name": "symfony/polyfill-php72", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", @@ -5047,7 +5117,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" }, "funding": [ { @@ -5067,16 +5137,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "shasum": "" }, "require": { @@ -5130,7 +5200,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" }, "funding": [ { @@ -5146,11 +5216,11 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:33+00:00" + "time": "2022-03-04T08:16:47+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -5209,7 +5279,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" }, "funding": [ { @@ -5229,16 +5299,16 @@ }, { "name": "symfony/process", - "version": "v6.0.3", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "298ed357274c1868c20a0061df256a1250a6c4af" + "reference": "1ccceccc6497e96f4f646218f04b97ae7d9fa7a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/298ed357274c1868c20a0061df256a1250a6c4af", - "reference": "298ed357274c1868c20a0061df256a1250a6c4af", + "url": "https://api.github.com/repos/symfony/process/zipball/1ccceccc6497e96f4f646218f04b97ae7d9fa7a1", + "reference": "1ccceccc6497e96f4f646218f04b97ae7d9fa7a1", "shasum": "" }, "require": { @@ -5270,7 +5340,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.3" + "source": "https://github.com/symfony/process/tree/v6.0.5" }, "funding": [ { @@ -5286,20 +5356,20 @@ "type": "tidelift" } ], - "time": "2022-01-26T17:23:29+00:00" + "time": "2022-01-30T18:19:12+00:00" }, { "name": "symfony/routing", - "version": "v6.0.3", + "version": "v6.0.5", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "b1debdf7a40e6bc7eee0f363ab9dd667fe04f099" + "reference": "a738b152426ac7fcb94bdab8188264652238bef1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/b1debdf7a40e6bc7eee0f363ab9dd667fe04f099", - "reference": "b1debdf7a40e6bc7eee0f363ab9dd667fe04f099", + "url": "https://api.github.com/repos/symfony/routing/zipball/a738b152426ac7fcb94bdab8188264652238bef1", + "reference": "a738b152426ac7fcb94bdab8188264652238bef1", "shasum": "" }, "require": { @@ -5358,7 +5428,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.3" + "source": "https://github.com/symfony/routing/tree/v6.0.5" }, "funding": [ { @@ -5374,7 +5444,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-01-31T19:46:53+00:00" }, { "name": "symfony/service-contracts", @@ -5490,12 +5560,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, "files": [ "Resources/functions.php" ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, "exclude-from-classmap": [ "/Tests/" ] @@ -5545,16 +5615,16 @@ }, { "name": "symfony/translation", - "version": "v6.0.3", + "version": "v6.0.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "71bb15335798f8c4da110911bcf2d2fead7a430d" + "reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/71bb15335798f8c4da110911bcf2d2fead7a430d", - "reference": "71bb15335798f8c4da110911bcf2d2fead7a430d", + "url": "https://api.github.com/repos/symfony/translation/zipball/f6639cb9b5e0c57fe31e3263b900a77eedb0c908", + "reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908", "shasum": "" }, "require": { @@ -5620,7 +5690,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.3" + "source": "https://github.com/symfony/translation/tree/v6.0.6" }, "funding": [ { @@ -5636,7 +5706,7 @@ "type": "tidelift" } ], - "time": "2022-01-07T00:29:03+00:00" + "time": "2022-03-02T12:58:14+00:00" }, { "name": "symfony/translation-contracts", @@ -5718,16 +5788,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.0.3", + "version": "v6.0.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7b701676fc64f9ef11f9b4870f16b48f66be4834" + "reference": "38358405ae948963c50a3aae3dfea598223ba15e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7b701676fc64f9ef11f9b4870f16b48f66be4834", - "reference": "7b701676fc64f9ef11f9b4870f16b48f66be4834", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/38358405ae948963c50a3aae3dfea598223ba15e", + "reference": "38358405ae948963c50a3aae3dfea598223ba15e", "shasum": "" }, "require": { @@ -5786,7 +5856,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.3" + "source": "https://github.com/symfony/var-dumper/tree/v6.0.6" }, "funding": [ { @@ -5802,20 +5872,20 @@ "type": "tidelift" } ], - "time": "2022-01-17T16:30:44+00:00" + "time": "2022-03-02T12:58:14+00:00" }, { "name": "tightenco/ziggy", - "version": "v1.4.3", + "version": "v1.4.4", "source": { "type": "git", "url": "https://github.com/tighten/ziggy.git", - "reference": "ffeff44dba822cf45cd2239691526d67b76c3323" + "reference": "ad1b6590978efe3ec36ca404e91f8acaa6c742bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/ffeff44dba822cf45cd2239691526d67b76c3323", - "reference": "ffeff44dba822cf45cd2239691526d67b76c3323", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/ad1b6590978efe3ec36ca404e91f8acaa6c742bd", + "reference": "ad1b6590978efe3ec36ca404e91f8acaa6c742bd", "shasum": "" }, "require": { @@ -5866,9 +5936,9 @@ ], "support": { "issues": "https://github.com/tighten/ziggy/issues", - "source": "https://github.com/tighten/ziggy/tree/v1.4.3" + "source": "https://github.com/tighten/ziggy/tree/v1.4.4" }, - "time": "2022-01-28T14:48:33+00:00" + "time": "2022-03-11T18:06:53+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6005,16 +6075,16 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "9bd89e83cecdf8c37b64909454249eaed98b2c89" + "reference": "b56450eed252f6801410d810c8e1727224ae0743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/9bd89e83cecdf8c37b64909454249eaed98b2c89", - "reference": "9bd89e83cecdf8c37b64909454249eaed98b2c89", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", "shasum": "" }, "require": { @@ -6051,7 +6121,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.0" + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" }, "funding": [ { @@ -6075,7 +6145,7 @@ "type": "tidelift" } ], - "time": "2022-01-24T18:59:03+00:00" + "time": "2022-03-08T17:03:00+00:00" }, { "name": "webmozart/assert", @@ -6466,30 +6536,30 @@ }, { "name": "composer/pcre", - "version": "1.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.3", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" + "symfony/phpunit-bridge": "^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -6517,7 +6587,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" + "source": "https://github.com/composer/pcre/tree/3.0.0" }, "funding": [ { @@ -6533,7 +6603,7 @@ "type": "tidelift" } ], - "time": "2022-01-21T20:24:37+00:00" + "time": "2022-02-25T20:21:48+00:00" }, { "name": "composer/semver", @@ -6618,20 +6688,20 @@ }, { "name": "composer/xdebug-handler", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8" + "reference": "ced299686f41dce890debac69273b47ffe98a40c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/12f1b79476638a5615ed00ea6adbb269cec96fd8", - "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", "shasum": "" }, "require": { - "composer/pcre": "^1", + "composer/pcre": "^1 || ^2 || ^3", "php": "^7.2.5 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, @@ -6664,7 +6734,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.1" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" }, "funding": [ { @@ -6680,7 +6750,7 @@ "type": "tidelift" } ], - "time": "2022-01-04T18:29:42+00:00" + "time": "2022-02-25T21:32:43+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -6721,29 +6791,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "doctrine/coding-standard": "^9", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", "autoload": { @@ -6770,7 +6841,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" }, "funding": [ { @@ -6786,7 +6857,7 @@ "type": "tidelift" } ], - "time": "2020-11-10T18:47:58+00:00" + "time": "2022-03-03T08:28:38+00:00" }, { "name": "facade/ignition-contracts", @@ -7190,16 +7261,16 @@ }, { "name": "laravel/sail", - "version": "v1.13.5", + "version": "v1.13.6", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "aeb6eeb55b22c328d2f301145b97288127691d48" + "reference": "6205041336b09b965af1d6af29261584e787bf52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/aeb6eeb55b22c328d2f301145b97288127691d48", - "reference": "aeb6eeb55b22c328d2f301145b97288127691d48", + "url": "https://api.github.com/repos/laravel/sail/zipball/6205041336b09b965af1d6af29261584e787bf52", + "reference": "6205041336b09b965af1d6af29261584e787bf52", "shasum": "" }, "require": { @@ -7246,7 +7317,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2022-02-17T19:59:03+00:00" + "time": "2022-03-07T15:35:47+00:00" }, { "name": "mockery/mockery", @@ -7322,25 +7393,29 @@ }, { "name": "myclabs/deep-copy", - "version": "1.10.2", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { @@ -7365,7 +7440,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" }, "funding": [ { @@ -7373,7 +7448,7 @@ "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { "name": "netresearch/jsonmapper", @@ -7906,16 +7981,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.13", + "version": "9.2.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8" + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/deac8540cb7bd40b2b8cfa679b76202834fd04e8", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", "shasum": "" }, "require": { @@ -7971,7 +8046,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.13" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" }, "funding": [ { @@ -7979,7 +8054,7 @@ "type": "github" } ], - "time": "2022-02-23T17:02:38+00:00" + "time": "2022-03-07T09:28:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -8224,16 +8299,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.16", + "version": "9.5.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc" + "reference": "1b5856028273bfd855e60a887278857d872ec67a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5ff8c545a50226c569310a35f4fa89d79f1ddfdc", - "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b5856028273bfd855e60a887278857d872ec67a", + "reference": "1b5856028273bfd855e60a887278857d872ec67a", "shasum": "" }, "require": { @@ -8311,7 +8386,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.18" }, "funding": [ { @@ -8323,7 +8398,7 @@ "type": "github" } ], - "time": "2022-02-23T17:10:58+00:00" + "time": "2022-03-08T06:52:28+00:00" }, { "name": "sebastian/cli-parser", @@ -9353,16 +9428,16 @@ }, { "name": "spatie/flare-client-php", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "5d48e00716e3bab813cafffe223bc85c5732a410" + "reference": "ceab058852a1278d9f57a7b95f1c348e4956d866" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/5d48e00716e3bab813cafffe223bc85c5732a410", - "reference": "5d48e00716e3bab813cafffe223bc85c5732a410", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/ceab058852a1278d9f57a7b95f1c348e4956d866", + "reference": "ceab058852a1278d9f57a7b95f1c348e4956d866", "shasum": "" }, "require": { @@ -9405,7 +9480,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.0.2" + "source": "https://github.com/spatie/flare-client-php/tree/1.1.0" }, "funding": [ { @@ -9413,20 +9488,20 @@ "type": "github" } ], - "time": "2022-02-16T16:14:24+00:00" + "time": "2022-03-11T13:21:28+00:00" }, { "name": "spatie/ignition", - "version": "1.0.5", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e" + "reference": "ec58c125c15eecaa20180f01ef9667d41a568ba8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/6b7bb804f4834b080f5ac941f6ac6800a485011e", - "reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e", + "url": "https://api.github.com/repos/spatie/ignition/zipball/ec58c125c15eecaa20180f01ef9667d41a568ba8", + "reference": "ec58c125c15eecaa20180f01ef9667d41a568ba8", "shasum": "" }, "require": { @@ -9434,7 +9509,7 @@ "ext-mbstring": "*", "monolog/monolog": "^2.0", "php": "^8.0", - "spatie/flare-client-php": "^1.0", + "spatie/flare-client-php": "^1.1", "symfony/console": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, @@ -9444,7 +9519,6 @@ "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "spatie/ray": "^1.32", "symfony/process": "^5.4|^6.0" }, "type": "library", @@ -9484,20 +9558,20 @@ "type": "github" } ], - "time": "2022-02-17T21:40:47+00:00" + "time": "2022-03-11T13:28:02+00:00" }, { "name": "spatie/laravel-ignition", - "version": "1.0.6", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "d349854331789aba9205fd755e0c1d1934ef1463" + "reference": "d7b223300d511145eea87fdabae1663c7c0088aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/d349854331789aba9205fd755e0c1d1934ef1463", - "reference": "d349854331789aba9205fd755e0c1d1934ef1463", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/d7b223300d511145eea87fdabae1663c7c0088aa", + "reference": "d7b223300d511145eea87fdabae1663c7c0088aa", "shasum": "" }, "require": { @@ -9508,7 +9582,7 @@ "monolog/monolog": "^2.3", "php": "^8.0", "spatie/flare-client-php": "^1.0.1", - "spatie/ignition": "^1.0", + "spatie/ignition": "^1.2.4", "symfony/console": "^5.0|^6.0", "symfony/var-dumper": "^5.0|^6.0" }, @@ -9571,7 +9645,7 @@ "type": "github" } ], - "time": "2022-02-15T11:02:15+00:00" + "time": "2022-03-11T14:19:27+00:00" }, { "name": "theseer/tokenizer", @@ -9625,16 +9699,16 @@ }, { "name": "vimeo/psalm", - "version": "4.21.0", + "version": "4.22.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "d8bec4c7aaee111a532daec32fb09de5687053d1" + "reference": "fc2c6ab4d5fa5d644d8617089f012f3bb84b8703" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/d8bec4c7aaee111a532daec32fb09de5687053d1", - "reference": "d8bec4c7aaee111a532daec32fb09de5687053d1", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/fc2c6ab4d5fa5d644d8617089f012f3bb84b8703", + "reference": "fc2c6ab4d5fa5d644d8617089f012f3bb84b8703", "shasum": "" }, "require": { @@ -9725,9 +9799,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.21.0" + "source": "https://github.com/vimeo/psalm/tree/4.22.0" }, - "time": "2022-02-18T04:34:15+00:00" + "time": "2022-02-24T20:34:05+00:00" }, { "name": "webmozart/path-util", diff --git a/config/services.php b/config/services.php index 2a1d616c774..7c6ec98245e 100644 --- a/config/services.php +++ b/config/services.php @@ -30,4 +30,8 @@ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), ], + 'telegram-bot-api' => [ + 'token' => env('TELEGRAM_BOT_TOKEN', 'YOUR BOT TOKEN HERE'), + ], + ]; diff --git a/database/factories/ScheduledContactReminderFactory.php b/database/factories/ScheduledContactReminderFactory.php index 699c88f8aa1..3cf25f833e4 100644 --- a/database/factories/ScheduledContactReminderFactory.php +++ b/database/factories/ScheduledContactReminderFactory.php @@ -2,8 +2,8 @@ namespace Database\Factories; -use App\Models\User; use App\Models\ContactReminder; +use App\Models\UserNotificationChannel; use App\Models\ScheduledContactReminder; use Illuminate\Database\Eloquent\Factories\Factory; @@ -24,10 +24,10 @@ class ScheduledContactReminderFactory extends Factory public function definition() { return [ - 'user_id' => User::factory(), + 'user_notification_channel_id' => UserNotificationChannel::factory(), 'contact_reminder_id' => ContactReminder::factory(), + 'scheduled_at' => $this->faker->dateTimeThisCentury(), 'triggered_at' => $this->faker->dateTimeThisCentury(), - 'triggered' => false, ]; } } diff --git a/database/migrations/2022_02_18_215852_create_reminders_table.php b/database/migrations/2022_02_18_215852_create_reminders_table.php index bd03a96409a..1e5227b3b10 100644 --- a/database/migrations/2022_02_18_215852_create_reminders_table.php +++ b/database/migrations/2022_02_18_215852_create_reminders_table.php @@ -29,17 +29,6 @@ public function up() $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade'); }); - Schema::create('scheduled_contact_reminders', function (Blueprint $table) { - $table->id(); - $table->unsignedBigInteger('contact_reminder_id'); - $table->unsignedBigInteger('user_id'); - $table->datetime('triggered_at'); - $table->boolean('triggered')->default(false); - $table->timestamps(); - $table->foreign('contact_reminder_id')->references('id')->on('contact_reminders')->onDelete('cascade'); - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - }); - Schema::create('user_notification_channels', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_id')->nullable(); @@ -54,6 +43,17 @@ public function up() $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); }); + Schema::create('scheduled_contact_reminders', function (Blueprint $table) { + $table->id(); + $table->unsignedBigInteger('contact_reminder_id'); + $table->unsignedBigInteger('user_notification_channel_id'); + $table->datetime('scheduled_at'); + $table->datetime('triggered_at')->nullable(); + $table->timestamps(); + $table->foreign('contact_reminder_id')->references('id')->on('contact_reminders')->onDelete('cascade'); + $table->foreign('user_notification_channel_id')->references('id')->on('user_notification_channels')->onDelete('cascade'); + }); + Schema::create('user_notification_sent', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_notification_channel_id')->nullable(); diff --git a/phpunit.xml b/phpunit.xml index c1e8be99945..7ac46bd42f8 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,34 +1,25 @@ - - - - - ./tests/Unit - - - - - ./app - - - - - - - - - - - - - - + + + + ./app + + + + + ./tests/Unit + + + + + + + + + + + + + + diff --git a/phpunit.xml.bak b/phpunit.xml.bak new file mode 100644 index 00000000000..c1e8be99945 --- /dev/null +++ b/phpunit.xml.bak @@ -0,0 +1,34 @@ + + + + + + ./tests/Unit + + + + + ./app + + + + + + + + + + + + + + + diff --git a/resources/js/Pages/Settings/Index.vue b/resources/js/Pages/Settings/Index.vue index 6e30638b39b..457bf148aa2 100644 --- a/resources/js/Pages/Settings/Index.vue +++ b/resources/js/Pages/Settings/Index.vue @@ -35,28 +35,30 @@ -

Account settings

-
- +
+

Account settings

+
+
    +
  • + 🥸 + + Manage users + +
  • +
  • + 🎃 + + Personalize your contacts data + +
  • +
  • + 💩 + + Cancel your account + +
  • +
+
diff --git a/resources/js/Pages/Settings/Notifications/Partials/Emails.vue b/resources/js/Pages/Settings/Notifications/Partials/Emails.vue index 5672209ce58..5a7ca1d1a9c 100644 --- a/resources/js/Pages/Settings/Notifications/Partials/Emails.vue +++ b/resources/js/Pages/Settings/Notifications/Partials/Emails.vue @@ -106,65 +106,17 @@ select { class="mr-1 rounded-md border-gray-300 bg-white py-2 px-3 shadow-sm focus:border-indigo-300 focus:outline-none focus:ring focus:ring-indigo-200 focus:ring-opacity-50 sm:text-sm" :required="required"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - m diff --git a/resources/js/Pages/Vault/Contact/ImportantDates/Index.vue b/resources/js/Pages/Vault/Contact/ImportantDates/Index.vue index 42df63ae66c..276d7a611bf 100644 --- a/resources/js/Pages/Vault/Contact/ImportantDates/Index.vue +++ b/resources/js/Pages/Vault/Contact/ImportantDates/Index.vue @@ -193,7 +193,7 @@ -
+
-

All the vaults in the account

+

All the vaults in the account

-
+
{{ vault.name }} diff --git a/resources/js/Shared/Layout.vue b/resources/js/Shared/Layout.vue index 1770bf909b2..7b7bc4432f3 100644 --- a/resources/js/Shared/Layout.vue +++ b/resources/js/Shared/Layout.vue @@ -14,9 +14,11 @@ main {
-