From a50ca7f13371397ce7c881b42cc92cdb6133edb4 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Thu, 23 Apr 2026 16:57:59 +0200 Subject: [PATCH 1/9] feat: :sparkles: add job to clean activity logs older than one year #96 --- app/Console/Commands/CleanOldActivities.php | 46 ++++++++++++++++++++ app/Console/Kernel.php | 2 + app/Jobs/CleanOldActivities.php | 48 +++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 app/Console/Commands/CleanOldActivities.php create mode 100644 app/Jobs/CleanOldActivities.php diff --git a/app/Console/Commands/CleanOldActivities.php b/app/Console/Commands/CleanOldActivities.php new file mode 100644 index 0000000..08c41a3 --- /dev/null +++ b/app/Console/Commands/CleanOldActivities.php @@ -0,0 +1,46 @@ +activity logs"; + $this->components->info("Cleaning {$messageTitle}..."); + + $force = $this->option('force'); + + if ($force && !$this->confirm('Are you sure you want to delete all activity logs ? This cannot be undone.')) { + $this->components->error("Clean of {$messageTitle} aborted."); + return; + } + + (new CleanOldActivitiesJob(force: $force))->handle(); + + $messageContent = $force ? "All {$messageTitle} deleted" : "Old {$messageTitle} cleaned"; + $this->components->success($messageContent); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 5048cf2..f90030b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use App\Jobs\CleanOldActivities; use App\Jobs\UpdatePlanificatedStatus; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -16,6 +17,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule): void { + $schedule->job(CleanOldActivities::class)->daily(); $schedule->job(UpdatePlanificatedStatus::class)->everyFiveMinutes(); } diff --git a/app/Jobs/CleanOldActivities.php b/app/Jobs/CleanOldActivities.php new file mode 100644 index 0000000..83ce6a8 --- /dev/null +++ b/app/Jobs/CleanOldActivities.php @@ -0,0 +1,48 @@ +force) { + $query->where('created_at', '<', Carbon::now()->subYear()); + } + + $query->cursor()->each(fn($model) => $model->delete()); + } +} From e6c0fe65e27fa81531fc25568ac3fa62a4b7a539 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 11:08:16 +0200 Subject: [PATCH 2/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20save=20only=20updated?= =?UTF-8?q?=20models=20in=20planificated=20status=20job?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Jobs/UpdatePlanificatedStatus.php | 47 +++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/app/Jobs/UpdatePlanificatedStatus.php b/app/Jobs/UpdatePlanificatedStatus.php index b19314c..8149286 100644 --- a/app/Jobs/UpdatePlanificatedStatus.php +++ b/app/Jobs/UpdatePlanificatedStatus.php @@ -20,37 +20,34 @@ class UpdatePlanificatedStatus */ public function handle(): void { - // Set all models to apply status modifications. collect([News::class, Strip::class]) ->each(function (string $model) { - // Get all published model with an unpublish_at date passed. - /** @var \Illuminate\Database\Eloquent\Collection $modelListToUnPublish */ - $modelListToUnPublish = $model::query() + /** @var \Illuminate\Database\Eloquent\Collection */ + $modelListToPublish = $model::query() + ->whereNotNull('publish_at') + ->where('publish_at', '<=', Carbon::now()) + ->where(function ($query) { + $query->whereNull('unpublish_at') + ->orWhere('unpublish_at', '>', Carbon::now()); + }) + ->where('published', false) + ->get(); + Log::debug(__CLASS__ . " models to publish " . $modelListToPublish->count()); + $modelListToPublish->each(function ($currentModel) { + $currentModel->published = true; + $currentModel->saveOrFail(); + }); + + /** @var \Illuminate\Database\Eloquent\Collection */ + $modelListToUnpublish = $model::query() ->whereNotNull('unpublish_at') ->where('unpublish_at', '<=', Carbon::now()) ->where('published', true) ->get(); - Log::debug(__CLASS__ . " model to unpublish " . $modelListToUnPublish->count()); - - // Unpublish all models with an unpublish_at date passed. - $modelListToUnPublish->each(function (News|Strip $modelToUnpublish) { - $modelToUnpublish->published = false; - $modelToUnpublish->saveOrFail(); - }); - - // Get all unpublished model with a publish_at date passed. - /** @var \Illuminate\Database\Eloquent\Collection $modelListToPublish */ - $modelListToPublish = $model::query() - ->where('publish_at', '<=', Carbon::now()) - ->whereNotNull('publish_at') - ->where('published', false) - ->get(); - Log::debug(__CLASS__ . " model to publish " . $modelListToPublish->count()); - - // Publish all models with a publish_at date passed. - $modelListToPublish->each(function (News|Strip $modelToPublish) { - $modelToPublish->published = true; - $modelToPublish->saveOrFail(); + Log::debug(__CLASS__ . " models to unpublish " . $modelListToUnpublish->count()); + $modelListToUnpublish->each(function ($currentModel) { + $currentModel->published = false; + $currentModel->saveOrFail(); }); }); } From 93e4ed4cae9d5b6bd3eaadf72450337f5b2dced2 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:03:52 +0200 Subject: [PATCH 3/9] fix: :bug: replace old 24slides/laravel-saml2 dependency from scaler-tech/laravel-saml2 --- composer.json | 2 +- composer.lock | 602 +++++++++++++++++++++++++------------------------- 2 files changed, 305 insertions(+), 299 deletions(-) diff --git a/composer.json b/composer.json index 71787c1..d593d98 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,6 @@ "license": "MIT", "require": { "php": "^8.5", - "24slides/laravel-saml2": "^2.4", "axlon/laravel-postal-code-validation": "^3.5", "diglactic/laravel-breadcrumbs": "^9.0", "guzzlehttp/guzzle": "^7.2", @@ -38,6 +37,7 @@ "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^8.1", "phpunit/phpunit": "^10.0", + "scaler-tech/laravel-saml2": "^2.7", "slevomat/coding-standard": "^8.10", "spatie/laravel-ignition": "^2.0", "thedoctor0/laravel-factory-generator": "^1.2" diff --git a/composer.lock b/composer.lock index 3d0af18..4159814 100644 --- a/composer.lock +++ b/composer.lock @@ -4,87 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "525f8c363aa3e328f479964a598e9b90", + "content-hash": "cccb06b7e95be8def883d76f1ab40771", "packages": [ - { - "name": "24slides/laravel-saml2", - "version": "2.5.2", - "source": { - "type": "git", - "url": "https://github.com/scaler-tech/laravel-saml2.git", - "reference": "d105b12995008ad6d1b40fe239f881ae47dbb553" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/scaler-tech/laravel-saml2/zipball/d105b12995008ad6d1b40fe239f881ae47dbb553", - "reference": "d105b12995008ad6d1b40fe239f881ae47dbb553", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "illuminate/console": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "illuminate/database": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "onelogin/php-saml": "^3.0 || ^4.0", - "php": ">=7.1" - }, - "require-dev": { - "mockery/mockery": "^0.9.9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0", - "squizlabs/php_codesniffer": "^2.3" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Saml2": "Slides\\Saml2\\Facades\\Auth" - }, - "providers": [ - "Slides\\Saml2\\ServiceProvider" - ] - }, - "branch-aliases": { - "dev-master": "2.4.x-dev" - } - }, - "autoload": { - "files": [ - "src/helpers.php" - ], - "psr-4": { - "Slides\\Saml2\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Scaler Tech", - "role": "Maintainer" - }, - { - "name": "Artem Brezhnev", - "email": "brezzhnev@gmail.com" - } - ], - "description": "SAML2 Service Provider integration for Laravel applications, based on OneLogin toolkit", - "homepage": "https://github.com/scaler-tech/laravel-saml2", - "keywords": [ - "SAML2", - "SSO", - "laravel", - "onelogin", - "saml" - ], - "support": { - "issues": "https://github.com/scaler-tech/laravel-saml2/issues", - "source": "https://github.com/scaler-tech/laravel-saml2" - }, - "abandoned": "scaler-tech/laravel-saml2", - "time": "2026-02-15T17:02:55+00:00" - }, { "name": "axlon/laravel-postal-code-validation", "version": "v3.9.0", @@ -1007,16 +928,16 @@ }, { "name": "giggsey/libphonenumber-for-php-lite", - "version": "9.0.27", + "version": "9.0.28", "source": { "type": "git", "url": "https://github.com/giggsey/libphonenumber-for-php-lite.git", - "reference": "ef1e41c8668d6462de5affd42de13ef36a39f88c" + "reference": "08acc9d605e1bb3d89dec504a09b6c435490f940" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/ef1e41c8668d6462de5affd42de13ef36a39f88c", - "reference": "ef1e41c8668d6462de5affd42de13ef36a39f88c", + "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/08acc9d605e1bb3d89dec504a09b6c435490f940", + "reference": "08acc9d605e1bb3d89dec504a09b6c435490f940", "shasum": "" }, "require": { @@ -1081,7 +1002,7 @@ "issues": "https://github.com/giggsey/libphonenumber-for-php-lite/issues", "source": "https://github.com/giggsey/libphonenumber-for-php-lite" }, - "time": "2026-04-01T12:19:06+00:00" + "time": "2026-04-13T11:33:01+00:00" }, { "name": "graham-campbell/result-type", @@ -2040,16 +1961,16 @@ }, { "name": "laravel/prompts", - "version": "v0.3.16", + "version": "v0.3.17", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "11e7d5f93803a2190b00e145142cb00a33d17ad2" + "reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/11e7d5f93803a2190b00e145142cb00a33d17ad2", - "reference": "11e7d5f93803a2190b00e145142cb00a33d17ad2", + "url": "https://api.github.com/repos/laravel/prompts/zipball/6a82ac19a28b916ae0885828795dbd4c59d9a818", + "reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818", "shasum": "" }, "require": { @@ -2093,22 +2014,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.16" + "source": "https://github.com/laravel/prompts/tree/v0.3.17" }, - "time": "2026-03-23T14:35:33+00:00" + "time": "2026-04-20T16:07:33+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.11", + "version": "v2.0.12", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "d1af40ac4a6ccc12bd062a7184f63c9995a63bdd" + "reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/d1af40ac4a6ccc12bd062a7184f63c9995a63bdd", - "reference": "d1af40ac4a6ccc12bd062a7184f63c9995a63bdd", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/a6abb4e54f6fcd3138120b9ad497f0bd146f9919", + "reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919", "shasum": "" }, "require": { @@ -2156,7 +2077,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-04-07T13:32:18+00:00" + "time": "2026-04-14T13:33:34+00:00" }, { "name": "laravel/tinker", @@ -2848,23 +2769,23 @@ }, { "name": "mews/purifier", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/mewebstudio/Purifier.git", - "reference": "acc71bc512dcf9b87144546d0e3055fc76d244ff" + "reference": "b2705cc6c832ce7229373418e191d71b6c037841" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/acc71bc512dcf9b87144546d0e3055fc76d244ff", - "reference": "acc71bc512dcf9b87144546d0e3055fc76d244ff", + "url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/b2705cc6c832ce7229373418e191d71b6c037841", + "reference": "b2705cc6c832ce7229373418e191d71b6c037841", "shasum": "" }, "require": { "ezyang/htmlpurifier": "^4.16.0", - "illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^7.2|^8.0" }, "require-dev": { @@ -2920,9 +2841,9 @@ ], "support": { "issues": "https://github.com/mewebstudio/Purifier/issues", - "source": "https://github.com/mewebstudio/Purifier/tree/3.4.3" + "source": "https://github.com/mewebstudio/Purifier/tree/3.4.4" }, - "time": "2025-02-24T16:00:29+00:00" + "time": "2026-04-15T16:41:08+00:00" }, { "name": "monolog/monolog", @@ -3567,70 +3488,6 @@ ], "time": "2024-09-09T07:06:30+00:00" }, - { - "name": "onelogin/php-saml", - "version": "4.3.1", - "source": { - "type": "git", - "url": "https://github.com/SAML-Toolkits/php-saml.git", - "reference": "b009f160e4ac11f49366a45e0d45706b48429353" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/b009f160e4ac11f49366a45e0d45706b48429353", - "reference": "b009f160e4ac11f49366a45e0d45706b48429353", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "robrichards/xmlseclibs": ">=3.1.4" - }, - "require-dev": { - "pdepend/pdepend": "^2.8.0", - "php-coveralls/php-coveralls": "^2.0", - "phploc/phploc": "^4.0 || ^5.0 || ^6.0 || ^7.0", - "phpunit/phpunit": "^9.5", - "sebastian/phpcpd": "^4.0 || ^5.0 || ^6.0 ", - "squizlabs/php_codesniffer": "^3.5.8" - }, - "suggest": { - "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs", - "ext-dom": "Install xml lib", - "ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)", - "ext-zlib": "Install zlib" - }, - "type": "library", - "autoload": { - "psr-4": { - "OneLogin\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP SAML Toolkit", - "homepage": "https://github.com/SAML-Toolkits/php-saml", - "keywords": [ - "Federation", - "SAML2", - "SSO", - "identity", - "saml" - ], - "support": { - "email": "sixto.martin.garcia@gmail.com", - "issues": "https://github.com/onelogin/SAML-Toolkits/issues", - "source": "https://github.com/onelogin/SAML-Toolkits/" - }, - "funding": [ - { - "url": "https://github.com/SAML-Toolkits", - "type": "github" - } - ], - "time": "2025-12-09T10:50:49+00:00" - }, { "name": "phpoption/phpoption", "version": "1.9.5", @@ -3708,16 +3565,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.52", + "version": "2.0.53", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "2552c4001631d1cc844332faea6a08a49c964b28" + "reference": "2d1a664b940b9b8f367185307dc010d11a2790f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/2552c4001631d1cc844332faea6a08a49c964b28", - "reference": "2552c4001631d1cc844332faea6a08a49c964b28", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/2d1a664b940b9b8f367185307dc010d11a2790f3", + "reference": "2d1a664b940b9b8f367185307dc010d11a2790f3", "shasum": "" }, "require": { @@ -3798,7 +3655,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.52" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.53" }, "funding": [ { @@ -3814,7 +3671,7 @@ "type": "tidelift" } ], - "time": "2026-03-19T02:54:44+00:00" + "time": "2026-04-10T01:30:02+00:00" }, { "name": "propaganistas/laravel-phone", @@ -4576,60 +4433,18 @@ }, "time": "2025-12-14T04:43:48+00:00" }, - { - "name": "robrichards/xmlseclibs", - "version": "3.1.5", - "source": { - "type": "git", - "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "03062be78178cbb5e8f605cd255dc32a14981f92" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/03062be78178cbb5e8f605cd255dc32a14981f92", - "reference": "03062be78178cbb5e8f605cd255dc32a14981f92", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "php": ">= 5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "RobRichards\\XMLSecLibs\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "A PHP library for XML Security", - "homepage": "https://github.com/robrichards/xmlseclibs", - "keywords": [ - "security", - "signature", - "xml", - "xmldsig" - ], - "support": { - "issues": "https://github.com/robrichards/xmlseclibs/issues", - "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.5" - }, - "time": "2026-03-13T10:31:56+00:00" - }, { "name": "sentry/sentry", - "version": "4.24.0", + "version": "4.25.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "5055cc792f630a427fdf9dcccd88faa94b50fd30" + "reference": "bfee3381e1f6dea8a5f3a18adba6419fe81c5f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/5055cc792f630a427fdf9dcccd88faa94b50fd30", - "reference": "5055cc792f630a427fdf9dcccd88faa94b50fd30", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/bfee3381e1f6dea8a5f3a18adba6419fe81c5f54", + "reference": "bfee3381e1f6dea8a5f3a18adba6419fe81c5f54", "shasum": "" }, "require": { @@ -4661,6 +4476,7 @@ "spiral/roadrunner-worker": "^3.6" }, "suggest": { + "ext-excimer": "Enable Sentry profiling with the Excimer PHP extension.", "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler." }, "type": "library", @@ -4697,7 +4513,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.24.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.25.0" }, "funding": [ { @@ -4709,7 +4525,7 @@ "type": "custom" } ], - "time": "2026-04-01T14:34:34+00:00" + "time": "2026-04-23T12:50:03+00:00" }, { "name": "sentry/sentry-laravel", @@ -6332,16 +6148,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -6391,7 +6207,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0" }, "funding": [ { @@ -6411,20 +6227,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df", + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df", "shasum": "" }, "require": { @@ -6473,7 +6289,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0" }, "funding": [ { @@ -6493,11 +6309,11 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -6560,7 +6376,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0" }, "funding": [ { @@ -6584,7 +6400,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -6645,7 +6461,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0" }, "funding": [ { @@ -6669,16 +6485,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -6730,7 +6546,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0" }, "funding": [ { @@ -6750,20 +6566,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", "shasum": "" }, "require": { @@ -6814,7 +6630,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.36.0" }, "funding": [ { @@ -6834,20 +6650,20 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { @@ -6894,7 +6710,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0" }, "funding": [ { @@ -6914,20 +6730,20 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + "reference": "2c408a6bb0313e6001a83628dc5506100474254e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/2c408a6bb0313e6001a83628dc5506100474254e", + "reference": "2c408a6bb0313e6001a83628dc5506100474254e", "shasum": "" }, "require": { @@ -6974,7 +6790,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.36.0" }, "funding": [ { @@ -6994,20 +6810,20 @@ "type": "tidelift" } ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2026-04-10T16:50:15+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { @@ -7057,7 +6873,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.36.0" }, "funding": [ { @@ -7077,7 +6893,7 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/process", @@ -7890,22 +7706,22 @@ }, { "name": "uwil/admin-secure-laravel", - "version": "5.0.0", + "version": "5.1.0", "source": { "type": "git", "url": "git@lab.s-web.fr:ldc-web/projets/ldc-web-admin-secure-laravel.git", - "reference": "7d9c052db4318752a312dc9763bc8c31ea053aa2" + "reference": "0299d8397111b5a80ea3200a9fd387b94c34f208" }, "dist": { "type": "zip", - "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/uwil/admin-secure-laravel.zip?sha=7d9c052db4318752a312dc9763bc8c31ea053aa2", - "reference": "7d9c052db4318752a312dc9763bc8c31ea053aa2", + "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/uwil/admin-secure-laravel.zip?sha=0299d8397111b5a80ea3200a9fd387b94c34f208", + "reference": "0299d8397111b5a80ea3200a9fd387b94c34f208", "shasum": "" }, "require": { "dxw/cidr": "^3.2", - "illuminate/support": "~11|~12", - "laravel/framework": "~11|~12", + "illuminate/support": "~11|~12|~13", + "laravel/framework": "~11|~12|~13", "php": "^8.3", "symfony/options-resolver": "^7.0" }, @@ -8139,23 +7955,23 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "reference": "d870a33f0f79d2b4579740b0620200221ee44aeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/d870a33f0f79d2b4579740b0620200221ee44aeb", + "reference": "d870a33f0f79d2b4579740b0620200221ee44aeb", "shasum": "" }, "require": { - "php": ">=7.0.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5" }, "suggest": { "ext-intl": "Use Intl for transliterator_transliterate() support" @@ -8185,7 +8001,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "source": "https://github.com/voku/portable-ascii/tree/2.1.0" }, "funding": [ { @@ -8209,7 +8025,7 @@ "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2026-04-16T23:10:39+00:00" } ], "packages-dev": [ @@ -9458,16 +9274,16 @@ }, { "name": "laravel/pint", - "version": "v1.29.0", + "version": "v1.29.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "bdec963f53172c5e36330f3a400604c69bf02d39" + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/bdec963f53172c5e36330f3a400604c69bf02d39", - "reference": "bdec963f53172c5e36330f3a400604c69bf02d39", + "url": "https://api.github.com/repos/laravel/pint/zipball/0770e9b7fafd50d4586881d456d6eb41c9247a80", + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80", "shasum": "" }, "require": { @@ -9478,14 +9294,14 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.94.2", - "illuminate/view": "^12.54.1", - "larastan/larastan": "^3.9.3", - "laravel-zero/framework": "^12.0.5", + "friendsofphp/php-cs-fixer": "^3.95.1", + "illuminate/view": "^12.56.0", + "larastan/larastan": "^3.9.6", + "laravel-zero/framework": "^12.1.0", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^2.4.0", "pestphp/pest": "^3.8.6", - "shipfastlabs/agent-detector": "^1.1.0" + "shipfastlabs/agent-detector": "^1.1.3" }, "bin": [ "builds/pint" @@ -9522,20 +9338,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2026-03-12T15:51:39+00:00" + "time": "2026-04-20T15:26:14+00:00" }, { "name": "laravel/sail", - "version": "v1.56.0", + "version": "v1.57.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "f43426bb42a1cb7a51a3861d9138063e54766d28" + "reference": "fa8d057b6e9310380ccbc3a209ed7f927d54f648" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/f43426bb42a1cb7a51a3861d9138063e54766d28", - "reference": "f43426bb42a1cb7a51a3861d9138063e54766d28", + "url": "https://api.github.com/repos/laravel/sail/zipball/fa8d057b6e9310380ccbc3a209ed7f927d54f648", + "reference": "fa8d057b6e9310380ccbc3a209ed7f927d54f648", "shasum": "" }, "require": { @@ -9585,7 +9401,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2026-04-01T15:17:32+00:00" + "time": "2026-04-14T13:32:04+00:00" }, { "name": "mockery/mockery", @@ -9827,6 +9643,70 @@ ], "time": "2024-10-15T16:06:32+00:00" }, + { + "name": "onelogin/php-saml", + "version": "4.3.1", + "source": { + "type": "git", + "url": "https://github.com/SAML-Toolkits/php-saml.git", + "reference": "b009f160e4ac11f49366a45e0d45706b48429353" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/b009f160e4ac11f49366a45e0d45706b48429353", + "reference": "b009f160e4ac11f49366a45e0d45706b48429353", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "robrichards/xmlseclibs": ">=3.1.4" + }, + "require-dev": { + "pdepend/pdepend": "^2.8.0", + "php-coveralls/php-coveralls": "^2.0", + "phploc/phploc": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "phpunit/phpunit": "^9.5", + "sebastian/phpcpd": "^4.0 || ^5.0 || ^6.0 ", + "squizlabs/php_codesniffer": "^3.5.8" + }, + "suggest": { + "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs", + "ext-dom": "Install xml lib", + "ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)", + "ext-zlib": "Install zlib" + }, + "type": "library", + "autoload": { + "psr-4": { + "OneLogin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP SAML Toolkit", + "homepage": "https://github.com/SAML-Toolkits/php-saml", + "keywords": [ + "Federation", + "SAML2", + "SSO", + "identity", + "saml" + ], + "support": { + "email": "sixto.martin.garcia@gmail.com", + "issues": "https://github.com/onelogin/SAML-Toolkits/issues", + "source": "https://github.com/onelogin/SAML-Toolkits/" + }, + "funding": [ + { + "url": "https://github.com/SAML-Toolkits", + "type": "github" + } + ], + "time": "2025-12-09T10:50:49+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.4", @@ -10475,6 +10355,132 @@ ], "time": "2026-01-27T05:48:37+00:00" }, + { + "name": "robrichards/xmlseclibs", + "version": "3.1.5", + "source": { + "type": "git", + "url": "https://github.com/robrichards/xmlseclibs.git", + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/03062be78178cbb5e8f605cd255dc32a14981f92", + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">= 5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "RobRichards\\XMLSecLibs\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A PHP library for XML Security", + "homepage": "https://github.com/robrichards/xmlseclibs", + "keywords": [ + "security", + "signature", + "xml", + "xmldsig" + ], + "support": { + "issues": "https://github.com/robrichards/xmlseclibs/issues", + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.5" + }, + "time": "2026-03-13T10:31:56+00:00" + }, + { + "name": "scaler-tech/laravel-saml2", + "version": "2.7.2", + "source": { + "type": "git", + "url": "https://github.com/scaler-tech/laravel-saml2.git", + "reference": "765b4bb0c56c1fb13b14779e843cd935c5b2eb6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scaler-tech/laravel-saml2/zipball/765b4bb0c56c1fb13b14779e843cd935c5b2eb6a", + "reference": "765b4bb0c56c1fb13b14779e843cd935c5b2eb6a", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "illuminate/console": "^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/database": "^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "onelogin/php-saml": "^4.0", + "php": ">=8.2" + }, + "replace": { + "24slides/laravel-saml2": "self.version" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.94", + "kubawerlos/php-cs-fixer-custom-fixers": "^3.36", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6 || ^10.5 || ^11.5 || ^12.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Saml2": "Slides\\Saml2\\Facades\\Auth" + }, + "providers": [ + "Slides\\Saml2\\ServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Slides\\Saml2\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Scaler Tech", + "homepage": "https://github.com/scaler-tech/laravel-saml2", + "role": "Maintainer" + }, + { + "name": "Artem Brezhnev", + "email": "brezzhnev@gmail.com" + } + ], + "description": "SAML2 Service Provider integration for Laravel applications, based on OneLogin toolkit", + "homepage": "https://github.com/scaler-tech/laravel-saml2", + "keywords": [ + "SAML2", + "SSO", + "laravel", + "onelogin", + "saml" + ], + "support": { + "issues": "https://github.com/scaler-tech/laravel-saml2/issues", + "source": "https://github.com/scaler-tech/laravel-saml2" + }, + "time": "2026-03-20T13:15:15+00:00" + }, { "name": "sebastian/cli-parser", "version": "2.0.1", From 0c9d7da807c1a862b406cde9438b184f9386b7d7 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:04:18 +0200 Subject: [PATCH 4/9] fix: :rotating_light: resolve phpstan errors with strict level 7 --- app/Console/Commands/MakeUser.php | 117 ++++++++++ app/Console/Commands/UserCreate.php | 207 ------------------ .../ActivityLogs/ActivityLogsEventEnum.php | 6 +- app/Enums/Country.php | 10 +- app/Enums/Sites/SpeciesEnum.php | 5 +- app/Enums/StaticPageType.php | 2 +- app/Enums/Strips/PictoEnum.php | 6 +- app/Enums/Testimonials/TypeEnum.php | 5 +- .../Controllers/Bo/ActivityLogController.php | 3 +- app/Http/Controllers/Bo/AisleController.php | 5 +- app/Http/Controllers/Bo/BrandController.php | 2 +- .../Controllers/Bo/CarouselController.php | 5 +- .../Controllers/Bo/DashboardController.php | 2 +- .../Bo/HistoricalMilestoneController.php | 2 +- .../Controllers/Bo/JobVideoController.php | 2 +- app/Http/Controllers/Bo/LogoController.php | 2 +- app/Http/Controllers/Bo/NetworkController.php | 2 +- app/Http/Controllers/Bo/NewsController.php | 2 +- app/Http/Controllers/Bo/SectionController.php | 16 +- app/Http/Controllers/Bo/SiteController.php | 10 +- app/Http/Controllers/Bo/SlideController.php | 2 +- .../Controllers/Bo/StaticPageController.php | 2 +- app/Http/Controllers/Bo/StickyController.php | 2 +- app/Http/Controllers/Bo/StripController.php | 2 +- .../Controllers/Bo/TestimonialController.php | 2 +- app/Http/Controllers/Bo/UploadController.php | 5 +- app/Http/Controllers/Bo/UserController.php | 4 +- app/Http/Controllers/Controller.php | 68 +++--- .../Controllers/Fo/StaticPageController.php | 13 +- app/Http/Middleware/HtmlSanitizer.php | 2 +- app/Http/Middleware/SecureHeaders.php | 6 +- .../Bo/Carousels/StoreCarouselRequest.php | 4 +- .../StoreHistoricalMilestoneRequest.php | 4 +- .../Bo/JobVideos/StoreJobVideoRequest.php | 4 +- .../Requests/Bo/Logos/StoreLogoRequest.php | 4 +- .../Requests/Bo/News/StoreNewsRequest.php | 4 +- .../Bo/Sections/UpdateSectionRequest.php | 2 +- .../Requests/Bo/Sites/StoreSiteRequest.php | 8 +- .../Requests/Bo/Slides/StoreSlideRequest.php | 6 +- .../StaticPages/UpdateStaticPageRequest.php | 2 +- .../Bo/Stickies/StoreStickyRequest.php | 4 +- .../Requests/Bo/Strips/StoreStripRequest.php | 8 +- .../Testimonials/StoreTestimonialRequest.php | 4 +- .../Requests/Bo/UpdateChangeOrderRequest.php | 2 +- .../Requests/Bo/UpdateMiniCrudRequest.php | 28 +-- app/Http/Requests/Bo/UpdateOrderRequest.php | 2 +- app/Http/Requests/Bo/UploadFileRequest.php | 2 +- .../Requests/Bo/Users/StoreUserRequest.php | 4 +- .../Requests/Bo/Users/UpdateUserRequest.php | 2 +- app/Http/Requests/Fo/ListenFormRequest.php | 4 +- app/Lib/Helpers/CollectionHelper.php | 44 ++-- app/Lib/Helpers/ExceptionsHelper.php | 20 +- app/Lib/Helpers/FileStorageHelper.php | 48 ++-- app/Lib/Helpers/ToolboxHelper.php | 155 +++++++------ app/Mail/SendConfirmationMail.php | 4 +- app/Mail/SendContactMail.php | 4 +- app/Models/ActivityLog.php | 29 ++- app/Models/Aisle.php | 12 +- app/Models/Brand.php | 14 +- app/Models/Carousel.php | 23 +- app/Models/HistoricalMilestone.php | 5 +- app/Models/JobVideo.php | 3 +- app/Models/Logo.php | 9 +- app/Models/Network.php | 14 +- app/Models/News.php | 13 +- app/Models/Section.php | 133 +++++------ app/Models/Site.php | 36 +-- app/Models/Slide.php | 5 +- app/Models/StaticPage.php | 12 +- app/Models/Sticky.php | 4 +- app/Models/Strip.php | 9 +- app/Models/Testimonial.php | 5 +- app/Models/User.php | 13 +- app/Traits/Controllers/ChangesModelOrder.php | 5 +- app/Traits/Enums/BaseEnum.php | 80 ++++--- app/Traits/Models/ActivityLog.php | 6 +- app/Traits/Models/MiniCrudModel.php | 24 +- app/Traits/Requests/HasPicture.php | 16 +- config/app.php | 2 +- config/sentry.php | 6 +- phpcs.xml | 11 +- phpstan.neon | 3 +- 82 files changed, 687 insertions(+), 697 deletions(-) create mode 100644 app/Console/Commands/MakeUser.php delete mode 100644 app/Console/Commands/UserCreate.php diff --git a/app/Console/Commands/MakeUser.php b/app/Console/Commands/MakeUser.php new file mode 100644 index 0000000..b5db5b1 --- /dev/null +++ b/app/Console/Commands/MakeUser.php @@ -0,0 +1,117 @@ +components->info("Creating a new backend user..."); + + $firstName = $this->askValid( + 'first_name', + 'First name', + 'Admin', + ['required', 'min:3', 'max:255'] + ); + $lastName = $this->askValid( + 'last_name', + 'Last name', + 'Saïtama', + ['required', 'min:3', 'max:255'] + ); + $email = $this->askValid( + 'email', + 'Email', + 'equipe.web@ldc.fr', + ['required', 'unique:users,email', 'email:rfc,strict,dns,spoof,filter'] + ); + $role = $this->askRole(); + + $user = new User([ + 'first_name' => $firstName, + 'last_name' => $lastName, + 'email' => $email, + 'role' => $role, + 'published' => true, + 'published_at' => Carbon::now(), + ]); + $user->saveOrFail(); + + $this->components->success("User {$firstName} {$lastName} created successfully."); + } + + /** + * Ask for a value and validate it, re-prompting on failure. + * + * @param string $field + * @param string $label + * @param string $default + * @param array $rules + * @return string + */ + private function askValid(string $field, string $label, string $default, array $rules): string + { + try { + $value = $this->ask(sprintf("Type the wanted user %s", $label), $default); + $validator = Validator::make([$field => $value], [$field => $rules]); + $validator->validate(); + return $value; + } catch (ValidationException $e) { + $this->components->error( + collect($e->errors())->flatten()->first() + ); + return $this->askValid($field, $label, $default, $rules); + } + } + + /** + * Ask for a role and return the corresponding RoleEnum. + * + * @return \App\Enums\Users\RoleEnum + */ + private function askRole(): \App\Enums\Users\RoleEnum + { + $options = collect([ + RoleEnum::conceptor, + RoleEnum::admin, + RoleEnum::visitor, + ])->mapWithKeys(fn(RoleEnum $role) => [ + Str::ucFirst($role->label()) => $role + ]); + + /** @var string $choice */ + $choice = $this->choice('Role', $options->keys()->all(), Str::ucFirst(RoleEnum::visitor->label())); + return $options->get($choice); + } +} diff --git a/app/Console/Commands/UserCreate.php b/app/Console/Commands/UserCreate.php deleted file mode 100644 index 3dee9e0..0000000 --- a/app/Console/Commands/UserCreate.php +++ /dev/null @@ -1,207 +0,0 @@ -first_name = null; - $this->addFirstName(); - - $this->last_name = null; - $this->addLastName(); - - $this->email = null; - $this->addEmail(); - - $this->role = null; - $this->addRole(); - - $user = new User([ - 'first_name' => $this->first_name, - 'last_name' => $this->last_name, - 'email' => $this->email, - 'role' => $this->role, - 'published' => true, - 'published_at' => Carbon::now(), - ]); - $user->saveOrFail(); - - $this->info('User created 👌'); - - return 0; - } - - /** - * Add a first name to the user. - * - * @return void - */ - private function addFirstName(): void - { - while (is_null($this->first_name)) { - try { - $tmp = $this->ask('Type the wanted user first name', 'Admin'); - $validator = Validator::make(['first_name' => $tmp], [ - 'first_name' => 'required|min:3|max:255' - ]); - $validator->validate(); - $this->first_name = $tmp; - } catch (ValidationException $e) { - $this->error(sprintf( - 'Please provide a valid first name %s', - \implode(',', collect($e->errors())->flatten()->all()) - )); - continue; - } //end try - }; //end while - } - - /** - * Add a last name to the user. - * - * @return void - */ - private function addLastName(): void - { - while (is_null($this->last_name)) { - try { - $tmp = $this->ask('Type the wanted user last name', 'Saïtama'); - $validator = Validator::make(['last_name' => $tmp], [ - 'last_name' => 'required|min:3|max:255' - ]); - $validator->validate(); - $this->last_name = $tmp; - } catch (ValidationException $e) { - $this->error(sprintf( - 'Please provide a valid last_name %s', - \implode(',', collect($e->errors())->flatten()->all()) - )); - continue; - } //end try - }; //end while - } - - /** - * Add an email to the user. - * - * @return void - */ - private function addEmail(): void - { - while (is_null($this->email)) { - try { - $tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr'); - $validator = Validator::make(['email' => $tmp], [ - 'email' => 'required|unique:users,email|email:rfc,dns' - ]); - $validator->validate(); - $this->email = $tmp; - } catch (ValidationException $e) { - $this->error(sprintf( - 'Please provide a valid email %s', - \implode(',', collect($e->errors())->flatten()->all()) - )); - continue; - } //end try - }; //end while - } - - /** - * Add a role to the user. - * - * @return void - */ - private function addRole(): void - { - while (is_null($this->role)) { - try { - $tmp = $this->choice( - 'Select his role', - [ - Str::ucFirst(RoleEnum::conceptor->label()), - Str::ucFirst(RoleEnum::admin->label()), - Str::ucFirst(RoleEnum::visitor->label()) - ], - Str::ucFirst(RoleEnum::visitor->label()), - ); - if ($tmp === Str::ucFirst(RoleEnum::conceptor->label())) { - $tmp = RoleEnum::conceptor; - } - if ($tmp === Str::ucFirst(RoleEnum::admin->label())) { - $tmp = RoleEnum::admin; - } - if ($tmp === Str::ucFirst(RoleEnum::visitor->label())) { - $tmp = RoleEnum::visitor; - } - $validator = Validator::make(['role' => $tmp], [ - 'role' => 'required' - ]); - $validator->validate(); - $this->role = $tmp; - } catch (ValidationException $e) { - $this->error(sprintf( - 'Please choose from the selection %s', - \implode(',', collect($e->errors())->flatten()->all()) - )); - continue; - } //end try - }; //end while - } -} diff --git a/app/Enums/ActivityLogs/ActivityLogsEventEnum.php b/app/Enums/ActivityLogs/ActivityLogsEventEnum.php index df94759..54a8dd3 100644 --- a/app/Enums/ActivityLogs/ActivityLogsEventEnum.php +++ b/app/Enums/ActivityLogs/ActivityLogsEventEnum.php @@ -14,7 +14,7 @@ enum ActivityLogsEventEnum: int case deleted = 4; /** - * Optionnal labels definition + * Optionnal labels definition. * * @phpstan-ignore-next-line */ @@ -27,7 +27,7 @@ enum ActivityLogsEventEnum: int /** - * Custom added classes definition + * Custom added classes definition. */ private const BOOTSTRAPCLASS = [ self::created->name => 'success', @@ -37,7 +37,7 @@ enum ActivityLogsEventEnum: int ]; /** - * Get Class + * Get Class. * * @return string */ diff --git a/app/Enums/Country.php b/app/Enums/Country.php index 6b79c3e..0fbffdb 100644 --- a/app/Enums/Country.php +++ b/app/Enums/Country.php @@ -518,7 +518,7 @@ enum Country: int /** * Get Valid Shipping Countries * - * @return array + * @return array */ public static function validShippingCountries(): array { @@ -544,7 +544,7 @@ enum Country: int /** * Get Valid Shipping Countries * - * @return array + * @return array */ public static function validBillingCountries(): array { @@ -568,7 +568,7 @@ enum Country: int /** * Get Alpha 2 ISO code of valid shipping countries * - * @return array + * @return array */ public static function getValidShippingCountriesIsoAplha2Codes(): array { @@ -578,7 +578,7 @@ enum Country: int /** * Get Alpha 2 ISO code of valid billing countries * - * @return array + * @return array */ public static function getValidBillingCountriesIsoAplha2Codes(): array { @@ -586,7 +586,7 @@ enum Country: int } /** - * Custom added ISOCODES definition + * Custom added ISOCODES definition. */ private const ISOCODES = [ self::afghanistan->name => 'AFG', diff --git a/app/Enums/Sites/SpeciesEnum.php b/app/Enums/Sites/SpeciesEnum.php index 4770563..33c0809 100644 --- a/app/Enums/Sites/SpeciesEnum.php +++ b/app/Enums/Sites/SpeciesEnum.php @@ -68,7 +68,7 @@ enum SpeciesEnum: int ]; /** - * Get picture alt attribute + * Get picture alt attribute. * * @return string */ @@ -77,7 +77,6 @@ enum SpeciesEnum: int return self::ALTS[$this->name]; } - /** * Alt attributes for pictures. */ @@ -92,7 +91,7 @@ enum SpeciesEnum: int ]; /** - * Get picture alt attribute + * Get picture alt attribute. * * @return string */ diff --git a/app/Enums/StaticPageType.php b/app/Enums/StaticPageType.php index bc3edd8..c7ae151 100644 --- a/app/Enums/StaticPageType.php +++ b/app/Enums/StaticPageType.php @@ -40,7 +40,7 @@ enum StaticPageType: int /** * Get the enums for the page which contains sections. * - * @return array + * @return array */ public static function containsSection(): array { diff --git a/app/Enums/Strips/PictoEnum.php b/app/Enums/Strips/PictoEnum.php index e81d495..c6af269 100644 --- a/app/Enums/Strips/PictoEnum.php +++ b/app/Enums/Strips/PictoEnum.php @@ -42,7 +42,7 @@ enum PictoEnum: int ]; /** - * Get picture path + * Get picture path. * * @return string */ @@ -64,7 +64,7 @@ enum PictoEnum: int ]; /** - * Get picture alt attribute + * Get picture alt attribute. * * @return string */ @@ -87,7 +87,7 @@ enum PictoEnum: int ]; /** - * Get picture alt attribute + * Get picture alt attribute. * * @return string */ diff --git a/app/Enums/Testimonials/TypeEnum.php b/app/Enums/Testimonials/TypeEnum.php index 5c51d9d..8560388 100644 --- a/app/Enums/Testimonials/TypeEnum.php +++ b/app/Enums/Testimonials/TypeEnum.php @@ -29,6 +29,9 @@ enum TypeEnum: int self::hire->name => 'On Embauche', ]; + /** + * Optionnal labels definition. + */ private const COLORS = [ self::breeding->name => 'tertiary', self::better_life->name => 'quad', @@ -39,7 +42,7 @@ enum TypeEnum: int ]; /** - * Get color name + * Get color name. * * @return string */ diff --git a/app/Http/Controllers/Bo/ActivityLogController.php b/app/Http/Controllers/Bo/ActivityLogController.php index 0de699c..8da59d8 100644 --- a/app/Http/Controllers/Bo/ActivityLogController.php +++ b/app/Http/Controllers/Bo/ActivityLogController.php @@ -21,7 +21,7 @@ class ActivityLogController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $query */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\ActivityLog> $query */ $query = ActivityLog::query()->with('user'); /** @var string $search Search field */ @@ -55,6 +55,7 @@ class ActivityLogController extends Controller */ public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View { + /** @var \Illuminate\Database\Eloquent\Model $targetModelClass */ $targetModelClass = $activity_log->model_class; $targetModel = $activity_log->model_class::where( (new $targetModelClass())->getRouteKeyName(), diff --git a/app/Http/Controllers/Bo/AisleController.php b/app/Http/Controllers/Bo/AisleController.php index 8585a51..64a7ead 100644 --- a/app/Http/Controllers/Bo/AisleController.php +++ b/app/Http/Controllers/Bo/AisleController.php @@ -34,8 +34,9 @@ class AisleController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $aisleModels */ - $aisleModels = Aisle::query()->with('network'); + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Aisle> $aisleModels */ + $aisleModels = Aisle::query()->with('network'); + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Network> $networkModels */ $networkModels = Network::query()->where('published', true)->get(); $selectedNetwork = intval($request->network); diff --git a/app/Http/Controllers/Bo/BrandController.php b/app/Http/Controllers/Bo/BrandController.php index eead3e0..9289cbd 100644 --- a/app/Http/Controllers/Bo/BrandController.php +++ b/app/Http/Controllers/Bo/BrandController.php @@ -32,7 +32,7 @@ class BrandController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $brandModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Brand> $brandModels */ $brandModels = Brand::query()->with('aisle'); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/CarouselController.php b/app/Http/Controllers/Bo/CarouselController.php index 0eeb469..e218020 100644 --- a/app/Http/Controllers/Bo/CarouselController.php +++ b/app/Http/Controllers/Bo/CarouselController.php @@ -36,9 +36,10 @@ class CarouselController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $carouselModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Carousel> $carouselModels */ $carouselModels = Carousel::query()->with('section'); - $sectionModels = Section::query()->whereHas('carousels')->get(); + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Section> $sectionModels */ + $sectionModels = Section::query()->whereHas('carousels')->get(); $selectedSection = intval($request->section); diff --git a/app/Http/Controllers/Bo/DashboardController.php b/app/Http/Controllers/Bo/DashboardController.php index e28be1b..3bc2a2f 100644 --- a/app/Http/Controllers/Bo/DashboardController.php +++ b/app/Http/Controllers/Bo/DashboardController.php @@ -7,7 +7,7 @@ use App\Http\Controllers\Controller; class DashboardController extends Controller { /** - * Dashboard Page + * Dashboard Page. * * @return \Illuminate\Contracts\View\View */ diff --git a/app/Http/Controllers/Bo/HistoricalMilestoneController.php b/app/Http/Controllers/Bo/HistoricalMilestoneController.php index 76a8275..1c082a8 100644 --- a/app/Http/Controllers/Bo/HistoricalMilestoneController.php +++ b/app/Http/Controllers/Bo/HistoricalMilestoneController.php @@ -28,7 +28,7 @@ class HistoricalMilestoneController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $historicalMilestoneModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\HistoricalMilestone> $historicalMilestoneModels */ $historicalMilestoneModels = HistoricalMilestone::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/JobVideoController.php b/app/Http/Controllers/Bo/JobVideoController.php index b12a90e..8e133f1 100644 --- a/app/Http/Controllers/Bo/JobVideoController.php +++ b/app/Http/Controllers/Bo/JobVideoController.php @@ -28,7 +28,7 @@ class JobVideoController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $jobVideoModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\JobVideo> $jobVideoModels */ $jobVideoModels = JobVideo::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/LogoController.php b/app/Http/Controllers/Bo/LogoController.php index 0184398..4fbf5ae 100644 --- a/app/Http/Controllers/Bo/LogoController.php +++ b/app/Http/Controllers/Bo/LogoController.php @@ -28,7 +28,7 @@ class LogoController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $logoModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Logo> $logoModels */ $logoModels = Logo::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/NetworkController.php b/app/Http/Controllers/Bo/NetworkController.php index 8b3170f..4ebc551 100644 --- a/app/Http/Controllers/Bo/NetworkController.php +++ b/app/Http/Controllers/Bo/NetworkController.php @@ -33,7 +33,7 @@ class NetworkController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $networkModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Network> $networkModels */ $networkModels = Network::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/NewsController.php b/app/Http/Controllers/Bo/NewsController.php index 72ca6b6..08afd25 100644 --- a/app/Http/Controllers/Bo/NewsController.php +++ b/app/Http/Controllers/Bo/NewsController.php @@ -33,7 +33,7 @@ class NewsController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $newsModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\News> $newsModels */ $newsModels = News::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/SectionController.php b/app/Http/Controllers/Bo/SectionController.php index 517d6ca..450a6bb 100644 --- a/app/Http/Controllers/Bo/SectionController.php +++ b/app/Http/Controllers/Bo/SectionController.php @@ -30,7 +30,7 @@ class SectionController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $query */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Section> $query */ $query = Section::query()->with('page'); // Filter by related page if requested. @@ -92,11 +92,15 @@ class SectionController extends Controller public function update(UpdateSectionRequest $request, Section $section): RedirectResponse { return DB::transaction(function () use ($request, $section) { - $section->fill(array_replace_recursive( - \json_decode(\json_encode($section->toArray()), true), - $request->validated() - )); - + $encoded = json_encode($section->toArray()); + if ($encoded === false) { + return redirect()->back()->with('error', trans('crud.messages.cannot_be_updated', [ + 'model' => Str::ucfirst(trans('models.classes.section')) + ])); + } + /** @var array $data */ + $data = json_decode($encoded, true); + $section->fill(array_replace_recursive($data, $request->validated())); if ($section->saveOrFail()) { return redirect()->route('bo.sections.edit', $section) diff --git a/app/Http/Controllers/Bo/SiteController.php b/app/Http/Controllers/Bo/SiteController.php index 382c043..3baf210 100644 --- a/app/Http/Controllers/Bo/SiteController.php +++ b/app/Http/Controllers/Bo/SiteController.php @@ -32,7 +32,7 @@ class SiteController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $siteModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Site> $siteModels */ $siteModels = Site::query(); /** @var string $search Search field */ @@ -90,7 +90,9 @@ class SiteController extends Controller $site->fill($request->safe()->except(['logos'])); if ($site->saveOrFail()) { - $site->logos()->attach(collect($request->validated('logos'))->pluck('id')); + /** @var array> $logos */ + $logos = $request->validated('logos') ?? []; + $site->logos()->attach(collect($logos)->pluck('id')); return redirect()->route('bo.sites.edit', $site) ->with('success', trans('crud.messages.has_been_created', [ 'model' => Str::ucfirst(trans('models.classes.site')) @@ -129,8 +131,10 @@ class SiteController extends Controller public function update(UpdateSiteRequest $request, Site $site): \Illuminate\Http\RedirectResponse { return DB::transaction(function () use ($request, $site) { + /** @var array> $logos */ + $logos = $request->validated('logos') ?? []; + $site->logos()->sync(collect($logos)->pluck('id')); $site->fill($request->safe()->except(['logos'])); - $site->logos()->sync(collect($request->validated('logos'))->pluck('id')); if ($site->saveOrFail()) { return redirect()->route('bo.sites.edit', $site) diff --git a/app/Http/Controllers/Bo/SlideController.php b/app/Http/Controllers/Bo/SlideController.php index 7d8beaa..8e8db7f 100644 --- a/app/Http/Controllers/Bo/SlideController.php +++ b/app/Http/Controllers/Bo/SlideController.php @@ -28,7 +28,7 @@ class SlideController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $slideModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Slide> $slideModels */ $slideModels = Slide::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/StaticPageController.php b/app/Http/Controllers/Bo/StaticPageController.php index 25f0e08..4f208c3 100644 --- a/app/Http/Controllers/Bo/StaticPageController.php +++ b/app/Http/Controllers/Bo/StaticPageController.php @@ -27,7 +27,7 @@ class StaticPageController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $query */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\StaticPage> $query */ $query = StaticPage::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/StickyController.php b/app/Http/Controllers/Bo/StickyController.php index cbef777..1e8f092 100644 --- a/app/Http/Controllers/Bo/StickyController.php +++ b/app/Http/Controllers/Bo/StickyController.php @@ -28,7 +28,7 @@ class StickyController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $stickyModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Sticky> $stickyModels */ $stickyModels = Sticky::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/StripController.php b/app/Http/Controllers/Bo/StripController.php index a568ba3..da8d82b 100644 --- a/app/Http/Controllers/Bo/StripController.php +++ b/app/Http/Controllers/Bo/StripController.php @@ -33,7 +33,7 @@ class StripController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $stripModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Strip> $stripModels */ $stripModels = Strip::query()->with('news'); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/TestimonialController.php b/app/Http/Controllers/Bo/TestimonialController.php index fd91503..2b8cef7 100644 --- a/app/Http/Controllers/Bo/TestimonialController.php +++ b/app/Http/Controllers/Bo/TestimonialController.php @@ -28,7 +28,7 @@ class TestimonialController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $testimonialModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Testimonial> $testimonialModels */ $testimonialModels = Testimonial::query(); /** @var string $search Search field */ diff --git a/app/Http/Controllers/Bo/UploadController.php b/app/Http/Controllers/Bo/UploadController.php index 934f118..20499fd 100644 --- a/app/Http/Controllers/Bo/UploadController.php +++ b/app/Http/Controllers/Bo/UploadController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Bo; use App\Http\Controllers\Controller; use App\Http\Requests\Bo\UploadFileRequest; use App\Lib\Helpers\FileStorageHelper; +use Illuminate\Database\Eloquent\Model; class UploadController extends Controller { @@ -19,9 +20,11 @@ class UploadController extends Controller { $modelClass = "App\\Models\\$request->folder"; - if (!class_exists($modelClass)) { + if (!class_exists($modelClass) && !is_subclass_of($modelClass, Model::class)) { return response()->json(['error' => 'Invalid model class'], 404); } + + /** @var \Illuminate\Database\Eloquent\Model $model */ $model = new $modelClass(); /** @var \Illuminate\Http\UploadedFile $image */ diff --git a/app/Http/Controllers/Bo/UserController.php b/app/Http/Controllers/Bo/UserController.php index 0894f69..1fbd19b 100644 --- a/app/Http/Controllers/Bo/UserController.php +++ b/app/Http/Controllers/Bo/UserController.php @@ -31,7 +31,7 @@ class UserController extends Controller */ public function index(Request $request): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Builder $userModels */ + /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\User> $userModels */ $userModels = User::query(); /** @var string $search Search field */ @@ -145,7 +145,7 @@ class UserController extends Controller { /** @var array */ $previousQueries = []; - \parse_str(\parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries); + \parse_str((string) \parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries); if ($user->deleteOrFail()) { return redirect()->route('bo.users.index', $previousQueries) ->with('success', trans('crud.messages.has_been_deleted', [ diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 04ca3c2..2de67cb 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -24,13 +24,14 @@ class Controller extends BaseController * Build Search query on specified fields * splitting search into words or using whole sentence * - * @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder. - * @param string $search The query string. - * @param callable|null $searchQuery The query string. - * @param string ...$fields Either a simple array or a string - * in case of a string the two fields - * would be concatenate to make the search. - * @return \Illuminate\Database\Eloquent\Builder + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder. + * @param string $search The searched string. + * @param callable|null $searchQuery The query string. + * @param string ...$fields Either a simple array or a string + * in case of a string the two fields + * would be concatenate to make the search. + * @return \Illuminate\Database\Eloquent\Builder */ protected function searchQuery( Builder $query, @@ -61,15 +62,16 @@ class Controller extends BaseController /** * Build query search on all fields * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param string $search - * @param array $fields - * @return \Illuminate\Database\Eloquent\Builder + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $search + * @param array> $fields + * @return \Illuminate\Database\Eloquent\Builder */ private function searchOnFields( Builder $query, string $search, - array $fields + array $fields, ): \Illuminate\Database\Eloquent\Builder { $table = $query->getModel()->getTable(); foreach ($fields as $field) { @@ -115,13 +117,17 @@ class Controller extends BaseController /** * Get the search value (on string or Enum). * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param string $search - * @param string $field - * @return string|array + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $search + * @param string $field + * @return string|array */ - protected function getSearchValue(Builder $query, string $search, string $field): string|array - { + protected function getSearchValue( + Builder $query, + string $search, + string $field, + ): string|array { $cast = $query->getModel()->getCasts()[$field] ?? null; if ( count($query->getModel()->getCasts()) and // Check if the model has casts. @@ -131,8 +137,8 @@ class Controller extends BaseController /** @var \App\Traits\Enums $cast */ // @phpstan-ignore-next-line $cases = collect($cast::toArray()); - $enum = $cases->filter(function ($item) use ($search) { - return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label)); + $enum = $cases->filter(function ($item) use ($search): bool { + return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label)) === 1; }); return $enum->toArray(); } else { @@ -143,12 +149,15 @@ class Controller extends BaseController /** * Sort columns with a query. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param array $ignore - * @return \Illuminate\Database\Eloquent\Builder + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\Builder $query + * @param array $ignore + * @return \Illuminate\Database\Eloquent\Builder */ - protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder - { + protected function sortQuery( + Builder $query, + array $ignore = [], + ): \Illuminate\Database\Eloquent\Builder { $rName = request()->route()->getName(); $table = $query->getModel()->getTable(); if (request()->input('sort_col')) { @@ -194,9 +203,10 @@ class Controller extends BaseController /** * Customize pagination with cache or config (default). * - * @param \Illuminate\Database\Eloquent\Builder $query + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\Builder $query * @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ protected function paginate( Builder $query, @@ -208,7 +218,7 @@ class Controller extends BaseController $pagination = ToolboxHelper::getValidatedEnum( Cache::get($cacheKey, $pagination->value()), 'pagination', - '\App\Enums\Pagination\ItemsPerPaginationEnum', + ItemsPerPaginationEnum::class, ); if (Cache::get($cacheKey) !== $pagination) { Cache::put($cacheKey, $pagination); @@ -228,7 +238,7 @@ class Controller extends BaseController $theme = ToolboxHelper::getValidatedEnum( $request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()), 'theme', - '\App\Http\Controllers\BootstrapThemeEnum', + BootstrapThemeEnum::class, ); if (Cache::get("theme") !== $theme) { Cache::put("theme", $theme); diff --git a/app/Http/Controllers/Fo/StaticPageController.php b/app/Http/Controllers/Fo/StaticPageController.php index 6e62caf..df4ec12 100644 --- a/app/Http/Controllers/Fo/StaticPageController.php +++ b/app/Http/Controllers/Fo/StaticPageController.php @@ -83,7 +83,7 @@ class StaticPageController extends Controller $staticPageModel = StaticPage::query()->where('type', StaticPageType::unveil)->first(); $sectionModels = Section::query()->where('page_id', $staticPageModel->id)->get(); $historicalMilestoneModels = HistoricalMilestone::query()->orderBy('year', 'ASC')->get(); - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Site> */ + /** @var \Illuminate\Database\Eloquent\Collection */ $siteModelList = Site::query()->orderBy('order')->get(); $keySection = $sectionModels->where('section', PageSectionEnum::unveil_pole)->first(); $missionsSection = $sectionModels->where('section', PageSectionEnum::unveil_missions)->first(); @@ -98,10 +98,9 @@ class StaticPageController extends Controller // * Calcul Viewbox leaflet map (). // Carte page “on se dévoile” : Point central = Laval + rayon = 100 km /** @var \App\Models\Site|null $lavalSite */ - // @phpstan-ignore-next-line $lavalSite = $siteModelList->first(fn(Site $site) => Str::contains($site->name, 'Laval')); if ($lavalSite) { - $viewBox = (object)[ + $viewBox = (object) [ 'lat' => $lavalSite->latitude, 'lng' => $lavalSite->longitude ]; @@ -252,8 +251,8 @@ class StaticPageController extends Controller public function listenForm(ListenFormRequest $request): \Illuminate\Http\RedirectResponse { Mail::to(config('mail.contact.' . ObjectEnum::make(intval($request->validated()['object']))->name())) - ->send(new SendContactMail((object)$request->validated())); - Mail::to($request->validated()['email'])->send(new SendConfirmationMail((object)$request->validated())); + ->send(new SendContactMail((object) $request->validated())); + Mail::to($request->validated()['email'])->send(new SendConfirmationMail((object) $request->validated())); return redirect()->route('fo.listen.show') ->with('success', trans( @@ -308,7 +307,7 @@ class StaticPageController extends Controller */ public function site(Site $site): \Illuminate\Contracts\View\View { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Site> */ + /** @var \Illuminate\Database\Eloquent\Collection */ $siteModels = Site::query()->orderBy('order')->get(); $siteModelList = $siteModels->keyBy('order'); @@ -321,7 +320,7 @@ class StaticPageController extends Controller $nextSiteModel = $siteModelList->first(); } - $viewBox = (object)[ + $viewBox = (object) [ 'lat' => $site->latitude, 'lng' => $site->longitude ]; diff --git a/app/Http/Middleware/HtmlSanitizer.php b/app/Http/Middleware/HtmlSanitizer.php index c7324fd..254b59f 100644 --- a/app/Http/Middleware/HtmlSanitizer.php +++ b/app/Http/Middleware/HtmlSanitizer.php @@ -12,7 +12,7 @@ class HtmlSanitizer * * @param \Illuminate\Http\Request $request * @param \Closure $next - * @param string|array ...$params + * @param string|array ...$params * @return \Symfony\Component\HttpFoundation\Response */ public function handle( diff --git a/app/Http/Middleware/SecureHeaders.php b/app/Http/Middleware/SecureHeaders.php index 4411171..14bf319 100644 --- a/app/Http/Middleware/SecureHeaders.php +++ b/app/Http/Middleware/SecureHeaders.php @@ -15,7 +15,7 @@ class SecureHeaders * Great starting point would be to go check out @Scott_Helme's: * https://securityheaders.com/ * - * @var array + * @var list */ private $unwantedHeaderList = [ 'X-Powered-By', @@ -112,9 +112,9 @@ class SecureHeaders } /** - * Remove unwanted headers + * Remove unwanted headers. * - * @param array $headerList + * @param list $headerList * @return void */ private function removeUnwantedHeaders(array $headerList): void diff --git a/app/Http/Requests/Bo/Carousels/StoreCarouselRequest.php b/app/Http/Requests/Bo/Carousels/StoreCarouselRequest.php index 72645de..f7d649b 100644 --- a/app/Http/Requests/Bo/Carousels/StoreCarouselRequest.php +++ b/app/Http/Requests/Bo/Carousels/StoreCarouselRequest.php @@ -45,7 +45,7 @@ class StoreCarouselRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -91,7 +91,7 @@ class StoreCarouselRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/HistoricalMilestones/StoreHistoricalMilestoneRequest.php b/app/Http/Requests/Bo/HistoricalMilestones/StoreHistoricalMilestoneRequest.php index a7ff739..d55cccf 100644 --- a/app/Http/Requests/Bo/HistoricalMilestones/StoreHistoricalMilestoneRequest.php +++ b/app/Http/Requests/Bo/HistoricalMilestones/StoreHistoricalMilestoneRequest.php @@ -36,7 +36,7 @@ class StoreHistoricalMilestoneRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -61,7 +61,7 @@ class StoreHistoricalMilestoneRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/JobVideos/StoreJobVideoRequest.php b/app/Http/Requests/Bo/JobVideos/StoreJobVideoRequest.php index e95a30e..d4da7b2 100644 --- a/app/Http/Requests/Bo/JobVideos/StoreJobVideoRequest.php +++ b/app/Http/Requests/Bo/JobVideos/StoreJobVideoRequest.php @@ -22,7 +22,7 @@ class StoreJobVideoRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -36,7 +36,7 @@ class StoreJobVideoRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Logos/StoreLogoRequest.php b/app/Http/Requests/Bo/Logos/StoreLogoRequest.php index 28742c6..d52731f 100644 --- a/app/Http/Requests/Bo/Logos/StoreLogoRequest.php +++ b/app/Http/Requests/Bo/Logos/StoreLogoRequest.php @@ -32,7 +32,7 @@ class StoreLogoRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -51,7 +51,7 @@ class StoreLogoRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/News/StoreNewsRequest.php b/app/Http/Requests/Bo/News/StoreNewsRequest.php index 1dca44b..e53b4d3 100644 --- a/app/Http/Requests/Bo/News/StoreNewsRequest.php +++ b/app/Http/Requests/Bo/News/StoreNewsRequest.php @@ -36,7 +36,7 @@ class StoreNewsRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -67,7 +67,7 @@ class StoreNewsRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Sections/UpdateSectionRequest.php b/app/Http/Requests/Bo/Sections/UpdateSectionRequest.php index fdee142..94092e8 100644 --- a/app/Http/Requests/Bo/Sections/UpdateSectionRequest.php +++ b/app/Http/Requests/Bo/Sections/UpdateSectionRequest.php @@ -56,7 +56,7 @@ class UpdateSectionRequest extends UpdateMiniCrudRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Sites/StoreSiteRequest.php b/app/Http/Requests/Bo/Sites/StoreSiteRequest.php index 0bcdf0d..20b8339 100644 --- a/app/Http/Requests/Bo/Sites/StoreSiteRequest.php +++ b/app/Http/Requests/Bo/Sites/StoreSiteRequest.php @@ -27,10 +27,12 @@ class StoreSiteRequest extends FormRequest */ protected function prepareForValidation(): void { + /** @var array $pictos */ + $pictos = $this->input('pictos') ?? []; $this->merge([ 'published' => $this->boolean('published'), 'invert_director_block' => $this->boolean('invert_director_block'), - 'pictos' => \collect($this->input('pictos'))->all(), + 'pictos' => \collect($pictos)->all(), ]); $this->mergePicture('logo'); $this->mergePicture('picture_1'); @@ -41,7 +43,7 @@ class StoreSiteRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -93,7 +95,7 @@ class StoreSiteRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Slides/StoreSlideRequest.php b/app/Http/Requests/Bo/Slides/StoreSlideRequest.php index d35bacd..bd887d7 100644 --- a/app/Http/Requests/Bo/Slides/StoreSlideRequest.php +++ b/app/Http/Requests/Bo/Slides/StoreSlideRequest.php @@ -39,7 +39,7 @@ class StoreSlideRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -92,7 +92,7 @@ class StoreSlideRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { @@ -114,7 +114,7 @@ class StoreSlideRequest extends FormRequest /** * Custom validaton messages. * - * @return array + * @return array */ public function messages(): array { diff --git a/app/Http/Requests/Bo/StaticPages/UpdateStaticPageRequest.php b/app/Http/Requests/Bo/StaticPages/UpdateStaticPageRequest.php index 939cd3a..fbb59e0 100644 --- a/app/Http/Requests/Bo/StaticPages/UpdateStaticPageRequest.php +++ b/app/Http/Requests/Bo/StaticPages/UpdateStaticPageRequest.php @@ -68,7 +68,7 @@ class UpdateStaticPageRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Stickies/StoreStickyRequest.php b/app/Http/Requests/Bo/Stickies/StoreStickyRequest.php index b749c3b..a5dbe86 100644 --- a/app/Http/Requests/Bo/Stickies/StoreStickyRequest.php +++ b/app/Http/Requests/Bo/Stickies/StoreStickyRequest.php @@ -22,7 +22,7 @@ class StoreStickyRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -43,7 +43,7 @@ class StoreStickyRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Strips/StoreStripRequest.php b/app/Http/Requests/Bo/Strips/StoreStripRequest.php index 0498415..3e0b2de 100644 --- a/app/Http/Requests/Bo/Strips/StoreStripRequest.php +++ b/app/Http/Requests/Bo/Strips/StoreStripRequest.php @@ -39,7 +39,7 @@ class StoreStripRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -59,8 +59,8 @@ class StoreStripRequest extends FormRequest $rules = array_merge( $rules, [ - 'picture_alt' => 'required_with|string|between:3,255', - 'picture_title' => 'required_with|string|between:3,255', + 'picture_alt' => 'required_with|string|between:3,255', + 'picture_title' => 'required_with|string|between:3,255', ], $this->pictureRules('picture', 100, 65, 100, 65, true), ); @@ -82,7 +82,7 @@ class StoreStripRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Testimonials/StoreTestimonialRequest.php b/app/Http/Requests/Bo/Testimonials/StoreTestimonialRequest.php index 37d2055..b54aee1 100644 --- a/app/Http/Requests/Bo/Testimonials/StoreTestimonialRequest.php +++ b/app/Http/Requests/Bo/Testimonials/StoreTestimonialRequest.php @@ -33,7 +33,7 @@ class StoreTestimonialRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -57,7 +57,7 @@ class StoreTestimonialRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/UpdateChangeOrderRequest.php b/app/Http/Requests/Bo/UpdateChangeOrderRequest.php index d6be727..f061d95 100644 --- a/app/Http/Requests/Bo/UpdateChangeOrderRequest.php +++ b/app/Http/Requests/Bo/UpdateChangeOrderRequest.php @@ -31,7 +31,7 @@ class UpdateChangeOrderRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { diff --git a/app/Http/Requests/Bo/UpdateMiniCrudRequest.php b/app/Http/Requests/Bo/UpdateMiniCrudRequest.php index 0be6769..66bd8c7 100644 --- a/app/Http/Requests/Bo/UpdateMiniCrudRequest.php +++ b/app/Http/Requests/Bo/UpdateMiniCrudRequest.php @@ -29,8 +29,8 @@ abstract class UpdateMiniCrudRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh + * @return array|string> + * @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh */ public function rules(): array @@ -38,7 +38,8 @@ abstract class UpdateMiniCrudRequest extends FormRequest // phpcs:enable $rules = []; foreach ($this->{$this->modelName}->data as $iptName => $input) { - $input = \json_decode(\json_encode($input), true); + $encoded = \json_encode($input); + $input = \json_decode($encoded !== false ? $encoded : '[]', true); switch ($input['inputType']) { case InputType::number->value: $rules = array_merge($rules, [ @@ -71,7 +72,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest $mergeRules = $this->compileValidate('required|string|min:15', $input); $mergeRules = collect($mergeRules) ->map(function ($rule) { - if (\strpos($rule, 'max:') !== false) { + if (\is_string($rule) && \strpos($rule, 'max:') !== false) { $max = \intval(str_replace('max:', '', $rule)); return function ($attribute, $value, $fail) use ($max) { if (\strlen(\strip_tags($value)) > $max) { @@ -80,7 +81,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest }; } return $rule; - }); + })->all(); $rules = array_merge($rules, [ "data.$iptName.value" => $mergeRules ]); @@ -99,11 +100,11 @@ abstract class UpdateMiniCrudRequest extends FormRequest }) : $input['dimensions']; // * Adapt dimensions - $sizes = (object)[ + $sizes = [ 'minHeight' => $dim['height'], 'maxHeight' => $dim['height'], - 'minWidth' => $dim['width'], - 'maxWidth' => $dim['width'], + 'minWidth' => $dim['width'], + 'maxWidth' => $dim['width'], ]; $rules = array_merge($rules, [ "data.$iptName.value" => [ @@ -155,22 +156,23 @@ abstract class UpdateMiniCrudRequest extends FormRequest break; } //end switch } //end foreach + // @phpstan-ignore-next-line return $rules; } /** - * Undocumented function + * Undocumented function. * - * @param string|array $inputTypeValidate - * @param array $input - * @return array + * @param string|array $inputTypeValidate + * @param array $input + * @return array */ public function compileValidate(string|array $inputTypeValidate, array $input): array { if (\is_string($inputTypeValidate)) { $inputTypeValidate = explode('|', $inputTypeValidate); } - /** @var array|string */ + /** @var array|string $inputValidate */ $inputValidate = \collect($input)->get('validate', $input); $inputValidate = \is_string($inputValidate) ? explode('|', $inputValidate) : $inputValidate; foreach ($inputValidate as $validate) { diff --git a/app/Http/Requests/Bo/UpdateOrderRequest.php b/app/Http/Requests/Bo/UpdateOrderRequest.php index cc998fb..6f89b90 100644 --- a/app/Http/Requests/Bo/UpdateOrderRequest.php +++ b/app/Http/Requests/Bo/UpdateOrderRequest.php @@ -38,7 +38,7 @@ class UpdateOrderRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { diff --git a/app/Http/Requests/Bo/UploadFileRequest.php b/app/Http/Requests/Bo/UploadFileRequest.php index 7b866a9..b231225 100644 --- a/app/Http/Requests/Bo/UploadFileRequest.php +++ b/app/Http/Requests/Bo/UploadFileRequest.php @@ -19,7 +19,7 @@ class UploadFileRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { diff --git a/app/Http/Requests/Bo/Users/StoreUserRequest.php b/app/Http/Requests/Bo/Users/StoreUserRequest.php index 043e6c7..d72d063 100644 --- a/app/Http/Requests/Bo/Users/StoreUserRequest.php +++ b/app/Http/Requests/Bo/Users/StoreUserRequest.php @@ -35,7 +35,7 @@ class StoreUserRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -51,7 +51,7 @@ class StoreUserRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Http/Requests/Bo/Users/UpdateUserRequest.php b/app/Http/Requests/Bo/Users/UpdateUserRequest.php index 2fb1472..658da09 100644 --- a/app/Http/Requests/Bo/Users/UpdateUserRequest.php +++ b/app/Http/Requests/Bo/Users/UpdateUserRequest.php @@ -32,7 +32,7 @@ class UpdateUserRequest extends StoreUserRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { diff --git a/app/Http/Requests/Fo/ListenFormRequest.php b/app/Http/Requests/Fo/ListenFormRequest.php index 4c26f48..06b0c09 100644 --- a/app/Http/Requests/Fo/ListenFormRequest.php +++ b/app/Http/Requests/Fo/ListenFormRequest.php @@ -30,7 +30,7 @@ class ListenFormRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array + * @return array|string> */ public function rules(): array { @@ -101,7 +101,7 @@ class ListenFormRequest extends FormRequest /** * Get custom attributes for validator errors. * - * @return array + * @return array */ public function attributes(): array { diff --git a/app/Lib/Helpers/CollectionHelper.php b/app/Lib/Helpers/CollectionHelper.php index 3487e10..2e99bbf 100644 --- a/app/Lib/Helpers/CollectionHelper.php +++ b/app/Lib/Helpers/CollectionHelper.php @@ -10,26 +10,27 @@ use Illuminate\Support\Collection; class CollectionHelper { /** - * Paginate a collection + * Paginate a collection. * - * @param \Illuminate\Support\Collection $results - * @param integer $pageSize - * @return \Illuminate\Pagination\LengthAwarePaginator + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Support\Collection $results + * @param integer $pageSize + * @return \Illuminate\Pagination\LengthAwarePaginator */ public static function paginate(Collection $results, int $pageSize): \Illuminate\Pagination\LengthAwarePaginator { $page = Paginator::resolveCurrentPage('page'); - return self::paginateManually($results, $pageSize, $page); } /** - * Paginate a collection + * Paginate a collection. * - * @param \Illuminate\Support\Collection $results - * @param integer $pageSize - * @param integer $page - * @return \Illuminate\Pagination\LengthAwarePaginator + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Support\Collection $results + * @param integer $pageSize + * @param integer $page + * @return \Illuminate\Pagination\LengthAwarePaginator */ public static function paginateManually( Collection $results, @@ -39,7 +40,7 @@ class CollectionHelper $total = $results->count(); return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [ - 'path' => Paginator::resolveCurrentPath(), + 'path' => Paginator::resolveCurrentPath(), 'pageName' => 'page', ]); } @@ -47,12 +48,13 @@ class CollectionHelper /** * Create a new length-aware paginator instance. * - * @param \Illuminate\Support\Collection $items - * @param integer $total - * @param integer $perPage - * @param integer $currentPage - * @param array $options - * @return \Illuminate\Pagination\LengthAwarePaginator + * @template TModel of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Support\Collection $items + * @param integer $total + * @param integer $perPage + * @param integer $currentPage + * @param array $options + * @return \Illuminate\Pagination\LengthAwarePaginator */ protected static function paginator( Collection $items, @@ -62,11 +64,11 @@ class CollectionHelper array $options ): \Illuminate\Pagination\LengthAwarePaginator { return Container::getInstance()->makeWith(LengthAwarePaginator::class, [ - 'items' => $items, - 'total' => $total, - 'perPage' => $perPage, + 'items' => $items, + 'total' => $total, + 'perPage' => $perPage, 'currentPage' => $currentPage, - 'options' => $options + 'options' => $options ]); } } diff --git a/app/Lib/Helpers/ExceptionsHelper.php b/app/Lib/Helpers/ExceptionsHelper.php index 0565e55..d8ea2ae 100644 --- a/app/Lib/Helpers/ExceptionsHelper.php +++ b/app/Lib/Helpers/ExceptionsHelper.php @@ -5,7 +5,7 @@ namespace App\Lib\Helpers; class ExceptionsHelper { /** - * Handle sentry event + * Handle sentry event. * * @param \Sentry\Event $event * @return null|\Sentry\Event @@ -26,7 +26,7 @@ class ExceptionsHelper } /** - * Anonimize Sentry Exception bag + * Anonimize Sentry Exception bag. * * @param \Sentry\ExceptionDataBag $exceptionDataBag * @return \Sentry\ExceptionDataBag @@ -42,7 +42,7 @@ class ExceptionsHelper } /** - * Anonymise sentry stacktrace + * Anonymise sentry stacktrace. * * @param \Sentry\Stacktrace $stackTrace * @return \Sentry\Stacktrace @@ -70,7 +70,7 @@ class ExceptionsHelper } /** - * Get anonymized sentry params + * Get anonymized sentry params. * * @param mixed[] $params * @return string[] @@ -80,7 +80,7 @@ class ExceptionsHelper foreach ($params as &$param) { $type = \strtolower(\gettype($param)); if (\is_string($param)) { - $type = \explode(' ', \trim(strtolower($param)))[0] ?? null; + $type = \explode(' ', \trim(strtolower($param)))[0]; } switch (true) { case $type === 'lambda': @@ -104,7 +104,7 @@ class ExceptionsHelper } /** - * Anonymize at least Sql queries + * Anonymize at least Sql queries. * * @param string $message * @return string @@ -119,14 +119,14 @@ class ExceptionsHelper } /** - * Anonymize stack trace + * Anonymize stack trace. * * @param \Throwable $e * @return string */ public static function getAnonymizedStackTrace(\Throwable $e): string { - $projectPath = \realpath(\sprintf('%s/../', \app_path())); + $projectPath = \realpath(\sprintf('%s/../', \app_path())) ?: ''; $traceStack = $e->getTrace(); $traceStr = ''; $maxStackStage = 0; @@ -158,9 +158,9 @@ class ExceptionsHelper } /** - * Handle Args + * Handle Args. * - * @param array $stack + * @param array $stack * @return string */ public static function handleArgs(array $stack): string diff --git a/app/Lib/Helpers/FileStorageHelper.php b/app/Lib/Helpers/FileStorageHelper.php index 4a93549..911aac2 100644 --- a/app/Lib/Helpers/FileStorageHelper.php +++ b/app/Lib/Helpers/FileStorageHelper.php @@ -25,8 +25,6 @@ use Illuminate\Support\Str; * The final path will be storage/modelfiles/posts/10/04/19/5f/black-cat-under-red-car-286071690833400.png * * ! No limits of file per folder will be handled. - * - * @author Munsch Jérémy */ class FileStorageHelper { @@ -40,7 +38,7 @@ class FileStorageHelper { /** @var \Illuminate\Filesystem\FilesystemAdapter */ $disk = Storage::disk('uploads'); - $path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); + $path = ToolboxHelper::mbReplaceString('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); return $disk->path($path); } @@ -57,7 +55,7 @@ class FileStorageHelper if (\strpos($path, 'storage') !== 0) { return; } - $path = ToolboxHelper::mbReplace('storage/', '', $path); + $path = ToolboxHelper::mbReplaceString('storage/', '', $path); if (Storage::disk('public')->exists($path)) { Storage::disk('public')->delete($path); } @@ -81,7 +79,7 @@ class FileStorageHelper if (\strpos($originalPath, 'storage') !== 0) { return; } - $originalPath = ToolboxHelper::mbReplace('storage/', '', $originalPath); + $originalPath = ToolboxHelper::mbReplaceString('storage/', '', $originalPath); if (Storage::disk('public')->exists($originalPath)) { Storage::disk('public')->delete($originalPath); } @@ -106,7 +104,7 @@ class FileStorageHelper $file, bool $slugify = false, string|null $filename = null, - bool $private = false + bool $private = false, ): string { // phpcs:enable $tableName = $model->getTable(); @@ -173,9 +171,9 @@ class FileStorageHelper /** @var \Illuminate\Filesystem\FilesystemAdapter */ $disk = Storage::disk('uploads'); $fileInfo = new \SplFileInfo($disk->path( - ToolboxHelper::mbReplace('/uploads/', '', \urldecode($path)) + ToolboxHelper::mbReplaceString('/uploads/', '', \urldecode($path)) )); - $htmlString = ToolboxHelper::mbReplace( + $htmlString = ToolboxHelper::mbReplaceString( $path, '/' . self::storeFile($model, $fileInfo, true), $htmlString @@ -216,7 +214,7 @@ class FileStorageHelper $filesToKeep = \collect(self::onlyUploadedFilesWithFileStorageHelper($newFiles)); $filesToRemove = $oldFiles->diff($filesToKeep); $filesToRemove->each(function (string $publicStorageFilePath) { - $path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); + $path = ToolboxHelper::mbReplaceString('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); if (Storage::disk('public')->exists($path)) { Storage::disk('public')->delete($path); } @@ -233,7 +231,7 @@ class FileStorageHelper { $filesToRemove = \collect(self::onlyUploadedFilesWithFileStorageHelper(self::findFilesInHtml($htmlString))); $filesToRemove->each(function (string $publicStorageFilePath) { - $path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); + $path = ToolboxHelper::mbReplaceString('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/')); if (Storage::disk('public')->exists($path)) { Storage::disk('public')->delete($path); } @@ -244,7 +242,7 @@ class FileStorageHelper * Find all occurence of files in html * * @param string $html - * @return array + * @return array */ public static function findFilesInHtml(string $html): array { @@ -259,20 +257,20 @@ class FileStorageHelper * Filter array to get only uploaded files that exists * on disk 'public' (using helper storage strategy) * - * @param array $urls - * @return array + * @param array $urls + * @return array */ public static function onlyUploadedFilesWithFileStorageHelper(array $urls): array { return \collect($urls)->unique() // * Filter to get only /uploads and using app url or empty ->filter(function (string $url) { - $path = \parse_url($url, \PHP_URL_PATH); + $path = (string) \parse_url($url, \PHP_URL_PATH); return \strpos(\ltrim($path, '/'), 'storage/modelfiles') === 0; })->filter(function (string $url) { - $path = \parse_url($url, \PHP_URL_PATH); + $path = (string) \parse_url($url, \PHP_URL_PATH); return Storage::disk('public') - ->exists(ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($path), '/'))); + ->exists(ToolboxHelper::mbReplaceString('storage/', '', \ltrim(\urldecode($path), '/'))); })->all(); } @@ -280,22 +278,22 @@ class FileStorageHelper * Filter array to get only uploaded files that exists * on disk 'uploads' * - * @param array $urls - * @return array + * @param array $urls + * @return array */ private static function onlyUploadedFilesWithFileManager(array $urls): array { return \collect($urls)->unique() // * Filter to get only /uploads and using app url or empty ->filter(function (string $url) { - $host = \parse_url($url, \PHP_URL_HOST); - $path = \parse_url($url, \PHP_URL_PATH); - return ($host === \parse_url(config('app.url'), PHP_URL_HOST) or \is_null($host)) and + $host = (string) \parse_url($url, \PHP_URL_HOST); + $path = (string) \parse_url($url, \PHP_URL_PATH); + return ($host === (string) \parse_url(config('app.url'), PHP_URL_HOST) or $host === '') and \strpos(\ltrim($path, '/'), 'uploads') === 0; })->filter(function (string $url) { - $path = \parse_url($url, \PHP_URL_PATH); + $path = (string) \parse_url($url, \PHP_URL_PATH); return Storage::disk('uploads') - ->exists(ToolboxHelper::mbReplace('uploads/', '', \ltrim(\urldecode($path), '/'))); + ->exists(ToolboxHelper::mbReplaceString('uploads/', '', \ltrim(\urldecode($path), '/'))); })->all(); } @@ -459,7 +457,7 @@ class FileStorageHelper '/\.{2,}/' ], '.', $filename); // Lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625 . - $filename = mb_strtolower($filename, mb_detect_encoding($filename)); + $filename = mb_strtolower($filename, mb_detect_encoding($filename) ?: null); // * ".file-name.-" becomes "file-name" $filename = trim($filename, '.-'); return $filename; @@ -468,7 +466,7 @@ class FileStorageHelper /** * Remove all model files for the given Model. * - * @param Model $model + * @param \Illuminate\Database\Eloquent\Model $model * @return void */ public static function removeModelFiles(Model $model): void diff --git a/app/Lib/Helpers/ToolboxHelper.php b/app/Lib/Helpers/ToolboxHelper.php index e057591..2bbfce8 100644 --- a/app/Lib/Helpers/ToolboxHelper.php +++ b/app/Lib/Helpers/ToolboxHelper.php @@ -3,7 +3,7 @@ namespace App\Lib\Helpers; use Carbon\Carbon; -use Illuminate\Database\Eloquent\Builder; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; use Illuminate\Support\Str; @@ -24,8 +24,8 @@ class ToolboxHelper /** * Run a terminal command and gives the output. * - * @param array|string $command The command to execute on terminal. - * @param boolean $throw Wether to throw en esception on failure or not. + * @param array|string $command The command to execute on terminal. + * @param boolean $throw Wether to throw en esception on failure or not. * @return string|false Return false on failure only if $throw is false. * @phpcs:disable Squiz.Commenting.FunctionComment.EmptyThrows * @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber @@ -36,7 +36,7 @@ class ToolboxHelper * @throws \LogicException * @throws \RuntimeException If the command fails. */ - public static function runConsoleCommand(array|string $command, bool $throw = true): string | false + public static function runConsoleCommand(array|string $command, bool $throw = true): string|false { // phpcs:enable $process = \Illuminate\Support\Facades\Process::command($command)->run(); @@ -54,7 +54,6 @@ class ToolboxHelper /** * @param array $array1 * @param array $array2 - * * @return array */ public static function arrayMergeRecursiveDistinct(array &$array1, array &$array2): array @@ -67,7 +66,6 @@ class ToolboxHelper $merged[$key] = $value; } } - return $merged; } @@ -230,11 +228,12 @@ class ToolboxHelper /** * Mutltibyte string replace. * - * @param array|string $search - * @param array|string $replace - * @param array|string $subject - * @param integer $count - * @return array|string|false + * @param array|string $search + * @param array|string $replace + * @param array|string $subject + * @param integer $count + * @return array|string|false + * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public static function mbReplace( array|string $search, @@ -248,37 +247,58 @@ class ToolboxHelper if (is_array($subject)) { // Call mb_replace for each single string in $subject . foreach ($subject as &$string) { - $string = &self::mbReplace($search, $replace, $string, $count); + $string = &self::mbReplace($search, $replace, $string, $count) ?: ''; } + return $subject; } elseif (is_array($search)) { if (!is_array($replace)) { foreach ($search as &$string) { - $subject = self::mbReplace($string, $replace, $subject, $count); + $subject = self::mbReplace($string, $replace, $subject, $count) ?: ''; } } else { $n = max(count($search), count($replace)); while ($n--) { - $subject = self::mbReplace(current($search), current($replace), $subject, $count); + $currentSearch = current($search); + $currentReplace = current($replace); + if ($currentSearch === false || $currentReplace === false) { + break; + } + $result = self::mbReplace($currentSearch, $currentReplace, $subject, $count); + $subject = is_string($result) ? $result : ''; next($search); next($replace); } } } else { - $parts = mb_split(preg_quote($search), $subject); - $count = count($parts) - 1; - $subject = implode($replace, $parts); + $parts = mb_split(preg_quote($search), $subject) ?: []; + $count = (int) count($parts) - 1; + $subject = implode(is_array($replace) ? '' : $replace, $parts); } //end if return $subject; } /** - * Asserts that the field is unique. + * Multibyte string replace (string only version). * - * @param string $table - * @param string $field - * @param string|integer|float|boolean|null|array $value - * @param integer|null $id - * @param callable|null $query + * @param string $search + * @param string $replace + * @param string $subject + * @return string + */ + public static function mbReplaceString(string $search, string $replace, string $subject): string + { + $parts = mb_split(preg_quote($search), $subject) ?: []; + return implode($replace, $parts); + } + + /** + * Asserts that the field is unique + * + * @param string $table + * @param string $field + * @param string|integer|float|boolean|null|array $value + * @param integer|null $id + * @param callable|null $query * @return void * @throws \Illuminate\Validation\ValidationException If the field is not unique. */ @@ -291,20 +311,24 @@ class ToolboxHelper ): void { if (!$query) { Validator::make([$field => $value], [ + /** @phpstan-ignore-next-line */ self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id), ], [ - self::mbReplace('.', '\.', "{$field}.unique") - => trans('crud.libs.toolbox.assertFieldIsUnique', ['attribute' => $field, 'value' => $value]) + /** @phpstan-ignore-next-line */ + self::mbReplace('.', '\.', "{$field}.unique") => trans('crud.libs.toolbox.assertFieldIsUnique', [ + 'attribute' => $field, + 'value' => is_array($value) ? implode(', ', array_map('strval', $value)) : (string) $value, + ]) ])->validate(); return; } Validator::make([$field => $value], [ - $field => Rule::unique($table)->where($query)->ignore($id), + $field => Rule::unique($table)->where(\Closure::fromCallable($query))->ignore($id), ], [ - $field . '.unique' => trans( - 'crud.libs.toolbox.assertFieldIsUnique', - ['attribute' => $field, 'value' => $value] - ) + $field . '.unique' => trans('crud.libs.toolbox.assertFieldIsUnique', [ + 'attribute' => $field, + 'value' => is_array($value) ? implode(', ', array_map('strval', $value)) : (string) $value, + ]) ])->validate(); } @@ -337,20 +361,20 @@ class ToolboxHelper /** * Dynamic model query. * - * @param string $defaultLocale - * @param \Illuminate\Database\Eloquent\Builder $q - * @param string $column - * @param string $value - * @return \Illuminate\Database\Eloquent\Builder + * @param string $defaultLocale + * @param \Illuminate\Contracts\Database\Eloquent\Builder $q + * @param string $column + * @param string $value + * @return \Illuminate\Contracts\Database\Eloquent\Builder */ public static function queryColumnWithLocales( string $defaultLocale, Builder $q, string $column, string $value - ): \Illuminate\Database\Eloquent\Builder { + ): \Illuminate\Contracts\Database\Eloquent\Builder { $currentLocale = app()->currentLocale(); - $locales = collect(config('app.locales')) + $locales = collect((array) config('app.locales', [])) ->mapWithKeys(fn (string $locale) => [$locale => $locale]); if (!$locales->has($defaultLocale)) { // * Remove default locale. @@ -378,15 +402,16 @@ class ToolboxHelper /** * Generates an array from a dot separated string. * - * @param string $path - * @param mixed $value - * @param string $separator - * @return array + * @param string $path + * @param mixed $value + * @param string|null $separator + * @return array */ - public static function dotStringToNestedArray(string $path, mixed $value, string $separator = '.'): array + public static function dotStringToNestedArray(string $path, mixed $value, string|null $separator = null): array { - $arr = $value; - $keys = array_reverse(explode($separator, $path)); + $arr = $value; + $separator = $separator ?: '.'; + $keys = array_reverse(explode($separator, $path)); foreach ($keys as $key) { $arr = [$key => $arr]; @@ -398,7 +423,7 @@ class ToolboxHelper * Convert deeply an object to array. * * @param mixed $input - * @return array + * @return array * @throws \RuntimeException If $input var is a scalar value. */ public static function objectToArray(mixed $input): array @@ -407,7 +432,7 @@ class ToolboxHelper if (!(is_object($input) or is_array($input))) { throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input)); } - $ret = (array)$input; + $ret = (array) $input; foreach ($ret as &$item) { // Recursively process EACH element only if not scalar. $item = (is_object($item) or is_array($item)) ? @@ -429,25 +454,25 @@ class ToolboxHelper if (!(is_object($input) or is_array($input))) { throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input)); } - $ret = (object)$input; + $ret = (array) $input; foreach ($ret as &$item) { // Recursively process EACH element only if not scalar. $item = (is_object($item) or is_array($item)) ? self::arrayToObject($item) : $item; } - return $ret; + return (object) $ret; } /** * Validate picture. * - * @param string $attribute - * @param string|null $value - * @param callable $fail - * @param object $sizes + * @param string $attribute + * @param string|null $value + * @param callable $fail + * @param array{minWidth: int, maxWidth: int, minHeight: int, maxHeight: int} $sizes * @return void */ - public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes): void + public static function validatePicture(string $attribute, string|null $value, callable $fail, array $sizes): void { if (!($useStorage = Storage::exists($value)) and !File::exists($value)) { $fail(trans(':attribute n\'existe pas dans le système de fichier', [ @@ -474,22 +499,22 @@ class ToolboxHelper $height = intval($dimensions[1]); $xMessage = trans( - ":attribute la largeur doit être comprise entre {$sizes->minWidth}px et {$sizes->maxWidth}px" + ":attribute la largeur doit être comprise entre {$sizes['minWidth']}px et {$sizes['maxWidth']}px" ); - if ($sizes->minWidth === $sizes->maxWidth) { - $xMessage = trans(":attribute la largeur doit être de {$sizes->minWidth}px"); + if ($sizes['minWidth'] === $sizes['maxWidth']) { + $xMessage = trans(":attribute la largeur doit être de {$sizes['minWidth']}px"); } $yMessage = trans( - ":attribute la hauteur doit être comprise entre {$sizes->minHeight}px et {$sizes->maxHeight}px" + ":attribute la hauteur doit être comprise entre {$sizes['minHeight']}px et {$sizes['maxHeight']}px" ); - if ($sizes->minHeight === $sizes->maxHeight) { - $yMessage = trans(":attribute la hauteur doit être de {$sizes->minHeight}px"); + if ($sizes['minHeight'] === $sizes['maxHeight']) { + $yMessage = trans(":attribute la hauteur doit être de {$sizes['minHeight']}px"); } - if (($width < $sizes->minWidth) or ($width > $sizes->maxWidth)) { + if (($width < $sizes['minWidth']) or ($width > $sizes['maxWidth'])) { $fail($xMessage); } - if (($height < $sizes->minHeight) or ($height > $sizes->maxHeight)) { + if (($height < $sizes['minHeight']) or ($height > $sizes['maxHeight'])) { $fail($yMessage); } } //end if @@ -546,7 +571,7 @@ class ToolboxHelper { return Arr::where( static::getClassesUsingNamespace($namespace), - fn (string $class_namespace) => \collect(class_implements($class_namespace, true))->filter() + fn (string $class_namespace) => \collect(class_implements($class_namespace, true) ?: [])->filter() ->contains(fn (string $class_interface) => $class_interface === $interface) ); } @@ -554,9 +579,9 @@ class ToolboxHelper /** * Get validated pagination from request. * - * @param integer $default - * @param string $field - * @param string $enumPath + * @param integer $default + * @param string $field + * @param class-string<\UnitEnum> $enumPath * @return integer */ public static function getValidatedEnum(int $default, string $field, string $enumPath): int diff --git a/app/Mail/SendConfirmationMail.php b/app/Mail/SendConfirmationMail.php index a7b8797..ba600e0 100644 --- a/app/Mail/SendConfirmationMail.php +++ b/app/Mail/SendConfirmationMail.php @@ -46,10 +46,10 @@ class SendConfirmationMail extends Mailable */ private function sanitizeStringInputs(): void { - $this->data = (object)Arr::map((array)$this->data, function ($el) { + $this->data = (object) Arr::map((array) $this->data, function ($el) { if (is_string($el)) { $el = \htmlspecialchars(\strip_tags(Blade::render( - (string)Markdown::parse($el) + (string) Markdown::parse($el) ))); $el = Str::of($el)->replaceMatches( '/[^\p{L}0-9\n\s\@\.\:\-\_\?\!\;\(\)\+\-\/\\\=]+/us', diff --git a/app/Mail/SendContactMail.php b/app/Mail/SendContactMail.php index 6d22619..3a5eedf 100644 --- a/app/Mail/SendContactMail.php +++ b/app/Mail/SendContactMail.php @@ -49,10 +49,10 @@ class SendContactMail extends Mailable */ private function sanitizeStringInputs(): void { - $this->data = (object)Arr::map((array)$this->data, function ($el) { + $this->data = (object) Arr::map((array) $this->data, function ($el) { if (is_string($el)) { $el = \htmlspecialchars(\strip_tags(Blade::render( - (string)Markdown::parse($el) + (string) Markdown::parse($el) ))); $el = Str::of($el)->replaceMatches( '/[^\p{L}0-9\n\s\@\.\:\-\_\?\!\;\(\)\+\-\/\\\=]+/us', diff --git a/app/Models/ActivityLog.php b/app/Models/ActivityLog.php index a49799f..84a5a67 100644 --- a/app/Models/ActivityLog.php +++ b/app/Models/ActivityLog.php @@ -3,25 +3,20 @@ namespace App\Models; use App\Enums\ActivityLogs\ActivityLogsEventEnum; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Notifications\Notifiable; use Illuminate\Support\Str; /** * @property string $model Target model. * @property string $model_id Id of the target model. * @property \App\Enums\ActivityLogs\ActivityLogsEventEnum $event Event of this activity (ActivityLogsEventEnum). - * @property array $data Changes. - * @property \Illuminate\Support\Carbon $created_at Created date. + * @property array $data Changes. + * @property-read \Illuminate\Support\Carbon $created_at Created date. * * @property-read \App\Models\User $user User BelongsTo relation. */ class ActivityLog extends Model { - use HasFactory; - use Notifiable; - /** * Indicates if the model should be timestamped. * @@ -32,7 +27,7 @@ class ActivityLog extends Model /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'is_anonymous', @@ -81,7 +76,8 @@ class ActivityLog extends Model $activity->model_id = $model->getKey(); $activity->event = $eventEnum; $activity->data = static::getChangedColumns($activity, $model, $eventEnum); - $activity->created_at = now(); + // @phpstan-ignore-next-line + $activity->created_at = now(); $activity->saveOrFail(); } @@ -91,17 +87,19 @@ class ActivityLog extends Model * @param self $activity * @param \Illuminate\Database\Eloquent\Model $model * @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum - * @return array + * @return array */ public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array { $modelClassName = $activity->model_class; + $modelTarget = new $modelClassName(); + /** Get type of each fields of the target model */ /** @var \Illuminate\Database\Eloquent\Model|null $targetModel */ - $targetModel = $activity->model_class::where( - (new $modelClassName())->getRouteKeyName(), + $targetModel = ($modelTarget instanceof \Illuminate\Database\Eloquent\Model) ? $activity->model_class::where( + $modelTarget->getRouteKeyName(), $activity->model_id - )->first(); + )->first() : null; if (\is_null($targetModel)) { return []; @@ -133,6 +131,7 @@ class ActivityLog extends Model // phpcs:enable $type = \gettype($value); switch ($type) { + // phpcs:ignore PSR2.ControlStructures.SwitchDeclaration.TerminatingComment case 'string': return match (true) { Str::length(\strip_tags($value)) !== Str::length($value) => 'html', @@ -163,12 +162,12 @@ class ActivityLog extends Model } //end switch } - // * RELATIONS + // * RELATIONS. /** * User BelongsTo relation. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\User,$this> */ public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo { diff --git a/app/Models/Aisle.php b/app/Models/Aisle.php index c6895ed..6019bcd 100644 --- a/app/Models/Aisle.php +++ b/app/Models/Aisle.php @@ -5,20 +5,18 @@ namespace App\Models; use App\Lib\Helpers\FileStorageHelper; use App\Traits\Models\ActivityLog; use App\Traits\Models\Orderable; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Validation\ValidationException; class Aisle extends Model { use ActivityLog; - use HasFactory; use Orderable; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'name', @@ -67,7 +65,7 @@ class Aisle extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -120,12 +118,12 @@ class Aisle extends Model return 'network_id'; } - // * RELATIONS + // * RELATIONS. /** * The network that belongs to the logo. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\Network,$this> */ public function network(): \Illuminate\Database\Eloquent\Relations\BelongsTo { @@ -135,7 +133,7 @@ class Aisle extends Model /** * Associated brands. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\Brand,$this> */ public function brands(): \Illuminate\Database\Eloquent\Relations\HasMany { diff --git a/app/Models/Brand.php b/app/Models/Brand.php index b575697..786a7c1 100644 --- a/app/Models/Brand.php +++ b/app/Models/Brand.php @@ -4,19 +4,17 @@ namespace App\Models; use App\Lib\Helpers\FileStorageHelper; use App\Traits\Models\ActivityLog; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Validation\ValidationException; class Brand extends Model { use ActivityLog; - use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'name', @@ -62,7 +60,7 @@ class Brand extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -72,10 +70,10 @@ class Brand extends Model */ private static function manageFields(self $model): void { - // * ASSERTIONS + // * ASSERTIONS. self::assertLimitPublishedModels($model); - // * TRANSFORMATIONS + // * TRANSFORMATIONS. $model->picture = FileStorageHelper::storeFile($model, $model->picture, true); } @@ -107,12 +105,12 @@ class Brand extends Model } } - // * RELATIONS + // * RELATIONS. /** * Associated aisle. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\Aisle,$this> */ public function aisle(): \Illuminate\Database\Eloquent\Relations\BelongsTo { diff --git a/app/Models/Carousel.php b/app/Models/Carousel.php index 28decd4..f78fabe 100644 --- a/app/Models/Carousel.php +++ b/app/Models/Carousel.php @@ -6,28 +6,26 @@ use App\Lib\Helpers\FileStorageHelper; use App\Lib\Helpers\ToolboxHelper; use App\Traits\Models\ActivityLog; use App\Traits\Models\Orderable; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; /** - * @property-read int $id Id. - * @property string $title Title. - * @property array $media Medias of the carousel. - * @property-read \Carbon\Carbon $created_at Created date. - * @property-read \Carbon\Carbon $updated_at Updated date. + * @property-read int $id Id. + * @property string $title Title. + * @property array $media Medias of the carousel. + * @property-read \Carbon\Carbon $created_at Created date. + * @property-read \Carbon\Carbon $updated_at Updated date. * * @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship. */ class Carousel extends Model { use ActivityLog; - use HasFactory; use Orderable; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'section_id', @@ -43,7 +41,7 @@ class Carousel extends Model * @var array */ protected $casts = [ - 'media' => 'array', + 'media' => 'array', 'published' => 'boolean', ]; @@ -78,7 +76,7 @@ class Carousel extends Model }); } - // * METHODS + // * METHODS. /** * Group ordering by section_id. @@ -90,13 +88,12 @@ class Carousel extends Model return 'section_id'; } - - // * RELATIONSHIPS + // * RELATIONSHIPS. /** * Get the sections that owns the Carousel * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\Section,$this> */ public function section(): \Illuminate\Database\Eloquent\Relations\BelongsTo { diff --git a/app/Models/HistoricalMilestone.php b/app/Models/HistoricalMilestone.php index c3823b6..4e100db 100644 --- a/app/Models/HistoricalMilestone.php +++ b/app/Models/HistoricalMilestone.php @@ -26,12 +26,13 @@ use Illuminate\Database\Eloquent\Model; class HistoricalMilestone extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\HistoricalMilestoneFactory> */ use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'title', @@ -78,7 +79,7 @@ class HistoricalMilestone extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. diff --git a/app/Models/JobVideo.php b/app/Models/JobVideo.php index e75853c..1d20f0b 100644 --- a/app/Models/JobVideo.php +++ b/app/Models/JobVideo.php @@ -18,12 +18,13 @@ use Illuminate\Database\Eloquent\Model; class JobVideo extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\JobVideoFactory> */ use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'title', diff --git a/app/Models/Logo.php b/app/Models/Logo.php index 86d7e97..1289cf3 100644 --- a/app/Models/Logo.php +++ b/app/Models/Logo.php @@ -21,12 +21,13 @@ use Illuminate\Database\Eloquent\Model; class Logo extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\LogoFactory> */ use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'label', @@ -57,7 +58,7 @@ class Logo extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -70,12 +71,12 @@ class Logo extends Model $model->picture = FileStorageHelper::storeFile($model, $model->picture, true); } - // * RELATIONS + // * RELATIONS. /** * The sites that belong to the logo. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\Site,$this> */ public function sites(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { diff --git a/app/Models/Network.php b/app/Models/Network.php index 30e06b0..8597e8d 100644 --- a/app/Models/Network.php +++ b/app/Models/Network.php @@ -5,7 +5,6 @@ namespace App\Models; use App\Lib\Helpers\FileStorageHelper; use App\Lib\Helpers\ToolboxHelper; use App\Traits\Models\ActivityLog; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; @@ -13,12 +12,11 @@ use Illuminate\Validation\ValidationException; class Network extends Model { use ActivityLog; - use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'seo_title', @@ -69,7 +67,7 @@ class Network extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -79,12 +77,12 @@ class Network extends Model */ private static function manageFields(self $model): void { - // * ASSERTIONS + // * ASSERTIONS. self::assertLimitPublishedModels($model); self::assertFieldIsUnique('name', $model->name, $model->id); self::assertFieldIsUnique('slug', Str::slug($model->name), $model->id); - // * TRANSFORMATIONS + // * TRANSFORMATIONS. self::setSlug($model, $model->name); $model->picture = FileStorageHelper::storeFile($model, $model->picture, true); } @@ -151,12 +149,12 @@ class Network extends Model } } - // * RELATIONS + // * RELATIONS. /** * The aisles that belong to the logo. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\Aisle,$this> */ public function aisles(): \Illuminate\Database\Eloquent\Relations\HasMany { diff --git a/app/Models/News.php b/app/Models/News.php index 2d3b5b7..48c67ff 100644 --- a/app/Models/News.php +++ b/app/Models/News.php @@ -6,11 +6,9 @@ use App\Lib\Helpers\FileStorageHelper; use App\Lib\Helpers\ToolboxHelper; use App\Traits\Models\ActivityLog; use App\Traits\Models\PlanificatedStatus; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; use Spatie\Sitemap\Contracts\Sitemapable; -use Spatie\Sitemap\Tags\Url; use Uwil\SitemapGenerator\Lib\SitemapHelper; /** @@ -41,13 +39,12 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper; class News extends Model implements Sitemapable { use ActivityLog; - use HasFactory; use PlanificatedStatus; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'seo_title', @@ -105,7 +102,7 @@ class News extends Model implements Sitemapable }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -172,11 +169,11 @@ class News extends Model implements Sitemapable } /** - * toSitemapTag method + * To sitemap tag method. * - * @return Url|string|array + * @return \Spatie\Sitemap\Tags\Url|string|array */ - public function toSitemapTag(): Url | string | array + public function toSitemapTag(): \Spatie\Sitemap\Tags\Url | string | array { $model = $this; $route = 'fo.news.show'; diff --git a/app/Models/Section.php b/app/Models/Section.php index 40fb7bb..10d747a 100644 --- a/app/Models/Section.php +++ b/app/Models/Section.php @@ -29,13 +29,14 @@ use App\Enums\StaticPageType; class Section extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\SectionFactory> */ use HasFactory; use MiniCrudModel; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'section', @@ -88,20 +89,19 @@ class Section extends Model } // * METHODS. - // * EMPTY BLOCS. /** * Empty bloc for picture. * - * @param array $data - * @param string $img - * @param string $imgAlt - * @param string $imgTitle - * @param integer $width - * @param integer $height - * @param boolean $required - * @param string $name - * @return array + * @param array $data + * @param string $img + * @param string $imgAlt + * @param string $imgTitle + * @param integer $width + * @param integer $height + * @param boolean $required + * @param string $name + * @return array */ public static function emptyPictureBloc( array $data, @@ -129,11 +129,11 @@ class Section extends Model /** * Empty bloc for link. * - * @param array $data - * @param string $url - * @param boolean $required - * @param string $name - * @return array + * @param array $data + * @param string $url + * @param boolean $required + * @param string $name + * @return array */ public static function emptyLinkBloc( array $data, @@ -154,9 +154,9 @@ class Section extends Model /** * Empty bloc for boolean new tab link. * - * @param array $data - * @param string $name - * @return array + * @param array $data + * @param string $name + * @return array */ public static function emptyLinkNewTabBloc( array $data, @@ -173,12 +173,11 @@ class Section extends Model /** * Empty bloc for key numbers. * - * @param array $data - * @param string $name - * @param integer $value - * @param boolean $required - * - * @return array + * @param array $data + * @param string $name + * @param integer $value + * @param boolean $required + * @return array */ public static function emptyKeyNumberBloc( array $data, @@ -199,10 +198,10 @@ class Section extends Model /** * Empty bloc for the button boolean. * - * @param array $data - * @param string $name - * @param boolean $value - * @return array + * @param array $data + * @param string $name + * @param boolean $value + * @return array */ public static function emptyButtonBooleanBloc( array $data, @@ -220,10 +219,10 @@ class Section extends Model /** * Empty bloc for a boolean. * - * @param array $data - * @param string $name - * @param boolean $value - * @return array + * @param array $data + * @param string $name + * @param boolean $value + * @return array */ public static function emptyBooleanBloc( array $data, @@ -241,11 +240,11 @@ class Section extends Model /** * Empty bloc for the h3 title. * - * @param array $data - * @param string $name - * @param string $value - * @param boolean $required - * @return array + * @param array $data + * @param string $name + * @param string $value + * @param boolean $required + * @return array */ public static function emptyStringBloc( array $data, @@ -266,12 +265,12 @@ class Section extends Model /** * Empty bloc for the WYSIWYG content. * - * @param array $data + * @param array $data * @param string $name * @param string $value * @param \App\Enums\CkEditorConfigName $config * @param boolean $required - * @return array + * @return array */ public static function emptyWysiwygBloc( array $data, @@ -292,7 +291,7 @@ class Section extends Model } /** - * Add part piece + * Add part piece. * * @return void */ @@ -305,15 +304,22 @@ class Section extends Model $this->countPartPieces() + 1 ); - $linesToSkip = 1; - $data = collect($this->data); + /** @var array $rawData */ + $rawData = $this->data; + $data = collect($rawData); + $linesToSkip = 1; + $groupedPieces = $data->skip($linesToSkip)->splitIn($data->count() / ($pieceTemplateLinesCount ?: 1)) ->concat([$pieceToAdd]) ->sort(function ($aCollect, $bCollect) { if ($this->section->equals(PageSectionEnum::produce_rhd)) { + /** @var array $aFirst */ + $aFirst = collect($aCollect)->first(); + /** @var array $bFirst */ + $bFirst = collect($bCollect)->first(); return strcmp( - strrev(collect(collect($aCollect)->first())->first()), - strrev(collect(collect($bCollect)->first())->first()) + strrev((string) collect($aFirst)->first()), + strrev((string) collect($bFirst)->first()) ); } return 0; @@ -323,7 +329,7 @@ class Section extends Model } /** - * Remove part piece + * Remove part piece. * * @param integer $index * @return integer Elements count removed. @@ -346,7 +352,7 @@ class Section extends Model } /** - * Count part pieces + * Count part pieces. * * @return integer */ @@ -367,9 +373,9 @@ class Section extends Model } /** - * Get part pieces + * Get part pieces. * - * @return array + * @return array */ private function getPartPieces(): array { @@ -378,28 +384,31 @@ class Section extends Model } /** - * Addable part piece block + * Addable part piece block. * * @param \App\Enums\Sections\PageSectionEnum $sectionEnum * @param integer $index - * @return array + * @return array|null */ public static function getAddablePartPieceBlock(PageSectionEnum $sectionEnum, int $index = 1): array|null { $data = null; $pieceTemplate = self::getAddablePartPieceBlockTemplate($sectionEnum); if (!is_null($pieceTemplate)) { - $data = json_decode(Str::of(json_encode($pieceTemplate))->replace('__index', strval($index)), true); - /** @var array $data */ + $encoded = json_encode($pieceTemplate); + if ($encoded !== false) { + /** @var array $data */ + $data = json_decode(Str::of($encoded)->replace('__index', strval($index)), true); + } } return $data; } /** - * Addable part piece block + * Addable part piece block. * * @param \App\Enums\Sections\PageSectionEnum $sectionEnum - * @return array + * @return array|null */ public static function getAddablePartPieceBlockIndexes(PageSectionEnum $sectionEnum): array|null { @@ -411,8 +420,10 @@ class Section extends Model } /** + * Addable part piece block template. + * * @param \App\Enums\Sections\PageSectionEnum $sectionEnum - * @return array|null + * @return array|null */ private static function getAddablePartPieceBlockTemplate(PageSectionEnum $sectionEnum): array|null { @@ -449,7 +460,7 @@ class Section extends Model * Returns the list of sections for a page type. * * @param \App\Enums\StaticPageType $type - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection */ public static function getSections(StaticPageType $type): \Illuminate\Database\Eloquent\Collection { @@ -460,7 +471,7 @@ class Section extends Model } /** - * Get the active section for a type page + * Get the active section for a type page. * * @param \App\Enums\StaticPageType $type * @return boolean @@ -475,12 +486,12 @@ class Section extends Model ); } - // * RELATIONS + // * RELATIONS. /** * Get the page that owns the section. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\StaticPage,$this> */ public function page(): \Illuminate\Database\Eloquent\Relations\BelongsTo { @@ -490,7 +501,7 @@ class Section extends Model /** * Get the sections that own the carousel. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\Carousel,$this> */ public function carousels(): \Illuminate\Database\Eloquent\Relations\HasMany { diff --git a/app/Models/Site.php b/app/Models/Site.php index 84c1069..282ad13 100644 --- a/app/Models/Site.php +++ b/app/Models/Site.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; use Spatie\Sitemap\Contracts\Sitemapable; -use Spatie\Sitemap\Tags\Url; use Uwil\SitemapGenerator\Lib\SitemapHelper; /** @@ -56,12 +55,13 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper; class Site extends Model implements Sitemapable { use ActivityLog; + /** @use HasFactory<\Database\Factories\SiteFactory> */ use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'seo_title', @@ -142,7 +142,7 @@ class Site extends Model implements Sitemapable }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -202,28 +202,28 @@ class Site extends Model implements Sitemapable ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id); } - // * RELATIONS - /** - * The logos that belong to the site. + * To sitemap tag method. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return \Spatie\Sitemap\Tags\Url|string|array */ - public function logos(): \Illuminate\Database\Eloquent\Relations\BelongsToMany - { - return $this->belongsToMany(Logo::class); - } - - /** - * toSitemapTag method - * - * @return Url|string|array - */ - public function toSitemapTag(): Url | string | array + public function toSitemapTag(): \Spatie\Sitemap\Tags\Url | string | array { $model = $this; $route = 'fo.sites.show'; $params = ['site' => $model]; return SitemapHelper::generateUrl($route, $params, $model); } + + // * RELATIONS. + + /** + * The logos that belong to the site. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\Logo,$this> + */ + public function logos(): \Illuminate\Database\Eloquent\Relations\BelongsToMany + { + return $this->belongsToMany(Logo::class); + } } diff --git a/app/Models/Slide.php b/app/Models/Slide.php index 5acd49a..a9bc234 100644 --- a/app/Models/Slide.php +++ b/app/Models/Slide.php @@ -29,6 +29,7 @@ use Illuminate\Validation\ValidationException; class Slide extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\SlideFactory> */ use HasFactory; /** @var integer Minimum number of published slides */ @@ -40,7 +41,7 @@ class Slide extends Model /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'type', @@ -106,7 +107,7 @@ class Slide extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. diff --git a/app/Models/StaticPage.php b/app/Models/StaticPage.php index 024c0e0..a157731 100644 --- a/app/Models/StaticPage.php +++ b/app/Models/StaticPage.php @@ -6,7 +6,6 @@ use App\Enums\StaticPageType; use App\Lib\Helpers\FileStorageHelper; use App\Lib\Helpers\ToolboxHelper; use App\Traits\Models\ActivityLog; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; @@ -29,12 +28,11 @@ use Illuminate\Support\Str; class StaticPage extends Model { use ActivityLog; - use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'seo_title', @@ -73,7 +71,7 @@ class StaticPage extends Model }); } - // * ROUTABLE + // * METHODS. /** * Get the value of the model's route key. @@ -99,8 +97,6 @@ class StaticPage extends Model return 'type'; } - // * METHODS - /** * Manage model fields. * @@ -162,12 +158,12 @@ class StaticPage extends Model return $query; } - // * RELATIONS + // * RELATIONS. /** * * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\Section,$this> */ public function sections(): \Illuminate\Database\Eloquent\Relations\HasMany { diff --git a/app/Models/Sticky.php b/app/Models/Sticky.php index b5d76d5..b5cc570 100644 --- a/app/Models/Sticky.php +++ b/app/Models/Sticky.php @@ -6,7 +6,6 @@ use App\Enums\StaticPageType; use App\Enums\Users\RoleEnum; use App\Traits\Models\ActivityLog; use Illuminate\Auth\Access\AuthorizationException; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; /** @@ -22,12 +21,11 @@ use Illuminate\Database\Eloquent\Model; class Sticky extends Model { use ActivityLog; - use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'type', diff --git a/app/Models/Strip.php b/app/Models/Strip.php index c2cf119..e0fed7a 100644 --- a/app/Models/Strip.php +++ b/app/Models/Strip.php @@ -26,13 +26,14 @@ use Illuminate\Database\Eloquent\Model; class Strip extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\StripFactory> */ use HasFactory; use PlanificatedStatus; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'picto', @@ -79,7 +80,7 @@ class Strip extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. @@ -95,12 +96,12 @@ class Strip extends Model } } - // * RELATIONS + // * RELATIONS. /** * Get the news that owns the strip. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\News,$this> */ public function news(): \Illuminate\Database\Eloquent\Relations\BelongsTo { diff --git a/app/Models/Testimonial.php b/app/Models/Testimonial.php index 687cd94..389983f 100644 --- a/app/Models/Testimonial.php +++ b/app/Models/Testimonial.php @@ -24,12 +24,13 @@ use Illuminate\Database\Eloquent\Model; class Testimonial extends Model { use ActivityLog; + /** @use HasFactory<\Database\Factories\TestimonialFactory> */ use HasFactory; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'name', @@ -71,7 +72,7 @@ class Testimonial extends Model }); } - // * METHODS + // * METHODS. /** * Manage model fields. diff --git a/app/Models/User.php b/app/Models/User.php index 5d6c0c4..152017e 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -24,13 +24,14 @@ use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use ActivityLog; + /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory; use Notifiable; /** * The attributes that are mass assignable. * - * @var array + * @var list */ protected $fillable = [ 'first_name', @@ -45,7 +46,7 @@ class User extends Authenticatable /** * The attributes that should be hidden for serialization. * - * @var array + * @var list */ protected $hidden = [ 'remember_token', @@ -57,10 +58,10 @@ class User extends Authenticatable * @var array */ protected $casts = [ - 'role' => RoleEnum::class, - 'last_connection' => 'date', - 'published' => 'boolean', - 'published_at' => 'datetime', + 'role' => RoleEnum::class, + 'last_connection' => 'date', + 'published' => 'boolean', + 'published_at' => 'datetime', ]; /** diff --git a/app/Traits/Controllers/ChangesModelOrder.php b/app/Traits/Controllers/ChangesModelOrder.php index 235f2fb..e6a549f 100644 --- a/app/Traits/Controllers/ChangesModelOrder.php +++ b/app/Traits/Controllers/ChangesModelOrder.php @@ -3,6 +3,7 @@ namespace App\Traits\Controllers; use App\Http\Requests\Bo\UpdateChangeOrderRequest; +use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Session; @@ -29,11 +30,11 @@ trait ChangesModelOrder throw new \RuntimeException("The {$className} class doesn't exist."); } - if (!\is_object($model)) { + if (!($model instanceof Model)) { throw new \RuntimeException("The second last param isn't an object."); } - if (get_class($model) !== (string)Str::of($className)->replaceStart('\\', '')) { + if (get_class($model) !== (string) Str::of($className)->replaceStart('\\', '')) { throw new \RuntimeException("The {$className} doesn't match second last binded param."); } diff --git a/app/Traits/Enums/BaseEnum.php b/app/Traits/Enums/BaseEnum.php index f636929..2fbbe16 100644 --- a/app/Traits/Enums/BaseEnum.php +++ b/app/Traits/Enums/BaseEnum.php @@ -4,9 +4,12 @@ namespace App\Traits\Enums; use Illuminate\Support\Str; +/** + * Provides rich functionality to PHP backed enums. + */ trait BaseEnum { - // * GENERIC METHODS + // * GENERIC METHODS. /** * Get enum value. @@ -38,12 +41,14 @@ trait BaseEnum return $this->name; } - // * STATIC FETCH METHODS + // * STATIC FETCH METHODS. /** * Get enum labels. * - * @return array + * @return array + * @throws \Error If missing definition label. + * @phpstan-ignore missingType.iterableValue */ public static function toLabels(): array { @@ -65,7 +70,8 @@ trait BaseEnum /** * Get enum values. * - * @return array + * @return array + * @phpstan-ignore missingType.iterableValue */ public static function toValues(): array { @@ -79,7 +85,8 @@ trait BaseEnum /** * Get enums. * - * @return array + * @return list + * @phpstan-ignore missingType.iterableValue */ public static function all(): array { @@ -89,7 +96,8 @@ trait BaseEnum /** * Get enums. * - * @return array + * @return array + * @phpstan-ignore missingType.iterableValue */ public static function toArray(): array { @@ -98,7 +106,7 @@ trait BaseEnum self::setCache('enums', \collect(self::cases()) ->mapWithKeys(function ($enum) use ($definitions) { $baseArray = [ - 'name' => $enum->name, + 'name' => $enum->name, 'label' => $enum->label(), 'value' => $enum->value, ]; @@ -109,7 +117,7 @@ trait BaseEnum } $baseArray[$index] = $elements[$enum->name]; } - return [$enum->name => (object)$baseArray]; + return [$enum->name => (object) $baseArray]; })->all()); } return self::getCache('enums'); @@ -120,21 +128,30 @@ trait BaseEnum * * @param self|integer|string $value * @param string $field - * @return self|null + * @return static|null */ public static function make(self|int|string $value, string $field = 'value'): self|null { if ($field === "label") { - $enumLabels = array_change_key_case(array_flip(self::toLabels()), CASE_LOWER); - $value = (isset($enumLabels[strtolower($value)])) ? $enumLabels[strtolower($value)] : false; - $field = 'name'; + $enumLabels = array_change_key_case( + array_flip(array_map(fn($value): string => Str::slug($value), self::toLabels())), + CASE_LOWER + ); + $searchValue = $value instanceof self ? (string) $value->value : (string) $value; + $slugged = Str::slug($searchValue); + $value = $enumLabels[$slugged] ?? false; + if ($value === false) { + return null; + } + $field = 'name'; } - return !\is_object($value) ? - \collect(self::cases())->keyBy($field)->get($value) : $value; + + /** @phpstan-ignore-next-line */ + return !\is_object($value) ? \collect(self::cases())->keyBy($field)->get($value) : $value; } /** - * Test if 2 enum are equals. + * Test if 2 enums are equals. * * @param object ...$others * @return boolean @@ -144,12 +161,11 @@ trait BaseEnum { foreach ($others as $other) { if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) { - throw new \Error(__METHOD__ . - ' requires $enum to use ' . BaseEnum::class); + throw new \Error(__METHOD__ . ' requires $enum to use ' . BaseEnum::class); } if ( get_class($this) === get_class($other) - && $this->value === $other->value + && $this->value === $other->value // @phpstan-ignore-line ) { return true; } @@ -167,14 +183,14 @@ trait BaseEnum return $this->value; } - - // * CACHE + // * CACHE. /** * Get cache array. * * @param string $index - * @return array + * @return array + * @phpstan-ignore missingType.iterableValue */ private static function getCache(string $index): array { @@ -188,9 +204,10 @@ trait BaseEnum /** * Set cache array. * - * @param string $index - * @param array $items + * @param string $index + * @param array $items * @return void + * @phpstan-ignore missingType.iterableValue */ private static function setCache(string $index, array $items): void { @@ -220,12 +237,13 @@ trait BaseEnum } } - // * PRIVATE + // * PRIVATE. /** * Fetch the LABELS constant if exists. * - * @return array|null + * @return array|null + * @phpstan-ignore missingType.iterableValue */ private static function getLabelsConstant(): array|null { @@ -241,21 +259,23 @@ trait BaseEnum /** * Get custom constants. * - * @return array + * @return array> + * @phpstan-ignore missingType.iterableValue */ private static function getCustomDefinitions(): array { - // ? Has custom props in cache ? if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) { $names = \collect(self::cases())->keyBy('name'); $GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants()) - ->filter(function (mixed $constant, string $key) use ($names) { + ->filter(function (mixed $constant, string $key) use ($names): bool { if ($key === 'LABELS' or !\is_array($constant)) { return false; } - return \collect($constant)->keys() - ->filter(fn (string $name) => $names->has($name))->count(); + $count = \collect($constant)->keys() + ->filter(fn (string $name) => $names->has($name)) + ->count(); + return $count > 0; })->all(); } return $GLOBALS[self::class]['customProps']; diff --git a/app/Traits/Models/ActivityLog.php b/app/Traits/Models/ActivityLog.php index 6c0ac7b..96a1cd5 100644 --- a/app/Traits/Models/ActivityLog.php +++ b/app/Traits/Models/ActivityLog.php @@ -2,8 +2,8 @@ namespace App\Traits\Models; -use App\Models\ActivityLog as ModelsActivityLog; use App\Observers\ModelObserver; +use App\Models\ActivityLog as ActivityLogModel; /** * If there is a static function in a trait (named boot[TraitName]), @@ -27,10 +27,10 @@ trait ActivityLog /** * Activities logs One-to-many relationship. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\ActivityLog, covariant static> */ public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany { - return $this->hasMany(ModelsActivityLog::class); + return $this->hasMany(ActivityLogModel::class, 'model_id'); } } diff --git a/app/Traits/Models/MiniCrudModel.php b/app/Traits/Models/MiniCrudModel.php index 3e72544..a07c052 100644 --- a/app/Traits/Models/MiniCrudModel.php +++ b/app/Traits/Models/MiniCrudModel.php @@ -11,7 +11,7 @@ trait MiniCrudModel /** * Fill the model with an array of attributes. * - * @param array $attributes + * @param array $attributes * @return $this * * @throws \Illuminate\Database\Eloquent\MassAssignmentException If fill prop is not allowed. @@ -34,7 +34,7 @@ trait MiniCrudModel */ public function minicrudCreating(): void { - /** @var array */ + /** @var array> */ $data = $this->data; foreach ($data as &$input) { switch ($input['inputType']) { @@ -64,8 +64,9 @@ trait MiniCrudModel */ public function minicrudUpdated(): void { - /** @var array $input */ - foreach ($this->data as $index => $input) { + /** @var array> $data */ + $data = $this->data; + foreach ($data as $index => $input) { switch ($input['inputType']) { case InputType::text->value: $original = ToolboxHelper::getOriginal($this, 'data'); @@ -92,8 +93,9 @@ trait MiniCrudModel */ public function minicrudDeleted(): void { - /** @var array $input */ - foreach ($this->data as $index => $input) { + /** @var array> $data */ + $data = $this->data; + foreach ($data as $index => $input) { switch ($input['inputType']) { case InputType::text->value: FileStorageHelper::removeModelFilesOfHtml($input['value']); @@ -112,7 +114,7 @@ trait MiniCrudModel /** * Set a specific prop. * - * @param array $data + * @param array $data * @return void */ private function setData(array $data): void @@ -127,7 +129,7 @@ trait MiniCrudModel /** * Set a specific prop. * - * @param array $value + * @param array $value * @return void */ protected function setDataAttribute(array $value): void @@ -142,7 +144,7 @@ trait MiniCrudModel * Set a specific prop. * * @param string|null $data - * @return array + * @return array */ protected function getDataAttribute(string|null $data): array { @@ -152,8 +154,8 @@ trait MiniCrudModel /** * Serialize properties. * - * @param array $data - * @return array + * @param array> $data + * @return array> * @throws \ErrorException If input type is no handled. * @throws \Illuminate\Validation\ValidationException If url is a bo url. * @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber diff --git a/app/Traits/Requests/HasPicture.php b/app/Traits/Requests/HasPicture.php index 8b5ec58..d3d770c 100644 --- a/app/Traits/Requests/HasPicture.php +++ b/app/Traits/Requests/HasPicture.php @@ -49,7 +49,7 @@ trait HasPicture * @param integer|null $size * @param string|null $requiredWith * @param string|null $requiredWithout - * @return array + * @return array|string> */ public function pictureRules( string $name = 'picture', @@ -62,10 +62,10 @@ trait HasPicture ?string $requiredWith = null, ?string $requiredWithout = null, ): array { - $dimensions = (object)[ - 'minWidth' => $minWidth ?? $this->minWidth, + $dimensions = [ + 'minWidth' => $minWidth ?? $this->minWidth, 'minHeight' => $minHeight ?? $this->minHeight, - 'maxWidth' => $maxWidth ?? $this->maxWidth, + 'maxWidth' => $maxWidth ?? $this->maxWidth, 'maxHeight' => $maxHeight ?? $this->maxHeight ]; return [ @@ -92,7 +92,7 @@ trait HasPicture * @param integer $limitMin * @param integer $limitMax * @param boolean $nullable - * @return array + * @return array|string> */ public function picturesRules( string $name = 'pictures', @@ -104,10 +104,10 @@ trait HasPicture int $limitMax = 5, bool $nullable = false ): array { - $sizes = (object)[ - 'minWidth' => $minWidth ?? $this->minWidth, + $sizes = [ + 'minWidth' => $minWidth ?? $this->minWidth, 'minHeight' => $minHeight ?? $this->minHeight, - 'maxWidth' => $maxWidth ?? $this->maxWidth, + 'maxWidth' => $maxWidth ?? $this->maxWidth, 'maxHeight' => $maxHeight ?? $this->maxHeight, ]; return [ diff --git a/config/app.php b/config/app.php index 3bb0a77..35e9102 100644 --- a/config/app.php +++ b/config/app.php @@ -41,7 +41,7 @@ return [ | */ - 'debug' => (bool)env('APP_DEBUG', false), + 'debug' => (bool) env('APP_DEBUG', false), /* |-------------------------------------------------------------------------- diff --git a/config/sentry.php b/config/sentry.php index 29627fe..3d0ed01 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -51,11 +51,11 @@ return [ 'missing_routes' => false, ], - // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii. + // See: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii. 'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false), - // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate. - 'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'), + // See: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate. + 'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float) env('SENTRY_TRACES_SAMPLE_RATE'), 'before_send' => [\App\Lib\Helpers\ExceptionsHelper::class, 'sentryEventHandler'], ]; diff --git a/phpcs.xml b/phpcs.xml index 6f483f1..74a2cd7 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -21,26 +21,28 @@ - + + + - + @@ -103,10 +105,14 @@ + + + + @@ -119,5 +125,4 @@ */database/migrations/* - diff --git a/phpstan.neon b/phpstan.neon index df74d87..19c7838 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -6,5 +6,4 @@ parameters: paths: - app/ - # Level 9 is the highest level - level: 5 + level: 7 From 70d9f09a0e91d1b4b8c419b7bb6ed3fbebfaa991 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:09:27 +0200 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=F0=9F=94=A7=20add=20redirection=20?= =?UTF-8?q?to=20omit=20index.php=20in=20.htaccess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/.htaccess | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/.htaccess b/public/.htaccess index 3aec5e2..1412a04 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -14,6 +14,10 @@ RewriteCond %{REQUEST_URI} (.+)/$ RewriteRule ^ %1 [L,R=301] + # Redirect /index.php/anything to /anything + RewriteCond %{THE_REQUEST} /index\.php/([^\s?]*) [NC] + RewriteRule ^index\.php/(.*)$ /$1 [L,R=301,NC] + # Send Requests To Front Controller... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f From e7330d27f8c522f97b88b93cca2a0fe86bbcb917 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:12:42 +0200 Subject: [PATCH 6/9] =?UTF-8?q?chore:=20=F0=9F=91=B7=20use=20variable=20to?= =?UTF-8?q?=20define=20version=20of=20docker=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f7f9c9a..1b64bcc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:070426-150359 +FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG} COPY --chown=www-data:www-data . /app/srcs USER root RUN chmod -R 755 /app/srcs/storage From 6add647e124a962821fab749fdb3fd9fa8a2f323 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:12:52 +0200 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=E2=9C=A8=20add=20commit=20lint=20f?= =?UTF-8?q?rom=20husky=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .husky/commit-msg | 3 + commitlint.config.cjs | 1 + package-lock.json | 722 +++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 4 files changed, 719 insertions(+), 8 deletions(-) create mode 100644 .husky/commit-msg create mode 100644 commitlint.config.cjs diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..8c332e2 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,3 @@ +#!/bin/sh + +npx --no -- commitlint --config node_modules/@uwil/husky-config/commitlint.config.cjs --edit $1 diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..4a3f8f8 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1 @@ +module.exports = require('@uwil/husky-config/commitlint.config.cjs'); diff --git a/package-lock.json b/package-lock.json index eff0269..5eec683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@types/toastify-js": "^1.12.1", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.36.2", + "@uwil/husky-config": "^1.0.1", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-vue": "^4.6.2", "@vue/compiler-sfc": "latest", @@ -382,6 +383,407 @@ "node": ">=6.9.0" } }, + "node_modules/@commitlint/cli": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz", + "integrity": "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^20.5.0", + "@commitlint/lint": "^20.5.0", + "@commitlint/load": "^20.5.0", + "@commitlint/read": "^20.5.0", + "@commitlint/types": "^20.5.0", + "tinyexec": "^1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz", + "integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-conventionalcommits": "^9.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", + "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@commitlint/ensure": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.0.tgz", + "integrity": "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", + "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", + "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.0.tgz", + "integrity": "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.5.0", + "@commitlint/parse": "^20.5.0", + "@commitlint/rules": "^20.5.0", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.0.tgz", + "integrity": "sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.5.0", + "@commitlint/types": "^20.5.0", + "cosmiconfig": "^9.0.1", + "cosmiconfig-typescript-loader": "^6.1.0", + "is-plain-obj": "^4.1.0", + "lodash.mergewith": "^4.6.2", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", + "integrity": "sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "2.6.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, + "node_modules/@commitlint/load/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/message": { + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.3.tgz", + "integrity": "sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.5.0.tgz", + "integrity": "sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-angular": "^8.2.0", + "conventional-commits-parser": "^6.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.5.0.tgz", + "integrity": "sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^20.4.3", + "@commitlint/types": "^20.5.0", + "git-raw-commits": "^5.0.0", + "minimist": "^1.2.8", + "tinyexec": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.0.tgz", + "integrity": "sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/types": "^20.5.0", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.0.tgz", + "integrity": "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^20.5.0", + "@commitlint/message": "^20.4.3", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", + "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.3.tgz", + "integrity": "sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.5.0.tgz", + "integrity": "sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-parser": "^6.3.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@conventional-changelog/git-client": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.7.0.tgz", + "integrity": "sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/child-process-utils": "^1.0.0", + "@simple-libs/stream-utils": "^1.2.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.4.0" + }, + "peerDependenciesMeta": { + "conventional-commits-filter": { + "optional": true + }, + "conventional-commits-parser": { + "optional": true + } + } + }, + "node_modules/@conventional-changelog/git-client/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz", @@ -1168,6 +1570,35 @@ "node": ">= 8.0.0" } }, + "node_modules/@simple-libs/child-process-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", + "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@simple-libs/stream-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", + "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, "node_modules/@sipec/vue3-tags-input": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@sipec/vue3-tags-input/-/vue3-tags-input-3.0.4.tgz", @@ -1618,6 +2049,21 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@uwil/husky-config": { + "version": "1.0.1", + "resolved": "https://lab.s-web.fr/api/v4/projects/259/packages/npm/@uwil/husky-config/-/@uwil/husky-config-1.0.1.tgz", + "integrity": "sha1-VGchal1LcEFXNFsQZxh5pn4495Q=", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@commitlint/cli": "^20.5.0", + "@commitlint/config-conventional": "^20.5.0", + "husky": "^9.1.7" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", @@ -2434,6 +2880,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, "node_modules/array-includes": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", @@ -3111,12 +3564,79 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/conventional-changelog-angular": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", + "integrity": "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.1.tgz", + "integrity": "sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-parser": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.4.0.tgz", + "integrity": "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", + "meow": "^13.0.0" + }, + "bin": { + "conventional-commits-parser": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-parser/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3368,6 +3888,19 @@ "node": ">=6.0.0" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.665", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz", @@ -3600,10 +4133,11 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4210,6 +4744,23 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -4553,6 +5104,36 @@ "node": ">= 10.0.0" } }, + "node_modules/git-raw-commits": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", + "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@conventional-changelog/git-client": "^2.6.0", + "meow": "^13.0.0" + }, + "bin": { + "git-raw-commits": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/git-raw-commits/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4591,6 +5172,32 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -4883,6 +5490,22 @@ "node": ">= 14" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -4943,6 +5566,17 @@ "node": ">=8" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5186,6 +5820,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -5358,6 +6002,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5555,18 +6209,60 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5732,7 +6428,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6189,10 +6884,11 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -8111,6 +8807,16 @@ "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==", "dev": true }, + "node_modules/tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/package.json b/package.json index 40c26e9..894892b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@types/toastify-js": "^1.12.1", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.36.2", + "@uwil/husky-config": "^1.0.1", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-vue": "^4.6.2", "@vue/compiler-sfc": "latest", From 5fe32c9f7355f482aebc0e5b18a2d452954dca0f Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 24 Apr 2026 15:25:52 +0200 Subject: [PATCH 8/9] fix: :fire: remove double click on leaflet markers #90 --- package-lock.json | 9 +++++---- resources/ts/fo/components/LeafletMapVueComponent.vue | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index eff0269..1a2aa3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2947,9 +2947,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", + "version": "1.0.30001790", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz", + "integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==", "dev": true, "funding": [ { @@ -2964,7 +2964,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", diff --git a/resources/ts/fo/components/LeafletMapVueComponent.vue b/resources/ts/fo/components/LeafletMapVueComponent.vue index f4b95f5..8591674 100644 --- a/resources/ts/fo/components/LeafletMapVueComponent.vue +++ b/resources/ts/fo/components/LeafletMapVueComponent.vue @@ -206,10 +206,6 @@ export default defineComponent({ // @ts-ignore this.oms.addMarker(marker); site.marker = marker; - - marker.on("dblclick", () => { - window.location.href = `/sites/${site.slug}`; - }); }); }, updateMarkers() { From d3af7c03be92c466ab0b3f42ab0696c7d42ccff5 Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Mon, 27 Apr 2026 10:09:37 +0200 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=F0=9F=94=A7=20add=20assets=20cache?= =?UTF-8?q?=20in=20.htaccess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/.htaccess | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/public/.htaccess b/public/.htaccess index 1412a04..9ce7c3d 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -23,3 +23,68 @@ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] + + + ExpiresActive On + + # Images + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/webp "access plus 1 year" + ExpiresByType image/svg+xml "access plus 1 year" + + # CSS / JS + ExpiresByType text/css "access plus 1 year" + ExpiresByType text/javascript "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + ExpiresByType application/x-javascript "access plus 1 year" + + # WOFF / WOFF2 / Fonts + ExpiresByType application/font-woff "access plus 1 year" + ExpiresByType font/woff "access plus 1 year" + ExpiresByType application/font-woff2 "access plus 1 year" + ExpiresByType font/woff2 "access plus 1 year" + + # Favicon + ExpiresByType image/x-icon "access plus 1 year" + + + + Header set Cache-Control "public, max-age=31536000, immutable" + + + + AddOutputFilterByType BROTLI_COMPRESS text/html text/css text/plain text/xml text/javascript application/javascript application/x-javascript + AddType text/plain .br + + + + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE image/svg+xml + + + + AddType application/javascript .js + AddType font/woff2 .woff2 + AddType application/font-woff2 .woff2 + AddType application/font-woff .woff + AddType font/woff .woff + AddType image/svg+xml .svg + + + + FileETag None + Header unset ETag + Header unset Set-Cookie + \ No newline at end of file