+ {{ trans('auth.security.ignore_if_not_requested') }} +
+diff --git a/.dockerignore b/.dockerignore index 4ff7ed4..050314d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -42,7 +42,6 @@ coverage/ *.pid.lock .phpunit.result.cache -.pest .php_cs.cache dist/ diff --git a/.env.example b/.env.example index 58cb2fe..39051f9 100644 --- a/.env.example +++ b/.env.example @@ -9,17 +9,30 @@ DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=phenix -DB_USERNAME=phenix -DB_PASSWORD= +DB_USERNAME=root +DB_PASSWORD=secret -LOG_CHANNEL=stream +LOG_CHANNEL=file -QUEUE_DRIVER=parallel +CACHE_STORE=redis +RATE_LIMIT_STORE="${CACHE_STORE}" + +QUEUE_DRIVER=redis CORS_ORIGIN= REDIS_HOST=127.0.0.1 REDIS_PORT=6379 +REDIS_USERNAME= REDIS_PASSWORD=null -SESSION_DRIVER=local +SESSION_DRIVER=redis + +MAIL_MAILER=smtp +MAIL_HOST=127.0.0.1 +MAIL_PORT=587 +MAIL_ENCRYPTION=tls +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_FROM_ADDRESS=hello@example.com +MAIL_FROM_NAME="Example" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 350a36c..0f0ad3f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -25,11 +25,10 @@ XDEBUG_MODE=off php public/index.php # Direct server start (faster, no debuggin ### Testing ```bash -composer test # Pest tests (XDEBUG_MODE=off) +composer test # PHPUnit tests (XDEBUG_MODE=off) composer test:coverage # With coverage reports -composer test:parallel # Parallel execution ``` -- **Test Framework**: Pest PHP with custom HTTP client helpers +- **Test Framework**: PHPUnit with custom HTTP client helpers - **Test Structure**: `tests/Feature/` and `tests/Unit/` with shared `TestCase` - **HTTP Testing**: Uses Amp HTTP client with helper functions: `get()`, `post()`, etc. @@ -133,7 +132,6 @@ class MyController extends Controller - `config/app.php` - Service provider registration and app config - `vendor/phenixphp/framework/src/Queue/` - Queue implementation details - `vendor/phenixphp/framework/src/Tasks/QueuableTask.php` - Base task class -- `tests/Pest.php` - HTTP testing helpers and setup - `bootstrap/app.php` - Application bootstrap via `AppBuilder` ## Common Pitfalls diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 49cf7b9..7912f33 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,6 +9,30 @@ on: jobs: test: runs-on: ubuntu-latest + services: + mysql: + image: mysql:8.0 + env: + MYSQL_DATABASE: phenix + MYSQL_USER: phenix + MYSQL_PASSWORD: secret + MYSQL_ROOT_PASSWORD: secret + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -psecret --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=10 + redis: + image: redis:7-alpine + ports: + - 6379:6379 + options: >- + --health-cmd="redis-cli ping" + --health-interval=10s + --health-timeout=5s + --health-retries=10 steps: - name: Checkout code @@ -20,7 +44,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: 8.2 - extensions: json, mbstring, pcntl, intl, fileinfo + extensions: json, mbstring, pcntl, intl, fileinfo, sockets, mysqli, sqlite3 coverage: xdebug - name: Setup problem matchers @@ -38,13 +62,14 @@ jobs: - name: Analyze code statically with PHPStan run: | - cp .env.example .env - vendor/bin/phpstan --xdebug + cp .env.example .env.testing + XDEBUG_MODE=off vendor/bin/phpstan --xdebug - name: Execute tests run: | - cp .env.example .env - vendor/bin/pest --coverage + cp .env.example .env.testing + php phenix key:generate .env.testing --force + vendor/bin/phpunit - name: Prepare paths for SonarQube analysis run: | @@ -52,7 +77,7 @@ jobs: sed -i "s|$GITHUB_WORKSPACE|/github/workspace|g" build/report.junit.xml - name: Run SonarQube analysis - uses: sonarsource/sonarcloud-github-action@master + uses: sonarsource/sonarqube-scan-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index d7f2b9d..083c01a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ tests/coverage node_modules npm-debug.log package-lock.json -package.json \ No newline at end of file +package.json +*.sqlite* diff --git a/app/Constants/OneTimePasswordScope.php b/app/Constants/OneTimePasswordScope.php new file mode 100644 index 0000000..a979f1b --- /dev/null +++ b/app/Constants/OneTimePasswordScope.php @@ -0,0 +1,21 @@ +setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query() + ->whereEqual('email', $request->body('email')) + ->whereNotNull('email_verified_at') + ->first(); + + if ($user !== null) { + $otpCount = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::RESET_PASSWORD->value) + ->whereGreaterThanOrEqual('created_at', Date::now()->subHour()->toDateTimeString()) + ->count(); + + if ($otpCount < 5) { + $user->sendOneTimePassword(OneTimePasswordScope::RESET_PASSWORD); + } + } + + return response()->json([ + 'message' => trans('auth.password_reset.sent'), + ], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php new file mode 100644 index 0000000..9b6f228 --- /dev/null +++ b/app/Http/Controllers/Auth/LoginController.php @@ -0,0 +1,132 @@ +setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100) + ->exists('users', 'email', function ($query): void { + $query->whereNotNull('email_verified_at'); + }), + 'password' => Password::required(), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query()->whereEqual('email', $request->body('email'))->first(); + $response = response()->json([ + 'message' => trans('auth.otp.login.sent'), + ]); + + if (! Hash::verify($user->password, (string) $request->body('password'))) { + $response = response()->json([ + 'message' => trans('auth.login.invalid_credentials'), + ], HttpStatus::UNAUTHORIZED); + } else { + $otpCount = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::LOGIN->value) + ->whereGreaterThanOrEqual('created_at', Date::now()->subHour()->toDateTimeString()) + ->count(); + + if ($otpCount >= 5) { + $response = response()->json([ + 'message' => trans('auth.otp.limit_exceeded'), + ], HttpStatus::TOO_MANY_REQUESTS); + } else { + $user->sendOneTimePassword(OneTimePasswordScope::LOGIN); + } + } + + return $response; + } + + public function authorize(Request $request): Response + { + $validator = new Validator($request); + $validator->setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100) + ->exists('users', 'email', function ($query): void { + $query->whereNotNull('email_verified_at'); + }), + 'otp' => Numeric::required()->digits(6), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query()->whereEqual('email', $request->body('email'))->first(); + + $otp = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::LOGIN->value) + ->whereEqual('code', hash('sha256', (string) $request->body('otp'))) + ->whereNull('used_at') + ->whereGreaterThanOrEqual('expires_at', Date::now()->toDateTimeString()) + ->first(); + + if (! $otp) { + return response()->json([ + 'message' => trans('auth.otp.invalid'), + ], HttpStatus::NOT_FOUND); + } + + $otp->usedAt = Date::now(); + $otp->save(); + + $token = $user->createToken('auth_token'); + + return response()->json([ + 'access_token' => $token->toString(), + 'expires_at' => $token->expiresAt()->toDateTimeString(), + 'token_type' => 'Bearer', + ]); + } + + public function logout(Request $request): Response + { + /** @var User|null $user */ + $user = $request->user(); + + $user?->currentAccessToken()?->delete(); + + return response()->json([ + 'message' => trans('auth.logout.success'), + ], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php new file mode 100644 index 0000000..eaba13a --- /dev/null +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -0,0 +1,83 @@ +setRules([ + 'name' => Str::required()->min(3)->max(20)->unique('users', 'name'), + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100)->unique('users', 'email'), + 'password' => Password::required()->secure(static fn (): bool => App::isProduction())->confirmed(), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = new User(); + $user->name = $request->body('name'); + $user->email = $request->body('email'); + $user->password = Hash::make($request->body('password')); + $user->save(); + + $user->sendOneTimePassword(OneTimePasswordScope::VERIFY_EMAIL); + + return response()->json($user, HttpStatus::CREATED); + } + + public function cancel(Request $request): Response + { + $validator = new Validator($request); + $validator->setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100) + ->exists('users', 'email', function ($query): void { + $query->whereNull('email_verified_at'); + }), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query() + ->whereEqual('email', $request->body('email')) + ->whereNull('email_verified_at') + ->first(); + + $user->delete(); + + return response()->json([ + 'message' => trans('auth.registration.cancelled'), + ], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/ResendVerificationOtpController.php b/app/Http/Controllers/Auth/ResendVerificationOtpController.php new file mode 100644 index 0000000..c10d3e8 --- /dev/null +++ b/app/Http/Controllers/Auth/ResendVerificationOtpController.php @@ -0,0 +1,61 @@ +setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100) + ->exists('users', 'email', function ($query): void { + $query->whereNull('email_verified_at'); + }), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query()->whereEqual('email', $request->body('email'))->first(); + + $otpCount = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::VERIFY_EMAIL->value) + ->whereGreaterThanOrEqual('created_at', Date::now()->subHour()->toDateTimeString()) + ->count(); + + if ($otpCount >= 5) { + return response()->json([ + 'message' => trans('auth.otp.limit_exceeded'), + ], HttpStatus::TOO_MANY_REQUESTS); + } + + $user->sendOneTimePassword(OneTimePasswordScope::VERIFY_EMAIL); + + return response()->json([ + 'message' => trans('auth.otp.email_verification.resent'), + ], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php new file mode 100644 index 0000000..54da489 --- /dev/null +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -0,0 +1,79 @@ +setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100), + 'otp' => Numeric::required()->digits(6), + 'password' => Password::required()->secure(static fn (): bool => App::isProduction())->confirmed(), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query() + ->whereEqual('email', $request->body('email')) + ->whereNotNull('email_verified_at') + ->first(); + + $otp = null; + + if ($user !== null) { + $otp = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::RESET_PASSWORD->value) + ->whereEqual('code', hash('sha256', (string) $request->body('otp'))) + ->whereNull('used_at') + ->whereGreaterThanOrEqual('expires_at', Date::now()->toDateTimeString()) + ->first(); + } + + if ($user === null || $otp === null) { + return response()->json([ + 'message' => trans('auth.otp.invalid'), + ], HttpStatus::NOT_FOUND); + } + + $otp->usedAt = Date::now(); + $otp->save(); + + $user->password = Hash::make($request->body('password')); + $user->save(); + + $user->tokens()->delete(); + + return response()->json([ + 'message' => trans('auth.password_reset.reset'), + ], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/TokenController.php b/app/Http/Controllers/Auth/TokenController.php new file mode 100644 index 0000000..cfd9c16 --- /dev/null +++ b/app/Http/Controllers/Auth/TokenController.php @@ -0,0 +1,64 @@ +user(); + + $tokens = $user->tokens() + ->whereGreaterThan('expires_at', Date::now()->toDateTimeString()) + ->get(); + + return response()->json($tokens); + } + + public function refresh(Request $request): Response + { + /** @var User $user */ + $user = $request->user(); + + $token = $user->refreshToken('auth_token'); + + return response()->json([ + 'access_token' => $token->toString(), + 'expires_at' => $token->expiresAt()->toDateTimeString(), + 'token_type' => 'Bearer', + ]); + } + + public function destroy(Request $request): Response + { + /** @var User $user */ + $user = $request->user(); + + $token = PersonalAccessToken::query() + ->whereEqual('id', $request->route('id')) + ->whereEqual('tokenable_type', User::class) + ->whereEqual('tokenable_id', $user->id) + ->first(); + + if (! $token) { + return response()->json([ + 'message' => trans('auth.token.not_found'), + ], HttpStatus::NOT_FOUND); + } + + $token->delete(); + + return response()->json([], HttpStatus::OK); + } +} diff --git a/app/Http/Controllers/Auth/VerifyEmailController.php b/app/Http/Controllers/Auth/VerifyEmailController.php new file mode 100644 index 0000000..e367846 --- /dev/null +++ b/app/Http/Controllers/Auth/VerifyEmailController.php @@ -0,0 +1,70 @@ +setRules([ + 'email' => Email::required()->validations( + new DNSCheckValidation(), + new NoRFCWarningsValidation() + )->max(100) + ->exists('users', 'email', function ($query) use ($request): void { + $query->whereEqual('email', $request->body('email')) + ->whereNull('email_verified_at'); + }), + 'otp' => Numeric::required()->digits(6), + ]); + + if ($validator->fails()) { + return response()->json([ + 'errors' => $validator->failing(), + ], HttpStatus::UNPROCESSABLE_ENTITY); + } + + $user = User::query()->whereEqual('email', $request->body('email'))->first(); + + $otp = UserOtp::query() + ->whereEqual('user_id', $user->id) + ->whereEqual('scope', OneTimePasswordScope::VERIFY_EMAIL->value) + ->whereEqual('code', hash('sha256', (string) $request->body('otp'))) + ->whereNull('used_at') + ->whereGreaterThanOrEqual('expires_at', Date::now()->toDateTimeString()) + ->first(); + + if (! $otp) { + return response()->json([ + 'message' => trans('auth.otp.invalid'), + ], HttpStatus::NOT_FOUND); + } + + $otp->usedAt = Date::now(); + $otp->save(); + + $user->emailVerifiedAt = Date::now(); + $user->save(); + + return response()->json([ + 'message' => trans('auth.email_verification.verified'), + ], HttpStatus::OK); + } +} diff --git a/app/Mail/LoginOtp.php b/app/Mail/LoginOtp.php new file mode 100644 index 0000000..dbafade --- /dev/null +++ b/app/Mail/LoginOtp.php @@ -0,0 +1,26 @@ +view('emails.otp', [ + 'title' => trans('auth.otp.login.title'), + 'message' => trans('auth.otp.login.message'), + 'otp' => $this->userOtp->otp, + ]) + ->subject(trans('auth.otp.login.subject')); + } +} diff --git a/app/Mail/ResetPasswordOtp.php b/app/Mail/ResetPasswordOtp.php new file mode 100644 index 0000000..0c651a3 --- /dev/null +++ b/app/Mail/ResetPasswordOtp.php @@ -0,0 +1,26 @@ +view('emails.otp', [ + 'title' => trans('auth.otp.reset_password.title'), + 'message' => trans('auth.otp.reset_password.message'), + 'otp' => $this->userOtp->otp, + ]) + ->subject(trans('auth.otp.reset_password.subject')); + } +} diff --git a/app/Mail/VerificationOtp.php b/app/Mail/VerificationOtp.php new file mode 100644 index 0000000..45cee54 --- /dev/null +++ b/app/Mail/VerificationOtp.php @@ -0,0 +1,26 @@ +view('emails.otp', [ + 'title' => trans('auth.otp.email_verification.title'), + 'message' => trans('auth.otp.email_verification.message'), + 'otp' => $this->userOtp->otp, + ]) + ->subject(trans('auth.otp.email_verification.subject')); + } +} diff --git a/app/Models/User.php b/app/Models/User.php new file mode 100644 index 0000000..a0b5712 --- /dev/null +++ b/app/Models/User.php @@ -0,0 +1,49 @@ +userId = $this->id; + $userOtp->save(); + + return $userOtp; + } + + public function sendOneTimePassword(OneTimePasswordScope $scope): void + { + $userOtp = $this->createOneTimePassword($scope); + $mailable = $this->resolveMailable($scope, $userOtp); + + Mail::to($this->email) + ->send($mailable); + } + + protected function resolveMailable(OneTimePasswordScope $scope, UserOtp $userOtp): Mailable + { + /** @phpstan-ignore-next-line */ + return match ($scope) { + OneTimePasswordScope::VERIFY_EMAIL => new VerificationOtp($userOtp), + OneTimePasswordScope::LOGIN => new LoginOtp($userOtp), + OneTimePasswordScope::RESET_PASSWORD => new ResetPasswordOtp($userOtp), + }; + } +} diff --git a/app/Models/UserOtp.php b/app/Models/UserOtp.php new file mode 100644 index 0000000..53d6c42 --- /dev/null +++ b/app/Models/UserOtp.php @@ -0,0 +1,77 @@ +id = Str::uuid()->toString(); + $otp->scope = $scope->value; + $otp->code = hash('sha256', (string) $value); + $otp->expiresAt = Date::now()->addMinutes(config('auth.otp.expiration', 10)); + $otp->otp = $value; + + return $otp; + } + + public function getScope(): OneTimePasswordScope + { + return OneTimePasswordScope::from($this->scope); + } +} diff --git a/app/Queries/UserOtpQuery.php b/app/Queries/UserOtpQuery.php new file mode 100644 index 0000000..68fcf96 --- /dev/null +++ b/app/Queries/UserOtpQuery.php @@ -0,0 +1,12 @@ +=8.1", + "psr/log": "^3|^2|^1", + "revolt/event-loop": "^1" + }, + "conflict": { + "amphp/file": "<3 || >=4" + }, + "require-dev": { + "amphp/file": "^3", + "amphp/http-server": "^3", + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "ext-pcntl": "*", + "phpunit/phpunit": "^9", + "psalm/phar": "~5.26.1" + }, + "suggest": { + "amphp/file": "Required for logging to a file", + "ext-sockets": "Required for socket transfer on systems that do not support SO_REUSEPORT" + }, + "bin": [ + "bin/cluster" + ], + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Cluster\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Bob Weinand" + } + ], + "description": "Building multi-core network applications with PHP.", + "homepage": "https://github.com/amphp/cluster", + "keywords": [ + "amp", + "amphp", + "async", + "cluster", + "multi-core", + "multi-process", + "non-blocking", + "parallel", + "sockets", + "watcher" + ], + "support": { + "issues": "https://github.com/amphp/cluster/issues", + "source": "https://github.com/amphp/cluster/tree/v2.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-12-21T02:00:08+00:00" + }, { "name": "amphp/dns", "version": "v2.4.0", @@ -693,16 +795,16 @@ }, { "name": "amphp/http-server", - "version": "v3.4.3", + "version": "v3.4.4", "source": { "type": "git", "url": "https://github.com/amphp/http-server.git", - "reference": "7aa962b0569f664af3ba23bc819f2a69884329cd" + "reference": "8dc32cc6a65c12a3543276305796b993c56b76ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/http-server/zipball/7aa962b0569f664af3ba23bc819f2a69884329cd", - "reference": "7aa962b0569f664af3ba23bc819f2a69884329cd", + "url": "https://api.github.com/repos/amphp/http-server/zipball/8dc32cc6a65c12a3543276305796b993c56b76ef", + "reference": "8dc32cc6a65c12a3543276305796b993c56b76ef", "shasum": "" }, "require": { @@ -778,7 +880,7 @@ ], "support": { "issues": "https://github.com/amphp/http-server/issues", - "source": "https://github.com/amphp/http-server/tree/v3.4.3" + "source": "https://github.com/amphp/http-server/tree/v3.4.4" }, "funding": [ { @@ -786,7 +888,7 @@ "type": "github" } ], - "time": "2025-05-18T15:43:42+00:00" + "time": "2026-02-08T18:16:29+00:00" }, { "name": "amphp/http-server-form-parser", @@ -952,16 +1054,16 @@ }, { "name": "amphp/http-server-session", - "version": "v3.0.0", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/amphp/http-server-session.git", - "reference": "88ee2106cd79a21f225bb631f8686d509002c11b" + "reference": "1cac38d80dc339a4befae96451d92ea364787e83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/http-server-session/zipball/88ee2106cd79a21f225bb631f8686d509002c11b", - "reference": "88ee2106cd79a21f225bb631f8686d509002c11b", + "url": "https://api.github.com/repos/amphp/http-server-session/zipball/1cac38d80dc339a4befae96451d92ea364787e83", + "reference": "1cac38d80dc339a4befae96451d92ea364787e83", "shasum": "" }, "require": { @@ -971,7 +1073,7 @@ "amphp/http-server": "^3", "amphp/serialization": "^1", "amphp/sync": "^2", - "paragonie/constant_time_encoding": "^2.2", + "paragonie/constant_time_encoding": "^2 || ^3", "php": ">=8.1" }, "conflict": { @@ -1016,7 +1118,7 @@ "homepage": "https://amphp.org/http-server-session", "support": { "issues": "https://github.com/amphp/http-server-session/issues", - "source": "https://github.com/amphp/http-server-session/tree/v3.0.0" + "source": "https://github.com/amphp/http-server-session/tree/v3.0.1" }, "funding": [ { @@ -1024,7 +1126,7 @@ "type": "github" } ], - "time": "2023-08-20T17:32:14+00:00" + "time": "2026-01-12T20:16:56+00:00" }, { "name": "amphp/log", @@ -1102,16 +1204,16 @@ }, { "name": "amphp/mysql", - "version": "v3.0.0", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/amphp/mysql.git", - "reference": "0eb9d1df67c206c043b1a1c6ad7ba1bc2aa836bf" + "reference": "bef63fda61eefca601be54aa1d983a6a31b4a50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/mysql/zipball/0eb9d1df67c206c043b1a1c6ad7ba1bc2aa836bf", - "reference": "0eb9d1df67c206c043b1a1c6ad7ba1bc2aa836bf", + "url": "https://api.github.com/repos/amphp/mysql/zipball/bef63fda61eefca601be54aa1d983a6a31b4a50f", + "reference": "bef63fda61eefca601be54aa1d983a6a31b4a50f", "shasum": "" }, "require": { @@ -1160,7 +1262,7 @@ "description": "Asynchronous MySQL client for PHP based on Amp.", "support": { "issues": "https://github.com/amphp/mysql/issues", - "source": "https://github.com/amphp/mysql/tree/v3.0.0" + "source": "https://github.com/amphp/mysql/tree/v3.0.1" }, "funding": [ { @@ -1168,20 +1270,20 @@ "type": "github" } ], - "time": "2024-03-10T17:33:58+00:00" + "time": "2025-11-08T22:59:09+00:00" }, { "name": "amphp/parallel", - "version": "v2.3.1", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/amphp/parallel.git", - "reference": "5113111de02796a782f5d90767455e7391cca190" + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/parallel/zipball/5113111de02796a782f5d90767455e7391cca190", - "reference": "5113111de02796a782f5d90767455e7391cca190", + "url": "https://api.github.com/repos/amphp/parallel/zipball/296b521137a54d3a02425b464e5aee4c93db2c60", + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60", "shasum": "" }, "require": { @@ -1244,7 +1346,7 @@ ], "support": { "issues": "https://github.com/amphp/parallel/issues", - "source": "https://github.com/amphp/parallel/tree/v2.3.1" + "source": "https://github.com/amphp/parallel/tree/v2.3.3" }, "funding": [ { @@ -1252,7 +1354,7 @@ "type": "github" } ], - "time": "2024-12-21T01:56:09+00:00" + "time": "2025-11-15T06:23:42+00:00" }, { "name": "amphp/parser", @@ -1525,16 +1627,16 @@ }, { "name": "amphp/redis", - "version": "v2.0.3", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/amphp/redis.git", - "reference": "1572c2fec2849d272570919e998f9a3c1a5b1703" + "reference": "964bcf6c2574645058371925a3668240a622bdab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/redis/zipball/1572c2fec2849d272570919e998f9a3c1a5b1703", - "reference": "1572c2fec2849d272570919e998f9a3c1a5b1703", + "url": "https://api.github.com/repos/amphp/redis/zipball/964bcf6c2574645058371925a3668240a622bdab", + "reference": "964bcf6c2574645058371925a3668240a622bdab", "shasum": "" }, "require": { @@ -1594,7 +1696,7 @@ ], "support": { "issues": "https://github.com/amphp/redis/issues", - "source": "https://github.com/amphp/redis/tree/v2.0.3" + "source": "https://github.com/amphp/redis/tree/v2.0.4" }, "funding": [ { @@ -1602,7 +1704,7 @@ "type": "github" } ], - "time": "2025-01-15T04:14:11+00:00" + "time": "2026-03-03T20:52:26+00:00" }, { "name": "amphp/serialization", @@ -1748,16 +1850,16 @@ }, { "name": "amphp/sql", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/amphp/sql.git", - "reference": "2a7962dba23bf017bbdd3c3a0af0eb212481627b" + "reference": "258bafe5ecf8a0491d86681f2a2af1dee2933a69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/sql/zipball/2a7962dba23bf017bbdd3c3a0af0eb212481627b", - "reference": "2a7962dba23bf017bbdd3c3a0af0eb212481627b", + "url": "https://api.github.com/repos/amphp/sql/zipball/258bafe5ecf8a0491d86681f2a2af1dee2933a69", + "reference": "258bafe5ecf8a0491d86681f2a2af1dee2933a69", "shasum": "" }, "require": { @@ -1767,7 +1869,7 @@ "require-dev": { "amphp/php-cs-fixer-config": "^2", "phpunit/phpunit": "^9", - "psalm/phar": "5.23" + "psalm/phar": "6.15.1" }, "type": "library", "autoload": { @@ -1790,7 +1892,7 @@ ], "support": { "issues": "https://github.com/amphp/sql/issues", - "source": "https://github.com/amphp/sql/tree/v2.0.1" + "source": "https://github.com/amphp/sql/tree/v2.1.1" }, "funding": [ { @@ -1798,20 +1900,20 @@ "type": "github" } ], - "time": "2024-11-23T16:16:34+00:00" + "time": "2026-02-25T04:44:15+00:00" }, { "name": "amphp/sql-common", - "version": "v2.0.3", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/amphp/sql-common.git", - "reference": "0c926e0348c238c61bead25af5c2fa0d5afaed8d" + "reference": "735da17ef0a66e7139c9f7584af5c3f9827f83c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/sql-common/zipball/0c926e0348c238c61bead25af5c2fa0d5afaed8d", - "reference": "0c926e0348c238c61bead25af5c2fa0d5afaed8d", + "url": "https://api.github.com/repos/amphp/sql-common/zipball/735da17ef0a66e7139c9f7584af5c3f9827f83c0", + "reference": "735da17ef0a66e7139c9f7584af5c3f9827f83c0", "shasum": "" }, "require": { @@ -1846,7 +1948,7 @@ ], "support": { "issues": "https://github.com/amphp/sql-common/issues", - "source": "https://github.com/amphp/sql-common/tree/v2.0.3" + "source": "https://github.com/amphp/sql-common/tree/v2.0.4" }, "funding": [ { @@ -1854,7 +1956,7 @@ "type": "github" } ], - "time": "2025-06-07T15:35:29+00:00" + "time": "2025-12-11T20:05:29+00:00" }, { "name": "amphp/sync", @@ -1933,23 +2035,22 @@ }, { "name": "async-aws/core", - "version": "1.27.0", + "version": "1.28.1", "source": { "type": "git", "url": "https://github.com/async-aws/core.git", - "reference": "00b69a04a36b5ba75e0448e46158c9718ac95755" + "reference": "e8b02ac30b17afaf1352cbd352dceb789d792d39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/async-aws/core/zipball/00b69a04a36b5ba75e0448e46158c9718ac95755", - "reference": "00b69a04a36b5ba75e0448e46158c9718ac95755", + "url": "https://api.github.com/repos/async-aws/core/zipball/e8b02ac30b17afaf1352cbd352dceb789d792d39", + "reference": "e8b02ac30b17afaf1352cbd352dceb789d792d39", "shasum": "" }, "require": { "ext-hash": "*", - "ext-json": "*", "ext-simplexml": "*", - "php": "^7.2.5 || ^8.0", + "php": "^8.2", "psr/cache": "^1.0 || ^2.0 || ^3.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "symfony/deprecation-contracts": "^2.1 || ^3.0", @@ -1961,10 +2062,15 @@ "async-aws/s3": "<1.1", "symfony/http-client": "5.2.0" }, + "require-dev": { + "phpunit/phpunit": "^11.5.42", + "symfony/error-handler": "^7.3.2 || ^8.0", + "symfony/phpunit-bridge": "^7.3.2 || ^8.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.27-dev" + "dev-master": "1.28-dev" } }, "autoload": { @@ -1985,7 +2091,7 @@ "sts" ], "support": { - "source": "https://github.com/async-aws/core/tree/1.27.0" + "source": "https://github.com/async-aws/core/tree/1.28.1" }, "funding": [ { @@ -1997,31 +2103,35 @@ "type": "github" } ], - "time": "2025-08-11T10:03:27+00:00" + "time": "2026-02-16T10:24:54+00:00" }, { "name": "async-aws/ses", - "version": "1.13.0", + "version": "1.14.1", "source": { "type": "git", "url": "https://github.com/async-aws/ses.git", - "reference": "e11cdc16cfa3d7ae45266d62d886a1d7a71a1c42" + "reference": "8ba4c7f5bbb4d1055f3ebedcf0ea1b8b79393e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/async-aws/ses/zipball/e11cdc16cfa3d7ae45266d62d886a1d7a71a1c42", - "reference": "e11cdc16cfa3d7ae45266d62d886a1d7a71a1c42", + "url": "https://api.github.com/repos/async-aws/ses/zipball/8ba4c7f5bbb4d1055f3ebedcf0ea1b8b79393e5b", + "reference": "8ba4c7f5bbb4d1055f3ebedcf0ea1b8b79393e5b", "shasum": "" }, "require": { "async-aws/core": "^1.9", - "ext-json": "*", - "php": "^7.2.5 || ^8.0" + "php": "^8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.42", + "symfony/error-handler": "^7.3.2 || ^8.0", + "symfony/phpunit-bridge": "^7.3.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.14-dev" } }, "autoload": { @@ -2042,7 +2152,7 @@ "ses" ], "support": { - "source": "https://github.com/async-aws/ses/tree/1.13.0" + "source": "https://github.com/async-aws/ses/tree/1.14.1" }, "funding": [ { @@ -2054,20 +2164,20 @@ "type": "github" } ], - "time": "2025-08-11T10:03:27+00:00" + "time": "2026-02-16T10:24:54+00:00" }, { "name": "cakephp/chronos", - "version": "3.2.0", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/cakephp/chronos.git", - "reference": "6c820947bc1372a250288ab164ec1b3bb7afab39" + "reference": "608bbc32c59f74a0ea3358c20436c8dd94536e7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/chronos/zipball/6c820947bc1372a250288ab164ec1b3bb7afab39", - "reference": "6c820947bc1372a250288ab164ec1b3bb7afab39", + "url": "https://api.github.com/repos/cakephp/chronos/zipball/608bbc32c59f74a0ea3358c20436c8dd94536e7c", + "reference": "608bbc32c59f74a0ea3358c20436c8dd94536e7c", "shasum": "" }, "require": { @@ -2079,7 +2189,7 @@ }, "require-dev": { "cakephp/cakephp-codesniffer": "^5.0", - "phpunit/phpunit": "^10.1.0 || ^11.1.3" + "phpunit/phpunit": "^10.5.58 || ^11.5.3 || ^12.1.3" }, "type": "library", "autoload": { @@ -2113,20 +2223,20 @@ "issues": "https://github.com/cakephp/chronos/issues", "source": "https://github.com/cakephp/chronos" }, - "time": "2025-06-28T11:35:59+00:00" + "time": "2026-03-25T23:05:15+00:00" }, { "name": "cakephp/core", - "version": "5.2.6", + "version": "5.2.12", "source": { "type": "git", "url": "https://github.com/cakephp/core.git", - "reference": "93f395b6d741775320c4b782ddb47b5c2906e7ad" + "reference": "f18f37c04832831ca37f5300212b1adddcc54b86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/core/zipball/93f395b6d741775320c4b782ddb47b5c2906e7ad", - "reference": "93f395b6d741775320c4b782ddb47b5c2906e7ad", + "url": "https://api.github.com/repos/cakephp/core/zipball/f18f37c04832831ca37f5300212b1adddcc54b86", + "reference": "f18f37c04832831ca37f5300212b1adddcc54b86", "shasum": "" }, "require": { @@ -2180,20 +2290,20 @@ "issues": "https://github.com/cakephp/cakephp/issues", "source": "https://github.com/cakephp/core" }, - "time": "2025-07-20T02:02:49+00:00" + "time": "2025-11-14T14:52:55+00:00" }, { "name": "cakephp/database", - "version": "5.2.6", + "version": "5.2.12", "source": { "type": "git", "url": "https://github.com/cakephp/database.git", - "reference": "1a2b357ed2deae8797c4ccb7a8062b1bdb5e27a2" + "reference": "cf855540be5a0f522394827398c9552fe1656146" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/database/zipball/1a2b357ed2deae8797c4ccb7a8062b1bdb5e27a2", - "reference": "1a2b357ed2deae8797c4ccb7a8062b1bdb5e27a2", + "url": "https://api.github.com/repos/cakephp/database/zipball/cf855540be5a0f522394827398c9552fe1656146", + "reference": "cf855540be5a0f522394827398c9552fe1656146", "shasum": "" }, "require": { @@ -2247,20 +2357,20 @@ "issues": "https://github.com/cakephp/cakephp/issues", "source": "https://github.com/cakephp/database" }, - "time": "2025-07-20T02:02:49+00:00" + "time": "2025-11-16T20:33:48+00:00" }, { "name": "cakephp/datasource", - "version": "5.2.6", + "version": "5.2.12", "source": { "type": "git", "url": "https://github.com/cakephp/datasource.git", - "reference": "4d40b398897ada47569e82b351cabf00e37b2ba1" + "reference": "906a8b719b6dc241fa81a55be20c9adc51c31f74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/datasource/zipball/4d40b398897ada47569e82b351cabf00e37b2ba1", - "reference": "4d40b398897ada47569e82b351cabf00e37b2ba1", + "url": "https://api.github.com/repos/cakephp/datasource/zipball/906a8b719b6dc241fa81a55be20c9adc51c31f74", + "reference": "906a8b719b6dc241fa81a55be20c9adc51c31f74", "shasum": "" }, "require": { @@ -2314,20 +2424,20 @@ "issues": "https://github.com/cakephp/cakephp/issues", "source": "https://github.com/cakephp/datasource" }, - "time": "2025-07-20T02:02:49+00:00" + "time": "2025-11-14T14:52:55+00:00" }, { "name": "cakephp/utility", - "version": "5.2.6", + "version": "5.2.12", "source": { "type": "git", "url": "https://github.com/cakephp/utility.git", - "reference": "3188be6abdbe27f85a44c2d317477dc7b43582eb" + "reference": "df9bc4e420db3b4a02cafad896398bad48813e50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/utility/zipball/3188be6abdbe27f85a44c2d317477dc7b43582eb", - "reference": "3188be6abdbe27f85a44c2d317477dc7b43582eb", + "url": "https://api.github.com/repos/cakephp/utility/zipball/df9bc4e420db3b4a02cafad896398bad48813e50", + "reference": "df9bc4e420db3b4a02cafad896398bad48813e50", "shasum": "" }, "require": { @@ -2378,7 +2488,7 @@ "issues": "https://github.com/cakephp/cakephp/issues", "source": "https://github.com/cakephp/utility" }, - "time": "2025-07-20T02:02:49+00:00" + "time": "2025-11-14T14:52:55+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -2570,6 +2680,70 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "shasum": "" + }, + "require": { + "php": "^8.2|^8.3|^8.4|^8.5" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.32|^2.1.31", + "phpunit/phpunit": "^8.5.48|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2025-10-31T18:51:33+00:00" + }, { "name": "egulias/email-validator", "version": "4.0.4", @@ -2702,24 +2876,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.3", + "version": "v1.1.4", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3" + "phpoption/phpoption": "^1.9.5" }, "require-dev": { - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" }, "type": "library", "autoload": { @@ -2748,7 +2922,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" }, "funding": [ { @@ -2760,26 +2934,26 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:45:45+00:00" + "time": "2025-12-27T19:43:20+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.9.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2870,7 +3044,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -2886,7 +3060,7 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:37:11+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", @@ -2973,16 +3147,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", "shasum": "" }, "require": { @@ -2998,7 +3172,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -3069,7 +3244,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.9.0" }, "funding": [ { @@ -3085,7 +3260,7 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2026-03-10T16:41:02+00:00" }, { "name": "kelunik/certificate", @@ -3145,6 +3320,125 @@ }, "time": "2023-02-03T21:26:53+00:00" }, + { + "name": "kelunik/rate-limit", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/kelunik/rate-limit.git", + "reference": "473e8dd66b2f164d0ca7da039eb77574dffcf5b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/rate-limit/zipball/473e8dd66b2f164d0ca7da039eb77574dffcf5b3", + "reference": "473e8dd66b2f164d0ca7da039eb77574dffcf5b3", + "shasum": "" + }, + "require": { + "amphp/redis": "^2", + "php": ">=8.1" + }, + "require-dev": { + "amphp/amp": "^3", + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "Kelunik\\RateLimit\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rate Limiting for Amp.", + "keywords": [ + "amp", + "amphp", + "limit", + "rate-limit", + "redis" + ], + "support": { + "issues": "https://github.com/kelunik/rate-limit/issues", + "source": "https://github.com/kelunik/rate-limit/tree/v3.0.0" + }, + "time": "2023-09-04T17:56:06+00:00" + }, + { + "name": "league/climate", + "version": "3.10.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/climate.git", + "reference": "f2d78fbc504740bcd0209e40a4586c886567ddc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/climate/zipball/f2d78fbc504740bcd0209e40a4586c886567ddc9", + "reference": "f2d78fbc504740bcd0209e40a4586c886567ddc9", + "shasum": "" + }, + "require": { + "php": "^7.3 || ^8.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "seld/cli-prompt": "^1.0" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6.12", + "mockery/mockery": "^1.6.12", + "phpunit/phpunit": "^9.6.21", + "squizlabs/php_codesniffer": "^3.10" + }, + "suggest": { + "ext-mbstring": "If ext-mbstring is not available you MUST install symfony/polyfill-mbstring" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\CLImate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joe Tannenbaum", + "email": "hey@joe.codes", + "homepage": "http://joe.codes/", + "role": "Developer" + }, + { + "name": "Craig Duncan", + "email": "git@duncanc.co.uk", + "homepage": "https://github.com/duncan3dc", + "role": "Developer" + } + ], + "description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.", + "keywords": [ + "cli", + "colors", + "command", + "php", + "terminal" + ], + "support": { + "issues": "https://github.com/thephpleague/climate/issues", + "source": "https://github.com/thephpleague/climate/tree/3.10.1" + }, + "time": "2026-03-19T19:32:55+00:00" + }, { "name": "league/container", "version": "4.2.5", @@ -3229,33 +3523,38 @@ }, { "name": "league/uri", - "version": "7.5.1", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "81fb5145d2644324614cc532b28efd0215bda430" + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", - "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.5", - "php": "^8.1" + "league/uri-interfaces": "^7.8.1", + "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", - "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", - "league/uri-components": "Needed to easily manipulate URI objects components", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-components": "to provide additional tools to manipulate URI objects components", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3283,6 +3582,7 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ + "URN", "data-uri", "file-uri", "ftp", @@ -3295,9 +3595,11 @@ "psr-7", "query-string", "querystring", + "rfc2141", "rfc3986", "rfc3987", "rfc6570", + "rfc8141", "uri", "uri-template", "url", @@ -3307,7 +3609,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.8.1" }, "funding": [ { @@ -3315,24 +3617,24 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2026-03-15T20:22:25+00:00" }, { "name": "league/uri-components", - "version": "7.5.1", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-components.git", - "reference": "4aabf0e2f2f9421ffcacab35be33e4fb5e63c44f" + "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/4aabf0e2f2f9421ffcacab35be33e4fb5e63c44f", - "reference": "4aabf0e2f2f9421ffcacab35be33e4fb5e63c44f", + "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/848ff9db2f0be06229d6034b7c2e33d41b4fd675", + "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675", "shasum": "" }, "require": { - "league/uri": "^7.5", + "league/uri": "^7.8.1", "php": "^8.1" }, "suggest": { @@ -3341,8 +3643,10 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "ext-mbstring": "to use the sorting algorithm of URLSearchParams", - "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3389,7 +3693,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-components/tree/7.5.1" + "source": "https://github.com/thephpleague/uri-components/tree/7.8.1" }, "funding": [ { @@ -3397,26 +3701,25 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2026-03-15T20:22:25+00:00" }, { "name": "league/uri-interfaces", - "version": "7.5.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928" }, "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/85d5c77c5d6d3af6c54db4a78246364908f3c928", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", - "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -3424,6 +3727,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 URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3448,7 +3752,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", @@ -3473,7 +3777,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.8.1" }, "funding": [ { @@ -3481,20 +3785,20 @@ "type": "github" } ], - "time": "2024-12-08T08:18:47+00:00" + "time": "2026-03-08T20:05:35+00:00" }, { "name": "monolog/monolog", - "version": "3.9.0", + "version": "3.10.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", "shasum": "" }, "require": { @@ -3512,7 +3816,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", + "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -3572,7 +3876,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" }, "funding": [ { @@ -3584,20 +3888,20 @@ "type": "tidelift" } ], - "time": "2025-03-24T10:02:05+00:00" + "time": "2026-01-02T08:56:05+00:00" }, { "name": "nesbot/carbon", - "version": "3.10.2", + "version": "3.11.3", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24" + "reference": "6a7e652845bb018c668220c2a545aded8594fbbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", - "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6a7e652845bb018c668220c2a545aded8594fbbf", + "reference": "6a7e652845bb018c668220c2a545aded8594fbbf", "shasum": "" }, "require": { @@ -3605,9 +3909,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" @@ -3615,13 +3919,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.75.0", + "friendsofphp/php-cs-fixer": "^v3.87.1", "kylekatarnls/multi-tester": "^2.5.3", "phpmd/phpmd": "^2.15.0", "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.17", - "phpunit/phpunit": "^10.5.46", - "squizlabs/php_codesniffer": "^3.13.0" + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0" }, "bin": [ "bin/carbon" @@ -3664,14 +3968,14 @@ } ], "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "https://carbon.nesbot.com", + "homepage": "https://carbonphp.github.io/carbon/", "keywords": [ "date", "datetime", "time" ], "support": { - "docs": "https://carbon.nesbot.com/docs", + "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html", "issues": "https://github.com/CarbonPHP/carbon/issues", "source": "https://github.com/CarbonPHP/carbon" }, @@ -3689,7 +3993,7 @@ "type": "tidelift" } ], - "time": "2025-08-02T09:36:06+00:00" + "time": "2026-03-11T17:23:39+00:00" }, { "name": "nikic/fast-route", @@ -3743,24 +4047,26 @@ }, { "name": "paragonie/constant_time_encoding", - "version": "v2.7.0", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105" + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", "shasum": "" }, "require": { - "php": "^7|^8" + "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" }, "type": "library", "autoload": { @@ -3806,25 +4112,26 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:18:48+00:00" + "time": "2025-09-24T15:06:41+00:00" }, { "name": "phenixphp/framework", - "version": "0.6.0", + "version": "0.8.5", "source": { "type": "git", "url": "https://github.com/phenixphp/framework.git", - "reference": "9c43d8518524928fa5eb6922dbbfed21f1b275cd" + "reference": "64b4d155ddc119f1291e65d33b01b2b6ff235d96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phenixphp/framework/zipball/9c43d8518524928fa5eb6922dbbfed21f1b275cd", - "reference": "9c43d8518524928fa5eb6922dbbfed21f1b275cd", + "url": "https://api.github.com/repos/phenixphp/framework/zipball/64b4d155ddc119f1291e65d33b01b2b6ff235d96", + "reference": "64b4d155ddc119f1291e65d33b01b2b6ff235d96", "shasum": "" }, "require": { "adbario/php-dot-notation": "^3.1", "amphp/cache": "^2.0", + "amphp/cluster": "^2.0", "amphp/file": "^v3.0.0", "amphp/http-client": "^v5.0.1", "amphp/http-server": "^v3.2.0", @@ -3837,12 +4144,16 @@ "amphp/postgres": "v2.0.0", "amphp/redis": "^2.0", "amphp/socket": "^2.1.0", + "dragonmantank/cron-expression": "^3.6", "egulias/email-validator": "^4.0", "ext-pcntl": "*", + "ext-sockets": "*", "fakerphp/faker": "^1.23", + "kelunik/rate-limit": "^3.0", "league/container": "^4.2", "nesbot/carbon": "^3.0", "phenixphp/http-cors": "^0.1.0", + "phenixphp/sqlite": "^0.1.1", "php": "^8.2", "ramsey/collection": "^2.0", "resend/resend-php": "^0.16.0", @@ -3894,9 +4205,9 @@ "description": "Phenix framework based on Amphp", "support": { "issues": "https://github.com/phenixphp/framework/issues", - "source": "https://github.com/phenixphp/framework/tree/0.6.0" + "source": "https://github.com/phenixphp/framework/tree/0.8.5" }, - "time": "2025-08-22T22:35:11+00:00" + "time": "2026-04-01T15:17:50+00:00" }, { "name": "phenixphp/http-cors", @@ -3937,44 +4248,105 @@ "time": "2024-05-01T02:55:36+00:00" }, { - "name": "phpoption/phpoption", - "version": "1.9.4", + "name": "phenixphp/sqlite", + "version": "0.1.2", "source": { "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" + "url": "https://github.com/phenixphp/sqlite.git", + "reference": "6a70e92387fefefbb93f9f1c1284f169c36dd4c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", - "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "url": "https://api.github.com/repos/phenixphp/sqlite/zipball/6a70e92387fefefbb93f9f1c1284f169c36dd4c9", + "reference": "6a70e92387fefefbb93f9f1c1284f169c36dd4c9", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "amphp/amp": "^3", + "amphp/parallel": "^2.3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/sql": "^2", + "amphp/sql-common": "^2", + "ext-sqlite3": "*", + "php": "^8.2" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + "amphp/file": "^3", + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpbench/phpbench": "^1.2.6", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^9", + "symfony/var-dumper": "^7.4" }, "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "1.9-dev" - } - }, "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { - "PhpOption\\": "src/PhpOption/" + "Phenix\\Sqlite\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" + ], + "authors": [ + { + "name": "Omar Barbosa", + "email": "contacto@omarbarbosa.com" + } + ], + "description": "Asynchronous SQLite 3 client for PHP based on Amp.", + "homepage": "https://github.com/phenixphp/sqlite", + "support": { + "issues": "https://github.com/phenixphp/sqlite/issues", + "source": "https://github.com/phenixphp/sqlite/tree/0.1.2" + }, + "time": "2026-03-02T15:28:29+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.5", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" ], "authors": [ { @@ -3997,7 +4369,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.4" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" }, "funding": [ { @@ -4009,7 +4381,7 @@ "type": "tidelift" } ], - "time": "2025-08-21T11:53:16+00:00" + "time": "2025-12-27T19:41:33+00:00" }, { "name": "psr/cache", @@ -4651,16 +5023,16 @@ }, { "name": "revolt/event-loop", - "version": "v1.0.7", + "version": "v1.0.8", "source": { "type": "git", "url": "https://github.com/revoltphp/event-loop.git", - "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3" + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/09bf1bf7f7f574453efe43044b06fafe12216eb3", - "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/b6fc06dce8e9b523c9946138fa5e62181934f91c", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c", "shasum": "" }, "require": { @@ -4717,9 +5089,9 @@ ], "support": { "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/v1.0.7" + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.8" }, - "time": "2025-01-25T19:27:39+00:00" + "time": "2025-08-27T21:33:23+00:00" }, { "name": "robmorgan/phinx", @@ -4807,27 +5179,82 @@ }, "time": "2023-12-05T13:24:00+00:00" }, + { + "name": "seld/cli-prompt", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/cli-prompt.git", + "reference": "b8dfcf02094b8c03b40322c229493bb2884423c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/b8dfcf02094b8c03b40322c229493bb2884423c5", + "reference": "b8dfcf02094b8c03b40322c229493bb2884423c5", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.63" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\CliPrompt\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", + "keywords": [ + "cli", + "console", + "hidden", + "input", + "prompt" + ], + "support": { + "issues": "https://github.com/Seldaek/cli-prompt/issues", + "source": "https://github.com/Seldaek/cli-prompt/tree/1.0.4" + }, + "time": "2020-12-15T21:32:01+00:00" + }, { "name": "symfony/amazon-mailer", - "version": "v7.3.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/amazon-mailer.git", - "reference": "7266d4285147c890f4f7f42dc875fe5a6df8006c" + "reference": "6fedfa970a1b5b2c93fd32c598df7db7d03070b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/amazon-mailer/zipball/7266d4285147c890f4f7f42dc875fe5a6df8006c", - "reference": "7266d4285147c890f4f7f42dc875fe5a6df8006c", + "url": "https://api.github.com/repos/symfony/amazon-mailer/zipball/6fedfa970a1b5b2c93fd32c598df7db7d03070b4", + "reference": "6fedfa970a1b5b2c93fd32c598df7db7d03070b4", "shasum": "" }, "require": { "async-aws/ses": "^1.8", "php": ">=8.2", - "symfony/mailer": "^7.2" + "symfony/mailer": "^7.2|^8.0" }, "require-dev": { - "symfony/http-client": "^6.4|^7.0" + "symfony/http-client": "^6.4|^7.0|^8.0" }, "type": "symfony-mailer-bridge", "autoload": { @@ -4855,7 +5282,7 @@ "description": "Symfony Amazon Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/amazon-mailer/tree/v7.3.0" + "source": "https://github.com/symfony/amazon-mailer/tree/v7.4.6" }, "funding": [ { @@ -4866,25 +5293,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-02-26T16:10:57+00:00" + "time": "2026-02-11T15:05:50+00:00" }, { "name": "symfony/clock", - "version": "v7.3.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", "shasum": "" }, "require": { @@ -4929,7 +5360,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.3.0" + "source": "https://github.com/symfony/clock/tree/v7.4.8" }, "funding": [ { @@ -4940,31 +5371,35 @@ "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": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/config", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "faef36e271bbeb74a9d733be4b56419b157762e2" + "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/faef36e271bbeb74a9d733be4b56419b157762e2", - "reference": "faef36e271bbeb74a9d733be4b56419b157762e2", + "url": "https://api.github.com/repos/symfony/config/zipball/2d19dde43fa2ff720b9a40763ace7226594f503b", + "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b", "shasum": "" }, "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1", + "symfony/filesystem": "^7.1|^8.0", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -4972,11 +5407,11 @@ "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5004,7 +5439,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.3.2" + "source": "https://github.com/symfony/config/tree/v7.4.8" }, "funding": [ { @@ -5024,20 +5459,20 @@ "type": "tidelift" } ], - "time": "2025-07-26T13:55:06+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/console", - "version": "v6.4.24", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350" + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350", - "reference": "59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350", + "url": "https://api.github.com/repos/symfony/console/zipball/9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", "shasum": "" }, "require": { @@ -5102,7 +5537,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.24" + "source": "https://github.com/symfony/console/tree/v6.4.36" }, "funding": [ { @@ -5122,7 +5557,7 @@ "type": "tidelift" } ], - "time": "2025-07-30T10:38:54+00:00" + "time": "2026-03-27T15:30:51+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5193,16 +5628,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.3.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + "reference": "f57b899fa736fd71121168ef268f23c206083f0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f57b899fa736fd71121168ef268f23c206083f0a", + "reference": "f57b899fa736fd71121168ef268f23c206083f0a", "shasum": "" }, "require": { @@ -5219,13 +5654,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": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5253,7 +5689,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.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.8" }, "funding": [ { @@ -5264,12 +5700,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": "2025-04-22T09:11:45+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -5349,16 +5789,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5", + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5", "shasum": "" }, "require": { @@ -5367,7 +5807,7 @@ "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0" + "symfony/process": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5395,7 +5835,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + "source": "https://github.com/symfony/filesystem/tree/v7.4.8" }, "funding": [ { @@ -5415,20 +5855,20 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:47+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-client", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "1c064a0c67749923483216b081066642751cc2c7" + "reference": "01933e626c3de76bea1e22641e205e78f6a34342" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/1c064a0c67749923483216b081066642751cc2c7", - "reference": "1c064a0c67749923483216b081066642751cc2c7", + "url": "https://api.github.com/repos/symfony/http-client/zipball/01933e626c3de76bea1e22641e205e78f6a34342", + "reference": "01933e626c3de76bea1e22641e205e78f6a34342", "shasum": "" }, "require": { @@ -5436,6 +5876,7 @@ "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/polyfill-php83": "^1.29", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -5458,12 +5899,13 @@ "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", "symfony/amphp-http-client-meta": "^1.0|^2.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5494,7 +5936,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.2" + "source": "https://github.com/symfony/http-client/tree/v7.4.8" }, "funding": [ { @@ -5514,7 +5956,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:36:08+00:00" + "time": "2026-03-30T12:55:43+00:00" }, { "name": "symfony/http-client-contracts", @@ -5596,16 +6038,16 @@ }, { "name": "symfony/mailer", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b" + "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/d43e84d9522345f96ad6283d5dfccc8c1cfc299b", - "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f6ea532250b476bfc1b56699b388a1bdbf168f62", + "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62", "shasum": "" }, "require": { @@ -5613,8 +6055,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": { @@ -5625,10 +6067,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": { @@ -5656,7 +6098,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.2" + "source": "https://github.com/symfony/mailer/tree/v7.4.8" }, "funding": [ { @@ -5676,43 +6118,44 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:36:08+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/mime", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" + "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "url": "https://api.github.com/repos/symfony/mime/zipball/6df02f99998081032da3407a8d6c4e1dcb5d4379", + "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "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" + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "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": { @@ -5744,7 +6187,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.3.2" + "source": "https://github.com/symfony/mime/tree/v7.4.8" }, "funding": [ { @@ -5764,7 +6207,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2026-03-30T14:11:46+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6437,29 +6880,29 @@ }, { "name": "symfony/resend-mailer", - "version": "v7.3.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/resend-mailer.git", - "reference": "591d06a6603845933e921c10cedb2afb97376c50" + "reference": "eb7f4d83128eef12fcceccf33e5b4b89f2e2474f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/resend-mailer/zipball/591d06a6603845933e921c10cedb2afb97376c50", - "reference": "591d06a6603845933e921c10cedb2afb97376c50", + "url": "https://api.github.com/repos/symfony/resend-mailer/zipball/eb7f4d83128eef12fcceccf33e5b4b89f2e2474f", + "reference": "eb7f4d83128eef12fcceccf33e5b4b89f2e2474f", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/mailer": "^7.2" + "php": ">=8.2", + "symfony/mailer": "^7.2|^8.0" }, "conflict": { "symfony/http-foundation": "<7.1" }, "require-dev": { - "symfony/http-client": "^6.4|^7.0", - "symfony/http-foundation": "^7.1", - "symfony/webhook": "^6.4|^7.0" + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^7.1|^8.0", + "symfony/webhook": "^6.4|^7.0|^8.0" }, "type": "symfony-mailer-bridge", "autoload": { @@ -6487,7 +6930,7 @@ "description": "Symfony Resend Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/resend-mailer/tree/v7.3.0" + "source": "https://github.com/symfony/resend-mailer/tree/v7.4.6" }, "funding": [ { @@ -6498,25 +6941,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-28T08:24:38+00:00" + "time": "2026-02-09T14:10:20+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": { @@ -6570,7 +7017,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": [ { @@ -6581,31 +7028,36 @@ "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.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-grapheme": "~1.33", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, @@ -6613,12 +7065,11 @@ "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.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6657,7 +7108,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.2" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -6677,27 +7128,27 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:47:49+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "81b48f4daa96272efcce9c7a6c4b58e629df3c90" + "reference": "33600f8489485425bfcddd0d983391038d3422e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/81b48f4daa96272efcce9c7a6c4b58e629df3c90", - "reference": "81b48f4daa96272efcce9c7a6c4b58e629df3c90", + "url": "https://api.github.com/repos/symfony/translation/zipball/33600f8489485425bfcddd0d983391038d3422e7", + "reference": "33600f8489485425bfcddd0d983391038d3422e7", "shasum": "" }, "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "symfony/translation-contracts": "^2.5.3|^3.3" }, "conflict": { "nikic/php-parser": "<5.0", @@ -6716,17 +7167,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": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^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": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6757,7 +7208,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.3.2" + "source": "https://github.com/symfony/translation/tree/v7.4.8" }, "funding": [ { @@ -6777,20 +7228,20 @@ "type": "tidelift" } ], - "time": "2025-07-30T17:31:46+00:00" + "time": "2026-03-24T13:12:05+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": { @@ -6839,7 +7290,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": [ { @@ -6850,25 +7301,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.8", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "url": "https://api.github.com/repos/symfony/uid/zipball/6883ebdf7bf6a12b37519dbc0df62b0222401b56", + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56", "shasum": "" }, "require": { @@ -6876,7 +7331,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": { @@ -6913,7 +7368,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.3.1" + "source": "https://github.com/symfony/uid/tree/v7.4.8" }, "funding": [ { @@ -6924,25 +7379,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": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "53205bea27450dc5c65377518b3275e126d45e75" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/53205bea27450dc5c65377518b3275e126d45e75", - "reference": "53205bea27450dc5c65377518b3275e126d45e75", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { @@ -6954,10 +7413,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": [ @@ -6996,7 +7455,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.2" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -7016,30 +7475,30 @@ "type": "tidelift" } ], - "time": "2025-07-29T20:02:46+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.2", + "version": "v5.6.3", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + "reference": "955e7815d677a3eaa7075231212f2110983adecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.3", + "graham-campbell/result-type": "^1.1.4", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3", - "symfony/polyfill-ctype": "^1.24", - "symfony/polyfill-mbstring": "^1.24", - "symfony/polyfill-php80": "^1.24" + "phpoption/phpoption": "^1.9.5", + "symfony/polyfill-ctype": "^1.26", + "symfony/polyfill-mbstring": "^1.26", + "symfony/polyfill-php80": "^1.26" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -7088,7 +7547,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" }, "funding": [ { @@ -7100,7 +7559,7 @@ "type": "tidelift" } ], - "time": "2025-04-30T23:37:27+00:00" + "time": "2025-12-27T19:49:13+00:00" } ], "packages-dev": [ @@ -7161,98 +7620,6 @@ ], "time": "2022-12-18T17:47:31+00:00" }, - { - "name": "brianium/paratest", - "version": "v6.11.1", - "source": { - "type": "git", - "url": "https://github.com/paratestphp/paratest.git", - "reference": "78e297a969049ca7cc370e80ff5e102921ef39a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/78e297a969049ca7cc370e80ff5e102921ef39a3", - "reference": "78e297a969049ca7cc370e80ff5e102921ef39a3", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-simplexml": "*", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", - "jean85/pretty-package-versions": "^2.0.5", - "php": "^7.3 || ^8.0", - "phpunit/php-code-coverage": "^9.2.25", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-timer": "^5.0.3", - "phpunit/phpunit": "^9.6.4", - "sebastian/environment": "^5.1.5", - "symfony/console": "^5.4.28 || ^6.3.4 || ^7.0.0", - "symfony/process": "^5.4.28 || ^6.3.4 || ^7.0.0" - }, - "require-dev": { - "doctrine/coding-standard": "^12.0.0", - "ext-pcov": "*", - "ext-posix": "*", - "infection/infection": "^0.27.6", - "squizlabs/php_codesniffer": "^3.7.2", - "symfony/filesystem": "^5.4.25 || ^6.3.1 || ^7.0.0", - "vimeo/psalm": "^5.7.7" - }, - "bin": [ - "bin/paratest", - "bin/paratest.bat", - "bin/paratest_for_phpstorm" - ], - "type": "library", - "autoload": { - "psr-4": { - "ParaTest\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Brian Scaturro", - "email": "scaturrob@gmail.com", - "role": "Developer" - }, - { - "name": "Filippo Tessarotto", - "email": "zoeslam@gmail.com", - "role": "Developer" - } - ], - "description": "Parallel testing for PHP", - "homepage": "https://github.com/paratestphp/paratest", - "keywords": [ - "concurrent", - "parallel", - "phpunit", - "testing" - ], - "support": { - "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v6.11.1" - }, - "funding": [ - { - "url": "https://github.com/sponsors/Slamdunk", - "type": "github" - }, - { - "url": "https://paypal.me/filippotessarotto", - "type": "paypal" - } - ], - "time": "2024-03-13T06:54:29+00:00" - }, { "name": "clue/ndjson-react", "version": "v1.3.0", @@ -7790,16 +8157,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.86.0", + "version": "v3.94.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36" + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4a952bd19dc97879b0620f495552ef09b55f7d36", - "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63", + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63", "shasum": "" }, "require": { @@ -7810,39 +8177,38 @@ "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", "react/child-process": "^0.6.6", "react/event-loop": "^1.5", - "react/promise": "^3.2", "react/socket": "^1.16", "react/stream": "^1.4", - "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", - "symfony/console": "^5.4.47 || ^6.4.13 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0", - "symfony/polyfill-mbstring": "^1.32", - "symfony/polyfill-php80": "^1.32", - "symfony/polyfill-php81": "^1.32", - "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0" + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.6", - "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.4", - "keradus/cli-executor": "^2.2", + "facile-it/paraunit": "^1.3.1 || ^2.7.1", + "infection/infection": "^0.32.3", + "justinrainbow/json-schema": "^6.6.4", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.8", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25", - "symfony/polyfill-php84": "^1.32", - "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1", - "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1" + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -7857,7 +8223,7 @@ "PhpCsFixer\\": "src/" }, "exclude-from-classmap": [ - "src/Fixer/Internal/*" + "src/**/Internal/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -7883,7 +8249,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.86.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2" }, "funding": [ { @@ -7891,7 +8257,7 @@ "type": "github" } ], - "time": "2025-08-13T22:36:21+00:00" + "time": "2026-02-20T16:13:53+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -7944,66 +8310,6 @@ }, "time": "2025-04-30T06:54:44+00:00" }, - { - "name": "jean85/pretty-package-versions", - "version": "2.1.1", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1.0", - "php": "^7.4|^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^7.5|^8.5|^9.6", - "rector/rector": "^2.0", - "vimeo/psalm": "^4.3 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A library to get pretty versions strings of installed dependencies", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "support": { - "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1" - }, - "time": "2025-03-19T14:43:43+00:00" - }, { "name": "mockery/mockery", "version": "1.6.12", @@ -8149,16 +8455,16 @@ }, { "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": { @@ -8201,9 +8507,9 @@ ], "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/collision", @@ -8294,447 +8600,41 @@ "time": "2023-01-03T12:54:54+00:00" }, { - "name": "pestphp/pest", - "version": "v1.23.1", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/pestphp/pest.git", - "reference": "5c56ad8772b89611c72a07e23f6e30aa29dc677a" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/5c56ad8772b89611c72a07e23f6e30aa29dc677a", - "reference": "5c56ad8772b89611c72a07e23f6e30aa29dc677a", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "nunomaduro/collision": "^5.11.0|^6.4.0", - "pestphp/pest-plugin": "^1.1.0", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^9.6.10" - }, - "require-dev": { - "illuminate/console": "^8.83.27", - "illuminate/support": "^8.83.27", - "laravel/dusk": "^6.25.2", - "pestphp/pest-dev-tools": "^1.0.0", - "pestphp/pest-plugin-parallel": "^1.2.1" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, - "bin": [ - "bin/pest" - ], "type": "library", "extra": { - "pest": { - "plugins": [ - "Pest\\Plugins\\Coverage", - "Pest\\Plugins\\Init", - "Pest\\Plugins\\Version", - "Pest\\Plugins\\Environment" - ] - }, - "laravel": { - "providers": [ - "Pest\\Laravel\\PestServiceProvider" - ] - }, "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "files": [ - "src/Functions.php", - "src/Pest.php" - ], - "psr-4": { - "Pest\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - } - ], - "description": "An elegant PHP Testing Framework.", - "keywords": [ - "framework", - "pest", - "php", - "test", - "testing", - "unit" - ], - "support": { - "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v1.23.1" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - } - ], - "time": "2023-07-12T19:42:47+00:00" - }, - { - "name": "pestphp/pest-plugin", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin.git", - "reference": "606c5f79c6a339b49838ffbee0151ca519efe378" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/606c5f79c6a339b49838ffbee0151ca519efe378", - "reference": "606c5f79c6a339b49838ffbee0151ca519efe378", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0.0", - "php": "^7.3 || ^8.0" - }, - "conflict": { - "pestphp/pest": "<1.0" - }, - "require-dev": { - "composer/composer": "^2.4.2", - "pestphp/pest": "^1.22.1", - "pestphp/pest-dev-tools": "^1.0.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Pest\\Plugin\\Manager", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Pest\\Plugin\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest plugin manager", - "keywords": [ - "framework", - "manager", - "pest", - "php", - "plugin", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin/tree/v1.1.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2022-09-18T13:18:17+00:00" - }, - { - "name": "pestphp/pest-plugin-faker", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-faker.git", - "reference": "9d93419f1f47ffd856ee544317b2f9144a129044" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-faker/zipball/9d93419f1f47ffd856ee544317b2f9144a129044", - "reference": "9d93419f1f47ffd856ee544317b2f9144a129044", - "shasum": "" - }, - "require": { - "fakerphp/faker": "^1.9.1", - "pestphp/pest": "^1.0", - "php": "^7.3 || ^8.0" - }, - "require-dev": { - "pestphp/pest-dev-tools": "dev-master" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/Faker.php" - ], - "psr-4": { - "Pest\\Faker\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest Faker Plugin", - "keywords": [ - "faker", - "framework", - "pest", - "php", - "plugin", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-faker/tree/v1.0.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2021-01-03T15:42:35+00:00" - }, - { - "name": "pestphp/pest-plugin-global-assertions", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-global-assertions.git", - "reference": "66eb17338393b84a5086ad01ef4f9ce972e177b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-global-assertions/zipball/66eb17338393b84a5086ad01ef4f9ce972e177b3", - "reference": "66eb17338393b84a5086ad01ef4f9ce972e177b3", - "shasum": "" - }, - "require": { - "pestphp/pest": "^1.0", - "pestphp/pest-plugin": "^1.0", - "php": "^7.3 || ^8.0" - }, - "conflict": { - "pestphp/pest": "<1.0" - }, - "require-dev": { - "pestphp/pest-dev-tools": "dev-master" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/compiled.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A plugin to add global assertions to Pest", - "keywords": [ - "assertions", - "framework", - "global", - "pest", - "php", - "test", - "testing", - "unit" - ], - "support": { - "issues": "https://github.com/pestphp/pest-plugin-global-assertions/issues", - "source": "https://github.com/pestphp/pest-plugin-global-assertions/tree/v1.0.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2021-01-03T15:35:12+00:00" - }, - { - "name": "pestphp/pest-plugin-parallel", - "version": "v1.2.1", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-parallel.git", - "reference": "842592eba2439ba6477f6d6c7ee4a4e7bccdcd10" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-parallel/zipball/842592eba2439ba6477f6d6c7ee4a4e7bccdcd10", - "reference": "842592eba2439ba6477f6d6c7ee4a4e7bccdcd10", - "shasum": "" - }, - "require": { - "brianium/paratest": "^6.8.1", - "pestphp/pest-plugin": "^1.1.0", - "php": "^7.3 || ^8.0" - }, - "conflict": { - "laravel/framework": "<8.55", - "nunomaduro/collision": "<5.8", - "pestphp/pest": "<1.16" - }, - "require-dev": { - "pestphp/pest": "^1.22.3", - "pestphp/pest-dev-tools": "^1.0.0" - }, - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Parallel\\Plugin" - ] - } - }, - "autoload": { - "files": [ - "src/Autoload.php", - "build/RunnerWorker.php", - "build/BaseRunner.php" - ], - "psr-4": { - "Pest\\Parallel\\": "src/" - }, - "exclude-from-classmap": [ - "ParaTest\\Runners\\PHPUnit\\Worker\\RunnerWorker", - "ParaTest\\Runners\\PHPUnit\\BaseRunner" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest Parallel Plugin", - "keywords": [ - "framework", - "parallel", - "pest", - "php", - "plugin", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-parallel/tree/v1.2.1" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/lukeraymonddowning", - "type": "github" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://github.com/octoper", - "type": "github" - }, - { - "url": "https://github.com/olivernybroe", - "type": "github" - }, - { - "url": "https://github.com/owenvoke", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2023-02-03T13:01:17+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" + "BSD-3-Clause" ], "authors": [ { @@ -8867,16 +8767,11 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.28", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9" - }, + "version": "1.12.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1", + "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1", "shasum": "" }, "require": { @@ -8921,7 +8816,7 @@ "type": "github" } ], - "time": "2025-07-17T17:15:39+00:00" + "time": "2026-02-28T20:30:03+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -9343,16 +9238,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.25", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "049c011e01be805202d8eebedef49f769a8ec7b7" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/049c011e01be805202d8eebedef49f769a8ec7b7", - "reference": "049c011e01be805202d8eebedef49f769a8ec7b7", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -9374,10 +9269,10 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.9", + "sebastian/comparator": "^4.0.10", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", + "sebastian/exporter": "^4.0.8", "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", @@ -9426,7 +9321,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.25" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -9450,7 +9345,7 @@ "type": "tidelift" } ], - "time": "2025-08-20T14:38:31+00:00" + "time": "2026-01-27T05:45:00+00:00" }, { "name": "react/cache", @@ -9526,16 +9421,16 @@ }, { "name": "react/child-process", - "version": "v0.6.6", + "version": "v0.6.7", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { @@ -9589,7 +9484,7 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, "funding": [ { @@ -9597,20 +9492,20 @@ "type": "open_collective" } ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2025-12-23T15:25:20+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -9665,7 +9560,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -9673,20 +9568,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -9737,7 +9632,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -9745,7 +9640,7 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", @@ -9822,16 +9717,16 @@ }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -9890,7 +9785,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -9898,7 +9793,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -10147,16 +10042,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.9", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -10209,7 +10104,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { @@ -10229,7 +10124,7 @@ "type": "tidelift" } ], - "time": "2025-08-10T06:51:50+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -10419,16 +10314,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -10484,15 +10379,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", @@ -11039,23 +10946,23 @@ }, { "name": "symfony/finder", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -11083,7 +10990,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.8" }, "funding": [ { @@ -11103,20 +11010,20 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.2", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37" + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37", - "reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", "shasum": "" }, "require": { @@ -11154,7 +11061,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.2" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.8" }, "funding": [ { @@ -11174,7 +11081,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:36:08+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-php81", @@ -11256,18 +11163,98 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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-24T13:30:11+00:00" + }, { "name": "symfony/process", - "version": "v7.3.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -11299,7 +11286,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.0" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -11310,25 +11297,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-04-17T09:11:12+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/stopwatch", - "version": "v7.3.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/70a852d72fec4d51efb1f48dcd968efcaf5ccb89", + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89", "shasum": "" }, "require": { @@ -11361,7 +11352,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" + "source": "https://github.com/symfony/stopwatch/tree/v7.4.8" }, "funding": [ { @@ -11372,25 +11363,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-02-24T10:49:57+00:00" + "time": "2026-03-24T13:12:05+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": { @@ -11419,7 +11414,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": [ { @@ -11427,7 +11422,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], @@ -11437,8 +11432,10 @@ "prefer-lowest": false, "platform": { "php": "^8.2", - "ext-pcntl": "*" + "ext-pcntl": "*", + "ext-sockets": "*", + "ext-sqlite3": "*" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/config/app.php b/config/app.php index 6393975..616d6d6 100644 --- a/config/app.php +++ b/config/app.php @@ -7,25 +7,89 @@ 'env' => env('APP_ENV', static fn (): string => 'local'), 'url' => env('APP_URL', static fn (): string => 'http://127.0.0.1'), 'port' => env('APP_PORT', static fn (): int => 1337), + 'cert_path' => env('APP_CERT_PATH', static fn (): string|null => null), 'key' => env('APP_KEY'), 'previous_key' => env('APP_PREVIOUS_KEY'), + + /* + |-------------------------------------------------------------------------- + | App mode + |-------------------------------------------------------------------------- + | Controls how the HTTP server determines client connection details. + | + | direct: + | The server is exposed directly to clients. Remote address, scheme, + | and host are taken from the TCP connection and request line. + | + | proxied: + | The server runs behind a reverse proxy or load balancer (e.g., Nginx, + | HAProxy, AWS ALB). Client information is derived from standard + | forwarding headers only when the request comes from a trusted proxy. + | Configure trusted proxies in `trusted_proxies` (IP addresses or CIDRs). + | When enabled, the server will honor `Forwarded`, `X-Forwarded-For`, + | `X-Forwarded-Proto`, and `X-Forwarded-Host` headers from trusted + | sources, matching Amphp's behind-proxy behavior. + | + | Supported values: "direct", "proxied" + | + */ + + 'app_mode' => env('APP_MODE', static fn (): string => 'direct'), + 'trusted_proxies' => env('APP_TRUSTED_PROXIES', static fn (): array => []), + + /* + |-------------------------------------------------------------------------- + | Server runtime mode + |-------------------------------------------------------------------------- + | Controls whether the HTTP server runs as a single process (default) or + | under amphp/cluster. + | + | Supported values: + | - "single" (single process) + | - "cluster" (run with vendor/bin/cluster and cluster sockets) + | + */ + 'server_mode' => env('APP_SERVER_MODE', static fn (): string => 'single'), 'debug' => env('APP_DEBUG', static fn (): bool => true), + 'locale' => 'en', + 'fallback_locale' => 'en', 'middlewares' => [ 'global' => [ \Phenix\Http\Middlewares\HandleCors::class, + \Phenix\Cache\RateLimit\Middlewares\RateLimiter::class, + \Phenix\Auth\Middlewares\TokenRateLimit::class, + ], + 'router' => [ + \Phenix\Http\Middlewares\ResponseHeaders::class, ], - 'router' => [], ], 'providers' => [ + \Phenix\Filesystem\FilesystemServiceProvider::class, \Phenix\Console\CommandsServiceProvider::class, \Phenix\Routing\RouteServiceProvider::class, \Phenix\Database\DatabaseServiceProvider::class, \Phenix\Redis\RedisServiceProvider::class, - \Phenix\Filesystem\FilesystemServiceProvider::class, + \Phenix\Auth\AuthServiceProvider::class, \Phenix\Tasks\TaskServiceProvider::class, \Phenix\Views\ViewServiceProvider::class, + \Phenix\Cache\CacheServiceProvider::class, \Phenix\Mail\MailServiceProvider::class, \Phenix\Crypto\CryptoServiceProvider::class, \Phenix\Queue\QueueServiceProvider::class, + \Phenix\Events\EventServiceProvider::class, + \Phenix\Translation\TranslationServiceProvider::class, + \Phenix\Scheduling\SchedulingServiceProvider::class, + \Phenix\Validation\ValidationServiceProvider::class, + ], + 'response' => [ + 'headers' => [ + \Phenix\Http\Headers\XDnsPrefetchControl::class, + \Phenix\Http\Headers\XFrameOptions::class, + \Phenix\Http\Headers\StrictTransportSecurity::class, + \Phenix\Http\Headers\XContentTypeOptions::class, + \Phenix\Http\Headers\ReferrerPolicy::class, + \Phenix\Http\Headers\CrossOriginResourcePolicy::class, + \Phenix\Http\Headers\CrossOriginOpenerPolicy::class, + ], ], ]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 0000000..b12347d --- /dev/null +++ b/config/auth.php @@ -0,0 +1,23 @@ + [ + 'model' => User::class, + ], + 'tokens' => [ + 'model' => Phenix\Auth\PersonalAccessToken::class, + 'prefix' => '', + 'expiration' => 60 * 12, // in minutes + 'rate_limit' => [ + 'attempts' => 5, + 'window' => 300, // window in seconds + ], + ], + 'otp' => [ + 'expiration' => 10, // in minutes + ], +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..c0c5238 --- /dev/null +++ b/config/cache.php @@ -0,0 +1,55 @@ + env('CACHE_STORE', static fn (): string => 'local'), + + 'stores' => [ + 'local' => [ + 'size_limit' => 1024, + 'gc_interval' => 5, + ], + + 'file' => [ + 'path' => base_path('storage/framework/cache'), + ], + + 'redis' => [ + 'connection' => env('CACHE_REDIS_CONNECTION', static fn (): string => 'default'), + ], + ], + + 'prefix' => env('CACHE_PREFIX', static fn (): string => 'phenix_cache_'), + + /* + |-------------------------------------------------------------------------- + | Default Cache TTL Minutes + |-------------------------------------------------------------------------- + | + | This option controls the default time-to-live (TTL) in minutes for cache + | items. It is used as the default expiration time for all cache stores + | unless a specific TTL is provided when setting a cache item. + */ + 'ttl' => env('CACHE_TTL', static fn (): int => 60), + + 'rate_limit' => [ + 'enabled' => env('RATE_LIMIT_ENABLED', static fn (): bool => true), + 'store' => env('RATE_LIMIT_STORE', static fn (): string => 'local'), + 'per_minute' => env('RATE_LIMIT_PER_MINUTE', static fn (): int => 60), + 'connection' => env('RATE_LIMIT_REDIS_CONNECTION', static fn (): string => 'default'), + ], +]; diff --git a/config/cors.php b/config/cors.php index 105b1ab..bf3b368 100644 --- a/config/cors.php +++ b/config/cors.php @@ -1,7 +1,9 @@ env('CORS_ORIGIN', static fn (): array => ['http://localhost', 'http://127.0.0.1']), + 'origins' => env('CORS_ORIGIN', static fn (): array => ['*']), 'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE'], 'max_age' => 8600, 'allowed_headers' => ['X-Request-Headers', 'Content-Type', 'Authorization', 'X-Requested-With'], diff --git a/config/database.php b/config/database.php index ad69ccf..22be9b3 100644 --- a/config/database.php +++ b/config/database.php @@ -6,6 +6,10 @@ 'default' => env('DB_CONNECTION', static fn (): string => 'mysql'), 'connections' => [ + 'sqlite' => [ + 'driver' => 'sqlite', + 'database' => env('DB_DATABASE', static fn (): string => base_path('database' . DIRECTORY_SEPARATOR . 'database.sqlite3')), + ], 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', static fn (): string => '127.0.0.1'), diff --git a/config/mail.php b/config/mail.php index bdef847..462f244 100644 --- a/config/mail.php +++ b/config/mail.php @@ -1,5 +1,7 @@ env('MAIL_MAILER', static fn (): string => 'smtp'), @@ -21,6 +23,10 @@ 'resend' => [ 'transport' => 'resend', ], + + 'log' => [ + 'transport' => 'log', + ], ], 'from' => [ diff --git a/config/queue.php b/config/queue.php index eaec4a4..25ab32b 100644 --- a/config/queue.php +++ b/config/queue.php @@ -1,5 +1,7 @@ env('QUEUE_DRIVER', static fn (): string => 'database'), diff --git a/config/services.php b/config/services.php index f382b6a..df85bee 100644 --- a/config/services.php +++ b/config/services.php @@ -1,5 +1,7 @@ [ 'key' => env('AWS_ACCESS_KEY_ID'), diff --git a/config/session.php b/config/session.php index 87ed685..67d2f8c 100644 --- a/config/session.php +++ b/config/session.php @@ -15,7 +15,7 @@ | */ - 'driver' => env('SESSION_DRIVER', static fn (): string => 'redis'), + 'driver' => env('SESSION_DRIVER', static fn (): string => 'local'), 'lifetime' => env('SESSION_LIFETIME', static fn (): int => 120), @@ -29,11 +29,11 @@ | connection in your database configuration options. */ - 'connection' => env('SESSION_CONNECTION', static fn (): string => 'default'), + 'connection' => env('SESSION_CONNECTION', static fn () => 'default'), 'cookie_name' => env( 'SESSION_COOKIE_NAME', - static fn (): string => Str::slug(env('APP_NAME', static fn (): string => 'phenix'), '_') . '_session' + static fn (): string => Str::slug(env('APP_NAME', static fn () => 'phenix'), '_') . '_session' ), 'path' => '/', diff --git a/database/migrations/20241217160717_create_user_table.php b/database/migrations/20241217160717_create_user_table.php new file mode 100644 index 0000000..3ee9474 --- /dev/null +++ b/database/migrations/20241217160717_create_user_table.php @@ -0,0 +1,24 @@ +table('users'); + $table->string('name', 100); + $table->string('email', 124)->unique(); + $table->string('password', 255); + $table->dateTime('email_verified_at')->nullable(); + $table->timestamps(); + $table->create(); + } + + public function down(): void + { + $this->table('users')->drop()->save(); + } +} diff --git a/database/migrations/20251028132601_user_one_time_passwords.php b/database/migrations/20251028132601_user_one_time_passwords.php new file mode 100644 index 0000000..8703985 --- /dev/null +++ b/database/migrations/20251028132601_user_one_time_passwords.php @@ -0,0 +1,32 @@ +table('user_one_time_passwords', ['id' => false, 'primary_key' => 'id']); + $table->uuid('id'); + $table->enum('scope', OneTimePasswordScope::toArray()); + $table->string('code', 255); + $table->unsignedInteger('user_id'); + $table->foreign('user_id') + ->references('id') + ->on('users') + ->onDelete(ColumnAction::CASCADE); + $table->datetime('expires_at'); + $table->datetime('used_at')->nullable(); + $table->timestamps(); + $table->create(); + } + + public function down(): void + { + $this->table('user_one_time_passwords')->drop(); + } +} \ No newline at end of file diff --git a/database/migrations/20251128110000_create_personal_access_tokens_table.php b/database/migrations/20251128110000_create_personal_access_tokens_table.php new file mode 100644 index 0000000..54600d8 --- /dev/null +++ b/database/migrations/20251128110000_create_personal_access_tokens_table.php @@ -0,0 +1,31 @@ +table('personal_access_tokens', ['id' => false, 'primary_key' => 'id']); + + $table->uuid('id'); + $table->string('tokenable_type', 100); + $table->unsignedInteger('tokenable_id'); + $table->string('name', 100); + $table->string('token', 255)->unique(); + $table->text('abilities')->nullable(); + $table->dateTime('last_used_at')->nullable(); + $table->dateTime('expires_at'); + $table->timestamps(); + $table->addIndex(['tokenable_type', 'tokenable_id'], ['name' => 'idx_tokenable']); + $table->addIndex(['expires_at'], ['name' => 'idx_expires_at']); + $table->create(); + } + + public function down(): void + { + $this->table('personal_access_tokens')->drop(); + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 93eb9de..d4f38ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,10 @@ services: context: . dockerfile: docker/Dockerfile target: local + cap_add: + - SYS_PTRACE + security_opt: + - seccomp:unconfined volumes: - .:/var/www/html:rw - /var/www/html/vendor diff --git a/docker/Dockerfile b/docker/Dockerfile index a69a17a..fce4d40 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -5,7 +5,10 @@ USER root RUN apk add --no-cache \ curl \ git \ - unzip + unzip \ + linux-headers \ + && docker-php-ext-install pcntl sockets \ + && docker-php-ext-enable pcntl sockets COPY --from=composer:latest /usr/bin/composer /usr/bin/composer diff --git a/lang/en/auth.php b/lang/en/auth.php new file mode 100644 index 0000000..336521e --- /dev/null +++ b/lang/en/auth.php @@ -0,0 +1,61 @@ + 'Unauthorized', + 'login' => [ + 'invalid_credentials' => 'Invalid credentials.', + ], + 'logout' => [ + 'success' => 'Logged out successfully.', + ], + 'email_verification' => [ + 'verified' => 'Email verified successfully.', + ], + 'otp' => [ + 'invalid' => 'The provided OTP is invalid.', + 'limit_exceeded' => 'You have exceeded the maximum number of OTP requests. Please try again later.', + 'label' => 'Verification code', + 'expiry' => 'This code expires in :minutes minutes.', + 'login' => [ + 'subject' => 'Your login verification code', + 'title' => 'Login verification code', + 'message' => 'Use the following verification code to complete your sign in.', + 'sent' => 'A verification code has been sent to your email address.', + ], + 'reset_password' => [ + 'subject' => 'Your password reset code', + 'title' => 'Password reset code', + 'message' => 'Use the following verification code to reset your password.', + ], + 'email_verification' => [ + 'subject' => 'Verify your email address', + 'title' => 'Email verification code', + 'message' => 'Use the following verification code to verify your email address.', + 'resent' => 'OTP has been resent successfully.', + ], + ], + 'password_reset' => [ + 'sent' => 'If your email address exists in our records, a password reset code has been sent.', + 'reset' => 'Password has been reset successfully.', + ], + 'security' => [ + 'warning' => 'For your security:', + 'never_share' => 'Never share this code with anyone. Our team will never ask you for your verification code.', + 'ignore_if_not_requested' => 'If you didn\'t request this verification, please ignore this email.', + ], + 'footer' => [ + 'copyright' => ':year :appName. All rights reserved.', + ], + 'rate_limit' => [ + 'error' => 'Too Many Requests', + 'exceeded' => 'Rate limit exceeded. Please try again later.', + ], + 'token' => [ + 'not_found' => 'Token not found.', + ], + 'registration' => [ + 'cancelled' => 'Registration cancelled.', + ], +]; diff --git a/lang/en/validation.php b/lang/en/validation.php new file mode 100644 index 0000000..ce3df5f --- /dev/null +++ b/lang/en/validation.php @@ -0,0 +1,75 @@ + 'The :field is invalid.', + 'required' => 'The :field field is required.', + 'string' => 'The :field must be a string.', + 'array' => 'The :field must be an array.', + 'boolean' => 'The :field field must be true or false.', + 'file' => 'The :field must be a file.', + 'url' => 'The :field must be a valid URL.', + 'email' => 'The :field must be a valid email address.', + 'uuid' => 'The :field must be a valid UUID.', + 'ulid' => 'The :field must be a valid ULID.', + 'integer' => 'The :field must be an integer.', + 'numeric' => 'The :field must be a number.', + 'float' => 'The :field must be a float.', + 'dictionary' => 'The :field field must be a dictionary.', + 'collection' => 'The :field must be a collection.', + 'list' => 'The :field must be a list.', + 'confirmed' => 'The :field must be confirmed with :other.', + 'in' => 'The selected :field is invalid. Allowed: :values.', + 'not_in' => 'The selected :field is invalid. Disallowed: :values.', + 'exists' => 'The selected :field is invalid.', + 'unique' => 'The selected :field is invalid.', + 'mimes' => 'The :field must be a file of type: :values.', + 'regex' => 'The :field format is invalid.', + 'starts_with' => 'The :field must start with: :values.', + 'ends_with' => 'The :field must end with: :values.', + 'does_not_start_with' => 'The :field must not start with: :values.', + 'does_not_end_with' => 'The :field must not end with: :values.', + 'digits' => 'The :field must be :digits digits.', + 'digits_between' => 'The :field must be between :min and :max digits.', + 'size' => [ + 'numeric' => 'The :field must be :size.', + 'string' => 'The :field must be :size characters.', + 'array' => 'The :field must contain :size items.', + 'file' => 'The :field must be :size kilobytes.', + ], + 'min' => [ + 'numeric' => 'The :field must be at least :min.', + 'string' => 'The :field must be at least :min characters.', + 'array' => 'The :field must have at least :min items.', + 'file' => 'The :field must be at least :min kilobytes.', + ], + 'max' => [ + 'numeric' => 'The :field may not be greater than :max.', + 'string' => 'The :field may not be greater than :max characters.', + 'array' => 'The :field may not have more than :max items.', + 'file' => 'The :field may not be greater than :max kilobytes.', + ], + 'between' => [ + 'numeric' => 'The :field must be between :min and :max.', + 'string' => 'The :field must be between :min and :max characters.', + 'array' => 'The :field must have between :min and :max items.', + 'file' => 'The :field must be between :min and :max kilobytes.', + ], + 'date' => [ + 'is_date' => 'The :field is not a valid date.', + 'after' => 'The :field must be a date after the specified date.', + 'format' => 'The :field does not match the format :format.', + 'equal_to' => 'The :field must be a date equal to :other.', + 'after_to' => 'The :field must be a date after :other.', + 'after_or_equal_to' => 'The :field must be a date after or equal to :other.', + 'before_or_equal_to' => 'The :field must be a date before or equal to :other.', + 'after_or_equal' => 'The :field must be a date after or equal to the specified date.', + 'before_or_equal' => 'The :field must be a date before or equal to the specified date.', + 'equal' => 'The :field must be a date equal to the specified date.', + 'before_to' => 'The :field must be a date before :other.', + 'before' => 'The :field must be a date before the specified date.', + ], + + 'fields' => [ + // + ], +]; diff --git a/resources/views/emails/email.php b/resources/views/emails/email.php new file mode 100644 index 0000000..3b797de --- /dev/null +++ b/resources/views/emails/email.php @@ -0,0 +1,150 @@ + + + +
+ + ++ {{ trans('auth.security.ignore_if_not_requested') }} +
+{{ $message }}
+ +{{ trans('auth.otp.expiry', ['minutes' => config('auth.otp.expiration')]) }}
+