From bb1ef5eda399ca0d0d96ec7938d28c41d73a6372 Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Tue, 25 Jun 2024 12:19:20 -0500 Subject: [PATCH 01/15] Start mailale, template. Update DB --- app/Mail/ResourceDigestEmail.php | 53 +++++++++++++++++++ .../2024_06_25_170331_create_jobs_table.php | 32 +++++++++++ ...71615_add_is_subscriber_to_users_table.php | 22 ++++++++ .../views/emails/resource-digest.blade.php | 13 +++++ 4 files changed, 120 insertions(+) create mode 100644 app/Mail/ResourceDigestEmail.php create mode 100644 database/migrations/2024_06_25_170331_create_jobs_table.php create mode 100644 database/migrations/2024_06_25_171615_add_is_subscriber_to_users_table.php create mode 100644 resources/views/emails/resource-digest.blade.php diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php new file mode 100644 index 00000000..71ee21fa --- /dev/null +++ b/app/Mail/ResourceDigestEmail.php @@ -0,0 +1,53 @@ + + */ + public function attachments(): array + { + return []; + } +} diff --git a/database/migrations/2024_06_25_170331_create_jobs_table.php b/database/migrations/2024_06_25_170331_create_jobs_table.php new file mode 100644 index 00000000..6098d9b1 --- /dev/null +++ b/database/migrations/2024_06_25_170331_create_jobs_table.php @@ -0,0 +1,32 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + } +}; diff --git a/database/migrations/2024_06_25_171615_add_is_subscriber_to_users_table.php b/database/migrations/2024_06_25_171615_add_is_subscriber_to_users_table.php new file mode 100644 index 00000000..902f736a --- /dev/null +++ b/database/migrations/2024_06_25_171615_add_is_subscriber_to_users_table.php @@ -0,0 +1,22 @@ +boolean('is_subscriber')->default(false); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('is_subscriber'); + }); + } +}; diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php new file mode 100644 index 00000000..a7cf799b --- /dev/null +++ b/resources/views/emails/resource-digest.blade.php @@ -0,0 +1,13 @@ + + + + + Your Title + + + +

{{ $details['title'] }} +

{{ $details['body'] }} + + + From 4c280ffc6fb33e06bea3934f14f896387b3b627d Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Tue, 2 Jul 2024 11:25:37 -0500 Subject: [PATCH 02/15] begin job and scheduler logic --- .../Commands/SendResourceDigestEmail.php | 41 +++++++++++++++++++ app/Console/Kernel.php | 2 + app/Mail/ResourceDigestEmail.php | 36 ++++++---------- .../views/emails/resource-digest.blade.php | 11 +++-- 4 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 app/Console/Commands/SendResourceDigestEmail.php diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php new file mode 100644 index 00000000..43b5d1cc --- /dev/null +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -0,0 +1,41 @@ +=', Carbon::now()->subDays(30))->get(); + + if ($resources->isEmpty()) { + $this->info('No resources created in the last 30 days. Email not sent.'); + return; + } + + $data = $resources->toArray(); + + User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { + foreach ($subscribedUsers as $user) { + Mail::to($user->email)->send(new ResourceDigestEmail(['details' => $data])); + } + }); + + $this->info('Monthly resource digest sent successfully to all subscribed users.'); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index bbeebd9b..79d7b2c8 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -18,6 +18,8 @@ protected function schedule(Schedule $schedule): void { $schedule->command('resource:expired -N') ->weeklyOn(Schedule::FRIDAY, '06:00'); + + $schedule->command('email:resource-digest')->monthlyOn(1, '00:00'); } /** diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index 71ee21fa..c16a042c 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -3,49 +3,39 @@ namespace App\Mail; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; +use Illuminate\Queue\SerializesModels; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; -use Illuminate\Queue\SerializesModels; +use Illuminate\Contracts\Queue\ShouldQueue; -class ResourceDigestEmail extends Mailable +class ResourceDigestEmail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; - /** - * Create a new message instance. - */ - public function __construct() + public $data; + + public function __construct($data) { - // + $this->data = $data; } - /** - * Get the message envelope. - */ - public function envelope(): Envelope + public function envelope() { return new Envelope( - subject: 'Resource Digest Email', + subject: 'New Onramp Resources!', + from: config('mail.from.address'), ); } - /** - * Get the message content definition. - */ - public function content(): Content + public function content() { return new Content( - view: 'view.name', + view: 'emails.resource_digest', + with: ['data' => $this->data], ); } - /** - * Get the attachments for the message. - * - * @return array - */ public function attachments(): array { return []; diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php index a7cf799b..1a0e4503 100644 --- a/resources/views/emails/resource-digest.blade.php +++ b/resources/views/emails/resource-digest.blade.php @@ -2,12 +2,17 @@ - Your Title + Monthly Resource Digest -

{{ $details['title'] }} -

{{ $details['body'] }} +

Monthly Resource Digest

+

Here are the resources created in the last 30 days:

+ From 122a5e3dffc55a11bb08c485adc837755d46fc1c Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Tue, 2 Jul 2024 16:28:42 -0500 Subject: [PATCH 03/15] Fix nova. Emails send successfully. --- .../Commands/SendResourceDigestEmail.php | 2 +- app/Mail/ResourceDigestEmail.php | 2 +- app/Models/User.php | 2 +- composer.json | 6 +- composer.lock | 2204 +++++++++++------ config/app.php | 1 + 6 files changed, 1467 insertions(+), 750 deletions(-) diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index 43b5d1cc..b61908cc 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -32,7 +32,7 @@ public function handle() User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { foreach ($subscribedUsers as $user) { - Mail::to($user->email)->send(new ResourceDigestEmail(['details' => $data])); + Mail::to($user->email)->queue(new ResourceDigestEmail(['details' => $data])); } }); diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index c16a042c..c3f71f68 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -31,7 +31,7 @@ public function envelope() public function content() { return new Content( - view: 'emails.resource_digest', + view: 'emails.resource-digest', with: ['data' => $this->data], ); } diff --git a/app/Models/User.php b/app/Models/User.php index bc16a23c..0acc42ca 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -84,7 +84,7 @@ public function isAdmin() public function hasTrack() { - return ! is_null($this->track_id); + return !is_null($this->track_id); } public function getInitialsAttribute() diff --git a/composer.json b/composer.json index 69ef03b3..6e3641ad 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "guzzlehttp/guzzle": "^7.2", "kg-bot/laravel-localization-to-vue": "dev-l10-compatibility", "laravel/framework": "^10.3", + "laravel/nova": "4.33.3", "laravel/slack-notification-channel": "^2.5", "laravel/socialite": "^5.6", "laravel/tinker": "^2.8", @@ -20,7 +21,10 @@ "larswiegers/laravel-translations-checker": "^0.4", "nathanheffley/laravel-slack-blocks": "^2.3", "spatie/laravel-translatable": "^6.7", + "spatie/nova-translatable": "^4.0", "stechstudio/laravel-ssh-tunnel": "^3.3", + "tightenco/nova-releases": "^1.0", + "tightenco/suggested-resources-shortcuts": "dev-mla/resource-digest", "tightenco/ziggy": "^1.5" }, "require-dev": { @@ -95,7 +99,7 @@ "@php artisan key:generate --ansi" ], "post-install-cmd": [ - "[ $COMPOSER_DEV_MODE -eq 1 ] || composer require laravel/nova:^4.0 spatie/nova-translatable spatie/laravel-translatable tightenco/nova-releases tightenco/suggested-resources-shortcuts" + "[ $COMPOSER_DEV_MODE -eq 1 ] && composer require laravel/nova:4.33.3 spatie/nova-translatable spatie/laravel-translatable tightenco/nova-releases tightenco/suggested-resources-shortcuts" ], "lint": [ "vendor/bin/duster lint" diff --git a/composer.lock b/composer.lock index 88652f5a..26460a2d 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": "cfecbbdb8df5f3e8951fe19d1a7dd129", + "content-hash": "7b61af6f573dfb55fbc27b6e90cded58", "packages": [ { "name": "brick/math", @@ -66,6 +66,64 @@ ], "time": "2023-11-29T23:19:16+00:00" }, + { + "name": "brick/money", + "version": "0.9.0", + "source": { + "type": "git", + "url": "https://github.com/brick/money.git", + "reference": "60f8b6ceab2e1c9527e625198a76498fa477804a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/money/zipball/60f8b6ceab2e1c9527e625198a76498fa477804a", + "reference": "60f8b6ceab2e1c9527e625198a76498fa477804a", + "shasum": "" + }, + "require": { + "brick/math": "~0.12.0", + "ext-json": "*", + "php": "^8.1" + }, + "require-dev": { + "brick/varexporter": "~0.3.0", + "ext-dom": "*", + "ext-pdo": "*", + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" + }, + "suggest": { + "ext-intl": "Required to format Money objects" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Money\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Money and currency library", + "keywords": [ + "brick", + "currency", + "money" + ], + "support": { + "issues": "https://github.com/brick/money/issues", + "source": "https://github.com/brick/money/tree/0.9.0" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-11-26T16:51:39+00:00" + }, { "name": "bugsnag/bugsnag", "version": "v3.29.1", @@ -470,34 +528,37 @@ "time": "2022-10-27T11:44:00+00:00" }, { - "name": "doctrine/inflector", - "version": "2.0.10", + "name": "doctrine/cache", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -526,23 +587,22 @@ "email": "schmittjoh@gmail.com" } ], - "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", - "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", "php", - "plural", - "singular", - "strings", - "uppercase", - "words" + "redis", + "xcache" ], "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" }, "funding": [ { @@ -554,40 +614,59 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2022-05-20T20:07:39+00:00" }, { - "name": "doctrine/lexer", - "version": "3.0.1", + "name": "doctrine/dbal", + "version": "3.8.4", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "url": "https://github.com/doctrine/dbal.git", + "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd", + "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd", "shasum": "" }, "require": { - "php": "^8.1" + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" + "doctrine/coding-standard": "12.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.1", + "phpstan/phpstan": "1.10.58", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "9.6.16", + "psalm/plugin-phpunit": "0.18.4", + "slevomat/coding-standard": "8.13.1", + "squizlabs/php_codesniffer": "3.9.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/console": "^4.4|^5.4|^6.0|^7.0", + "vimeo/psalm": "4.30.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." }, + "bin": [ + "bin/doctrine-dbal" + ], "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" + "Doctrine\\DBAL\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -604,22 +683,39 @@ "email": "roman@code-factory.org" }, { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" } ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" ], "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.8.4" }, "funding": [ { @@ -631,108 +727,89 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2024-04-25T07:04:44+00:00" }, { - "name": "dragonmantank/cron-expression", - "version": "v3.3.3", + "name": "doctrine/deprecations", + "version": "1.1.3", "source": { "type": "git", - "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" - }, - "replace": { - "mtdowling/cron-expression": "^1.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", "autoload": { "psr-4": { - "Cron\\": "src/Cron/" + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Chris Tankersley", - "email": "chris@ctankersley.com", - "homepage": "https://github.com/dragonmantank" - } - ], - "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", - "keywords": [ - "cron", - "schedule" - ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", "support": { - "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" }, - "funding": [ - { - "url": "https://github.com/dragonmantank", - "type": "github" - } - ], - "time": "2023-08-10T19:36:49+00:00" + "time": "2024-01-30T19:34:25+00:00" }, { - "name": "egulias/email-validator", - "version": "4.0.2", + "name": "doctrine/event-manager", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/egulias/EmailValidator.git", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + "url": "https://github.com/doctrine/event-manager.git", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", "shasum": "" }, "require": { - "doctrine/lexer": "^2.0 || ^3.0", - "php": ">=8.1", - "symfony/polyfill-intl-idn": "^1.26" + "php": "^8.1" }, - "require-dev": { - "phpunit/phpunit": "^10.2", - "vimeo/psalm": "^5.12" + "conflict": { + "doctrine/common": "<2.9" }, - "suggest": { - "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, "autoload": { "psr-4": { - "Egulias\\EmailValidator\\": "src" + "Doctrine\\Common\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -741,55 +818,88 @@ ], "authors": [ { - "name": "Eduardo Gulias Davis" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], - "description": "A library for validating emails against several RFCs", - "homepage": "https://github.com/egulias/EmailValidator", + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", "keywords": [ - "email", - "emailvalidation", - "emailvalidator", - "validation", - "validator" + "event", + "event dispatcher", + "event manager", + "event system", + "events" ], "support": { - "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.1" }, "funding": [ { - "url": "https://github.com/egulias", - "type": "github" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" } ], - "time": "2023-10-06T06:47:41+00:00" + "time": "2024-05-22T20:47:39+00:00" }, { - "name": "erusev/parsedown", - "version": "1.7.4", + "name": "doctrine/inflector", + "version": "2.0.10", "source": { "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35" + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { - "psr-0": { - "Parsedown": "" + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -798,102 +908,394 @@ ], "authors": [ { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ - "markdown", - "parser" + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" ], "support": { - "issues": "https://github.com/erusev/parsedown/issues", - "source": "https://github.com/erusev/parsedown/tree/1.7.x" + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, - "time": "2019-12-30T22:54:17+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" }, { - "name": "firebase/php-jwt", - "version": "v6.10.1", + "name": "doctrine/lexer", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "500501c2ce893c824c801da135d02661199f60c5" + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", - "reference": "500501c2ce893c824c801da135d02661199f60c5", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { - "guzzlehttp/guzzle": "^7.4", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "psr/cache": "^2.0||^3.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - }, - "suggest": { - "ext-sodium": "Support EdDSA (Ed25519) signatures", - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { "psr-4": { - "Firebase\\JWT\\": "src" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" }, { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ - "jwt", + "annotations", + "docblock", + "lexer", + "parser", "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, - "time": "2024-05-18T18:05:11+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" }, { - "name": "fruitcake/php-cors", - "version": "v1.3.0", + "name": "dragonmantank/cron-expression", + "version": "v3.3.3", "source": { "type": "git", - "url": "https://github.com/fruitcake/php-cors.git", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", "shasum": "" }, "require": { - "php": "^7.4|^8.0", + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2023-08-10T19:36:49+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-10-06T06:47:41+00:00" + }, + { + "name": "erusev/parsedown", + "version": "1.7.4", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+00:00" + }, + { + "name": "firebase/php-jwt", + "version": "v6.10.1", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "500501c2ce893c824c801da135d02661199f60c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", + "reference": "500501c2ce893c824c801da135d02661199f60c5", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" + }, + "time": "2024-05-18T18:05:11+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", "symfony/http-foundation": "^4.4|^5.4|^6|^7" }, "require-dev": { @@ -1423,23 +1825,99 @@ "time": "2023-12-03T19:50:20+00:00" }, { - "name": "kg-bot/laravel-localization-to-vue", - "version": "dev-l10-compatibility", + "name": "inertiajs/inertia-laravel", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/laravel-shift/laravel-localization-to-vue.git", - "reference": "722c69ca5921c4aa7d84d172ba9de6c78aa30c8d" + "url": "https://github.com/inertiajs/inertia-laravel.git", + "reference": "36730d13b1dab9017069004fd458b3e67449a326" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel-shift/laravel-localization-to-vue/zipball/722c69ca5921c4aa7d84d172ba9de6c78aa30c8d", - "reference": "722c69ca5921c4aa7d84d172ba9de6c78aa30c8d", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/36730d13b1dab9017069004fd458b3e67449a326", + "reference": "36730d13b1dab9017069004fd458b3e67449a326", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "5.*|^6|^7|^8|^9|^10.0", - "php": "^8.0" + "laravel/framework": "^8.74|^9.0|^10.0|^11.0", + "php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0", + "symfony/console": "^5.3|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^6.4|^7.0|^8.0|^9.0", + "phpunit/phpunit": "^8.0|^9.5.8|^10.4", + "roave/security-advisories": "dev-master" + }, + "suggest": { + "ext-pcntl": "Recommended when running the Inertia SSR server via the `inertia:start-ssr` artisan command." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Inertia\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "./helpers.php" + ], + "psr-4": { + "Inertia\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Reinink", + "email": "jonathan@reinink.ca", + "homepage": "https://reinink.ca" + } + ], + "description": "The Laravel adapter for Inertia.js.", + "keywords": [ + "inertia", + "laravel" + ], + "support": { + "issues": "https://github.com/inertiajs/inertia-laravel/issues", + "source": "https://github.com/inertiajs/inertia-laravel/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/reinink", + "type": "github" + } + ], + "time": "2024-06-13T01:25:09+00:00" + }, + { + "name": "kg-bot/laravel-localization-to-vue", + "version": "dev-l10-compatibility", + "source": { + "type": "git", + "url": "https://github.com/laravel-shift/laravel-localization-to-vue.git", + "reference": "722c69ca5921c4aa7d84d172ba9de6c78aa30c8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel-shift/laravel-localization-to-vue/zipball/722c69ca5921c4aa7d84d172ba9de6c78aa30c8d", + "reference": "722c69ca5921c4aa7d84d172ba9de6c78aa30c8d", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": "5.*|^6|^7|^8|^9|^10.0", + "php": "^8.0" }, "type": "library", "extra": { @@ -1692,6 +2170,132 @@ }, "time": "2024-05-28T15:46:19+00:00" }, + { + "name": "laravel/nova", + "version": "4.33.3", + "source": { + "type": "git", + "url": "git@github.com:laravel/nova.git", + "reference": "0f308ea895bb202cced2493722b40ec172e0c108" + }, + "dist": { + "type": "zip", + "url": "https://nova.laravel.com/dist/laravel/nova/laravel-nova-0f308ea895bb202cced2493722b40ec172e0c108-zip-e38c97.zip", + "reference": "0f308ea895bb202cced2493722b40ec172e0c108", + "shasum": "2ec5564e35e52cac368274b063880d9068a1e345" + }, + "require": { + "brick/money": "^0.5|^0.6|^0.7|^0.8|^0.9", + "doctrine/dbal": "^2.13.3|^3.1.2|^4.0", + "ext-json": "*", + "illuminate/support": "^8.83.4|^9.3.1|^10.0|^11.0", + "inertiajs/inertia-laravel": "^0.4.5|^0.5.2|^0.6.0|^1.0", + "laravel/ui": "^3.3|^4.0", + "nesbot/carbon": "^2.53.1|^3.0", + "php": "^7.3|^8.0", + "rap2hpoutre/fast-excel": "^3.2|^4.1|^5.0", + "spatie/once": "^1.1|^2.0|^3.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.22.1", + "symfony/process": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "larastan/larastan": "^1.0.1|^2.5.1", + "laravel/nova-dusk-suite": "8.4.x-dev|9.4.x-dev|10.4.x-dev|11.4.x-dev", + "laravel/pint": "^1.6", + "laravel/scout": "^9.8|^10.0", + "mockery/mockery": "^1.4.4", + "orchestra/testbench-dusk": "^6.44|^7.40|^8.22|^9.0", + "phpunit/phpunit": "^9.6|^10.5", + "predis/predis": "^1.1.9|^2.0.2" + }, + "suggest": { + "ext-intl": "Required to format Currency field" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Nova\\NovaCoreServiceProvider" + ], + "aliases": { + "Nova": "Laravel\\Nova\\Nova" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Nova\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Laravel\\Nova\\Tests\\": "tests/" + } + }, + "scripts": { + "post-autoload-dump": [ + "@clear", + "@php vendor/bin/dusk-updater detect --auto-update --ansi", + "@php vendor/bin/testbench-dusk package:discover --ansi" + ], + "clear": [ + "@php vendor/bin/testbench-dusk package:purge-skeleton --ansi", + "@php vendor/bin/testbench-dusk package:dusk-purge --ansi" + ], + "dusk:prepare": [ + "@php -r \"file_exists('phpunit.dusk.xml') || copy('phpunit.dusk.xml.dist', 'phpunit.dusk.xml'); \"", + "@php -r \"if (file_exists('workbench/.env.dusk')) { copy('workbench/.env.dusk', 'vendor/laravel/nova-dusk-suite/.env'); } else { copy('workbench/.env.dusk.example', 'vendor/laravel/nova-dusk-suite/.env'); }\"" + ], + "dusk:dev-assets": [ + "TAILWIND_MODE=build npm run dev", + "@php vendor/bin/testbench-dusk nova:publish --force --ansi" + ], + "dusk:assets": [ + "TAILWIND_MODE=build npm run prod", + "@php vendor/bin/testbench-dusk nova:publish --force --ansi" + ], + "dusk:test": [ + "@php vendor/bin/testbench-dusk package:dusk-purge --ansi", + "@php vendor/bin/phpunit -c phpunit.dusk.xml --stop-on-failure --stop-on-error" + ], + "dusk:filter": [ + "./vendor/bin/testbench-dusk package:dusk-purge --ansi && ./vendor/bin/phpunit -c phpunit.dusk.xml --filter" + ], + "test:local": [ + "@php vendor/bin/phpunit -c phpunit.xml --group date-field,datetime-field,external-network --testdox", + "@php vendor/bin/phpunit -c phpunit.dusk.xml --group date-field,datetime-field,external-network --testdox" + ], + "serve": [ + "@clear", + "@php vendor/bin/testbench package:discover --ansi", + "@php vendor/bin/testbench workbench:build --ansi", + "@php vendor/bin/testbench serve" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "A wonderful administration interface for Laravel.", + "keywords": [ + "admin", + "laravel" + ], + "support": { + "source": "https://github.com/laravel/nova/tree/v4.33.3" + }, + "time": "2024-04-18T00:44:42+00:00" + }, { "name": "laravel/prompts", "version": "v0.1.23", @@ -3147,6 +3751,99 @@ ], "time": "2023-02-08T01:06:31+00:00" }, + { + "name": "openspout/openspout", + "version": "v4.24.2", + "source": { + "type": "git", + "url": "https://github.com/openspout/openspout.git", + "reference": "24272c1f7d073cc64fa3ecc2a863dc5d13be33a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/openspout/openspout/zipball/24272c1f7d073cc64fa3ecc2a863dc5d13be33a8", + "reference": "24272c1f7d073cc64fa3ecc2a863dc5d13be33a8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-filter": "*", + "ext-libxml": "*", + "ext-xmlreader": "*", + "ext-zip": "*", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + }, + "require-dev": { + "ext-zlib": "*", + "friendsofphp/php-cs-fixer": "^3.59.3", + "infection/infection": "^0.29.5", + "phpbench/phpbench": "^1.2.15", + "phpstan/phpstan": "^1.11.4", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpunit/phpunit": "^10.5.20 || ^11.2.2" + }, + "suggest": { + "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", + "ext-mbstring": "To handle non UTF-8 CSV files (if \"iconv\" is not already installed)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenSpout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Adrien Loison", + "email": "adrien@box.com" + } + ], + "description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way", + "homepage": "https://github.com/openspout/openspout", + "keywords": [ + "OOXML", + "csv", + "excel", + "memory", + "odf", + "ods", + "office", + "open", + "php", + "read", + "scale", + "spreadsheet", + "stream", + "write", + "xlsx" + ], + "support": { + "issues": "https://github.com/openspout/openspout/issues", + "source": "https://github.com/openspout/openspout/tree/v4.24.2" + }, + "funding": [ + { + "url": "https://paypal.me/filippotessarotto", + "type": "custom" + }, + { + "url": "https://github.com/Slamdunk", + "type": "github" + } + ], + "time": "2024-06-17T08:53:37+00:00" + }, { "name": "paragonie/constant_time_encoding", "version": "v2.7.0", @@ -3449,6 +4146,55 @@ ], "time": "2024-03-03T02:14:58+00:00" }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, { "name": "psr/clock", "version": "1.0.0", @@ -4166,34 +4912,43 @@ "time": "2024-04-27T21:32:50+00:00" }, { - "name": "spatie/laravel-package-tools", - "version": "1.16.4", + "name": "rap2hpoutre/fast-excel", + "version": "v5.5.0", "source": { "type": "git", - "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53" + "url": "https://github.com/rap2hpoutre/fast-excel.git", + "reference": "83604f2a16fbb0374747299173abe691b24916da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", - "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "url": "https://api.github.com/repos/rap2hpoutre/fast-excel/zipball/83604f2a16fbb0374747299173abe691b24916da", + "reference": "83604f2a16fbb0374747299173abe691b24916da", "shasum": "" }, "require": { - "illuminate/contracts": "^9.28|^10.0|^11.0", + "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", + "openspout/openspout": "^4.24", "php": "^8.0" }, "require-dev": { - "mockery/mockery": "^1.5", - "orchestra/testbench": "^7.7|^8.0", - "pestphp/pest": "^1.22", - "phpunit/phpunit": "^9.5.24", - "spatie/pest-plugin-test-time": "^1.1" + "illuminate/database": "^6.20.12 || ^7.30.4 || ^8.24.0 || ^9.0 || ^10.0 || ^11.0", + "phpunit/phpunit": "^9.5 || ^10.1", + "squizlabs/php_codesniffer": "3.*" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Rap2hpoutre\\FastExcel\\Providers\\FastExcelServiceProvider" + ] + } + }, "autoload": { + "files": [ + "src/functions/fastexcel.php" + ], "psr-4": { - "Spatie\\LaravelPackageTools\\": "src" + "Rap2hpoutre\\FastExcel\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4202,37 +4957,98 @@ ], "authors": [ { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "role": "Developer" + "name": "rap2h", + "email": "raphaelht@gmail.com" } ], - "description": "Tools for creating Laravel packages", - "homepage": "https://github.com/spatie/laravel-package-tools", + "description": "Fast Excel import/export for Laravel", "keywords": [ - "laravel-package-tools", - "spatie" + "csv", + "excel", + "laravel", + "xls", + "xlsx" ], "support": { - "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.4" + "issues": "https://github.com/rap2hpoutre/fast-excel/issues", + "source": "https://github.com/rap2hpoutre/fast-excel/tree/v5.5.0" }, "funding": [ { - "url": "https://github.com/spatie", + "url": "https://github.com/rap2hpoutre", "type": "github" } ], - "time": "2024-03-20T07:29:11+00:00" + "time": "2024-06-03T08:00:43+00:00" }, { - "name": "spatie/laravel-translatable", - "version": "6.7.1", + "name": "spatie/laravel-package-tools", + "version": "1.16.4", "source": { "type": "git", - "url": "https://github.com/spatie/laravel-translatable.git", - "reference": "d55384cbcf867b3cf21ff4d062403596d94acf81" - }, + "url": "https://github.com/spatie/laravel-package-tools.git", + "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^9.28|^10.0|^11.0", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "orchestra/testbench": "^7.7|^8.0", + "pestphp/pest": "^1.22", + "phpunit/phpunit": "^9.5.24", + "spatie/pest-plugin-test-time": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\LaravelPackageTools\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Tools for creating Laravel packages", + "homepage": "https://github.com/spatie/laravel-package-tools", + "keywords": [ + "laravel-package-tools", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-package-tools/issues", + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.4" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-03-20T07:29:11+00:00" + }, + { + "name": "spatie/laravel-translatable", + "version": "6.7.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-translatable.git", + "reference": "d55384cbcf867b3cf21ff4d062403596d94acf81" + }, "dist": { "type": "zip", "url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/d55384cbcf867b3cf21ff4d062403596d94acf81", @@ -4307,6 +5123,127 @@ ], "time": "2024-05-14T11:35:51+00:00" }, + { + "name": "spatie/nova-translatable", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/nova-translatable.git", + "reference": "ab229fd5191f71702cde8596a9c9456c489622e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/nova-translatable/zipball/ab229fd5191f71702cde8596a9c9456c489622e8", + "reference": "ab229fd5191f71702cde8596a9c9456c489622e8", + "shasum": "" + }, + "require": { + "laravel/nova": "^4.0", + "php": "^7.3|^8.0", + "spatie/laravel-translatable": "^5.0|^6.0" + }, + "require-dev": { + "mockery/mockery": "^1.4", + "orchestra/testbench": "^5.0|^6.0|^7.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\NovaTranslatable\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Making Nova fields translatable", + "homepage": "https://github.com/spatie/nova-translatable", + "keywords": [ + "laravel", + "nova" + ], + "support": { + "issues": "https://github.com/spatie/nova-translatable/issues", + "source": "https://github.com/spatie/nova-translatable/tree/4.0.2" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2024-05-27T09:25:42+00:00" + }, + { + "name": "spatie/once", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/once.git", + "reference": "25252b821765d72566be17c52ea05b35329f0f8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/once/zipball/25252b821765d72566be17c52ea05b35329f0f8f", + "reference": "25252b821765d72566be17c52ea05b35329f0f8f", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "pestphp/pest": "^1.21", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Spatie\\Once\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A magic memoization function", + "homepage": "https://github.com/spatie/once", + "keywords": [ + "cache", + "callable", + "memoization", + "once", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/once/tree/3.1.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2024-05-27T09:17:58+00:00" + }, { "name": "stechstudio/laravel-ssh-tunnel", "version": "3.3.0", @@ -5398,6 +6335,90 @@ ], "time": "2024-01-29T20:11:03+00:00" }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "e76343c631b453088e2260ac41dfebe21954de81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e76343c631b453088e2260ac41dfebe21954de81", + "reference": "e76343c631b453088e2260ac41dfebe21954de81", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, { "name": "symfony/polyfill-intl-idn", "version": "v1.29.0", @@ -6599,62 +7620,146 @@ "time": "2024-05-31T14:49:08+00:00" }, { - "name": "tightenco/ziggy", - "version": "v1.8.2", + "name": "tightenco/nova-releases", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/tighten/ziggy.git", - "reference": "939576ad0f3d3e633a9401c8c377bc7bc873ff35" + "url": "https://github.com/tighten/nova-releases.git", + "reference": "42ee696ebc9bfe1d89ef41c090987adbc3e31988" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/939576ad0f3d3e633a9401c8c377bc7bc873ff35", - "reference": "939576ad0f3d3e633a9401c8c377bc7bc873ff35", + "url": "https://api.github.com/repos/tighten/nova-releases/zipball/42ee696ebc9bfe1d89ef41c090987adbc3e31988", + "reference": "42ee696ebc9bfe1d89ef41c090987adbc3e31988", "shasum": "" }, "require": { - "ext-json": "*", - "laravel/framework": ">=5.4@dev" - }, - "require-dev": { - "orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", - "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0" + "erusev/parsedown": "^1.7", + "laravel/framework": ">=7.0", + "php": ">=7.2.5" }, "type": "library", "extra": { "laravel": { "providers": [ - "Tightenco\\Ziggy\\ZiggyServiceProvider" + "Tightenco\\NovaReleases\\CardServiceProvider" ] } }, "autoload": { "psr-4": { - "Tightenco\\Ziggy\\": "src/" + "Tightenco\\NovaReleases\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Daniel Coulbourne", - "email": "daniel@tighten.co" - }, - { - "name": "Jake Bathman", - "email": "jake@tighten.co" - }, - { - "name": "Jacob Baker-Kretzmar", - "email": "jacob@tighten.co" - } - ], - "description": "Generates a Blade directive exporting all of your named Laravel routes. Also provides a nice route() helper function in JavaScript.", - "homepage": "https://github.com/tighten/ziggy", + "description": "Keep on top of Nova Releases", "keywords": [ - "Ziggy", + "laravel", + "nova" + ], + "support": { + "issues": "https://github.com/tighten/nova-releases/issues", + "source": "https://github.com/tighten/nova-releases/tree/v1.0.0" + }, + "abandoned": true, + "time": "2020-09-12T02:08:21+00:00" + }, + { + "name": "tightenco/suggested-resources-shortcuts", + "version": "dev-mla/resource-digest", + "dist": { + "type": "path", + "url": "./nova-components/SuggestedResourcesShortcuts", + "reference": "9e899018f8d75262fc9d071636fd8fb71faeba9b" + }, + "require": { + "php": "^7.3|^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Tightenco\\SuggestedResourcesShortcuts\\CardServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Tightenco\\SuggestedResourcesShortcuts\\": "src/" + } + }, + "license": [ + "MIT" + ], + "description": "A Laravel Nova card.", + "keywords": [ + "laravel", + "nova" + ], + "transport-options": { + "relative": true + } + }, + { + "name": "tightenco/ziggy", + "version": "v1.8.2", + "source": { + "type": "git", + "url": "https://github.com/tighten/ziggy.git", + "reference": "939576ad0f3d3e633a9401c8c377bc7bc873ff35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/939576ad0f3d3e633a9401c8c377bc7bc873ff35", + "reference": "939576ad0f3d3e633a9401c8c377bc7bc873ff35", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": ">=5.4@dev" + }, + "require-dev": { + "orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", + "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Tightenco\\Ziggy\\ZiggyServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Tightenco\\Ziggy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Coulbourne", + "email": "daniel@tighten.co" + }, + { + "name": "Jake Bathman", + "email": "jake@tighten.co" + }, + { + "name": "Jacob Baker-Kretzmar", + "email": "jacob@tighten.co" + } + ], + "description": "Generates a Blade directive exporting all of your named Laravel routes. Also provides a nice route() helper function in JavaScript.", + "homepage": "https://github.com/tighten/ziggy", + "keywords": [ + "Ziggy", "javascript", "laravel", "routes" @@ -7288,468 +8393,145 @@ "MIT" ], "authors": [ - { - "name": "Brian Scaturro", - "email": "scaturrob@gmail.com", - "role": "Developer" - }, - { - "name": "Filippo Tessarotto", - "email": "zoeslam@gmail.com", - "role": "Developer" - } - ], - "description": "Parallel testing for PHP", - "homepage": "https://github.com/paratestphp/paratest", - "keywords": [ - "concurrent", - "parallel", - "phpunit", - "testing" - ], - "support": { - "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v6.11.1" - }, - "funding": [ - { - "url": "https://github.com/sponsors/Slamdunk", - "type": "github" - }, - { - "url": "https://paypal.me/filippotessarotto", - "type": "paypal" - } - ], - "time": "2024-03-13T06:54:29+00:00" - }, - { - "name": "composer/class-map-generator", - "version": "1.3.3", - "source": { - "type": "git", - "url": "https://github.com/composer/class-map-generator.git", - "reference": "61804f9973685ec7bead0fb7fe022825e3cd418e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/61804f9973685ec7bead0fb7fe022825e3cd418e", - "reference": "61804f9973685ec7bead0fb7fe022825e3cd418e", - "shasum": "" - }, - "require": { - "composer/pcre": "^2.1 || ^3.1", - "php": "^7.2 || ^8.0", - "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" - }, - "require-dev": { - "phpstan/phpstan": "^1.6", - "phpstan/phpstan-deprecation-rules": "^1", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/filesystem": "^5.4 || ^6", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\ClassMapGenerator\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" - } - ], - "description": "Utilities to scan PHP code and generate class maps.", - "keywords": [ - "classmap" - ], - "support": { - "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.3.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-06-10T11:53:54+00:00" - }, - { - "name": "composer/pcre", - "version": "3.1.4", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "04229f163664973f68f38f6f73d917799168ef24" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", - "reference": "04229f163664973f68f38f6f73d917799168ef24", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.4" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-27T13:40:54+00:00" - }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "time": "2022-05-20T20:07:39+00:00" - }, - { - "name": "doctrine/dbal", - "version": "3.8.4", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd", - "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", - "doctrine/deprecations": "^0.5.3|^1", - "doctrine/event-manager": "^1|^2", - "php": "^7.4 || ^8.0", - "psr/cache": "^1|^2|^3", - "psr/log": "^1|^2|^3" - }, - "require-dev": { - "doctrine/coding-standard": "12.0.0", - "fig/log-test": "^1", - "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.58", - "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.16", - "psalm/plugin-phpunit": "0.18.4", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.9.0", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "vimeo/psalm": "4.30.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" }, { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" } ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlite", - "sqlserver", - "sqlsrv" + "concurrent", + "parallel", + "phpunit", + "testing" ], "support": { - "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.4" + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v6.11.1" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", - "type": "tidelift" + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" } ], - "time": "2024-04-25T07:04:44+00:00" + "time": "2024-03-13T06:54:29+00:00" }, { - "name": "doctrine/deprecations", - "version": "1.1.3", + "name": "composer/class-map-generator", + "version": "1.3.3", "source": { "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "url": "https://github.com/composer/class-map-generator.git", + "reference": "61804f9973685ec7bead0fb7fe022825e3cd418e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/61804f9973685ec7bead0fb7fe022825e3cd418e", + "reference": "61804f9973685ec7bead0fb7fe022825e3cd418e", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "composer/pcre": "^2.1 || ^3.1", + "php": "^7.2 || ^8.0", + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" }, "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + "phpstan/phpstan": "^1.6", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/filesystem": "^5.4 || ^6", + "symfony/phpunit-bridge": "^5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Composer\\ClassMapGenerator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Utilities to scan PHP code and generate class maps.", + "keywords": [ + "classmap" + ], "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "issues": "https://github.com/composer/class-map-generator/issues", + "source": "https://github.com/composer/class-map-generator/tree/1.3.3" }, - "time": "2024-01-30T19:34:25+00:00" + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-06-10T11:53:54+00:00" }, { - "name": "doctrine/event-manager", - "version": "2.0.1", + "name": "composer/pcre", + "version": "3.1.4", "source": { "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + "url": "https://github.com/composer/pcre.git", + "reference": "04229f163664973f68f38f6f73d917799168ef24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", + "reference": "04229f163664973f68f38f6f73d917799168ef24", "shasum": "" }, "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" + "php": "^7.4 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "Doctrine\\Common\\": "src" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -7758,58 +8540,37 @@ ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" + "PCRE", + "preg", + "regex", + "regular expression" ], "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.1" + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.4" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", + "url": "https://packagist.com", "type": "custom" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" + "url": "https://github.com/composer", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], - "time": "2024-05-22T20:47:39+00:00" + "time": "2024-05-27T13:40:54+00:00" }, { "name": "doctrine/instantiator", @@ -9182,55 +9943,6 @@ ], "time": "2024-04-05T04:35:58+00:00" }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.2", diff --git a/config/app.php b/config/app.php index 31622f30..e799be37 100644 --- a/config/app.php +++ b/config/app.php @@ -194,6 +194,7 @@ App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, + App\Providers\NovaServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\PreferencesServiceProvider::class, App\Providers\LocalizationServiceProvider::class, From 2841c0abdfd16d20657d073a78b6bc226d5da4be Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Tue, 2 Jul 2024 19:27:16 -0500 Subject: [PATCH 04/15] A little cleanup and renaming. Add failed jobs table --- .../Commands/SendResourceDigestEmail.php | 6 +++- app/Console/Kernel.php | 5 +-- app/Mail/ResourceDigestEmail.php | 2 +- config/logging.php | 13 +++----- ..._07_02_223118_create_failed_jobs_table.php | 32 +++++++++++++++++++ .../views/emails/resource-digest.blade.php | 5 --- 6 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 database/migrations/2024_07_02_223118_create_failed_jobs_table.php diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index b61908cc..b69058bf 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -11,7 +11,7 @@ class SendResourceDigestEmail extends Command { - protected $signature = 'email:resource-digest'; + protected $signature = 'send:send-resource-digest-email'; protected $description = 'Send the monthly resource digest email'; public function __construct() @@ -21,6 +21,8 @@ public function __construct() public function handle() { + $this->info('Starting to send resource digest emails.'); + $resources = Resource::where('created_at', '>=', Carbon::now()->subDays(30))->get(); if ($resources->isEmpty()) { @@ -31,7 +33,9 @@ public function handle() $data = $resources->toArray(); User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { + $this->info('Processing a chunk of subscribed users.'); foreach ($subscribedUsers as $user) { + $this->info('Queueing email for user: ' . $user->email); Mail::to($user->email)->queue(new ResourceDigestEmail(['details' => $data])); } }); diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 79d7b2c8..172b21fc 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,13 +2,14 @@ namespace App\Console; +use App\Console\Commands\SendResourceDigestEmail; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { protected $commands = [ - // + SendResourceDigestEmail::class, ]; /** @@ -19,7 +20,7 @@ protected function schedule(Schedule $schedule): void $schedule->command('resource:expired -N') ->weeklyOn(Schedule::FRIDAY, '06:00'); - $schedule->command('email:resource-digest')->monthlyOn(1, '00:00'); + $schedule->command('send:send-resource-digest-email')->monthlyOn(1, '00:00'); } /** diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index c3f71f68..90fd5b08 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -24,7 +24,7 @@ public function envelope() { return new Envelope( subject: 'New Onramp Resources!', - from: config('mail.from.address'), + from: 'no-reply@onramp.com', ); } diff --git a/config/logging.php b/config/logging.php index f4ffa8c1..f104aac5 100644 --- a/config/logging.php +++ b/config/logging.php @@ -53,20 +53,17 @@ 'channels' => [ 'stack' => [ 'driver' => 'stack', - 'channels' => ['daily', 'bugsnag'], - 'ignore_exceptions' => false, - ], - - 'bugsnag' => [ - 'driver' => 'bugsnag', + 'channels' => ['single'], ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), - 'level' => env('LOG_LEVEL', 'debug'), + 'level' => 'debug', + ], + 'bugsnag' => [ + 'driver' => 'bugsnag', ], - 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), diff --git a/database/migrations/2024_07_02_223118_create_failed_jobs_table.php b/database/migrations/2024_07_02_223118_create_failed_jobs_table.php new file mode 100644 index 00000000..249da817 --- /dev/null +++ b/database/migrations/2024_07_02_223118_create_failed_jobs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php index 1a0e4503..ad7059c7 100644 --- a/resources/views/emails/resource-digest.blade.php +++ b/resources/views/emails/resource-digest.blade.php @@ -8,11 +8,6 @@

Monthly Resource Digest

Here are the resources created in the last 30 days:

-
    - @foreach ($data as $resource) -
  • {{ $resource['title'] }} - {{ $resource['created_at'] }}
  • - @endforeach -
From 037b8919b971bb7745e2d2901baaa2c1117f3c30 Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Tue, 2 Jul 2024 19:29:06 -0500 Subject: [PATCH 05/15] Remove sanity checks --- app/Console/Commands/SendResourceDigestEmail.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index b69058bf..d59b23a8 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -21,21 +21,18 @@ public function __construct() public function handle() { - $this->info('Starting to send resource digest emails.'); - $resources = Resource::where('created_at', '>=', Carbon::now()->subDays(30))->get(); if ($resources->isEmpty()) { $this->info('No resources created in the last 30 days. Email not sent.'); + return; } $data = $resources->toArray(); User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { - $this->info('Processing a chunk of subscribed users.'); foreach ($subscribedUsers as $user) { - $this->info('Queueing email for user: ' . $user->email); Mail::to($user->email)->queue(new ResourceDigestEmail(['details' => $data])); } }); From 3c13a1e96f9665bd54f6c24b3afb4927f11b10ee Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Wed, 3 Jul 2024 08:35:10 -0500 Subject: [PATCH 06/15] Some more cleanup. Start template. --- app/Console/Kernel.php | 2 +- app/Mail/ResourceDigestEmail.php | 2 +- config/logging.php | 13 ++++++++----- .../views/emails/resource-digest.blade.php | 18 ++++++------------ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 172b21fc..e1b11ab3 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -20,7 +20,7 @@ protected function schedule(Schedule $schedule): void $schedule->command('resource:expired -N') ->weeklyOn(Schedule::FRIDAY, '06:00'); - $schedule->command('send:send-resource-digest-email')->monthlyOn(1, '00:00'); + $schedule->command('send:send-resource-digest-email')->monthly(); } /** diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index 90fd5b08..ceda6268 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -31,7 +31,7 @@ public function envelope() public function content() { return new Content( - view: 'emails.resource-digest', + markdown: 'emails.resource-digest', with: ['data' => $this->data], ); } diff --git a/config/logging.php b/config/logging.php index f104aac5..f4ffa8c1 100644 --- a/config/logging.php +++ b/config/logging.php @@ -53,17 +53,20 @@ 'channels' => [ 'stack' => [ 'driver' => 'stack', - 'channels' => ['single'], + 'channels' => ['daily', 'bugsnag'], + 'ignore_exceptions' => false, + ], + + 'bugsnag' => [ + 'driver' => 'bugsnag', ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), - 'level' => 'debug', - ], - 'bugsnag' => [ - 'driver' => 'bugsnag', + 'level' => env('LOG_LEVEL', 'debug'), ], + 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php index ad7059c7..a19feea4 100644 --- a/resources/views/emails/resource-digest.blade.php +++ b/resources/views/emails/resource-digest.blade.php @@ -1,13 +1,7 @@ - - +@component('mail::message') + # hello this is email - - Monthly Resource Digest - - - -

Monthly Resource Digest

-

Here are the resources created in the last 30 days:

- - - + @component('mail::panel') + [some markdown](https://www.cats.com) + @endcomponent +@endcomponent From 2ae654b39c858a304cc91ea72c8fc12deb43618c Mon Sep 17 00:00:00 2001 From: MarcyLina Date: Wed, 3 Jul 2024 13:37:32 +0000 Subject: [PATCH 07/15] Dusting --- app/Completable.php | 4 +--- app/Console/Commands/SendResourceDigestEmail.php | 4 ++-- app/Mail/ResourceDigestEmail.php | 4 ++-- app/Models/User.php | 2 +- database/migrations/2024_06_25_170331_create_jobs_table.php | 6 ------ .../2024_07_02_223118_create_failed_jobs_table.php | 6 ------ 6 files changed, 6 insertions(+), 20 deletions(-) diff --git a/app/Completable.php b/app/Completable.php index 88795081..198f028c 100644 --- a/app/Completable.php +++ b/app/Completable.php @@ -2,6 +2,4 @@ namespace App; -interface Completable -{ -} +interface Completable {} diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index d59b23a8..d90d1e7c 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -2,12 +2,12 @@ namespace App\Console\Commands; -use Illuminate\Console\Command; -use Illuminate\Support\Facades\Mail; use App\Mail\ResourceDigestEmail; use App\Models\Resource; use App\Models\User; use Carbon\Carbon; +use Illuminate\Console\Command; +use Illuminate\Support\Facades\Mail; class SendResourceDigestEmail extends Command { diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index ceda6268..68950a7c 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -3,11 +3,11 @@ namespace App\Mail; use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; -use Illuminate\Queue\SerializesModels; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; -use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\SerializesModels; class ResourceDigestEmail extends Mailable implements ShouldQueue { diff --git a/app/Models/User.php b/app/Models/User.php index 0acc42ca..bc16a23c 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -84,7 +84,7 @@ public function isAdmin() public function hasTrack() { - return !is_null($this->track_id); + return ! is_null($this->track_id); } public function getInitialsAttribute() diff --git a/database/migrations/2024_06_25_170331_create_jobs_table.php b/database/migrations/2024_06_25_170331_create_jobs_table.php index 6098d9b1..cb4e8783 100644 --- a/database/migrations/2024_06_25_170331_create_jobs_table.php +++ b/database/migrations/2024_06_25_170331_create_jobs_table.php @@ -6,9 +6,6 @@ return new class extends Migration { - /** - * Run the migrations. - */ public function up(): void { Schema::create('jobs', function (Blueprint $table) { @@ -22,9 +19,6 @@ public function up(): void }); } - /** - * Reverse the migrations. - */ public function down(): void { Schema::dropIfExists('jobs'); diff --git a/database/migrations/2024_07_02_223118_create_failed_jobs_table.php b/database/migrations/2024_07_02_223118_create_failed_jobs_table.php index 249da817..85264d8b 100644 --- a/database/migrations/2024_07_02_223118_create_failed_jobs_table.php +++ b/database/migrations/2024_07_02_223118_create_failed_jobs_table.php @@ -6,9 +6,6 @@ return new class extends Migration { - /** - * Run the migrations. - */ public function up(): void { Schema::create('failed_jobs', function (Blueprint $table) { @@ -22,9 +19,6 @@ public function up(): void }); } - /** - * Reverse the migrations. - */ public function down(): void { Schema::dropIfExists('failed_jobs'); From 24b525922d3508e2359c0ec8b122c21a7d055462 Mon Sep 17 00:00:00 2001 From: MarcyLina Date: Wed, 3 Jul 2024 13:37:33 +0000 Subject: [PATCH 08/15] Ignore Dusting commit in git blame --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index a8f7dfc1..a2adebcf 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,4 @@ # Dusting c380d69ba5f0813410af5eba98c3d3b83e4c288f b7707e028a9838565a51d617382b0f2690bcd5cb +2ae654b39c858a304cc91ea72c8fc12deb43618c From aebb0c9f811c66acc6a0737c064e0747c2114bde Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Fri, 5 Jul 2024 08:47:50 -0500 Subject: [PATCH 09/15] WIP --- .../Commands/SendResourceDigestEmail.php | 9 +++++++-- app/Mail/ResourceDigestEmail.php | 8 ++++---- .../views/emails/resource-digest.blade.php | 20 +++++++++++++++---- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index d90d1e7c..5389ce64 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -7,6 +7,7 @@ use App\Models\User; use Carbon\Carbon; use Illuminate\Console\Command; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; class SendResourceDigestEmail extends Command @@ -25,15 +26,19 @@ public function handle() if ($resources->isEmpty()) { $this->info('No resources created in the last 30 days. Email not sent.'); - return; } + // Convert resources to array $data = $resources->toArray(); User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { foreach ($subscribedUsers as $user) { - Mail::to($user->email)->queue(new ResourceDigestEmail(['details' => $data])); + try { + Mail::to($user->email)->queue(new ResourceDigestEmail($data)); + } catch (\Exception $e) { + Log::error('Failed to send email to ' . $user->email . ': ' . $e->getMessage()); + } } }); diff --git a/app/Mail/ResourceDigestEmail.php b/app/Mail/ResourceDigestEmail.php index 68950a7c..e4d746ba 100644 --- a/app/Mail/ResourceDigestEmail.php +++ b/app/Mail/ResourceDigestEmail.php @@ -13,11 +13,11 @@ class ResourceDigestEmail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; - public $data; + public $resources; - public function __construct($data) + public function __construct($resources) { - $this->data = $data; + $this->resources = $resources; } public function envelope() @@ -32,7 +32,7 @@ public function content() { return new Content( markdown: 'emails.resource-digest', - with: ['data' => $this->data], + with: ['resources' => $this->resources], ); } diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php index a19feea4..8ebd7aee 100644 --- a/resources/views/emails/resource-digest.blade.php +++ b/resources/views/emails/resource-digest.blade.php @@ -1,7 +1,19 @@ @component('mail::message') - # hello this is email +# Here are the latest resources: - @component('mail::panel') - [some markdown](https://www.cats.com) - @endcomponent +@component('mail::panel') +@foreach ($resources as $resource) +- {{ $resource['name'] }} +@endforeach @endcomponent + +### Happy Coding! + +### Your friends at {{ config('app.name') }} +@endcomponent + +{{-- @foreach ($resources as $resource) +
  • +{{ $resource['name'] }} +
  • +@endforeach --}} From de91c30c7cb7cb493fee134d2ddceab8c8cf58d8 Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Fri, 5 Jul 2024 08:49:40 -0500 Subject: [PATCH 10/15] remove comment --- app/Console/Commands/SendResourceDigestEmail.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index 5389ce64..07f1513c 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -29,7 +29,6 @@ public function handle() return; } - // Convert resources to array $data = $resources->toArray(); User::where('is_subscriber', true)->chunk(100, function ($subscribedUsers) use ($data) { From 8a091e69260ae3f2a92d3eecb43edac75a4a70ac Mon Sep 17 00:00:00 2001 From: MarcyLina Date: Fri, 5 Jul 2024 13:51:02 +0000 Subject: [PATCH 11/15] Dusting --- app/Console/Commands/SendResourceDigestEmail.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/SendResourceDigestEmail.php b/app/Console/Commands/SendResourceDigestEmail.php index 07f1513c..1fbc428a 100644 --- a/app/Console/Commands/SendResourceDigestEmail.php +++ b/app/Console/Commands/SendResourceDigestEmail.php @@ -6,6 +6,7 @@ use App\Models\Resource; use App\Models\User; use Carbon\Carbon; +use Exception; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; @@ -26,6 +27,7 @@ public function handle() if ($resources->isEmpty()) { $this->info('No resources created in the last 30 days. Email not sent.'); + return; } @@ -35,7 +37,7 @@ public function handle() foreach ($subscribedUsers as $user) { try { Mail::to($user->email)->queue(new ResourceDigestEmail($data)); - } catch (\Exception $e) { + } catch (Exception $e) { Log::error('Failed to send email to ' . $user->email . ': ' . $e->getMessage()); } } From 9708a894fb907c47d44c6daf8aa87dd7a2c562c1 Mon Sep 17 00:00:00 2001 From: MarcyLina Date: Fri, 5 Jul 2024 13:51:03 +0000 Subject: [PATCH 12/15] Ignore Dusting commit in git blame --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index a2adebcf..cbdc5270 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -2,3 +2,4 @@ c380d69ba5f0813410af5eba98c3d3b83e4c288f b7707e028a9838565a51d617382b0f2690bcd5cb 2ae654b39c858a304cc91ea72c8fc12deb43618c +8a091e69260ae3f2a92d3eecb43edac75a4a70ac From 660a90aeb8879d9af6edd8c488e0999e5e6cb039 Mon Sep 17 00:00:00 2001 From: Marcy Acevedo Date: Fri, 2 Aug 2024 13:51:04 -0500 Subject: [PATCH 13/15] Add newsletter preference section. Add subcriber cast. Cleanup --- app/Models/User.php | 199 +++++++++--------- database/seeders/ContentSeeder.php | 40 ++-- .../views/emails/resource-digest.blade.php | 6 - resources/views/preferences.blade.php | 50 ++++- 4 files changed, 171 insertions(+), 124 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index bc16a23c..5f4cd9fd 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -10,103 +10,104 @@ class User extends Authenticatable { - use HasFactory; - use Notifiable; - - protected $guarded = [ - 'id', - ]; - - protected $hidden = [ - 'password', 'remember_token', 'github_token', - ]; - - protected $casts = [ - 'email_verified_at' => 'datetime', - 'preferences' => 'object', - ]; - - public function track() - { - return $this->belongsTo(Track::class); - } - - public function completions() - { - return $this->hasMany(Completion::class); - } - - public function suggestedResources() - { - return $this->hasMany(SuggestedResource::class); - } - - public function complete(Completable $completable) - { - return $this->completions()->create([ - 'completable_id' => $completable->getKey(), - 'completable_type' => $completable->getMorphClass(), - ]); - } - - public function undoComplete($completable) - { - return $this->completions()->where([ - 'completable_id' => $completable->getKey(), - 'completable_type' => $completable->getMorphClass(), - ])->delete(); - } - - public function moduleCompletions() - { - return $this->completions()->modules(); - } - - public function resourceCompletions() - { - return $this->completions()->resources(); - } - - public function skillCompletions() - { - return $this->completions()->skills(); - } - - public function isAtLeastEditor() - { - return in_array($this->role, ['editor', 'admin']); - } - - public function isAdmin() - { - return in_array($this->role, ['admin']); - } - - public function hasTrack() - { - return ! is_null($this->track_id); - } - - public function getInitialsAttribute() - { - return collect(explode(' ', $this->name)) - ->reduce(function ($initials, $word) { - return $initials .= strtoupper($word[0]); - }); - } - - public function getFirstNameAttribute() - { - return explode(' ', $this->name)[0]; - } - - public function getProfilePictureAttribute() - { - return $this->github_avatar ?? 'https://www.gravatar.com/avatar/' . md5(strtolower($this->email)) . '?d=mp'; - } - - public function sendPasswordResetNotification($token) - { - $this->notify(new ResetPassword($token)); - } + use HasFactory; + use Notifiable; + + protected $guarded = [ + 'id', + ]; + + protected $hidden = [ + 'password', 'remember_token', 'github_token', + ]; + + protected $casts = [ + 'email_verified_at' => 'datetime', + 'preferences' => 'object', + 'is_subscriber' => 'boolean', + ]; + + public function track() + { + return $this->belongsTo(Track::class); + } + + public function completions() + { + return $this->hasMany(Completion::class); + } + + public function suggestedResources() + { + return $this->hasMany(SuggestedResource::class); + } + + public function complete(Completable $completable) + { + return $this->completions()->create([ + 'completable_id' => $completable->getKey(), + 'completable_type' => $completable->getMorphClass(), + ]); + } + + public function undoComplete($completable) + { + return $this->completions()->where([ + 'completable_id' => $completable->getKey(), + 'completable_type' => $completable->getMorphClass(), + ])->delete(); + } + + public function moduleCompletions() + { + return $this->completions()->modules(); + } + + public function resourceCompletions() + { + return $this->completions()->resources(); + } + + public function skillCompletions() + { + return $this->completions()->skills(); + } + + public function isAtLeastEditor() + { + return in_array($this->role, ['editor', 'admin']); + } + + public function isAdmin() + { + return in_array($this->role, ['admin']); + } + + public function hasTrack() + { + return !is_null($this->track_id); + } + + public function getInitialsAttribute() + { + return collect(explode(' ', $this->name)) + ->reduce(function ($initials, $word) { + return $initials .= strtoupper($word[0]); + }); + } + + public function getFirstNameAttribute() + { + return explode(' ', $this->name)[0]; + } + + public function getProfilePictureAttribute() + { + return $this->github_avatar ?? 'https://www.gravatar.com/avatar/' . md5(strtolower($this->email)) . '?d=mp'; + } + + public function sendPasswordResetNotification($token) + { + $this->notify(new ResetPassword($token)); + } } diff --git a/database/seeders/ContentSeeder.php b/database/seeders/ContentSeeder.php index 979bb611..d0102d00 100644 --- a/database/seeders/ContentSeeder.php +++ b/database/seeders/ContentSeeder.php @@ -8,27 +8,33 @@ class ContentSeeder extends Seeder { - use CanSeedProdData; + use CanSeedProdData; - public function run(): void - { - User::factory()->create([ - 'email' => 'testuser@tighten.co', - 'password' => bcrypt('password'), - 'role' => 'admin', - ]); + public function run(): void + { + User::factory()->create([ + 'email' => 'testadmin@tighten.co', + 'password' => bcrypt('password'), + 'role' => 'admin', + ]); - $seedsDirectory = config('seeder.directory', 'database/json'); + User::factory()->create([ + 'email' => 'testuser@tighten.co', + 'password' => bcrypt('password'), + 'role' => 'user', + ]); - $seeds = $this->getSeedFiles($seedsDirectory); + $seedsDirectory = config('seeder.directory', 'database/json'); - if (! $seeds) { - $this->command->warn('The directory ' . $seedsDirectory . ' is empty.'); - $this->command->line('You can create seeds from the production database by calling php artisan generate:seeds-from-db --all'); + $seeds = $this->getSeedFiles($seedsDirectory); - return; - } + if (!$seeds) { + $this->command->warn('The directory ' . $seedsDirectory . ' is empty.'); + $this->command->line('You can create seeds from the production database by calling php artisan generate:seeds-from-db --all'); - $this->seed($this->command, $seeds); - } + return; + } + + $this->seed($this->command, $seeds); + } } diff --git a/resources/views/emails/resource-digest.blade.php b/resources/views/emails/resource-digest.blade.php index 8ebd7aee..38bd8f35 100644 --- a/resources/views/emails/resource-digest.blade.php +++ b/resources/views/emails/resource-digest.blade.php @@ -11,9 +11,3 @@ ### Your friends at {{ config('app.name') }} @endcomponent - -{{-- @foreach ($resources as $resource) -
  • -{{ $resource['name'] }} -
  • -@endforeach --}} diff --git a/resources/views/preferences.blade.php b/resources/views/preferences.blade.php index bb174d6e..6916b640 100644 --- a/resources/views/preferences.blade.php +++ b/resources/views/preferences.blade.php @@ -136,16 +136,62 @@ class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none tex +
    +

    {{ __('Email Preferences') }}

    +
    + +
    +

    + {{ __('Choose whether or not you\'d like to receive monthly updates listing new resources.') }} +

    + +
    +
    + + +
    + + +
    + + + +
    +
    + + @error($localePreferenceKey)) +

    + {{ $errors->first($localePreferenceKey) }} +

    + @enderror +
    +
    +
    +

    {{ __('Background Experience') }}

    -

    +

    {{ __('Track your progress in modules based on your current background experience.') }}

    -
    +