diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 8627586e..88fc5943 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -13,7 +13,7 @@ jobs: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.2.0 + uses: dependabot/fetch-metadata@v2.3.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Auto-merge Dependabot PRs for semver-minor updates diff --git a/app/Actions/Article/CreateArticleAction.php b/app/Actions/Article/CreateArticleAction.php index e2457168..3c442ef5 100644 --- a/app/Actions/Article/CreateArticleAction.php +++ b/app/Actions/Article/CreateArticleAction.php @@ -27,6 +27,25 @@ public function execute(ArticleData $articleData): Article ); } + $user = Auth::user(); + + if ($user->isAdmin() || $user->isModerator()) { + $articleData->published_at = new Carbon( + time: today(), + timezone: config('app.timezone') + ); + + $articleData->submitted_at = new Carbon( + time: $articleData->submitted_at, + timezone: config('app.timezone') + ); + + $articleData->approved_at = new Carbon( + time: today(), + timezone: config('app.timezone') + ); + } + // @phpstan-ignore-next-line return Article::query()->create([ 'title' => $articleData->title, @@ -34,8 +53,9 @@ public function execute(ArticleData $articleData): Article 'body' => $articleData->body, 'published_at' => $articleData->published_at, 'submitted_at' => $articleData->submitted_at, + 'approved_at' => $articleData->approved_at, 'canonical_url' => $articleData->canonical_url, - 'user_id' => Auth::id(), + 'user_id' => $user->id, ]); } } diff --git a/app/Actions/Article/DeclineArticleAction.php b/app/Actions/Article/DeclineArticleAction.php new file mode 100644 index 00000000..12d75316 --- /dev/null +++ b/app/Actions/Article/DeclineArticleAction.php @@ -0,0 +1,31 @@ +update([ + 'declined_at' => Carbon::now(), + 'reason' => $reason, + 'submitted_at' => null, + ]); + + $article->user->notify(new ArticleDeclinedNotification($article)); + + $article->refresh(); + + return $article; + }); + } +} diff --git a/app/Actions/Article/UpdateArticleAction.php b/app/Actions/Article/UpdateArticleAction.php index ddb508de..e645bf42 100644 --- a/app/Actions/Article/UpdateArticleAction.php +++ b/app/Actions/Article/UpdateArticleAction.php @@ -31,6 +31,10 @@ public function execute(ArticleData $articleData, Article $article): Article ); } + if ($articleData->declined_at) { + $articleData->declined_at = null; + } + $article->update($articleData->toArray()); $article->refresh(); diff --git a/app/Data/ArticleData.php b/app/Data/ArticleData.php index fca6e491..9620e2ba 100644 --- a/app/Data/ArticleData.php +++ b/app/Data/ArticleData.php @@ -17,5 +17,7 @@ public function __construct( public ?string $canonical_url = null, public ?Carbon $published_at = null, public ?Carbon $submitted_at = null, + public ?Carbon $declined_at = null, + public ?Carbon $approved_at = null, ) {} } diff --git a/app/Filament/Resources/ArticleResource.php b/app/Filament/Resources/ArticleResource.php index a462240a..83e9e2a0 100644 --- a/app/Filament/Resources/ArticleResource.php +++ b/app/Filament/Resources/ArticleResource.php @@ -5,10 +5,13 @@ namespace App\Filament\Resources; use App\Actions\Article\ApprovedArticleAction; +use App\Actions\Article\DeclineArticleAction; use App\Filament\Resources\ArticleResource\Pages; use App\Models\Article; use Awcodes\FilamentBadgeableColumn\Components\Badge; use Awcodes\FilamentBadgeableColumn\Components\BadgeableColumn; +use Filament\Forms\Components\Textarea; +use Filament\Notifications\Notification; use Filament\Resources\Resource; use Filament\Support\Enums\MaxWidth; use Filament\Tables; @@ -99,7 +102,6 @@ public static function table(Table $table): Table return ''; }) - ->searchable() ->sortable(), ]) ->actions([ @@ -123,15 +125,27 @@ public static function table(Table $table): Table ->label('Décliner') ->icon('heroicon-s-x-mark') ->color('warning') - ->modalHeading(__('Voulez vous décliner cet article')) - ->successNotificationTitle(__('Opération effectuée avec succès')) + ->form([ + Textarea::make('reason') + ->label(__('Raison du refus')) + ->maxLength(255) + ->required(), + ]) + ->modalHeading('Décliner l\'article') + ->modalDescription('Veuillez fournir une raison détaillée pour le refus de cet article. L\'auteur recevra cette explication.') + ->successNotificationTitle('Article décliné avec succès') ->requiresConfirmation() ->modalIcon('heroicon-s-x-mark') - ->action(function ($record): void { + ->action(function (array $data, Article $record): void { Gate::authorize('decline', $record); - $record->declined_at = now(); - $record->save(); + app(DeclineArticleAction::class)->execute($data['reason'], $record); + + Notification::make() + ->title('Article décliné') + ->body('L\'auteur a été notifié de la raison du refus.') + ->success() + ->send(); }), Tables\Actions\Action::make('show') ->icon('untitledui-eye') diff --git a/app/Filament/Resources/ArticleResource/Pages/ListArticles.php b/app/Filament/Resources/ArticleResource/Pages/ListArticles.php index a793cae9..f8be7594 100644 --- a/app/Filament/Resources/ArticleResource/Pages/ListArticles.php +++ b/app/Filament/Resources/ArticleResource/Pages/ListArticles.php @@ -7,6 +7,7 @@ use App\Filament\Resources\ArticleResource; use App\Models\Article; use Closure; +use Filament\Resources\Components\Tab; use Filament\Resources\Pages\ListRecords; final class ListArticles extends ListRecords @@ -17,4 +18,13 @@ public function isTableRecordSelectable(): Closure { return fn (Article $record): bool => $record->isNotPublished(); } + + public function getTabs(): array + { + return [ + 'En attente' => Tab::make()->query(fn ($query) => $query->awaitingApproval()), + 'Apprové' => Tab::make()->query(fn ($query) => $query->published()), + 'Décliné' => Tab::make()->query(fn ($query) => $query->declined()), + ]; + } } diff --git a/app/Livewire/Components/SponsorSubscription.php b/app/Livewire/Components/SponsorSubscription.php index 9eb2f9f0..4c0a0804 100644 --- a/app/Livewire/Components/SponsorSubscription.php +++ b/app/Livewire/Components/SponsorSubscription.php @@ -134,7 +134,7 @@ public function submit(): void 'status' => $payload->transaction->status, 'transaction_reference' => $payload->transaction->reference, 'user_id' => $user->id, - 'fees' => $payload->transaction->fee, + 'fees' => empty(get_object_vars($payload->transaction->fees)) ? 0 : $payload->transaction->fees->fee, 'type' => TransactionType::ONETIME->value, 'metadata' => [ 'currency' => $payload->transaction->currency, diff --git a/app/Models/Article.php b/app/Models/Article.php index 32c697b6..8616bc63 100644 --- a/app/Models/Article.php +++ b/app/Models/Article.php @@ -32,6 +32,7 @@ * @property bool $is_pinned * @property int $is_sponsored * @property string | null $canonical_url + * @property string | null $reason * @property int | null $tweet_id * @property int $user_id * @property string | null $locale @@ -63,6 +64,7 @@ final class Article extends Model implements HasMedia, ReactableInterface, Sitem 'body', 'slug', 'canonical_url', + 'reason', 'show_toc', 'is_pinned', 'user_id', diff --git a/app/Notifications/ArticleDeclinedNotification.php b/app/Notifications/ArticleDeclinedNotification.php new file mode 100644 index 00000000..d6148720 --- /dev/null +++ b/app/Notifications/ArticleDeclinedNotification.php @@ -0,0 +1,41 @@ +subject(__('emails/article.article_declined.subject')) + ->markdown('emails.article_declined', ['article' => $this->article]); + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'article' => $this->article, + 'owner' => $this->article->user->name, + 'email' => $this->article->user->email, + ]; + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index e7e51e32..1430832a 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -9,18 +9,15 @@ use App\Events\CommentWasAdded; use App\Events\ReplyWasCreated; use App\Events\SponsoringPaymentInitialize; -use App\Events\ThreadWasCreated; use App\Events\UserBannedEvent; use App\Events\UserUnbannedEvent; // use App\Listeners\SendCompanyEmailVerificationNotification; use App\Listeners\NotifyMentionedUsers; -use App\Listeners\PostNewThreadNotification; use App\Listeners\SendBanNotificationListener; use App\Listeners\SendNewArticleNotification; use App\Listeners\SendNewCommentNotification; // use App\Listeners\SendWelcomeCompanyNotification; use App\Listeners\SendNewReplyNotification; -use App\Listeners\SendNewThreadNotification; use App\Listeners\SendPaymentNotification; use App\Listeners\SendUnbanNotificationListener; use App\Listeners\SendWelcomeMailNotification; @@ -42,10 +39,6 @@ final class EventServiceProvider extends ServiceProvider SendNewReplyNotification::class, NotifyMentionedUsers::class, ], - ThreadWasCreated::class => [ - SendNewThreadNotification::class, - PostNewThreadNotification::class, - ], ArticleWasSubmittedForApproval::class => [ SendNewArticleNotification::class, ], diff --git a/composer.json b/composer.json index 630d4607..6f7932fa 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "gehrisandro/tailwind-merge-laravel": "^1.2", "graham-campbell/markdown": "^15.2", "guzzlehttp/guzzle": "^7.7.0", + "internachi/modular": "^2.3", "jenssegers/agent": "^2.6.4", "laravel-notification-channels/telegram": "^5.0", "laravel-notification-channels/twitter": "^8.1", diff --git a/composer.lock b/composer.lock index 1f31d4df..2ddd4e9d 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": "4c716d8363d3d8066535ca12060d6e28", + "content-hash": "9e2c8137faec35e0ddbd84e450feab24", "packages": [ { "name": "abraham/twitteroauth", @@ -1578,6 +1578,341 @@ ], "time": "2025-01-08T16:17:16+00:00" }, + { + "name": "composer/class-map-generator", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/composer/class-map-generator.git", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/134b705ddb0025d397d8318a75825fe3c9d1da34", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34", + "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.12 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpunit/phpunit": "^8", + "symfony/filesystem": "^5.4 || ^6" + }, + "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.6.1" + }, + "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": "2025-03-24T13:50:44+00:00" + }, + { + "name": "composer/composer", + "version": "2.8.6", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "937c775a644bd7d2c3dfbb352747488463a6e673" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/937c775a644bd7d2c3dfbb352747488463a6e673", + "reference": "937c775a644bd7d2c3dfbb352747488463a6e673", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.5", + "composer/class-map-generator": "^1.4.0", + "composer/metadata-minifier": "^1.0", + "composer/pcre": "^2.2 || ^3.2", + "composer/semver": "^3.3", + "composer/spdx-licenses": "^1.5.7", + "composer/xdebug-handler": "^2.0.2 || ^3.0.3", + "justinrainbow/json-schema": "^5.3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "react/promise": "^2.11 || ^3.2", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.2", + "seld/signal-handler": "^2.0", + "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/polyfill-php73": "^1.24", + "symfony/polyfill-php80": "^1.24", + "symfony/polyfill-php81": "^1.24", + "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3" + }, + "require-dev": { + "phpstan/phpstan": "^1.11.8", + "phpstan/phpstan-deprecation-rules": "^1.2.0", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpstan/phpstan-symfony": "^1.4.0", + "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "phpstan/rules.neon" + ] + }, + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "https://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/composer/issues", + "security": "https://github.com/composer/composer/security/policy", + "source": "https://github.com/composer/composer/tree/2.8.6" + }, + "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": "2025-02-25T12:03:50+00:00" + }, + { + "name": "composer/metadata-minifier", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/metadata-minifier.git", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2", + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\MetadataMinifier\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Small utility library that handles metadata minification and expansion.", + "keywords": [ + "composer", + "compression" + ], + "support": { + "issues": "https://github.com/composer/metadata-minifier/issues", + "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" + }, + "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": "2021-04-07T13:37:33+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "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.3.2" + }, + "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-11-12T16:29:46+00:00" + }, { "name": "composer/semver", "version": "3.4.3", @@ -1659,6 +1994,152 @@ ], "time": "2024-09-19T14:15:21+00:00" }, + { + "name": "composer/spdx-licenses", + "version": "1.5.8", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", + "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/spdx-licenses/issues", + "source": "https://github.com/composer/spdx-licenses/tree/1.5.8" + }, + "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": "2023-11-20T07:44:33+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "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-06T16:37:16+00:00" + }, { "name": "cyrildewit/eloquent-viewable", "version": "v7.0.3", @@ -4030,6 +4511,76 @@ ], "time": "2023-12-03T19:50:20+00:00" }, + { + "name": "internachi/modular", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/InterNACHI/modular.git", + "reference": "e7ff4074001d3df50d9ce877385c55d88e254484" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/InterNACHI/modular/zipball/e7ff4074001d3df50d9ce877385c55d88e254484", + "reference": "e7ff4074001d3df50d9ce877385c55d88e254484", + "shasum": "" + }, + "require": { + "composer/composer": "^2.1", + "ext-dom": "*", + "ext-simplexml": "*", + "illuminate/support": "^9|^10|^11|^12|13.x-dev|dev-master|dev-main", + "php": ">=8.0" + }, + "require-dev": { + "ext-json": "*", + "friendsofphp/php-cs-fixer": "^3.14", + "livewire/livewire": "^2.5|^3.0", + "mockery/mockery": "^1.5", + "orchestra/testbench": "^7.52|^8.33|^9.11|^10.0|dev-master|dev-main", + "phpunit/phpunit": "^9.5|^10.5|^11.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Modules": "InterNACHI\\Modular\\Support\\Facades\\Modules" + }, + "providers": [ + "InterNACHI\\Modular\\Support\\ModularServiceProvider", + "InterNACHI\\Modular\\Support\\ModularizedCommandsServiceProvider", + "InterNACHI\\Modular\\Support\\ModularEventServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "InterNACHI\\Modular\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Morrell", + "homepage": "http://www.cmorrell.com" + } + ], + "description": "Modularize your Laravel apps", + "keywords": [ + "laravel", + "modular", + "module", + "modules" + ], + "support": { + "issues": "https://github.com/InterNACHI/modular/issues", + "source": "https://github.com/InterNACHI/modular/tree/2.3.0" + }, + "time": "2025-02-28T22:15:39+00:00" + }, { "name": "jaybizzle/crawler-detect", "version": "v1.3.0", @@ -4183,7 +4734,76 @@ }, "autoload": { "psr-4": { - "Jenssegers\\Agent\\": "src/" + "Jenssegers\\Agent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jens Segers", + "homepage": "https://jenssegers.com" + } + ], + "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", + "homepage": "https://github.com/jenssegers/agent", + "keywords": [ + "Agent", + "browser", + "desktop", + "laravel", + "mobile", + "platform", + "user agent", + "useragent" + ], + "support": { + "issues": "https://github.com/jenssegers/agent/issues", + "source": "https://github.com/jenssegers/agent/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/jenssegers", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/jenssegers/agent", + "type": "tidelift" + } + ], + "time": "2020-06-13T08:05:20+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4192,37 +4812,33 @@ ], "authors": [ { - "name": "Jens Segers", - "homepage": "https://jenssegers.com" + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" } ], - "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", - "homepage": "https://github.com/jenssegers/agent", + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", "keywords": [ - "Agent", - "browser", - "desktop", - "laravel", - "mobile", - "platform", - "user agent", - "useragent" + "json", + "schema" ], "support": { - "issues": "https://github.com/jenssegers/agent/issues", - "source": "https://github.com/jenssegers/agent/tree/v2.6.4" + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" }, - "funding": [ - { - "url": "https://github.com/jenssegers", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/jenssegers/agent", - "type": "tidelift" - } - ], - "time": "2020-06-13T08:05:20+00:00" + "time": "2024-07-06T21:00:26+00:00" }, { "name": "kelunik/certificate", @@ -8951,6 +9567,79 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, { "name": "revolt/event-loop", "version": "v1.0.6", @@ -9007,68 +9696,246 @@ "email": "me@kelunik.com" } ], - "description": "Rock-solid event loop for concurrent PHP applications.", + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + }, + "time": "2023-11-30T05:34:44+00:00" + }, + { + "name": "ryangjchandler/blade-capture-directive", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/ryangjchandler/blade-capture-directive.git", + "reference": "cb6f58663d97f17bece176295240b740835e14f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/cb6f58663d97f17bece176295240b740835e14f1", + "reference": "cb6f58663d97f17bece176295240b740835e14f1", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0|^11.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.9.2" + }, + "require-dev": { + "nunomaduro/collision": "^7.0|^8.0", + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^8.0|^9.0", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^10.0", + "spatie/laravel-ray": "^1.26" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "BladeCaptureDirective": "RyanChandler\\BladeCaptureDirective\\Facades\\BladeCaptureDirective" + }, + "providers": [ + "RyanChandler\\BladeCaptureDirective\\BladeCaptureDirectiveServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "RyanChandler\\BladeCaptureDirective\\": "src", + "RyanChandler\\BladeCaptureDirective\\Database\\Factories\\": "database/factories" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ryan Chandler", + "email": "support@ryangjchandler.co.uk", + "role": "Developer" + } + ], + "description": "Create inline partials in your Blade templates with ease.", + "homepage": "https://github.com/ryangjchandler/blade-capture-directive", + "keywords": [ + "blade-capture-directive", + "laravel", + "ryangjchandler" + ], + "support": { + "issues": "https://github.com/ryangjchandler/blade-capture-directive/issues", + "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.0.0" + }, + "funding": [ + { + "url": "https://github.com/ryangjchandler", + "type": "github" + } + ], + "time": "2024-02-26T18:08:49+00:00" + }, + { + "name": "seld/jsonlint", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "support": { + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2024-07-11T14:55:45+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", + "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", "keywords": [ - "async", - "asynchronous", - "concurrency", - "event", - "event-loop", - "non-blocking", - "scheduler" + "phar" ], "support": { - "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + "issues": "https://github.com/Seldaek/phar-utils/issues", + "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1" }, - "time": "2023-11-30T05:34:44+00:00" + "time": "2022-08-31T10:31:18+00:00" }, { - "name": "ryangjchandler/blade-capture-directive", - "version": "v1.0.0", + "name": "seld/signal-handler", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/ryangjchandler/blade-capture-directive.git", - "reference": "cb6f58663d97f17bece176295240b740835e14f1" + "url": "https://github.com/Seldaek/signal-handler.git", + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/cb6f58663d97f17bece176295240b740835e14f1", - "reference": "cb6f58663d97f17bece176295240b740835e14f1", + "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", "shasum": "" }, "require": { - "illuminate/contracts": "^10.0|^11.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9.2" + "php": ">=7.2.0" }, "require-dev": { - "nunomaduro/collision": "^7.0|^8.0", - "nunomaduro/larastan": "^2.0", - "orchestra/testbench": "^8.0|^9.0", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", - "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1", "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.0", - "spatie/laravel-ray": "^1.26" + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^7.5.20 || ^8.5.23", + "psr/log": "^1 || ^2 || ^3" }, "type": "library", "extra": { - "laravel": { - "aliases": { - "BladeCaptureDirective": "RyanChandler\\BladeCaptureDirective\\Facades\\BladeCaptureDirective" - }, - "providers": [ - "RyanChandler\\BladeCaptureDirective\\BladeCaptureDirectiveServiceProvider" - ] + "branch-alias": { + "dev-main": "2.x-dev" } }, "autoload": { "psr-4": { - "RyanChandler\\BladeCaptureDirective\\": "src", - "RyanChandler\\BladeCaptureDirective\\Database\\Factories\\": "database/factories" + "Seld\\Signal\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -9077,29 +9944,24 @@ ], "authors": [ { - "name": "Ryan Chandler", - "email": "support@ryangjchandler.co.uk", - "role": "Developer" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "Create inline partials in your Blade templates with ease.", - "homepage": "https://github.com/ryangjchandler/blade-capture-directive", + "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development", "keywords": [ - "blade-capture-directive", - "laravel", - "ryangjchandler" + "posix", + "sigint", + "signal", + "sigterm", + "unix" ], "support": { - "issues": "https://github.com/ryangjchandler/blade-capture-directive/issues", - "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.0.0" + "issues": "https://github.com/Seldaek/signal-handler/issues", + "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2" }, - "funding": [ - { - "url": "https://github.com/ryangjchandler", - "type": "github" - } - ], - "time": "2024-02-26T18:08:49+00:00" + "time": "2023-09-03T09:24:00+00:00" }, { "name": "sentry/sentry", @@ -11066,6 +11928,72 @@ ], "time": "2024-09-25T14:20:29+00:00" }, + { + "name": "symfony/filesystem", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.2.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-10-25T15:15:23+00:00" + }, { "name": "symfony/finder", "version": "v7.2.2", @@ -12265,6 +13193,82 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php73", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.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-09-09T11:45:10+00:00" + }, { "name": "symfony/polyfill-php80", "version": "v1.31.0", @@ -12345,6 +13349,82 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php81", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.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-09-09T11:45:10+00:00" + }, { "name": "symfony/polyfill-php83", "version": "v1.31.0", @@ -17374,7 +18454,7 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -17382,6 +18462,6 @@ "ext-fileinfo": "*", "ext-json": "*" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/config/app-modules.php b/config/app-modules.php new file mode 100644 index 00000000..33a994a1 --- /dev/null +++ b/config/app-modules.php @@ -0,0 +1,105 @@ + 'Laravelcm', + + /* + |-------------------------------------------------------------------------- + | Composer "Vendor" Name + |-------------------------------------------------------------------------- + | + | This is the prefix used for your composer.json file. This should be the + | kebab-case version of your module namespace (if left null, we will + | generate the kebab-case version for you). + | + */ + + 'modules_vendor' => 'laravelcm', + + /* + |-------------------------------------------------------------------------- + | Modules Directory + |-------------------------------------------------------------------------- + | + | If you want to install modules in a custom directory, you can do so here. + | Keeping the default `app-modules/` directory is highly recommended, + | though, as it keeps your modules near the rest of your application code + | in an alpha-sorted directory listing. + | + */ + + 'modules_directory' => 'app-modules', + + /* + |-------------------------------------------------------------------------- + | Base Test Case + |-------------------------------------------------------------------------- + | + | This is the base TestCase class name that auto-generated Tests should + | extend. By default, it assumes the default \Tests\TestCase exists. + | + */ + + 'tests_base' => 'Tests\TestCase', + + /* + |-------------------------------------------------------------------------- + | Custom Stubs + |-------------------------------------------------------------------------- + | + | If you would like to use your own custom stubs for new modules, you can + | configure those here. This should be an array where the key is the path + | relative to the module and the value is the absolute path to the stub + | stub file. Destination paths and contents support placeholders. See the + | README.md file for more information. + | + | For example: + | + | 'stubs' => [ + | 'src/Providers/StubClassNamePrefixServiceProvider.php' => base_path('stubs/app-modules/ServiceProvider.php'), + | ], + */ + + 'stubs' => [ + 'composer.json' => base_path('stubs/app-modules/composer-stub.json'), + 'src/Providers/StubClassNamePrefixServiceProvider.php' => base_path('stubs/app-modules/app/ServiceProvider.php'), + 'src/StubClassNamePrefixPlugin.php' => base_path('stubs/app-modules/app/Plugin.php'), + 'src/Models/.gitkeep' => base_path('stubs/app-modules/.gitkeep'), + 'tests/.gitkeep' => base_path('stubs/app-modules/.gitkeep'), + 'database/factories/.gitkeep' => base_path('stubs/app-modules/.gitkeep'), + 'database/migrations/.gitkeep' => base_path('stubs/app-modules/.gitkeep'), + 'database/seeders/.gitkeep' => base_path('stubs/app-modules/.gitkeep'), + ], + + /* + |-------------------------------------------------------------------------- + | Custom override of event discovery + |-------------------------------------------------------------------------- + | + | This is a custom override of the event discovery feature. If you want to + | disable event discovery, set this to false. If you want to enable event + | discovery, set this to true. We will still check the app namespace for + | the presence of event discovery. + */ + + 'should_discover_events' => true, +]; diff --git a/database/migrations/2025_02_20_112613_add_reason_field_to_articles_table.php b/database/migrations/2025_02_20_112613_add_reason_field_to_articles_table.php new file mode 100644 index 00000000..16b8cd48 --- /dev/null +++ b/database/migrations/2025_02_20_112613_add_reason_field_to_articles_table.php @@ -0,0 +1,17 @@ +string('reason')->nullable()->after('canonical_url'); + }); + } +}; diff --git a/lang/en/emails/article.php b/lang/en/emails/article.php new file mode 100644 index 00000000..6c406acc --- /dev/null +++ b/lang/en/emails/article.php @@ -0,0 +1,20 @@ + [ + 'subject' => 'Your article has been declined', + 'head' => 'Your article :title has been declined for the following reason:', + 'recommandation_body' => 'Don\'t be discouraged! You can:', + 'recommandation_1' => '1. Review your article and the reason for the decline', + 'recommandation_2' => '2. Make the necessary changes', + 'recommandation_3' => '3. Resubmit your article once the corrections are made', + 'help' => 'Our team is here to help you improve your content.', + 'closing' => 'Best regards,', + 'team' => 'The Laravel Cameroon Team', + 'button_update_article' => 'Edit my article', + ], + +]; diff --git a/lang/fr/emails/article.php b/lang/fr/emails/article.php new file mode 100644 index 00000000..1c612c56 --- /dev/null +++ b/lang/fr/emails/article.php @@ -0,0 +1,20 @@ + [ + 'subject' => 'Votre article a été décliné', + 'head' => 'Votre article :title a été décliné pour la raison suivante :', + 'recommandation_body' => 'Ne vous découragez pas ! Vous pouvez :', + 'recommandation_1' => '1. Consulter votre article et la raison du refus', + 'recommandation_2' => '2. Apporter les modifications nécessaires', + 'recommandation_3' => '3. Re-soumettre votre article une fois les corrections effectuées', + 'help' => 'Notre équipe est là pour vous aider à améliorer votre contenu.', + 'closing' => 'Cordialement,', + 'team' => 'L\'équipe Laravel Cameroun', + 'button_update_article' => 'Modifier mon article', + ], + +]; diff --git a/resources/views/emails/article_declined.blade.php b/resources/views/emails/article_declined.blade.php new file mode 100644 index 00000000..e62d4ea3 --- /dev/null +++ b/resources/views/emails/article_declined.blade.php @@ -0,0 +1,28 @@ + + + + +{{ __('emails/article.article_declined.head', ['title' => $article->title]) }} + +{{ $article->reason }} + +{{ __('emails/article.article_declined.recommandation_body') }} + +{{ __('emails/article.article_declined.recommandation_1') }} +{{ __('emails/article.article_declined.recommandation_2') }} +{{ __('emails/article.article_declined.recommandation_3') }} + + +{{ __('emails/article.article_declined.button_update_article') }} + + +{{ __('emails/article.article_declined.help') }} + + + +

+ {{ __('emails/article.article_declined.closing') }}
+ {{ __('emails/article.article_declined.team') }} +

+ +
diff --git a/stubs/app-modules/.gitkeep b/stubs/app-modules/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/stubs/app-modules/app/Plugin.php b/stubs/app-modules/app/Plugin.php new file mode 100644 index 00000000..fbfda925 --- /dev/null +++ b/stubs/app-modules/app/Plugin.php @@ -0,0 +1,26 @@ +discoverResources( + in: __DIR__.'/Filament/Resources', + for: 'Laravelcm\\StubClassNamePrefix\\Filament\\Resources' + ); + } + + public function boot(Panel $panel): void {} +} diff --git a/stubs/app-modules/app/ServiceProvider.php b/stubs/app-modules/app/ServiceProvider.php new file mode 100644 index 00000000..19b3c8e3 --- /dev/null +++ b/stubs/app-modules/app/ServiceProvider.php @@ -0,0 +1,23 @@ + $panel->getId() !== 'admin' || $panel->plugin(new StubClassNamePrefixPlugin)); + } + + public function boot(): void + { + Relation::morphMap([]); + } +} diff --git a/stubs/app-modules/composer-stub.json b/stubs/app-modules/composer-stub.json new file mode 100644 index 00000000..906e86eb --- /dev/null +++ b/stubs/app-modules/composer-stub.json @@ -0,0 +1,26 @@ +{ + "name": "StubComposerName", + "description": "Module StubComposerName for Laravel.cm", + "type": "library", + "version": "1.0", + "license": "proprietary", + "require": { + "filament/filament": "^3.2" + }, + "autoload": { + "psr-4": { + "Laravelcm\\StubClassNamePrefix\\": "src/", + "Laravelcm\\StubClassNamePrefix\\Tests\\": "tests/", + "Laravelcm\\StubClassNamePrefix\\Database\\Factories\\": "database/factories/", + "Laravelcm\\StubClassNamePrefix\\Database\\Seeders\\": "database/seeders/" + } + }, + "minimum-stability": "stable", + "extra": { + "laravel": { + "providers": [ + "Laravelcm\\StubClassNamePrefix\\Providers\\StubClassNamePrefixServiceProvider" + ] + } + } +} diff --git a/tests/Feature/Filament/ArticleResourceTest.php b/tests/Feature/Filament/ArticleResourceTest.php index 2d02d951..326af861 100644 --- a/tests/Feature/Filament/ArticleResourceTest.php +++ b/tests/Feature/Filament/ArticleResourceTest.php @@ -35,11 +35,8 @@ $article->refresh(); - expect($article->approved_at) - ->not() - ->toBe(null) - ->and($article->declined_at) - ->toBe(null); + expect($article->approved_at)->toBeInstanceOf(\Carbon\Carbon::class) + ->and($article->declined_at)->toBeNull(); Livewire::test(ArticleResource\Pages\ListArticles::class) ->assertTableActionHidden('approved', $article) @@ -50,15 +47,14 @@ $article = $this->articles->first(); Livewire::test(ArticleResource\Pages\ListArticles::class) - ->callTableAction('declined', $article); + ->callTableAction('declined', $article, data: [ + 'reason' => 'Ce contenu ne respecte pas nos règles éditoriales.', + ]); $article->refresh(); - expect($article->declined_at) - ->not - ->toBe(null) - ->and($article->approved_at) - ->toBe(null); + expect($article->declined_at)->toBeInstanceOf(\Carbon\Carbon::class) + ->and($article->approved_at)->toBeNull(); Livewire::test(ArticleResource\Pages\ListArticles::class) ->assertTableActionHidden('approved', $article)