diff --git a/.github/workflows/tag_version.yml b/.github/workflows/tag_version.yml new file mode 100644 index 0000000..c6ba323 --- /dev/null +++ b/.github/workflows/tag_version.yml @@ -0,0 +1,42 @@ +name: Tag Develop on PR Merge + +on: + pull_request: + branches: [ develop ] + types: [ closed ] # só dispara quando o PR é fechado + +jobs: + tag-dev: + # Só executa se o PR foi merged (não se foi fechado sem merge) + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + permissions: + contents: write # necessário para criar tags + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # necessário para buscar tags existentes + + - name: Create dev tag if not exists + run: | + # Ler a versão base do version.txt + BASE_VERSION=$(cat version.txt) + COMMIT_SHORT=$(git rev-parse --short HEAD) + DEV_TAG="${BASE_VERSION}-dev.${COMMIT_SHORT}" + + echo "Versão base: $BASE_VERSION" + echo "Commit do merge: $COMMIT_SHORT" + echo "Tag proposta: $DEV_TAG" + + # Buscar todas as tags remotas + git fetch --tags + + # Verificar se a tag já existe + if git rev-parse --tags "$DEV_TAG" >/dev/null 2>&1; then + echo "⚠️ A tag $DEV_TAG já existe. Pulando criação." + else + echo "✅ Criando e enviando tag: $DEV_TAG" + git tag "$DEV_TAG" + git push origin "$DEV_TAG" + fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d7ac41..3c419b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,15 +3,6 @@ Todas as mudanças relevantes serão documentadas nesse arquivo. O formato é baseado no [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0), e esse projeto adere ao [Semantic Versionning](https://semver.org/spec/v2.0.0.html). -## [1.2.0] - 2025-11-18 -### Modificado -- Reorganizado mensageria e documentado -- Cobertura para os testes - -### Adicionado -- Logs para o containers -- Auditoria para envio dos emails - ## [1.1.0] - 2024-10-28 ### Modificado - Requisição para endpoint diff --git a/Dockerfile b/Dockerfile index d09d6ba..e58cc48 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ RUN apt-get update && apt-get install -y \ libfreetype6-dev \ libonig-dev \ libzip-dev \ + libpq-dev \ unzip \ zip \ libxml2-dev \ @@ -30,7 +31,7 @@ RUN apt-get update && apt-get install -y \ gnupg \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install gd \ - && docker-php-ext-install pdo pdo_mysql mbstring exif pcntl bcmath opcache intl zip sockets \ + && docker-php-ext-install pdo pdo_pgsql pgsql mbstring exif pcntl bcmath opcache intl zip sockets \ && /usr/bin/composer install \ && rm -rf /var/lib/apt/lists/* \ && chown -R www-data:www-data /var/www/html diff --git a/app/Console/Commands/ImportRegistrationCommand.php b/app/Console/Commands/ImportRegistrationCommand.php index 1ec5793..411a892 100644 --- a/app/Console/Commands/ImportRegistrationCommand.php +++ b/app/Console/Commands/ImportRegistrationCommand.php @@ -2,6 +2,7 @@ namespace App\Console\Commands; +use App\Events\ImportRegistrationEvent; use Illuminate\Console\Command; use App\Services\RabbitMQService; use Illuminate\Support\Facades\Log; @@ -56,11 +57,7 @@ protected function processMessage(AMQPMessage $msg) return; } - foreach ($registrations as $registration) { - Mail::to($registration['agent_email'])->send(new ImporteRegistrationMail($registration)); - Log::info('Email enviado para ' . $registration['agent_email']); - - } + event(new ImportRegistrationEvent($registrations)); // Confirmar a mensagem após processamento $msg->ack(); } catch (\Exception $e) { diff --git a/app/Events/ImportRegistrationEvent.php b/app/Events/ImportRegistrationEvent.php new file mode 100644 index 0000000..975aa74 --- /dev/null +++ b/app/Events/ImportRegistrationEvent.php @@ -0,0 +1,35 @@ +registrations = $registrations; + } + + /** + * Get the channels the event should broadcast on. + * + * @return array + */ + public function broadcastOn(): array + { + return [ + new PrivateChannel('channel-name'), + ]; + } +} diff --git a/app/Listeners/ImportRegistrationListener.php b/app/Listeners/ImportRegistrationListener.php new file mode 100644 index 0000000..8832508 --- /dev/null +++ b/app/Listeners/ImportRegistrationListener.php @@ -0,0 +1,73 @@ +registrations as $registration) { + if (!$this->isValidRegistration($registration)) { + Log::error('Chaves obrigatórias ausentes na inscrição: ' . json_encode($registration)); + continue; + } + + Log::info('Enviando e-mail para: ' . $registration['agent_email']); + + // Cria o Mailable + $mailable = new ImporteRegistrationMail($registration); + + // Audita em EmailDispatch com o conteúdo renderizado + EmailDispatch::create([ + 'to' => $registration['agent_name'], + 'subject' => $mailable->envelope()->subject, + 'content' => $mailable->render(), + 'mailable_type' => ImporteRegistrationMail::class, + 'meta' => [ + 'registration' => $registration['registration'], + 'opp_id' => $registration['opp_id'], + 'opp_name' => $registration['opp_name'], + 'number' => $registration['number'], + 'agent_name' => $registration['agent_name'], + 'agent_email' => $registration['agent_email'], + ], + 'dispatched_at' => now(), + ]); + + Mail::to($registration['agent_email'])->send($mailable); + Log::info('Email enviado e auditado para: ' . $registration['agent_email']); + } + } + + /** + * Valida se a inscrição possui as chaves obrigatórias + */ + protected function isValidRegistration(array $registration): bool + { + return isset( + $registration['registration'], + $registration['opp_id'], + $registration['opp_name'], + $registration['number'], + $registration['agent_name'], + $registration['agent_email'] + ); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index efc0cc7..a4a3691 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -3,8 +3,10 @@ namespace App\Providers; use App\Events\OpinionManagementEvent; +use App\Events\ImportRegistrationEvent; use App\Listeners\AuditMessageListener; use App\Listeners\OpinionManagementListener; +use App\Listeners\ImportRegistrationListener; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider @@ -13,6 +15,9 @@ class EventServiceProvider extends ServiceProvider OpinionManagementEvent::class => [ OpinionManagementListener::class, ], + ImportRegistrationEvent::class => [ + ImportRegistrationListener::class, + ], ]; /** * Register services. diff --git a/composer.lock b/composer.lock index bf7d0b5..6d6cf44 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "brick/math", - "version": "0.14.0", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.0" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -64,7 +64,7 @@ "type": "github" } ], - "time": "2025-08-29T12:40:03+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -379,29 +379,28 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" + "php": "^8.2|^8.3|^8.4|^8.5" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.32|^2.1.31", + "phpunit/phpunit": "^8.5.48|^9.0" }, "type": "library", "extra": { @@ -432,7 +431,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" }, "funding": [ { @@ -440,7 +439,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2025-10-31T18:51:33+00:00" }, { "name": "egulias/email-validator", @@ -511,31 +510,31 @@ }, { "name": "fruitcake/php-cors", - "version": "v1.3.0", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6|^7" + "php": "^8.1", + "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" }, "require-dev": { - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -566,7 +565,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" }, "funding": [ { @@ -578,7 +577,7 @@ "type": "github" } ], - "time": "2023-10-12T05:21:21+00:00" + "time": "2025-12-03T09:33:47+00:00" }, { "name": "graham-campbell/result-type", @@ -1155,16 +1154,16 @@ }, { "name": "laravel/framework", - "version": "v12.30.1", + "version": "v12.42.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "7f61e8679f9142f282a0184ac7ef9e3834bfd023" + "reference": "509b33095564c5165366d81bbaa0afaac28abe75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/7f61e8679f9142f282a0184ac7ef9e3834bfd023", - "reference": "7f61e8679f9142f282a0184ac7ef9e3834bfd023", + "url": "https://api.github.com/repos/laravel/framework/zipball/509b33095564c5165366d81bbaa0afaac28abe75", + "reference": "509b33095564c5165366d81bbaa0afaac28abe75", "shasum": "" }, "require": { @@ -1192,7 +1191,6 @@ "monolog/monolog": "^3.0", "nesbot/carbon": "^3.8.4", "nunomaduro/termwind": "^2.0", - "phiki/phiki": "^2.0.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", @@ -1253,6 +1251,7 @@ "illuminate/process": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", + "illuminate/reflection": "self.version", "illuminate/routing": "self.version", "illuminate/session": "self.version", "illuminate/support": "self.version", @@ -1277,13 +1276,13 @@ "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", "opis/json-schema": "^2.4.1", - "orchestra/testbench-core": "^10.6.5", + "orchestra/testbench-core": "^10.8.1", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", "predis/predis": "^2.3|^3.0", - "resend/resend-php": "^0.10.0", + "resend/resend-php": "^0.10.0|^1.0", "symfony/cache": "^7.2.0", "symfony/http-client": "^7.2.0", "symfony/psr-http-message-bridge": "^7.2.0", @@ -1317,7 +1316,7 @@ "predis/predis": "Required to use the predis connector (^2.3|^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0|^1.0).", "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", @@ -1339,6 +1338,7 @@ "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Log/functions.php", + "src/Illuminate/Reflection/helpers.php", "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], @@ -1347,7 +1347,8 @@ "Illuminate\\Support\\": [ "src/Illuminate/Macroable/", "src/Illuminate/Collections/", - "src/Illuminate/Conditionable/" + "src/Illuminate/Conditionable/", + "src/Illuminate/Reflection/" ] } }, @@ -1371,20 +1372,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-09-18T21:07:07+00:00" + "time": "2025-12-09T15:51:23+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.6", + "version": "v0.3.8", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "86a8b692e8661d0fb308cec64f3d176821323077" + "reference": "096748cdfb81988f60090bbb839ce3205ace0d35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", - "reference": "86a8b692e8661d0fb308cec64f3d176821323077", + "url": "https://api.github.com/repos/laravel/prompts/zipball/096748cdfb81988f60090bbb839ce3205ace0d35", + "reference": "096748cdfb81988f60090bbb839ce3205ace0d35", "shasum": "" }, "require": { @@ -1400,9 +1401,9 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" + "pestphp/pest": "^2.3|^3.4|^4.0", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -1428,22 +1429,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.6" + "source": "https://github.com/laravel/prompts/tree/v0.3.8" }, - "time": "2025-07-07T14:17:42+00:00" + "time": "2025-11-21T20:52:52+00:00" }, { "name": "laravel/sanctum", - "version": "v4.2.0", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677" + "reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/f5fb373be39a246c74a060f2cf2ae2c2145b3664", + "reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664", "shasum": "" }, "require": { @@ -1457,9 +1458,8 @@ }, "require-dev": { "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^11.3" + "orchestra/testbench": "^9.15|^10.8", + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { @@ -1494,20 +1494,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2025-07-09T19:45:24+00:00" + "time": "2025-11-21T13:59:03+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.4", + "version": "v2.0.7", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/cb291e4c998ac50637c7eeb58189c14f5de5b9dd", + "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -1555,20 +1555,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-03-19T13:51:03+00:00" + "time": "2025-11-21T20:52:36+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.1", + "version": "v2.10.2", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + "reference": "3bcb5f62d6f837e0f093a601e26badafb127bd4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "url": "https://api.github.com/repos/laravel/tinker/zipball/3bcb5f62d6f837e0f093a601e26badafb127bd4c", + "reference": "3bcb5f62d6f837e0f093a601e26badafb127bd4c", "shasum": "" }, "require": { @@ -1619,40 +1619,40 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.1" + "source": "https://github.com/laravel/tinker/tree/v2.10.2" }, - "time": "2025-01-27T14:24:01+00:00" + "time": "2025-11-20T16:29:12+00:00" }, { "name": "lcobucci/clock", - "version": "3.3.1", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.29", - "lcobucci/coding-standard": "^11.1.0", + "infection/infection": "^0.31", + "lcobucci/coding-standard": "^11.2.0", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.10.25", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^11.3.6" + "phpstan/phpstan": "^2.0.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0.0", + "phpstan/phpstan-strict-rules": "^2.0.0", + "phpunit/phpunit": "^12.0.0" }, "type": "library", "autoload": { @@ -1673,7 +1673,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.3.1" + "source": "https://github.com/lcobucci/clock/tree/3.5.0" }, "funding": [ { @@ -1685,7 +1685,7 @@ "type": "patreon" } ], - "time": "2024-09-24T20:45:14+00:00" + "time": "2025-10-27T09:03:17+00:00" }, { "name": "lcobucci/jwt", @@ -1763,16 +1763,16 @@ }, { "name": "league/commonmark", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", "shasum": "" }, "require": { @@ -1809,7 +1809,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.8-dev" + "dev-main": "2.9-dev" } }, "autoload": { @@ -1866,7 +1866,7 @@ "type": "tidelift" } ], - "time": "2025-07-20T12:47:49+00:00" + "time": "2025-11-26T21:48:24+00:00" }, { "name": "league/config", @@ -1952,16 +1952,16 @@ }, { "name": "league/flysystem", - "version": "3.30.0", + "version": "3.30.2", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", - "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", + "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", "shasum": "" }, "require": { @@ -2029,22 +2029,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.30.2" }, - "time": "2025-06-25T13:29:59+00:00" + "time": "2025-11-10T17:13:11+00:00" }, { "name": "league/flysystem-local", - "version": "3.30.0", + "version": "3.30.2", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" + "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", - "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ab4f9d0d672f601b102936aa728801dd1a11968d", + "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d", "shasum": "" }, "require": { @@ -2078,9 +2078,9 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.2" }, - "time": "2025-05-21T10:34:19+00:00" + "time": "2025-11-10T11:23:37+00:00" }, { "name": "league/mime-type-detection", @@ -2140,33 +2140,38 @@ }, { "name": "league/uri", - "version": "7.5.1", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "81fb5145d2644324614cc532b28efd0215bda430" + "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", - "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807", + "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.5", - "php": "^8.1" + "league/uri-interfaces": "^7.7", + "php": "^8.1", + "psr/http-factory": "^1" }, "conflict": { "league/uri-schemes": "^1.0" }, "suggest": { "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", "ext-fileinfo": "to create Data URI from file contennts", "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", + "ext-uri": "to use the PHP native URI class", "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", "league/uri-components": "Needed to easily manipulate URI objects components", + "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -2194,6 +2199,7 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ + "URN", "data-uri", "file-uri", "ftp", @@ -2206,9 +2212,11 @@ "psr-7", "query-string", "querystring", + "rfc2141", "rfc3986", "rfc3987", "rfc6570", + "rfc8141", "uri", "uri-template", "url", @@ -2218,7 +2226,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.5.1" + "source": "https://github.com/thephpleague/uri/tree/7.7.0" }, "funding": [ { @@ -2226,26 +2234,25 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2025-12-07T16:02:06+00:00" }, { "name": "league/uri-interfaces", - "version": "7.5.0", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c", + "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", - "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -2253,6 +2260,7 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -2277,7 +2285,7 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common interfaces and classes for URI representation and interaction", + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", "homepage": "https://uri.thephpleague.com", "keywords": [ "data-uri", @@ -2302,7 +2310,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0" }, "funding": [ { @@ -2310,7 +2318,7 @@ "type": "github" } ], - "time": "2024-12-08T08:18:47+00:00" + "time": "2025-12-07T16:03:21+00:00" }, { "name": "monolog/monolog", @@ -2417,16 +2425,16 @@ }, { "name": "nesbot/carbon", - "version": "3.10.3", + "version": "3.11.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f" + "reference": "bdb375400dcd162624531666db4799b36b64e4a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", - "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", + "reference": "bdb375400dcd162624531666db4799b36b64e4a1", "shasum": "" }, "require": { @@ -2434,9 +2442,9 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3.12 || ^7.0", + "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -2518,29 +2526,29 @@ "type": "tidelift" } ], - "time": "2025-09-06T13:39:36+00:00" + "time": "2025-12-02T21:04:28+00:00" }, { "name": "nette/schema", - "version": "v1.3.2", + "version": "v1.3.3", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.4" + "php": "8.1 - 8.5" }, "require-dev": { "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^1.0", + "phpstan/phpstan-nette": "^2.0@stable", "tracy/tracy": "^2.8" }, "type": "library", @@ -2550,6 +2558,9 @@ } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -2578,26 +2589,26 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.2" + "source": "https://github.com/nette/schema/tree/v1.3.3" }, - "time": "2024-10-06T23:10:23+00:00" + "time": "2025-10-30T22:57:59+00:00" }, { "name": "nette/utils", - "version": "v4.0.8", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + "reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "url": "https://api.github.com/repos/nette/utils/zipball/fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", + "reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", "shasum": "" }, "require": { - "php": "8.0 - 8.5" + "php": "8.2 - 8.5" }, "conflict": { "nette/finder": "<3", @@ -2620,7 +2631,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -2667,22 +2678,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.8" + "source": "https://github.com/nette/utils/tree/v4.1.0" }, - "time": "2025-08-06T21:43:34+00:00" + "time": "2025-12-01T17:49:23+00:00" }, { "name": "nikic/php-parser", - "version": "v5.6.1", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -2725,37 +2736,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-08-13T20:13:15+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.1", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.2.6" + "symfony/console": "^7.3.6" }, "require-dev": { - "illuminate/console": "^11.44.7", - "laravel/pint": "^1.22.0", + "illuminate/console": "^11.46.1", + "laravel/pint": "^1.25.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.2", - "phpstan/phpstan": "^1.12.25", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.2.6", + "symfony/var-dumper": "^7.3.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -2798,7 +2809,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" }, "funding": [ { @@ -2814,7 +2825,7 @@ "type": "github" } ], - "time": "2025-05-08T08:14:37+00:00" + "time": "2025-11-20T02:34:59+00:00" }, { "name": "nyholm/psr7", @@ -2980,24 +2991,26 @@ }, { "name": "paragonie/constant_time_encoding", - "version": "v3.0.0", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", "shasum": "" }, "require": { "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^9", - "vimeo/psalm": "^4|^5" + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" }, "type": "library", "autoload": { @@ -3043,7 +3056,7 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:36:18+00:00" + "time": "2025-09-24T15:06:41+00:00" }, { "name": "paragonie/random_compat", @@ -3095,89 +3108,18 @@ }, "time": "2020-10-15T08:29:30+00:00" }, - { - "name": "phiki/phiki", - "version": "v2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phikiphp/phiki.git", - "reference": "160785c50c01077780ab217e5808f00ab8f05a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phikiphp/phiki/zipball/160785c50c01077780ab217e5808f00ab8f05a13", - "reference": "160785c50c01077780ab217e5808f00ab8f05a13", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "league/commonmark": "^2.5.3", - "php": "^8.2", - "psr/simple-cache": "^3.0" - }, - "require-dev": { - "illuminate/support": "^11.45", - "laravel/pint": "^1.18.1", - "orchestra/testbench": "^9.15", - "pestphp/pest": "^3.5.1", - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.0", - "symfony/var-dumper": "^7.1.6" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Phiki\\Adapters\\Laravel\\PhikiServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Phiki\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ryan Chandler", - "email": "support@ryangjchandler.co.uk", - "homepage": "https://ryangjchandler.co.uk", - "role": "Developer" - } - ], - "description": "Syntax highlighting using TextMate grammars in PHP.", - "support": { - "issues": "https://github.com/phikiphp/phiki/issues", - "source": "https://github.com/phikiphp/phiki/tree/v2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sponsors/ryangjchandler", - "type": "github" - }, - { - "url": "https://buymeacoffee.com/ryangjchandler", - "type": "other" - } - ], - "time": "2025-09-20T17:21:02+00:00" - }, { "name": "php-amqplib/php-amqplib", - "version": "v3.7.3", + "version": "v3.7.4", "source": { "type": "git", "url": "https://github.com/php-amqplib/php-amqplib.git", - "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59" + "reference": "381b6f7c600e0e0c7463cdd7f7a1a3bc6268e5fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9f50fe69a9f1a19e2cb25596a354d705de36fe59", - "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/381b6f7c600e0e0c7463cdd7f7a1a3bc6268e5fd", + "reference": "381b6f7c600e0e0c7463cdd7f7a1a3bc6268e5fd", "shasum": "" }, "require": { @@ -3243,9 +3185,9 @@ ], "support": { "issues": "https://github.com/php-amqplib/php-amqplib/issues", - "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.3" + "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.4" }, - "time": "2025-02-18T20:11:13+00:00" + "time": "2025-11-23T17:00:56+00:00" }, { "name": "phpoption/phpoption", @@ -3324,16 +3266,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.46", + "version": "3.0.47", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" + "reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9d6ca36a6c2dd434765b1071b2644a1c683b385d", + "reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d", "shasum": "" }, "require": { @@ -3414,7 +3356,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.47" }, "funding": [ { @@ -3430,7 +3372,7 @@ "type": "tidelift" } ], - "time": "2025-06-26T16:29:55+00:00" + "time": "2025-10-06T01:07:24+00:00" }, { "name": "psr/clock", @@ -3846,16 +3788,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.12", + "version": "v0.12.16", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "cd23863404a40ccfaf733e3af4db2b459837f7e7" + "reference": "ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/cd23863404a40ccfaf733e3af4db2b459837f7e7", - "reference": "cd23863404a40ccfaf733e3af4db2b459837f7e7", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67", + "reference": "ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67", "shasum": "" }, "require": { @@ -3863,18 +3805,19 @@ "ext-tokenizer": "*", "nikic/php-parser": "^5.0 || ^4.0", "php": "^8.0 || ^7.4", - "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2" + "bamarni/composer-bin-plugin": "^1.2", + "composer/class-map-generator": "^1.6" }, "suggest": { + "composer/class-map-generator": "Improved tab completion performance with better class discovery.", "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ @@ -3918,9 +3861,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.12" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.16" }, - "time": "2025-09-20T13:46:31+00:00" + "time": "2025-12-07T03:39:01+00:00" }, { "name": "ralouphie/getallheaders", @@ -4122,16 +4065,16 @@ }, { "name": "sentry/sentry", - "version": "4.16.0", + "version": "4.19.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "c5b086e4235762da175034bc463b0d31cbb38d2e" + "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/c5b086e4235762da175034bc463b0d31cbb38d2e", - "reference": "c5b086e4235762da175034bc463b0d31cbb38d2e", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/1c21d60bebe67c0122335bd3fe977990435af0a3", + "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3", "shasum": "" }, "require": { @@ -4142,7 +4085,7 @@ "jean85/pretty-package-versions": "^1.5|^2.0.4", "php": "^7.2|^8.0", "psr/log": "^1.0|^2.0|^3.0", - "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0" + "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0" }, "conflict": { "raven/raven": "*" @@ -4155,7 +4098,6 @@ "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^8.5|^9.6", - "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", "vimeo/psalm": "^4.17" }, "suggest": { @@ -4195,7 +4137,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.16.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.19.1" }, "funding": [ { @@ -4207,27 +4149,27 @@ "type": "custom" } ], - "time": "2025-09-22T13:38:03+00:00" + "time": "2025-12-02T15:57:41+00:00" }, { "name": "sentry/sentry-laravel", - "version": "4.16.0", + "version": "4.20.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "b33b2e487b02db02d92988228f142d7fa2be2bfa" + "reference": "95f2542ee1ebc993529b63f5c8543184abd00650" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/b33b2e487b02db02d92988228f142d7fa2be2bfa", - "reference": "b33b2e487b02db02d92988228f142d7fa2be2bfa", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/95f2542ee1ebc993529b63f5c8543184abd00650", + "reference": "95f2542ee1ebc993529b63f5c8543184abd00650", "shasum": "" }, "require": { "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", - "sentry/sentry": "^4.15.2", + "sentry/sentry": "^4.19.0", "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0" }, "require-dev": { @@ -4235,6 +4177,7 @@ "guzzlehttp/guzzle": "^7.2", "laravel/folio": "^1.1", "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", + "laravel/pennant": "^1.0", "livewire/livewire": "^2.0 | ^3.0", "mockery/mockery": "^1.3", "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", @@ -4284,7 +4227,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/4.16.0" + "source": "https://github.com/getsentry/sentry-laravel/tree/4.20.0" }, "funding": [ { @@ -4296,26 +4239,25 @@ "type": "custom" } ], - "time": "2025-09-10T16:38:18+00:00" + "time": "2025-12-02T10:37:40+00:00" }, { "name": "symfony/clock", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "php": ">=8.4", + "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -4354,7 +4296,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.3.0" + "source": "https://github.com/symfony/clock/tree/v8.0.0" }, "funding": [ { @@ -4365,25 +4307,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-11-12T15:46:48+00:00" }, { "name": "symfony/console", - "version": "v7.3.3", + "version": "v7.4.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7" + "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", - "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "url": "https://api.github.com/repos/symfony/console/zipball/6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", + "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", "shasum": "" }, "require": { @@ -4391,7 +4337,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -4405,16 +4351,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4448,7 +4394,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.3" + "source": "https://github.com/symfony/console/tree/v7.4.1" }, "funding": [ { @@ -4468,20 +4414,20 @@ "type": "tidelift" } ], - "time": "2025-08-25T06:35:40+00:00" + "time": "2025-12-05T15:23:39+00:00" }, { "name": "symfony/css-selector", - "version": "v7.3.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135", + "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135", "shasum": "" }, "require": { @@ -4517,7 +4463,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + "source": "https://github.com/symfony/css-selector/tree/v7.4.0" }, "funding": [ { @@ -4528,12 +4474,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-10-30T13:39:42+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4604,32 +4554,33 @@ }, { "name": "symfony/error-handler", - "version": "v7.3.2", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", - "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -4661,7 +4612,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.3.2" + "source": "https://github.com/symfony/error-handler/tree/v7.4.0" }, "funding": [ { @@ -4681,28 +4632,28 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:57+00:00" + "time": "2025-11-05T14:29:59+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + "reference": "573f95783a2ec6e38752979db139f09fec033f03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", + "reference": "573f95783a2ec6e38752979db139f09fec033f03", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -4711,13 +4662,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4745,7 +4697,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.0" }, "funding": [ { @@ -4765,7 +4717,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2025-10-30T14:17:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4845,23 +4797,23 @@ }, { "name": "symfony/finder", - "version": "v7.3.2", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "340b9ed7320570f319028a2cbec46d40535e94bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "url": "https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd", + "reference": "340b9ed7320570f319028a2cbec46d40535e94bd", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4889,7 +4841,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.2" + "source": "https://github.com/symfony/finder/tree/v7.4.0" }, "funding": [ { @@ -4909,27 +4861,26 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2025-11-05T05:42:40+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.3.3", + "version": "v7.4.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00" + "reference": "bd1af1e425811d6f077db240c3a588bdb405cd27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00", - "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1af1e425811d6f077db240c3a588bdb405cd27", + "reference": "bd1af1e425811d6f077db240c3a588bdb405cd27", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { "doctrine/dbal": "<3.6", @@ -4938,13 +4889,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/clock": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^6.4.12|^7.1.5|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4972,7 +4923,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.1" }, "funding": [ { @@ -4992,29 +4943,29 @@ "type": "tidelift" } ], - "time": "2025-08-20T08:04:18+00:00" + "time": "2025-12-07T11:13:10+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.3", + "version": "v7.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b" + "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b", - "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6e6f0a5fa8763f75a504b930163785fb6dd055f", + "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -5024,6 +4975,7 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", + "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -5041,27 +4993,27 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^7.1|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.1|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "type": "library", @@ -5090,7 +5042,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.2" }, "funding": [ { @@ -5110,20 +5062,20 @@ "type": "tidelift" } ], - "time": "2025-08-29T08:23:45+00:00" + "time": "2025-12-08T07:43:37+00:00" }, { "name": "symfony/mailer", - "version": "v7.3.3", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575" + "reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/a32f3f45f1990db8c4341d5122a7d3a381c7e575", - "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", + "reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", "shasum": "" }, "require": { @@ -5131,8 +5083,8 @@ "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^7.2", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.2|^8.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -5143,10 +5095,10 @@ "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5174,7 +5126,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.3" + "source": "https://github.com/symfony/mailer/tree/v7.4.0" }, "funding": [ { @@ -5194,24 +5146,25 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2025-11-21T15:26:00+00:00" }, { "name": "symfony/mime", - "version": "v7.3.2", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -5226,11 +5179,11 @@ "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0" }, "type": "library", "autoload": { @@ -5262,7 +5215,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.3.2" + "source": "https://github.com/symfony/mime/tree/v7.4.0" }, "funding": [ { @@ -5282,24 +5235,24 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2025-11-16T10:14:42+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -5333,7 +5286,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" }, "funding": [ { @@ -5353,7 +5306,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T10:16:07+00:00" + "time": "2025-11-12T15:55:31+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6186,16 +6139,16 @@ }, { "name": "symfony/process", - "version": "v7.3.3", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" + "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", - "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", + "url": "https://api.github.com/repos/symfony/process/zipball/7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", + "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", "shasum": "" }, "require": { @@ -6227,7 +6180,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.3" + "source": "https://github.com/symfony/process/tree/v7.4.0" }, "funding": [ { @@ -6247,26 +6200,26 @@ "type": "tidelift" } ], - "time": "2025-08-18T09:42:54+00:00" + "time": "2025-10-16T11:21:06+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.3.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "reference": "0101ff8bd0506703b045b1670960302d302a726c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/0101ff8bd0506703b045b1670960302d302a726c", + "reference": "0101ff8bd0506703b045b1670960302d302a726c", "shasum": "" }, "require": { "php": ">=8.2", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^6.4|^7.0|^8.0" }, "conflict": { "php-http/discovery": "<1.15", @@ -6276,11 +6229,12 @@ "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0" }, "type": "symfony-bridge", "autoload": { @@ -6314,7 +6268,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.0" }, "funding": [ { @@ -6325,25 +6279,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-26T08:57:56+00:00" + "time": "2025-11-13T08:38:49+00:00" }, { "name": "symfony/routing", - "version": "v7.3.2", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4" + "reference": "4720254cb2644a0b876233d258a32bf017330db7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4", - "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "url": "https://api.github.com/repos/symfony/routing/zipball/4720254cb2644a0b876233d258a32bf017330db7", + "reference": "4720254cb2644a0b876233d258a32bf017330db7", "shasum": "" }, "require": { @@ -6357,11 +6315,11 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6395,7 +6353,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.2" + "source": "https://github.com/symfony/routing/tree/v7.4.0" }, "funding": [ { @@ -6415,20 +6373,20 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:36:08+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -6482,7 +6440,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -6493,44 +6451,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v7.3.3", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", - "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc", + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -6569,7 +6530,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.3" + "source": "https://github.com/symfony/string/tree/v8.0.1" }, "funding": [ { @@ -6589,38 +6550,31 @@ "type": "tidelift" } ], - "time": "2025-08-25T06:35:40+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "symfony/translation", - "version": "v7.3.3", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e0837b4cbcef63c754d89a4806575cada743a38d" + "reference": "770e3b8b0ba8360958abedcabacd4203467333ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e0837b4cbcef63c754d89a4806575cada743a38d", - "reference": "e0837b4cbcef63c754d89a4806575cada743a38d", + "url": "https://api.github.com/repos/symfony/translation/zipball/770e3b8b0ba8360958abedcabacd4203467333ca", + "reference": "770e3b8b0ba8360958abedcabacd4203467333ca", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation-contracts": "^3.6.1" }, "conflict": { "nikic/php-parser": "<5.0", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" + "symfony/service-contracts": "<2.5" }, "provide": { "symfony/translation-implementation": "2.3|3.0" @@ -6628,17 +6582,17 @@ "require-dev": { "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -6669,7 +6623,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.3.3" + "source": "https://github.com/symfony/translation/tree/v8.0.1" }, "funding": [ { @@ -6689,20 +6643,20 @@ "type": "tidelift" } ], - "time": "2025-08-01T21:02:37+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + "reference": "65a8bc82080447fae78373aa10f8d13b38338977" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", + "reference": "65a8bc82080447fae78373aa10f8d13b38338977", "shasum": "" }, "require": { @@ -6751,7 +6705,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" }, "funding": [ { @@ -6762,25 +6716,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-27T08:32:26+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/uid", - "version": "v7.3.1", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + "reference": "2498e9f81b7baa206f44de583f2f48350b90142c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c", + "reference": "2498e9f81b7baa206f44de583f2f48350b90142c", "shasum": "" }, "require": { @@ -6788,7 +6746,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6825,7 +6783,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.3.1" + "source": "https://github.com/symfony/uid/tree/v7.4.0" }, "funding": [ { @@ -6836,25 +6794,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2025-09-25T11:02:55+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.3.3", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" + "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", - "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41fd6c4ae28c38b294b42af6db61446594a0dece", + "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece", "shasum": "" }, "require": { @@ -6866,10 +6828,10 @@ "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -6908,7 +6870,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.0" }, "funding": [ { @@ -6928,7 +6890,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2025-10-27T20:36:44+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7226,64 +7188,6 @@ } ], "time": "2024-11-21T01:49:47+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" } ], "packages-dev": [ @@ -7689,16 +7593,16 @@ }, { "name": "laravel/pint", - "version": "v1.25.1", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9" + "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9", - "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/69dcca060ecb15e4b564af63d1f642c81a241d6f", + "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f", "shasum": "" }, "require": { @@ -7709,13 +7613,13 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.87.2", - "illuminate/view": "^11.46.0", - "larastan/larastan": "^3.7.1", - "laravel-zero/framework": "^11.45.0", + "friendsofphp/php-cs-fixer": "^3.90.0", + "illuminate/view": "^12.40.1", + "larastan/larastan": "^3.8.0", + "laravel-zero/framework": "^12.0.4", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.1", - "pestphp/pest": "^2.36.0" + "nunomaduro/termwind": "^2.3.3", + "pestphp/pest": "^3.8.4" }, "bin": [ "builds/pint" @@ -7741,6 +7645,7 @@ "description": "An opinionated code formatter for PHP.", "homepage": "https://laravel.com", "keywords": [ + "dev", "format", "formatter", "lint", @@ -7751,20 +7656,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-09-19T02:57:12+00:00" + "time": "2025-11-25T21:15:52+00:00" }, { "name": "laravel/sail", - "version": "v1.45.0", + "version": "v1.51.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "019a2933ff4a9199f098d4259713f9bc266a874e" + "reference": "1c74357df034e869250b4365dd445c9f6ba5d068" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/019a2933ff4a9199f098d4259713f9bc266a874e", - "reference": "019a2933ff4a9199f098d4259713f9bc266a874e", + "url": "https://api.github.com/repos/laravel/sail/zipball/1c74357df034e869250b4365dd445c9f6ba5d068", + "reference": "1c74357df034e869250b4365dd445c9f6ba5d068", "shasum": "" }, "require": { @@ -7777,7 +7682,7 @@ }, "require-dev": { "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^1.10" + "phpstan/phpstan": "^2.0" }, "bin": [ "bin/sail" @@ -7814,7 +7719,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2025-08-25T19:28:31+00:00" + "time": "2025-12-09T13:33:49+00:00" }, { "name": "lucascudo/laravel-pt-br-localization", @@ -8020,16 +7925,16 @@ }, { "name": "nunomaduro/collision", - "version": "v8.8.2", + "version": "v8.8.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", "shasum": "" }, "require": { @@ -8051,7 +7956,7 @@ "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2", + "pestphp/pest": "^3.8.2 || ^4.0.0", "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", @@ -8115,7 +8020,7 @@ "type": "patreon" } ], - "time": "2025-06-25T02:12:12+00:00" + "time": "2025-11-20T02:55:25+00:00" }, { "name": "phar-io/manifest", @@ -8572,16 +8477,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.39", + "version": "11.5.46", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ad5597f79d8489d2870073ac0bc0dd0ad1fa9931" + "reference": "75dfe79a2aa30085b7132bb84377c24062193f33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ad5597f79d8489d2870073ac0bc0dd0ad1fa9931", - "reference": "ad5597f79d8489d2870073ac0bc0dd0ad1fa9931", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/75dfe79a2aa30085b7132bb84377c24062193f33", + "reference": "75dfe79a2aa30085b7132bb84377c24062193f33", "shasum": "" }, "require": { @@ -8605,7 +8510,7 @@ "sebastian/comparator": "^6.3.2", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.1", - "sebastian/exporter": "^6.3.0", + "sebastian/exporter": "^6.3.2", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.1.3", @@ -8653,7 +8558,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.39" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.46" }, "funding": [ { @@ -8677,7 +8582,7 @@ "type": "tidelift" } ], - "time": "2025-09-14T06:20:41+00:00" + "time": "2025-12-06T08:01:15+00:00" }, { "name": "sebastian/cli-parser", @@ -9144,16 +9049,16 @@ }, { "name": "sebastian/exporter", - "version": "6.3.1", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "8f67e53d3fcaf53105f95cc14f1630493d0fa2e6" + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/8f67e53d3fcaf53105f95cc14f1630493d0fa2e6", - "reference": "8f67e53d3fcaf53105f95cc14f1630493d0fa2e6", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", "shasum": "" }, "require": { @@ -9210,7 +9115,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.1" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" }, "funding": [ { @@ -9230,7 +9135,7 @@ "type": "tidelift" } ], - "time": "2025-09-22T05:34:00+00:00" + "time": "2025-09-24T06:12:51+00:00" }, { "name": "sebastian/global-state", @@ -10100,28 +10005,28 @@ }, { "name": "symfony/yaml", - "version": "v7.3.3", + "version": "v7.4.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", - "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -10152,7 +10057,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.3.3" + "source": "https://github.com/symfony/yaml/tree/v7.4.1" }, "funding": [ { @@ -10172,20 +10077,20 @@ "type": "tidelift" } ], - "time": "2025-08-27T11:34:33+00:00" + "time": "2025-12-04T18:11:45+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -10214,7 +10119,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -10222,7 +10127,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], @@ -10237,5 +10142,5 @@ "platform-dev": { "ext-pcntl": "*" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/phpunit.xml b/phpunit.xml index 2f317b6..b779e68 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -8,10 +8,7 @@ tests/Unit - - - tests/Feature - + diff --git a/tests/Unit/Console/Commands/ImportRegistrationCommandTest.php b/tests/Unit/Console/Commands/ImportRegistrationCommandTest.php index 57e3335..75b89bd 100644 --- a/tests/Unit/Console/Commands/ImportRegistrationCommandTest.php +++ b/tests/Unit/Console/Commands/ImportRegistrationCommandTest.php @@ -3,7 +3,9 @@ namespace Tests\Unit\Console\Commands; use App\Console\Commands\ImportRegistrationCommand; +use App\Events\ImportRegistrationEvent; use App\Services\RabbitMQService; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use App\Mail\ImporteRegistrationMail; @@ -19,6 +21,7 @@ protected function setUp(): void { parent::setUp(); Mail::fake(); + Event::fake(); Log::shouldReceive('info')->byDefault(); Log::shouldReceive('error')->byDefault(); } @@ -30,64 +33,350 @@ protected function tearDown(): void parent::tearDown(); } - // Para criar um mock do AMQPMessage - protected function createMockAMQPMessage(string $body, string $routingKey): AMQPMessage + /** + * Para criar um mock do AMQPMessage com ack + */ + protected function createMockAMQPMessage(string $body, bool $shouldAck = true): AMQPMessage { $message = Mockery::mock(AMQPMessage::class); $message->shouldReceive('getBody')->andReturn($body); - $message->shouldReceive('get')->with('routing_key')->andReturn($routingKey); + + if ($shouldAck) { + $message->shouldReceive('ack')->once()->andReturnNull(); + } + return $message; } - public function test_handle_processes_valid_message_and_sends_emails() + /** + * Teste: Processa mensagem válida do RabbitMQ e dispara evento ImportRegistrationEvent + */ + public function test_processes_valid_rabbitmq_message_and_dispatches_event() + { + // Arrange: Mock do serviço RabbitMQ + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + // Dados no formato especificado pelo usuário + $messageBody = json_encode([ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ] + ]); + + $msgMock = $this->createMockAMQPMessage($messageBody); + + // Act: Processa a mensagem + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + $method->invoke($command, $msgMock); + + // Assert: Verifica se o evento foi disparado + Event::assertDispatched(ImportRegistrationEvent::class, function ($event) { + return is_array($event->registrations) && + count($event->registrations) === 1 && + $event->registrations[0]['registration'] === 154069287 && + $event->registrations[0]['opp_name'] === 'Teste de importe'; + }); + } + + /** + * Teste: Processa múltiplas inscrições e dispara evento com todos os dados + */ + public function test_processes_multiple_registrations_and_dispatches_event() { - config(['sentry.dsn' => null]); - // Mockando para evitar conexaoes reais ao Rabbitmq + // Arrange $queueService = Mockery::mock(RabbitMQService::class); $this->app->instance(RabbitMQService::class, $queueService); - // Dados completos que a classe ImporteRegistrationMail espera $messageBody = json_encode([ [ - 'registration' => '12345', - 'opp_id' => '1', - 'opp_name' => 'Oportunidade Teste 1', - 'number' => '001', - 'agent_name' => 'João Silva', - 'agent_email' => 'test1@example.com', + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@gmail.com', ], [ - 'registration' => '67890', - 'opp_id' => '2', - 'opp_name' => 'Oportunidade Teste 2', - 'number' => '002', - 'agent_name' => 'Maria Santos', - 'agent_email' => 'test2@example.com', + 'registration' => 154069288, + 'opp_id' => 7302, + 'opp_name' => 'Segunda oportunidade', + 'number' => 'on-154026964', + 'agent_name' => 'JOAO DA SILVA', + 'agent_email' => 'joao.silva@example.com', ] ]); - $msgMock = $this->createMockAMQPMessage($messageBody, 'module_import_registration_draft'); + $msgMock = $this->createMockAMQPMessage($messageBody); - Log::shouldReceive('info')->byDefault(); - Mail::fake(); + // Act + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + $method->invoke($command, $msgMock); + + // Assert + Event::assertDispatched(ImportRegistrationEvent::class, function ($event) { + return is_array($event->registrations) && + count($event->registrations) === 2 && + $event->registrations[0]['registration'] === 154069287 && + $event->registrations[1]['registration'] === 154069288; + }); + } + + /** + * Teste: Verifica se a mensagem é confirmada (ack) após processamento bem-sucedido + */ + public function test_acknowledges_message_after_successful_processing() + { + // Arrange + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + $messageBody = json_encode([ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@gmail.com', + ] + ]); + + // Configurando expectativa explícita do ack + $msgMock = $this->createMockAMQPMessage($messageBody, true); + // Act $command = new ImportRegistrationCommand($queueService); $reflection = new \ReflectionClass($command); $method = $reflection->getMethod('processMessage'); $method->setAccessible(true); + $method->invoke($command, $msgMock); - try { - $method->invoke($command, $msgMock); - } catch (\Exception $e) { - $this->fail('Exception in processMessage: ' . $e->getMessage()); - } - $sentEmails = Mail::sent(ImporteRegistrationMail::class); + // Assert: O mock do Mockery irá falhar se ack() não for chamado exatamente uma vez + $this->assertTrue(true); + } - // Verificar cada email individualmente - Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { - return $mail->content()->with['agent_email'] === 'test1@example.com'; - }); + /** + * Teste: Loga informação ao receber mensagem + */ + public function test_logs_info_when_receiving_message() + { + // Arrange + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + $messageBody = json_encode([ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@gmail.com', + ] + ]); + + $msgMock = $this->createMockAMQPMessage($messageBody); + + // Expectativa explícita de log + Log::shouldReceive('info') + ->once() + ->with('Mensagem recebida: ' . $messageBody); + + // Act + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + $method->invoke($command, $msgMock); + + // Assert implícito via Mockery + $this->assertTrue(true); + } + + /** + * Teste: Loga erro quando JSON é inválido (não lança exceção, apenas retorna) + */ + public function test_logs_error_when_json_is_invalid() + { + // Arrange + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + // Mensagem JSON inválida + $invalidJson = 'invalid json format {['; + $msgMock = Mockery::mock(AMQPMessage::class); + $msgMock->shouldReceive('getBody')->andReturn($invalidJson); + // Não deve chamar ack quando há erro + $msgMock->shouldNotReceive('ack'); + + // Expectativa de log + Log::shouldReceive('info') + ->once() + ->with('Mensagem recebida: ' . $invalidJson); + + Log::shouldReceive('error') + ->once() + ->with('Formato de mensagem inválido'); + + // Act + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + $method->invoke($command, $msgMock); + + // Assert: Evento não deve ser disparado + Event::assertNotDispatched(ImportRegistrationEvent::class); + } + + /** + * Teste: Captura exceção e envia para Sentry quando ocorre erro durante processamento + */ + public function test_captures_processing_exception_with_sentry() + { + // Arrange: Simula falha no processamento + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + // Mock do evento para lançar exceção + Event::shouldReceive('dispatch') + ->andThrow(new \Exception('Erro ao processar evento')); + + $messageBody = json_encode([ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@gmail.com', + ] + ]); + + $msgMock = Mockery::mock(AMQPMessage::class); + $msgMock->shouldReceive('getBody')->andReturn($messageBody); + // Não deve chamar ack quando há exceção + $msgMock->shouldNotReceive('ack'); + + Log::shouldReceive('info') + ->once() + ->with('Mensagem recebida: ' . $messageBody); + + Log::shouldReceive('error') + ->once() + ->with('Erro ao processar a mensagem'); + + // Act + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + + // Não deve lançar exceção - deve ser capturada internamente + $method->invoke($command, $msgMock); + + // Assert + $this->assertTrue(true); + } + + /** + * Teste: Não processa mensagem quando o formato não é array + */ + public function test_does_not_process_invalid_message_format() + { + // Arrange + $queueService = Mockery::mock(RabbitMQService::class); + $this->app->instance(RabbitMQService::class, $queueService); + + // JSON válido mas não é array + $messageBody = json_encode('string simples'); + + $msgMock = Mockery::mock(AMQPMessage::class); + $msgMock->shouldReceive('getBody')->andReturn($messageBody); + // Não deve chamar ack + $msgMock->shouldNotReceive('ack'); + + Log::shouldReceive('info') + ->once() + ->with('Mensagem recebida: ' . $messageBody); + + Log::shouldReceive('error') + ->once() + ->with('Formato de mensagem inválido'); + + // Act + $command = new ImportRegistrationCommand($queueService); + $reflection = new \ReflectionClass($command); + $method = $reflection->getMethod('processMessage'); + $method->setAccessible(true); + $method->invoke($command, $msgMock); + + // Assert: Evento não deve ser disparado + Event::assertNotDispatched(ImportRegistrationEvent::class); + } + + /** + * Teste: Verifica configuração do comando + */ + public function test_command_signature_and_description() + { + // Arrange + $queueService = Mockery::mock(RabbitMQService::class); + $command = new ImportRegistrationCommand($queueService); + + // Act + $reflection = new \ReflectionClass($command); + $signatureProperty = $reflection->getProperty('signature'); + $signatureProperty->setAccessible(true); + $signature = $signatureProperty->getValue($command); + + $descriptionProperty = $reflection->getProperty('description'); + $descriptionProperty->setAccessible(true); + $description = $descriptionProperty->getValue($command); + + // Assert + $this->assertEquals('rabbitmq:import-registration-command', $signature); + $this->assertEquals('Comando para consumir a fila des imports de inscrição', $description); } + /** + * Teste: Handle chama o método consume com parâmetros corretos + */ + public function test_handle_calls_consume_with_correct_parameters() + { + // Arrange + config([ + 'rabbitmq.queues.queue_import_registration' => 'test_queue', + 'rabbitmq.exchange_default' => 'test_exchange', + 'rabbitmq.routing.module_import_registration_draft' => 'test_routing_key' + ]); + + $queueService = Mockery::mock(RabbitMQService::class); + $queueService->shouldReceive('consume') + ->once() + ->with('test_queue', 'test_exchange', 'test_routing_key', Mockery::type('Closure')) + ->andReturn(null); + + $this->app->instance(RabbitMQService::class, $queueService); + + $command = new ImportRegistrationCommand($queueService); + + // Act + $command->handle(); + // Assert: Mockery irá verificar se consume foi chamado corretamente + $this->assertTrue(true); + } } diff --git a/tests/Unit/Listeners/ImportRegistrationListenerTest.php b/tests/Unit/Listeners/ImportRegistrationListenerTest.php new file mode 100644 index 0000000..de3a345 --- /dev/null +++ b/tests/Unit/Listeners/ImportRegistrationListenerTest.php @@ -0,0 +1,348 @@ +byDefault(); + Log::shouldReceive('error')->byDefault(); + } + + /** + * Teste: Envia email com sucesso para uma inscrição válida + */ + public function test_sends_email_successfully_for_valid_registration() + { + // Arrange + $registrationData = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ]; + + $event = new ImportRegistrationEvent([$registrationData]); + $listener = new ImportRegistrationListener(); + + Log::shouldReceive('info') + ->once() + ->with('Enviando e-mail para: liliuchoa616@mail.com'); + + Log::shouldReceive('info') + ->once() + ->with('Email enviado e auditado para: liliuchoa616@mail.com'); + + // Act + $listener->handle($event); + + // Assert: Verifica se o email foi enviado + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) use ($registrationData) { + return $mail->hasTo('liliuchoa616@mail.com') && + $mail->content()->with['registration'] === 154069287 && + $mail->content()->with['opp_name'] === 'Teste de importe' && + $mail->content()->with['agent_name'] === 'MARIA LILIANA UCHOA DO NASCIMENTO'; + }); + + // Assert: Verifica se foi criado o registro de auditoria + $this->assertDatabaseHas('email_dispatches', [ + 'to' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'mailable_type' => ImporteRegistrationMail::class, + ]); + } + + /** + * Teste: Envia múltiplos emails para múltiplas inscrições + */ + public function test_sends_multiple_emails_for_multiple_registrations() + { + // Arrange + $registrations = [ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ], + [ + 'registration' => 154069288, + 'opp_id' => 7302, + 'opp_name' => 'Segunda oportunidade', + 'number' => 'on-154026964', + 'agent_name' => 'JOAO DA SILVA', + 'agent_email' => 'joao.silva@example.com', + ] + ]; + + $event = new ImportRegistrationEvent($registrations); + $listener = new ImportRegistrationListener(); + + // Act + $listener->handle($event); + + // Assert: Verifica se ambos os emails foram enviados + Mail::assertSent(ImporteRegistrationMail::class, 2); + + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { + return $mail->hasTo('liliuchoa616@mail.com'); + }); + + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { + return $mail->hasTo('joao.silva@example.com'); + }); + + // Assert: Verifica se ambos os registros de auditoria foram criados + $this->assertDatabaseCount('email_dispatches', 2); + } + + /** + * Teste: Cria registro de auditoria no EmailDispatch ao enviar email + */ + public function test_creates_email_dispatch_audit_record() + { + // Arrange + $registrationData = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ]; + + $event = new ImportRegistrationEvent([$registrationData]); + $listener = new ImportRegistrationListener(); + + // Act + $listener->handle($event); + + // Assert: Verifica o registro de auditoria + $this->assertDatabaseHas('email_dispatches', [ + 'to' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'subject' => 'Convite para uma nova fase', + 'mailable_type' => ImporteRegistrationMail::class, + ]); + + // Verifica os metadados salvos + $emailDispatch = EmailDispatch::first(); + $this->assertEquals(154069287, $emailDispatch->meta['registration']); + $this->assertEquals(7301, $emailDispatch->meta['opp_id']); + $this->assertEquals('Teste de importe', $emailDispatch->meta['opp_name']); + $this->assertEquals('on-154026963', $emailDispatch->meta['number']); + $this->assertEquals('MARIA LILIANA UCHOA DO NASCIMENTO', $emailDispatch->meta['agent_name']); + $this->assertEquals('liliuchoa616@mail.com', $emailDispatch->meta['agent_email']); + $this->assertNotNull($emailDispatch->dispatched_at); + } + + /** + * Teste: Não envia email quando faltam campos obrigatórios + */ + public function test_does_not_send_email_when_required_fields_are_missing() + { + // Arrange: Inscrição sem campo 'agent_email' + $invalidRegistration = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + // 'agent_email' está faltando + ]; + + $event = new ImportRegistrationEvent([$invalidRegistration]); + $listener = new ImportRegistrationListener(); + + Log::shouldReceive('error') + ->once() + ->with('Chaves obrigatórias ausentes na inscrição: ' . json_encode($invalidRegistration)); + + // Act + $listener->handle($event); + + // Assert: Verifica que nenhum email foi enviado + Mail::assertNotSent(ImporteRegistrationMail::class); + + // Assert: Verifica que nenhum registro de auditoria foi criado + $this->assertDatabaseCount('email_dispatches', 0); + } + + /** + * Teste: Processa apenas inscrições válidas quando há mix de válidas e inválidas + */ + public function test_processes_only_valid_registrations_in_mixed_batch() + { + // Arrange + $registrations = [ + [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ], + [ + // Inscrição inválida - faltando 'agent_email' + 'registration' => 154069288, + 'opp_id' => 7302, + 'opp_name' => 'Segunda oportunidade', + 'number' => 'on-154026964', + 'agent_name' => 'JOAO DA SILVA', + ], + [ + 'registration' => 154069289, + 'opp_id' => 7303, + 'opp_name' => 'Terceira oportunidade', + 'number' => 'on-154026965', + 'agent_name' => 'PEDRO SANTOS', + 'agent_email' => 'pedro.santos@example.com', + ] + ]; + + $event = new ImportRegistrationEvent($registrations); + $listener = new ImportRegistrationListener(); + + // Act + $listener->handle($event); + + // Assert: Verifica que apenas 2 emails foram enviados (os válidos) + Mail::assertSent(ImporteRegistrationMail::class, 2); + + // Assert: Verifica que apenas 2 registros de auditoria foram criados + $this->assertDatabaseCount('email_dispatches', 2); + + // Assert: Verifica que os emails corretos foram enviados + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { + return $mail->hasTo('liliuchoa616@mail.com'); + }); + + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { + return $mail->hasTo('pedro.santos@example.com'); + }); + } + + /** + * Teste: Valida todos os campos obrigatórios + */ + public function test_validates_all_required_fields() + { + // Arrange: Testa cada campo obrigatório faltando + $requiredFields = ['registration', 'opp_id', 'opp_name', 'number', 'agent_name', 'agent_email']; + + foreach ($requiredFields as $missingField) { + Mail::fake(); // Reseta o fake para cada iteração + + $incompleteRegistration = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ]; + + // Remove o campo que está sendo testado + unset($incompleteRegistration[$missingField]); + + $event = new ImportRegistrationEvent([$incompleteRegistration]); + $listener = new ImportRegistrationListener(); + + // Act + $listener->handle($event); + + // Assert: Verifica que nenhum email foi enviado quando qualquer campo obrigatório está faltando + Mail::assertNotSent(ImporteRegistrationMail::class, + "Email não deveria ser enviado quando o campo '{$missingField}' está faltando" + ); + } + } + + /** + * Teste: Verifica o conteúdo do email enviado + */ + public function test_email_contains_correct_data() + { + // Arrange + $registrationData = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ]; + + $event = new ImportRegistrationEvent([$registrationData]); + $listener = new ImportRegistrationListener(); + + // Act + $listener->handle($event); + + // Assert: Verifica todos os campos do email + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) use ($registrationData) { + $content = $mail->content(); + return $content->with['registration'] === 154069287 && + $content->with['opp_id'] === 7301 && + $content->with['opp_name'] === 'Teste de importe' && + $content->with['number'] === 'on-154026963' && + $content->with['agent_name'] === 'MARIA LILIANA UCHOA DO NASCIMENTO' && + $content->with['agent_email'] === 'liliuchoa616@mail.com'; + }); + + // Assert: Verifica o envelope (assunto) + Mail::assertSent(ImporteRegistrationMail::class, function ($mail) { + return $mail->envelope()->subject === 'Convite para uma nova fase'; + }); + } + + /** + * Teste: Loga as informações corretas durante o envio + */ + public function test_logs_correct_information_during_sending() + { + // Arrange + $registrationData = [ + 'registration' => 154069287, + 'opp_id' => 7301, + 'opp_name' => 'Teste de importe', + 'number' => 'on-154026963', + 'agent_name' => 'MARIA LILIANA UCHOA DO NASCIMENTO', + 'agent_email' => 'liliuchoa616@mail.com', + ]; + + $event = new ImportRegistrationEvent([$registrationData]); + $listener = new ImportRegistrationListener(); + + Log::shouldReceive('info') + ->once() + ->with('Enviando e-mail para: liliuchoa616@mail.com'); + + Log::shouldReceive('info') + ->once() + ->with('Email enviado e auditado para: liliuchoa616@mail.com'); + + // Act + $listener->handle($event); + + // Assert implícito via Mockery + $this->assertTrue(true); + } +}