From fd75dfbea847012c8d3d30f35aeb86e0a853ccfd Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 16:11:13 +0100 Subject: [PATCH 01/14] Laravel: add AST-based Route/Event/Schedule detection, remove controller heuristic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the broad reflection heuristic that marked all public controller methods as used with precise AST-based detection of: - Route::get/post/put/patch/delete/any/match — extract [Class, 'method'] from action arg - Route::resource — mark 7 CRUD methods (index/create/store/show/edit/update/destroy) - Route::apiResource — mark 5 CRUD methods (index/store/show/update/destroy) - Event::listen — mark handle() + __construct() on listener class - Event::subscribe — mark subscribe() + __construct() on subscriber class - Schedule::job — mark handle() + __construct() on job class All other reflection-based checks (Eloquent, commands, jobs, middleware, notifications, form requests, factories, seeders, policies, mailables, broadcast events, JSON resources, validation rules) remain unchanged. --- rules.neon | 12 + src/Provider/LaravelUsageProvider.php | 685 +++++++++++++++++++++ tests/Rule/DeadCodeRuleTest.php | 5 + tests/Rule/data/providers/laravel.php | 838 ++++++++++++++++++++++++++ 4 files changed, 1540 insertions(+) create mode 100644 src/Provider/LaravelUsageProvider.php create mode 100644 tests/Rule/data/providers/laravel.php diff --git a/rules.neon b/rules.neon index 81d421e..3215dee 100644 --- a/rules.neon +++ b/rules.neon @@ -101,6 +101,13 @@ services: arguments: enabled: %shipmonkDeadCode.usageProviders.phpstan.enabled% + - + class: ShipMonk\PHPStan\DeadCode\Provider\LaravelUsageProvider + tags: + - shipmonk.deadCode.memberUsageProvider + arguments: + enabled: %shipmonkDeadCode.usageProviders.laravel.enabled% + - class: ShipMonk\PHPStan\DeadCode\Provider\NetteUsageProvider tags: @@ -228,6 +235,8 @@ parameters: enabled: null doctrine: enabled: null + laravel: + enabled: null nette: enabled: null streamWrapper: @@ -295,6 +304,9 @@ parametersSchema: doctrine: structure([ enabled: schema(bool(), nullable()) ]) + laravel: structure([ + enabled: schema(bool(), nullable()) + ]) nette: structure([ enabled: schema(bool(), nullable()) ]) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php new file mode 100644 index 0000000..f5fc186 --- /dev/null +++ b/src/Provider/LaravelUsageProvider.php @@ -0,0 +1,685 @@ +enabled = $enabled ?? InstalledVersions::isInstalled('laravel/framework'); + } + + public function getUsages( + Node $node, + Scope $scope + ): array + { + if (!$this->enabled) { + return []; + } + + $usages = []; + + if ($node instanceof InClassNode) { // @phpstan-ignore phpstanApi.instanceofAssumption + $usages = [...$usages, ...$this->getMethodUsagesFromReflection($node)]; + } + + if ($node instanceof StaticCall) { + $usages = [...$usages, ...$this->getUsagesFromStaticCall($node, $scope)]; + } + + return $usages; + } + + /** + * @return list + */ + private function getMethodUsagesFromReflection(InClassNode $node): array + { + $classReflection = $node->getClassReflection(); + $nativeReflection = $classReflection->getNativeReflection(); + + $usages = []; + + foreach ($nativeReflection->getMethods() as $method) { + if ($method->getDeclaringClass()->getName() !== $nativeReflection->getName()) { + continue; + } + + $note = $this->shouldMarkAsUsed($method, $classReflection); + + if ($note !== null) { + $usages[] = $this->createUsage($classReflection->getNativeMethod($method->getName()), $note); + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromStaticCall( + StaticCall $node, + Scope $scope + ): array + { + $callerType = $node->class instanceof Expr + ? $scope->getType($node->class) + : $scope->resolveTypeByName($node->class); + + $classNames = $callerType->getObjectClassNames(); + + $usages = []; + + foreach ($classNames as $className) { + if ($className === 'Illuminate\Support\Facades\Route' || $className === 'Illuminate\Routing\Router') { + $usages = [...$usages, ...$this->getUsagesFromRouteCall($node, $scope)]; + } + + if ($className === 'Illuminate\Support\Facades\Event' || $className === 'Illuminate\Events\Dispatcher') { + $usages = [...$usages, ...$this->getUsagesFromEventCall($node, $scope)]; + } + + if ($className === 'Illuminate\Support\Facades\Schedule' || $className === 'Illuminate\Console\Scheduling\Schedule') { + $usages = [...$usages, ...$this->getUsagesFromScheduleCall($node, $scope)]; + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromRouteCall( + StaticCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier) { + return []; + } + + $methodName = $node->name->name; + $usages = []; + + if (in_array($methodName, ['get', 'post', 'put', 'patch', 'delete', 'any'], true)) { + foreach ($this->extractCallablesFromArg($node, $scope, 1) as [$className, $method]) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + + if ($methodName === 'match') { + foreach ($this->extractCallablesFromArg($node, $scope, 2) as [$className, $method]) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + + if ($methodName === 'resource') { + $resourceMethods = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']; + + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { + foreach ($resourceMethods as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + if ($methodName === 'apiResource') { + $apiResourceMethods = ['index', 'store', 'show', 'update', 'destroy']; + + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { + foreach ($apiResourceMethods as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromEventCall( + StaticCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier) { + return []; + } + + $methodName = $node->name->name; + $usages = []; + + if ($methodName === 'listen') { + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { + foreach (['handle', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + if ($methodName === 'subscribe') { + foreach ($this->extractClassNamesFromArg($node, $scope, 0) as $className) { + foreach (['subscribe', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromScheduleCall( + StaticCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier) { + return []; + } + + $methodName = $node->name->name; + $usages = []; + + if ($methodName === 'job') { + foreach ($this->extractClassNamesFromArg($node, $scope, 0) as $className) { + foreach (['handle', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + return $usages; + } + + /** + * Extracts [class, method] pairs from a callable array argument like [Controller::class, 'method']. + * + * @return list + */ + private function extractCallablesFromArg( + StaticCall $node, + Scope $scope, + int $argIndex + ): array + { + $arg = $node->getArgs()[$argIndex] ?? null; + + if ($arg === null) { + return []; + } + + $argType = $scope->getType($arg->value); + $callables = []; + + foreach ($argType->getConstantArrays() as $arrayType) { + $callable = []; + + foreach ($arrayType->getValueTypes() as $valueType) { + $callable[] = array_map( + static function ($stringType): string { + return $stringType->getValue(); + }, + $valueType->getConstantStrings(), + ); + } + + if (count($callable) === 2) { + foreach ($callable[0] as $className) { + foreach ($callable[1] as $methodName) { + $callables[] = [$className, $methodName]; + } + } + } + } + + return $callables; + } + + /** + * Extracts class names from a class-string argument like Controller::class. + * + * @return list + */ + private function extractClassNamesFromArg( + StaticCall $node, + Scope $scope, + int $argIndex + ): array + { + $arg = $node->getArgs()[$argIndex] ?? null; + + if ($arg === null) { + return []; + } + + $argType = $scope->getType($arg->value); + $classNames = []; + + foreach ($argType->getConstantStrings() as $stringType) { + $classNames[] = $stringType->getValue(); + } + + return $classNames; + } + + private function shouldMarkAsUsed( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + return $this->isEloquentModelMethod($method, $classReflection) + ?? $this->isCommandMethod($method, $classReflection) + ?? $this->isJobMethod($method, $classReflection) + ?? $this->isServiceProviderMethod($method, $classReflection) + ?? $this->isMiddlewareMethod($method, $classReflection) + ?? $this->isNotificationMethod($method, $classReflection) + ?? $this->isFormRequestMethod($method, $classReflection) + ?? $this->isFactoryMethod($method, $classReflection) + ?? $this->isSeederMethod($method, $classReflection) + ?? $this->isPolicyMethod($method, $classReflection) + ?? $this->isMailableMethod($method, $classReflection) + ?? $this->isBroadcastEventMethod($method, $classReflection) + ?? $this->isJsonResourceMethod($method, $classReflection) + ?? $this->isValidationRuleMethod($method, $classReflection); + } + + private function isEloquentModelMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Eloquent\Model')) { + return null; + } + + $methodName = $method->getName(); + + if ($method->isConstructor()) { + return 'Laravel Eloquent model constructor'; + } + + if (in_array($methodName, ['boot', 'booted', 'casts', 'newFactory'], true)) { + return 'Laravel Eloquent lifecycle/framework method'; + } + + if (strpos($methodName, 'scope') === 0 && $methodName !== 'scope') { + return 'Laravel Eloquent query scope'; + } + + if ($this->methodReturnsType($method, 'Illuminate\Database\Eloquent\Relations')) { + return 'Laravel Eloquent relationship'; + } + + if ($this->methodReturnsExactType($method, 'Illuminate\Database\Eloquent\Casts\Attribute')) { + return 'Laravel Eloquent attribute accessor'; + } + + return null; + } + + private function isCommandMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Console\Command')) { + return null; + } + + if ($method->isConstructor() || $method->getName() === 'handle') { + return 'Laravel console command method'; + } + + return null; + } + + private function isJobMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if ( + !$classReflection->is('Illuminate\Contracts\Queue\ShouldQueue') + && !$classReflection->hasTraitUse('Illuminate\Foundation\Bus\Dispatchable') + ) { + return null; + } + + $jobMethods = [ + '__construct', 'handle', 'failed', 'middleware', 'retryUntil', + 'uniqueId', 'tags', 'backoff', 'uniqueVia', 'displayName', + ]; + + if (in_array($method->getName(), $jobMethods, true)) { + return 'Laravel job method'; + } + + return null; + } + + private function isServiceProviderMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Support\ServiceProvider')) { + return null; + } + + if ($method->isConstructor() || in_array($method->getName(), ['register', 'boot'], true)) { + return 'Laravel service provider method'; + } + + return null; + } + + private function isMiddlewareMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + $methodName = $method->getName(); + + if ($methodName !== 'handle' && $methodName !== 'terminate') { + return null; + } + + if (!$classReflection->hasNativeMethod('handle')) { + return null; + } + + $handleMethod = $classReflection->getNativeReflection()->getMethod('handle'); // @phpstan-ignore missingType.checkedException + $params = $handleMethod->getParameters(); + + if ($params === []) { + return null; + } + + $firstParamType = $params[0]->getType(); + + if (!$firstParamType instanceof ReflectionNamedType) { + return null; + } + + if ($firstParamType->getName() === 'Illuminate\Http\Request') { + return 'Laravel middleware method'; + } + + return null; + } + + private function isNotificationMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Notifications\Notification')) { + return null; + } + + $methodName = $method->getName(); + + $notificationMethods = [ + 'via', 'toMail', 'toArray', 'toDatabase', 'toBroadcast', 'toVonage', 'toSlack', + ]; + + if (in_array($methodName, $notificationMethods, true)) { + return 'Laravel notification method'; + } + + if (strpos($methodName, 'routeNotificationFor') === 0) { + return 'Laravel notification routing method'; + } + + return null; + } + + private function isFormRequestMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Foundation\Http\FormRequest')) { + return null; + } + + $formRequestMethods = [ + 'authorize', 'rules', 'messages', 'attributes', + 'prepareForValidation', 'passedValidation', 'failedValidation', 'failedAuthorization', + ]; + + if (in_array($method->getName(), $formRequestMethods, true)) { + return 'Laravel form request method'; + } + + return null; + } + + private function isFactoryMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Eloquent\Factories\Factory')) { + return null; + } + + if (in_array($method->getName(), ['definition', 'configure'], true)) { + return 'Laravel factory method'; + } + + return null; + } + + private function isSeederMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Seeder')) { + return null; + } + + if ($method->getName() === 'run') { + return 'Laravel seeder method'; + } + + return null; + } + + private function isPolicyMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->hasTraitUse('Illuminate\Auth\Access\HandlesAuthorization')) { + return null; + } + + $policyMethods = [ + 'before', 'viewAny', 'view', 'create', 'update', 'delete', 'restore', 'forceDelete', + ]; + + if (in_array($method->getName(), $policyMethods, true)) { + return 'Laravel policy method'; + } + + return null; + } + + private function isMailableMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Mail\Mailable')) { + return null; + } + + $mailableMethods = ['build', 'content', 'envelope', 'attachments', 'headers']; + + if (in_array($method->getName(), $mailableMethods, true)) { + return 'Laravel mailable method'; + } + + return null; + } + + private function isBroadcastEventMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Contracts\Broadcasting\ShouldBroadcast')) { + return null; + } + + $broadcastMethods = ['broadcastOn', 'broadcastWith', 'broadcastAs', 'broadcastWhen']; + + if (in_array($method->getName(), $broadcastMethods, true)) { + return 'Laravel broadcast event method'; + } + + return null; + } + + private function isJsonResourceMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Http\Resources\Json\JsonResource')) { + return null; + } + + $resourceMethods = ['toArray', 'with', 'additional', 'paginationInformation']; + + if (in_array($method->getName(), $resourceMethods, true)) { + return 'Laravel JSON resource method'; + } + + return null; + } + + private function isValidationRuleMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if ( + !$classReflection->is('Illuminate\Contracts\Validation\ValidationRule') + && !$classReflection->is('Illuminate\Contracts\Validation\Rule') + ) { + return null; + } + + $ruleMethods = ['validate', 'passes', 'message']; + + if (in_array($method->getName(), $ruleMethods, true)) { + return 'Laravel validation rule method'; + } + + return null; + } + + /** + * Checks if the method return type starts with the given prefix (for namespace matching). + */ + private function methodReturnsType( + ReflectionMethod $method, + string $typePrefix + ): bool + { + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + return false; + } + + return strpos($returnType->getName(), $typePrefix) === 0; + } + + /** + * Checks if the method return type exactly matches the given type. + */ + private function methodReturnsExactType( + ReflectionMethod $method, + string $type + ): bool + { + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + return false; + } + + return $returnType->getName() === $type; + } + + private function createUsage( + ExtendedMethodReflection $methodReflection, + string $reason + ): ClassMethodUsage + { + return new ClassMethodUsage( + UsageOrigin::createVirtual($this, VirtualUsageData::withNote($reason)), + new ClassMethodRef( + $methodReflection->getDeclaringClass()->getName(), + $methodReflection->getName(), + false, + ), + ); + } + +} diff --git a/tests/Rule/DeadCodeRuleTest.php b/tests/Rule/DeadCodeRuleTest.php index 8a0ce67..a7e6de3 100644 --- a/tests/Rule/DeadCodeRuleTest.php +++ b/tests/Rule/DeadCodeRuleTest.php @@ -44,6 +44,7 @@ use ShipMonk\PHPStan\DeadCode\Provider\BuiltinUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\DoctrineUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\EnumUsageProvider; +use ShipMonk\PHPStan\DeadCode\Provider\LaravelUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\MemberUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\NetteUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\PhpBenchUsageProvider; @@ -929,6 +930,7 @@ public static function provideFiles(): Traversable yield 'provider-behat' => [__DIR__ . '/data/providers/behat.php', self::requiresPhp(8_00_00)]; yield 'provider-doctrine' => [__DIR__ . '/data/providers/doctrine.php', self::requiresPhp(8_01_00)]; yield 'provider-phpstan' => [__DIR__ . '/data/providers/phpstan.php']; + yield 'provider-laravel' => [__DIR__ . '/data/providers/laravel.php', self::requiresPhp(8_01_00)]; yield 'provider-nette' => [__DIR__ . '/data/providers/nette.php']; yield 'provider-apiphpdoc' => [__DIR__ . '/data/providers/api-phpdoc.php', self::requiresPhp(8_01_00)]; yield 'provider-enum' => [__DIR__ . '/data/providers/enum.php', self::requiresPhp(8_01_00)]; @@ -1116,6 +1118,9 @@ private function getMemberUsageProviders(): array $this->providersEnabled, $this->createPhpStanContainerMock(), ), + new LaravelUsageProvider( + $this->providersEnabled, + ), new NetteUsageProvider( self::getContainer()->getByType(ReflectionProvider::class), $this->providersEnabled, diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php new file mode 100644 index 0000000..b21d513 --- /dev/null +++ b/tests/Rule/data/providers/laravel.php @@ -0,0 +1,838 @@ + $attributes */ + public function __construct(array $attributes = []) {} +} + +namespace Illuminate\Database\Eloquent\Relations; + +abstract class Relation +{ +} + +class HasMany extends Relation +{ +} + +class BelongsTo extends Relation +{ +} + +class BelongsToMany extends Relation +{ +} + +namespace Illuminate\Database\Eloquent\Casts; + +class Attribute +{ +} + +namespace Illuminate\Database\Eloquent\Factories; + +abstract class Factory +{ +} + +namespace Illuminate\Console; + +class Command +{ +} + +namespace Illuminate\Contracts\Queue; + +interface ShouldQueue +{ +} + +namespace Illuminate\Foundation\Bus; + +trait Dispatchable +{ +} + +namespace Illuminate\Support; + +abstract class ServiceProvider +{ + public function __construct($app) {} +} + +namespace Illuminate\Http; + +class Request +{ +} + +namespace Illuminate\Notifications; + +class Notification +{ +} + +namespace Illuminate\Foundation\Http; + +class FormRequest +{ +} + +namespace Illuminate\Database; + +class Seeder +{ +} + +namespace Illuminate\Auth\Access; + +trait HandlesAuthorization +{ +} + +namespace Illuminate\Mail; + +class Mailable +{ +} + +namespace Illuminate\Contracts\Broadcasting; + +interface ShouldBroadcast +{ +} + +namespace Illuminate\Http\Resources\Json; + +class JsonResource +{ +} + +namespace Illuminate\Contracts\Validation; + +interface ValidationRule +{ +} + +interface Rule +{ +} + +namespace Illuminate\Support\Facades; + +class Route +{ + /** @param mixed $action */ + public static function get(string $uri, $action): void {} + /** @param mixed $action */ + public static function post(string $uri, $action): void {} + /** @param mixed $action */ + public static function put(string $uri, $action): void {} + /** @param mixed $action */ + public static function patch(string $uri, $action): void {} + /** @param mixed $action */ + public static function delete(string $uri, $action): void {} + /** @param mixed $action */ + public static function any(string $uri, $action): void {} + /** + * @param list $methods + * @param mixed $action + */ + public static function match(array $methods, string $uri, $action): void {} + public static function resource(string $name, string $controller): void {} + public static function apiResource(string $name, string $controller): void {} +} + +class Event +{ + /** @param mixed $event */ + public static function listen($event, string $listener): void {} + public static function subscribe(string $subscriber): void {} +} + +class Schedule +{ + public static function job(string $job): void {} +} + +// ===================== +// Test Classes +// ===================== + +namespace Laravel; + +use Illuminate\Auth\Access\HandlesAuthorization; +use Illuminate\Console\Command; +use Illuminate\Contracts\Broadcasting\ShouldBroadcast; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Contracts\Validation\Rule as ValidationRuleOld; +use Illuminate\Contracts\Validation\ValidationRule; +use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Seeder; +use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Http\Request; +use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Mail\Mailable; +use Illuminate\Notifications\Notification; +use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Schedule; +use Illuminate\Support\ServiceProvider; + +// --- Controllers (AST-based via Route:: calls) --- + +class UserController extends Controller +{ + public function index(): void + { + } + + public function show(): void + { + } + + public function unusedAction(): void // error: Unused Laravel\UserController::unusedAction + { + } + + private function helperMethod(): void // error: Unused Laravel\UserController::helperMethod + { + } +} + +class PostController extends Controller +{ + public function index(): void {} + public function create(): void {} + public function store(): void {} + public function show(): void {} + public function edit(): void {} + public function update(): void {} + public function destroy(): void {} +} + +class CommentController extends Controller +{ + public function index(): void {} + public function store(): void {} + public function show(): void {} + public function update(): void {} + public function destroy(): void {} + public function create(): void {} // error: Unused Laravel\CommentController::create + public function edit(): void {} // error: Unused Laravel\CommentController::edit +} + +// --- Event Listeners --- + +class OrderCreatedEvent +{ +} + +class OrderEventListener +{ + public function __construct() + { + } + + public function handle(): void + { + } + + public function unusedMethod(): void // error: Unused Laravel\OrderEventListener::unusedMethod + { + } +} + +class OrderEventSubscriber +{ + public function __construct() + { + } + + public function subscribe(): void + { + } + + public function unusedMethod(): void // error: Unused Laravel\OrderEventSubscriber::unusedMethod + { + } +} + +// --- Scheduled Jobs (AST-based via Schedule:: calls) --- + +class CleanupJob +{ + public function __construct() + { + } + + public function handle(): void + { + } + + public function unusedMethod(): void // error: Unused Laravel\CleanupJob::unusedMethod + { + } +} + +// --- Eloquent Models --- + +class User extends Model +{ + public function __construct(array $attributes = []) + { + parent::__construct($attributes); + } + + public static function boot(): void + { + } + + public static function booted(): void + { + } + + /** @return array */ + protected function casts(): array + { + return []; + } + + protected static function newFactory(): Factory + { + return new UserFactory(); + } + + public function scopeActive(object $query): object + { + return $query; + } + + public function posts(): HasMany + { + return new HasMany(); + } + + public function company(): BelongsTo + { + return new BelongsTo(); + } + + public function roles(): BelongsToMany + { + return new BelongsToMany(); + } + + protected function firstName(): Attribute + { + return new Attribute(); + } + + private function notAFrameworkMethod(): void // error: Unused Laravel\User::notAFrameworkMethod + { + } +} + +// --- Commands --- + +class ImportDataCommand extends Command +{ + public function __construct() + { + } + + public function handle(): int + { + return 0; + } + + private function helperMethod(): void // error: Unused Laravel\ImportDataCommand::helperMethod + { + } +} + +// --- Jobs --- + +class SendEmailJob implements ShouldQueue +{ + use Dispatchable; + + public function __construct() + { + } + + public function handle(): void + { + } + + public function failed(): void + { + } + + /** @return list */ + public function middleware(): array + { + return []; + } + + public function retryUntil(): \DateTimeInterface + { + return new \DateTimeImmutable(); + } + + public function uniqueId(): string + { + return ''; + } + + /** @return list */ + public function tags(): array + { + return []; + } + + /** @return list */ + public function backoff(): array + { + return []; + } + + private function notAJobMethod(): void // error: Unused Laravel\SendEmailJob::notAJobMethod + { + } +} + +// Job with only Dispatchable trait (no ShouldQueue interface) + +class SyncJob +{ + use Dispatchable; + + public function __construct() + { + } + + public function handle(): void + { + } + + private function privateHelper(): void // error: Unused Laravel\SyncJob::privateHelper + { + } +} + +// --- Service Providers --- + +class AppServiceProvider extends ServiceProvider +{ + public function __construct($app) + { + parent::__construct($app); + } + + public function register(): void + { + } + + public function boot(): void + { + } + + private function helperMethod(): void // error: Unused Laravel\AppServiceProvider::helperMethod + { + } +} + +// --- Middleware --- + +class AuthenticateMiddleware +{ + public function handle(Request $request, \Closure $next): mixed + { + return $next($request); + } + + public function terminate(Request $request, mixed $response): void + { + } + + private function helperMethod(): void // error: Unused Laravel\AuthenticateMiddleware::helperMethod + { + } +} + +// Not a middleware: handle() has no parameters + +class NotMiddlewareNoParams +{ + public function handle(): mixed // error: Unused Laravel\NotMiddlewareNoParams::handle + { + return null; + } + + public function terminate(): void // error: Unused Laravel\NotMiddlewareNoParams::terminate + { + } +} + +// Not a middleware: handle() first param is not Request + +class NotMiddlewareWrongParam +{ + public function handle(string $something): mixed // error: Unused Laravel\NotMiddlewareWrongParam::handle + { + return null; + } + + public function terminate(): void // error: Unused Laravel\NotMiddlewareWrongParam::terminate + { + } +} + +// --- Notifications --- + +class InvoiceNotification extends Notification +{ + /** @return list */ + public function via(object $notifiable): array + { + return ['mail']; + } + + public function toMail(object $notifiable): object + { + return new \stdClass(); + } + + /** @return array */ + public function toArray(object $notifiable): array + { + return []; + } + + /** @return array */ + public function toDatabase(object $notifiable): array + { + return []; + } + + public function toBroadcast(object $notifiable): object + { + return new \stdClass(); + } + + public function toVonage(object $notifiable): object + { + return new \stdClass(); + } + + public function toSlack(object $notifiable): object + { + return new \stdClass(); + } + + private function helperMethod(): void // error: Unused Laravel\InvoiceNotification::helperMethod + { + } +} + +// --- Form Requests --- + +class StoreUserRequest extends FormRequest +{ + public function authorize(): bool + { + return true; + } + + /** @return array */ + public function rules(): array + { + return []; + } + + /** @return array */ + public function messages(): array + { + return []; + } + + /** @return array */ + public function attributes(): array + { + return []; + } + + protected function prepareForValidation(): void + { + } + + protected function passedValidation(): void + { + } + + private function helperMethod(): void // error: Unused Laravel\StoreUserRequest::helperMethod + { + } +} + +// --- Factories --- + +class UserFactory extends Factory +{ + /** @return array */ + public function definition(): array + { + return []; + } + + public function configure(): static + { + return $this; + } + + private function helperMethod(): void // error: Unused Laravel\UserFactory::helperMethod + { + } +} + +// --- Seeders --- + +class DatabaseSeeder extends Seeder +{ + public function run(): void + { + } + + private function helperMethod(): void // error: Unused Laravel\DatabaseSeeder::helperMethod + { + } +} + +// --- Policies --- + +class PostPolicy +{ + use HandlesAuthorization; + + public function before(object $user): ?bool + { + return null; + } + + public function viewAny(object $user): bool + { + return true; + } + + public function view(object $user, object $post): bool + { + return true; + } + + public function create(object $user): bool + { + return true; + } + + public function update(object $user, object $post): bool + { + return true; + } + + public function delete(object $user, object $post): bool + { + return true; + } + + public function restore(object $user, object $post): bool + { + return true; + } + + public function forceDelete(object $user, object $post): bool + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\PostPolicy::helperMethod + { + } +} + +// --- Mailables --- + +class WelcomeEmail extends Mailable +{ + public function build(): self + { + return $this; + } + + public function content(): object + { + return new \stdClass(); + } + + public function envelope(): object + { + return new \stdClass(); + } + + /** @return list */ + public function attachments(): array + { + return []; + } + + public function headers(): object + { + return new \stdClass(); + } + + private function helperMethod(): void // error: Unused Laravel\WelcomeEmail::helperMethod + { + } +} + +// --- Broadcast Events --- + +class OrderShipped implements ShouldBroadcast +{ + /** @return list */ + public function broadcastOn(): array + { + return []; + } + + /** @return array */ + public function broadcastWith(): array + { + return []; + } + + public function broadcastAs(): string + { + return ''; + } + + public function broadcastWhen(): bool + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\OrderShipped::helperMethod + { + } +} + +// --- JSON Resources --- + +class UserResource extends JsonResource +{ + /** @return array */ + public function toArray(object $request): array + { + return []; + } + + /** @return array */ + public function with(object $request): array + { + return []; + } + + /** @return array */ + public function additional(object $request): array + { + return []; + } + + /** @return array */ + public function paginationInformation(object $request): array + { + return []; + } + + private function helperMethod(): void // error: Unused Laravel\UserResource::helperMethod + { + } +} + +// --- Validation Rules --- + +class UppercaseRule implements ValidationRule +{ + public function validate(string $attribute, mixed $value, \Closure $fail): void + { + } + + private function helperMethod(): void // error: Unused Laravel\UppercaseRule::helperMethod + { + } +} + +class OldValidationRule implements ValidationRuleOld +{ + public function passes(string $attribute, mixed $value): bool + { + return true; + } + + public function message(): string + { + return ''; + } + + private function helperMethod(): void // error: Unused Laravel\OldValidationRule::helperMethod + { + } +} + +// ===================== +// Route/Event/Schedule Registrations (AST-based detection) +// ===================== + +function registerRoutes(): void +{ + Route::get('/users', [UserController::class, 'index']); + Route::post('/users', [UserController::class, 'show']); + Route::put('/users/{id}', [UserController::class, 'index']); + Route::patch('/users/{id}', [UserController::class, 'show']); + Route::delete('/users/{id}', [UserController::class, 'index']); + Route::any('/any', [UserController::class, 'show']); + Route::match(['GET', 'POST'], '/match', [UserController::class, 'index']); + Route::resource('posts', PostController::class); + Route::apiResource('comments', CommentController::class); +} + +function registerEvents(): void +{ + Event::listen(OrderCreatedEvent::class, OrderEventListener::class); + Event::subscribe(OrderEventSubscriber::class); +} + +function registerSchedule(): void +{ + Schedule::job(CleanupJob::class); +} From 59146e59ec9d2612ea1d27722d8a2b9ba81f300e Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 16:19:55 +0100 Subject: [PATCH 02/14] =?UTF-8?q?Laravel:=20fix=20review=20issues=20?= =?UTF-8?q?=E2=80=94=20routeNotificationFor,=20policy=20detection,=20route?= =?UTF-8?q?=20=5F=5Fconstruct,=20invokable=20controllers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move routeNotificationFor* detection from Notification to Notifiable/RoutesNotifications trait users - Replace deprecated HandlesAuthorization trait check with *Policy naming convention for policy detection - Mark __construct as used for controllers referenced in Route:: registrations - Support invokable controllers (Route::get('/path', Controller::class) marking __invoke + __construct) --- src/Provider/LaravelUsageProvider.php | 78 +++++++++++++++++++++------ tests/Rule/data/providers/laravel.php | 59 ++++++++++++++++---- 2 files changed, 112 insertions(+), 25 deletions(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index f5fc186..2449dc1 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -20,6 +20,8 @@ use function count; use function in_array; use function strpos; +use function strrpos; +use function substr; final class LaravelUsageProvider implements MemberUsageProvider { @@ -128,24 +130,48 @@ private function getUsagesFromRouteCall( if (in_array($methodName, ['get', 'post', 'put', 'patch', 'delete', 'any'], true)) { foreach ($this->extractCallablesFromArg($node, $scope, 1) as [$className, $method]) { - $usages[] = new ClassMethodUsage( - UsageOrigin::createRegular($node, $scope), - new ClassMethodRef($className, $method, false), - ); + foreach ([$method, '__construct'] as $usedMethod) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $usedMethod, false), + ); + } + } + + // Invokable controllers: Route::get('/path', Controller::class) + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { + foreach (['__invoke', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } } } if ($methodName === 'match') { foreach ($this->extractCallablesFromArg($node, $scope, 2) as [$className, $method]) { - $usages[] = new ClassMethodUsage( - UsageOrigin::createRegular($node, $scope), - new ClassMethodRef($className, $method, false), - ); + foreach ([$method, '__construct'] as $usedMethod) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $usedMethod, false), + ); + } + } + + // Invokable controllers: Route::match(['GET'], '/path', Controller::class) + foreach ($this->extractClassNamesFromArg($node, $scope, 2) as $className) { + foreach (['__invoke', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } } } if ($methodName === 'resource') { - $resourceMethods = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']; + $resourceMethods = ['__construct', 'index', 'create', 'store', 'show', 'edit', 'update', 'destroy']; foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { foreach ($resourceMethods as $method) { @@ -158,7 +184,7 @@ private function getUsagesFromRouteCall( } if ($methodName === 'apiResource') { - $apiResourceMethods = ['index', 'store', 'show', 'update', 'destroy']; + $apiResourceMethods = ['__construct', 'index', 'store', 'show', 'update', 'destroy']; foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { foreach ($apiResourceMethods as $method) { @@ -331,7 +357,8 @@ private function shouldMarkAsUsed( ?? $this->isMailableMethod($method, $classReflection) ?? $this->isBroadcastEventMethod($method, $classReflection) ?? $this->isJsonResourceMethod($method, $classReflection) - ?? $this->isValidationRuleMethod($method, $classReflection); + ?? $this->isValidationRuleMethod($method, $classReflection) + ?? $this->isNotifiableMethod($method, $classReflection); } private function isEloquentModelMethod( @@ -478,10 +505,6 @@ private function isNotificationMethod( return 'Laravel notification method'; } - if (strpos($methodName, 'routeNotificationFor') === 0) { - return 'Laravel notification routing method'; - } - return null; } @@ -543,7 +566,11 @@ private function isPolicyMethod( ClassReflection $classReflection ): ?string { - if (!$classReflection->hasTraitUse('Illuminate\Auth\Access\HandlesAuthorization')) { + $className = $classReflection->getName(); + $lastSeparator = strrpos($className, '\\'); + $shortName = $lastSeparator !== false ? substr($className, $lastSeparator + 1) : $className; + + if (substr($shortName, -6) !== 'Policy') { return null; } @@ -633,6 +660,25 @@ private function isValidationRuleMethod( return null; } + private function isNotifiableMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if ( + !$classReflection->hasTraitUse('Illuminate\Notifications\Notifiable') + && !$classReflection->hasTraitUse('Illuminate\Notifications\RoutesNotifications') + ) { + return null; + } + + if (strpos($method->getName(), 'routeNotificationFor') === 0) { + return 'Laravel notification routing method'; + } + + return null; + } + /** * Checks if the method return type starts with the given prefix (for namespace matching). */ diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index b21d513..fc213cd 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -85,21 +85,24 @@ class Notification { } -namespace Illuminate\Foundation\Http; +trait RoutesNotifications +{ +} -class FormRequest +trait Notifiable { + use RoutesNotifications; } -namespace Illuminate\Database; +namespace Illuminate\Foundation\Http; -class Seeder +class FormRequest { } -namespace Illuminate\Auth\Access; +namespace Illuminate\Database; -trait HandlesAuthorization +class Seeder { } @@ -174,7 +177,6 @@ public static function job(string $job): void {} namespace Laravel; -use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Console\Command; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Queue\ShouldQueue; @@ -192,6 +194,7 @@ public static function job(string $job): void {} use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Mail\Mailable; +use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notification; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Event; @@ -203,6 +206,10 @@ public static function job(string $job): void {} class UserController extends Controller { + public function __construct() + { + } + public function index(): void { } @@ -242,6 +249,21 @@ public function create(): void {} // error: Unused Laravel\CommentController::cr public function edit(): void {} // error: Unused Laravel\CommentController::edit } +class InvokableController extends Controller +{ + public function __construct() + { + } + + public function __invoke(): void + { + } + + public function unusedAction(): void // error: Unused Laravel\InvokableController::unusedAction + { + } +} + // --- Event Listeners --- class OrderCreatedEvent @@ -353,6 +375,26 @@ private function notAFrameworkMethod(): void // error: Unused Laravel\User::notA } } +// Model with notification routing (routeNotificationFor* belongs on the notifiable model, not Notification) +class NotifiableUser extends Model +{ + use Notifiable; + + public function routeNotificationForSlack(): string + { + return ''; + } + + public function routeNotificationForMail(): string + { + return ''; + } + + private function notAFrameworkMethod(): void // error: Unused Laravel\NotifiableUser::notAFrameworkMethod + { + } +} + // --- Commands --- class ImportDataCommand extends Command @@ -633,8 +675,6 @@ private function helperMethod(): void // error: Unused Laravel\DatabaseSeeder::h class PostPolicy { - use HandlesAuthorization; - public function before(object $user): ?bool { return null; @@ -822,6 +862,7 @@ function registerRoutes(): void Route::delete('/users/{id}', [UserController::class, 'index']); Route::any('/any', [UserController::class, 'show']); Route::match(['GET', 'POST'], '/match', [UserController::class, 'index']); + Route::get('/invokable', InvokableController::class); Route::resource('posts', PostController::class); Route::apiResource('comments', CommentController::class); } From 122dd487dd7d048bf7b43d02f2acebf6a60623e6 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 16:39:13 +0100 Subject: [PATCH 03/14] Laravel: add migration, observer, and middleware constructor support - Detect migration classes (up/down methods) - Detect observers via Model::observe() calls and #[ObservedBy] attribute - Mark middleware __construct as used alongside handle/terminate --- src/Provider/LaravelUsageProvider.php | 120 ++++++++++++++++++++++++- tests/Rule/data/providers/laravel.php | 123 ++++++++++++++++++++++++++ 2 files changed, 242 insertions(+), 1 deletion(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 2449dc1..8a10422 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -13,12 +13,15 @@ use PHPStan\Node\InClassNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Type\ObjectType; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage; use ShipMonk\PHPStan\DeadCode\Graph\UsageOrigin; use function array_map; use function count; use function in_array; +use function is_array; +use function is_string; use function strpos; use function strrpos; use function substr; @@ -26,6 +29,12 @@ final class LaravelUsageProvider implements MemberUsageProvider { + private const OBSERVER_EVENT_METHODS = [ + 'creating', 'created', 'updating', 'updated', 'saving', 'saved', + 'deleting', 'deleted', 'restoring', 'restored', 'replicating', + 'retrieved', 'forceDeleting', 'forceDeleted', 'trashed', + ]; + private bool $enabled; public function __construct(?bool $enabled) @@ -46,6 +55,7 @@ public function getUsages( if ($node instanceof InClassNode) { // @phpstan-ignore phpstanApi.instanceofAssumption $usages = [...$usages, ...$this->getMethodUsagesFromReflection($node)]; + $usages = [...$usages, ...$this->getObserverUsagesFromModelAttribute($node)]; } if ($node instanceof StaticCall) { @@ -110,6 +120,14 @@ private function getUsagesFromStaticCall( } } + if ( + $node->name instanceof Identifier + && $node->name->name === 'observe' + && (new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf($callerType)->yes() + ) { + $usages = [...$usages, ...$this->getUsagesFromObserveCall($node, $scope)]; + } + return $usages; } @@ -268,6 +286,89 @@ private function getUsagesFromScheduleCall( return $usages; } + /** + * @return list + */ + private function getUsagesFromObserveCall( + StaticCall $node, + Scope $scope + ): array + { + $arg = $node->getArgs()[0] ?? null; + + if ($arg === null) { + return []; + } + + $argType = $scope->getType($arg->value); + $observerClassNames = []; + + foreach ($argType->getConstantStrings() as $stringType) { + $observerClassNames[] = $stringType->getValue(); + } + + foreach ($argType->getConstantArrays() as $arrayType) { + foreach ($arrayType->getValueTypes() as $valueType) { + foreach ($valueType->getConstantStrings() as $stringType) { + $observerClassNames[] = $stringType->getValue(); + } + } + } + + $usages = []; + + foreach ($observerClassNames as $observerClassName) { + foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($observerClassName, $method, false), + ); + } + } + + return $usages; + } + + /** + * @return list + */ + private function getObserverUsagesFromModelAttribute(InClassNode $node): array + { + $classReflection = $node->getClassReflection(); + + if (!(new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf(new ObjectType($classReflection->getName()))->yes()) { + return []; + } + + $nativeReflection = $classReflection->getNativeReflection(); + $attributes = $nativeReflection->getAttributes('Illuminate\Database\Eloquent\Attributes\ObservedBy'); + + $usages = []; + + foreach ($attributes as $attribute) { + $args = $attribute->getArguments(); + + foreach ($args as $arg) { + $classNames = is_array($arg) ? $arg : [$arg]; + + foreach ($classNames as $className) { + if (!is_string($className)) { + continue; + } + + foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createVirtual($this, VirtualUsageData::withNote('Laravel observer via #[ObservedBy]')), + new ClassMethodRef($className, $method, false), + ); + } + } + } + } + + return $usages; + } + /** * Extracts [class, method] pairs from a callable array argument like [Controller::class, 'method']. * @@ -353,6 +454,7 @@ private function shouldMarkAsUsed( ?? $this->isFormRequestMethod($method, $classReflection) ?? $this->isFactoryMethod($method, $classReflection) ?? $this->isSeederMethod($method, $classReflection) + ?? $this->isMigrationMethod($method, $classReflection) ?? $this->isPolicyMethod($method, $classReflection) ?? $this->isMailableMethod($method, $classReflection) ?? $this->isBroadcastEventMethod($method, $classReflection) @@ -458,7 +560,7 @@ private function isMiddlewareMethod( { $methodName = $method->getName(); - if ($methodName !== 'handle' && $methodName !== 'terminate') { + if ($methodName !== 'handle' && $methodName !== 'terminate' && !$method->isConstructor()) { return null; } @@ -561,6 +663,22 @@ private function isSeederMethod( return null; } + private function isMigrationMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Migrations\Migration')) { + return null; + } + + if (in_array($method->getName(), ['up', 'down'], true)) { + return 'Laravel migration method'; + } + + return null; + } + private function isPolicyMethod( ReflectionMethod $method, ClassReflection $classReflection diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index fc213cd..68d0fd4 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -16,6 +16,9 @@ abstract class Model { /** @param array $attributes */ public function __construct(array $attributes = []) {} + + /** @param class-string|list $classes */ + public static function observe(string|array $classes): void {} } namespace Illuminate\Database\Eloquent\Relations; @@ -106,6 +109,23 @@ class Seeder { } +namespace Illuminate\Database\Migrations; + +abstract class Migration +{ +} + +namespace Illuminate\Database\Eloquent\Attributes; + +use Attribute; + +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +class ObservedBy +{ + /** @param class-string|list $classes */ + public function __construct(string|array $classes) {} +} + namespace Illuminate\Mail; class Mailable @@ -182,12 +202,14 @@ public static function job(string $job): void {} use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Validation\Rule as ValidationRuleOld; use Illuminate\Contracts\Validation\ValidationRule; +use Illuminate\Database\Eloquent\Attributes\ObservedBy; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Seeder; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Http\FormRequest; @@ -849,6 +871,101 @@ private function helperMethod(): void // error: Unused Laravel\OldValidationRule } } +// --- Migrations --- + +class CreateUsersTable extends Migration +{ + public function up(): void + { + } + + public function down(): void + { + } + + private function helperMethod(): void // error: Unused Laravel\CreateUsersTable::helperMethod + { + } +} + +// --- Observers --- + +class UserObserver +{ + public function __construct() + { + } + + public function creating(object $user): void + { + } + + public function updated(object $user): void + { + } + + public function helperMethod(): void // error: Unused Laravel\UserObserver::helperMethod + { + } +} + +#[ObservedBy(PostObserver::class)] +class ObservedPost extends Model +{ +} + +class PostObserver +{ + public function __construct() + { + } + + public function saving(object $post): void + { + } + + public function deleted(object $post): void + { + } + + public function helperMethod(): void // error: Unused Laravel\PostObserver::helperMethod + { + } +} + +class AuditObserver +{ + public function __construct() + { + } + + public function created(object $model): void + { + } + + public function helperMethod(): void // error: Unused Laravel\AuditObserver::helperMethod + { + } +} + +// --- Middleware with constructor --- + +class ThrottleMiddleware +{ + public function __construct() + { + } + + public function handle(Request $request, \Closure $next): mixed + { + return $next($request); + } + + private function helperMethod(): void // error: Unused Laravel\ThrottleMiddleware::helperMethod + { + } +} + // ===================== // Route/Event/Schedule Registrations (AST-based detection) // ===================== @@ -877,3 +994,9 @@ function registerSchedule(): void { Schedule::job(CleanupJob::class); } + +function registerObservers(): void +{ + User::observe(UserObserver::class); + User::observe([AuditObserver::class]); +} From f541bb9b00fe8e03e1d814b70e53ae54394b17e2 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 16:47:20 +0100 Subject: [PATCH 04/14] Laravel: add policy detection via authorize() calls and Gate facade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Detect $this->authorize('ability', $model) in controllers using AuthorizesRequests trait - Resolve model → policy class using Laravel naming convention - Support Gate::define() for explicit ability registration - Support Gate::policy() to mark all public methods on registered policy classes - Convert kebab-case ability names to camelCase (e.g. 'force-download' → 'forceDownload') --- src/Provider/LaravelUsageProvider.php | 238 +++++++++++++++++++++++++- tests/Rule/DeadCodeRuleTest.php | 1 + tests/Rule/data/providers/laravel.php | 127 ++++++++++++++ 3 files changed, 365 insertions(+), 1 deletion(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 8a10422..86c608e 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -5,6 +5,7 @@ use Composer\InstalledVersions; use PhpParser\Node; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Identifier; use PHPStan\Analyser\Scope; @@ -13,6 +14,7 @@ use PHPStan\Node\InClassNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage; @@ -22,9 +24,12 @@ use function in_array; use function is_array; use function is_string; +use function lcfirst; +use function str_replace; use function strpos; use function strrpos; use function substr; +use function ucwords; final class LaravelUsageProvider implements MemberUsageProvider { @@ -35,10 +40,16 @@ final class LaravelUsageProvider implements MemberUsageProvider 'retrieved', 'forceDeleting', 'forceDeleted', 'trashed', ]; + private ReflectionProvider $reflectionProvider; + private bool $enabled; - public function __construct(?bool $enabled) + public function __construct( + ReflectionProvider $reflectionProvider, + ?bool $enabled + ) { + $this->reflectionProvider = $reflectionProvider; $this->enabled = $enabled ?? InstalledVersions::isInstalled('laravel/framework'); } @@ -62,6 +73,10 @@ public function getUsages( $usages = [...$usages, ...$this->getUsagesFromStaticCall($node, $scope)]; } + if ($node instanceof MethodCall) { + $usages = [...$usages, ...$this->getUsagesFromMethodCall($node, $scope)]; + } + return $usages; } @@ -118,6 +133,10 @@ private function getUsagesFromStaticCall( if ($className === 'Illuminate\Support\Facades\Schedule' || $className === 'Illuminate\Console\Scheduling\Schedule') { $usages = [...$usages, ...$this->getUsagesFromScheduleCall($node, $scope)]; } + + if ($className === 'Illuminate\Support\Facades\Gate' || $className === 'Illuminate\Auth\Access\Gate') { + $usages = [...$usages, ...$this->getUsagesFromGateCall($node, $scope)]; + } } if ( @@ -286,6 +305,223 @@ private function getUsagesFromScheduleCall( return $usages; } + /** + * @return list + */ + private function getUsagesFromGateCall( + StaticCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier) { + return []; + } + + $methodName = $node->name->name; + $usages = []; + + if ($methodName === 'define') { + foreach ($this->extractCallablesFromArg($node, $scope, 1) as [$className, $method]) { + foreach ([$method, '__construct'] as $usedMethod) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $usedMethod, false), + ); + } + } + + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { + foreach (['__invoke', '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $method, false), + ); + } + } + } + + if ($methodName === 'policy') { + foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $policyClassName) { + $usages = [...$usages, ...$this->markAllPublicPolicyMethods($policyClassName, UsageOrigin::createRegular($node, $scope))]; + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromMethodCall( + MethodCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier) { + return []; + } + + if ($node->name->name !== 'authorize') { + return []; + } + + $callerType = $scope->getType($node->var); + + $hasAuthorize = false; + + foreach ($callerType->getObjectClassNames() as $callerClassName) { + if ($this->reflectionProvider->hasClass($callerClassName)) { + $callerReflection = $this->reflectionProvider->getClass($callerClassName); + + if ($callerReflection->hasTraitUse('Illuminate\Foundation\Auth\Access\AuthorizesRequests')) { + $hasAuthorize = true; + break; + } + } + } + + if (!$hasAuthorize) { + return []; + } + + return $this->getUsagesFromAuthorizeCall($node, $scope); + } + + /** + * @return list + */ + private function getUsagesFromAuthorizeCall( + MethodCall $node, + Scope $scope + ): array + { + $args = $node->getArgs(); + $abilityArg = $args[0] ?? null; + $modelArg = $args[1] ?? null; + + if ($abilityArg === null) { + return []; + } + + $abilityType = $scope->getType($abilityArg->value); + $abilityNames = []; + + foreach ($abilityType->getConstantStrings() as $stringType) { + $abilityNames[] = $this->kebabToCamelCase($stringType->getValue()); + } + + if ($abilityNames === []) { + return []; + } + + $policyClassNames = []; + + if ($modelArg !== null) { + $modelType = $scope->getType($modelArg->value); + + foreach ($modelType->getObjectClassNames() as $modelClassName) { + $policyClassName = $this->resolvePolicyClassName($modelClassName); + + if ($policyClassName !== null) { + $policyClassNames[] = $policyClassName; + } + } + + foreach ($modelType->getConstantStrings() as $modelStringType) { + $policyClassName = $this->resolvePolicyClassName($modelStringType->getValue()); + + if ($policyClassName !== null) { + $policyClassNames[] = $policyClassName; + } + } + } + + $usages = []; + + foreach ($policyClassNames as $policyClassName) { + foreach ($abilityNames as $abilityName) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($policyClassName, $abilityName, false), + ); + } + } + + return $usages; + } + + private function resolvePolicyClassName(string $modelClassName): ?string + { + $lastSeparator = strrpos($modelClassName, '\\'); + + if ($lastSeparator === false) { + return null; + } + + $namespace = substr($modelClassName, 0, $lastSeparator); + $shortName = substr($modelClassName, $lastSeparator + 1); + + $firstSeparator = strpos($namespace, '\\'); + $rootNamespace = $firstSeparator !== false + ? substr($namespace, 0, $firstSeparator) + : $namespace; + + $policyClassName = $rootNamespace . '\\Policies\\' . $shortName . 'Policy'; + + if ($this->reflectionProvider->hasClass($policyClassName)) { + return $policyClassName; + } + + return null; + } + + /** + * @return list + */ + private function markAllPublicPolicyMethods( + string $policyClassName, + UsageOrigin $origin + ): array + { + if (!$this->reflectionProvider->hasClass($policyClassName)) { + return []; + } + + $classReflection = $this->reflectionProvider->getClass($policyClassName); + $nativeReflection = $classReflection->getNativeReflection(); + $usages = []; + + foreach ($nativeReflection->getMethods() as $method) { + if ($method->getDeclaringClass()->getName() !== $nativeReflection->getName()) { + continue; + } + + if ($method->isPublic()) { + $usages[] = new ClassMethodUsage( + $origin, + new ClassMethodRef($policyClassName, $method->getName(), false), + ); + } + } + + return $usages; + } + + private function kebabToCamelCase(string $string): string + { + if (strpos($string, '-') === false) { + return $string; + } + + return lcfirst( + str_replace( + '-', + '', + ucwords($string, '-'), + ), + ); + } + /** * @return list */ diff --git a/tests/Rule/DeadCodeRuleTest.php b/tests/Rule/DeadCodeRuleTest.php index a7e6de3..8bf2cce 100644 --- a/tests/Rule/DeadCodeRuleTest.php +++ b/tests/Rule/DeadCodeRuleTest.php @@ -1119,6 +1119,7 @@ private function getMemberUsageProviders(): array $this->createPhpStanContainerMock(), ), new LaravelUsageProvider( + self::getContainer()->getByType(ReflectionProvider::class), $this->providersEnabled, ), new NetteUsageProvider( diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 68d0fd4..4ac7613 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -6,8 +6,11 @@ namespace Illuminate\Routing; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; + abstract class Controller { + use AuthorizesRequests; } namespace Illuminate\Database\Eloquent; @@ -154,6 +157,14 @@ interface Rule { } +namespace Illuminate\Foundation\Auth\Access; + +trait AuthorizesRequests +{ + /** @param mixed ...$arguments */ + public function authorize(string $ability, ...$arguments): void {} +} + namespace Illuminate\Support\Facades; class Route @@ -191,6 +202,13 @@ class Schedule public static function job(string $job): void {} } +class Gate +{ + /** @param mixed $callback */ + public static function define(string $ability, $callback): void {} + public static function policy(string $model, string $policy): void {} +} + // ===================== // Test Classes // ===================== @@ -220,6 +238,7 @@ public static function job(string $job): void {} use Illuminate\Notifications\Notification; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Schedule; use Illuminate\Support\ServiceProvider; @@ -742,6 +761,16 @@ private function helperMethod(): void // error: Unused Laravel\PostPolicy::helpe } } +// --- Policy with custom abilities (detected via authorize() and Gate::policy()) --- + +class Song extends Model +{ +} + +class Album extends Model +{ +} + // --- Mailables --- class WelcomeEmail extends Mailable @@ -1000,3 +1029,101 @@ function registerObservers(): void User::observe(UserObserver::class); User::observe([AuditObserver::class]); } + +function registerPolicies(): void +{ + Gate::policy(Album::class, \Laravel\Policies\AlbumPolicy::class); + Gate::define('manage-songs', [\Laravel\Policies\SongPolicy::class, 'access']); + Gate::define('check-license', \Laravel\Policies\LicenseChecker::class); + Route::get('/songs/{song}', [SongController::class, 'show']); + Route::get('/songs/{song}/download', [SongController::class, 'download']); + Route::post('/songs/upload', [SongController::class, 'upload']); +} + +// --- Controller using authorize() --- + +class SongController extends Controller +{ + public function show(Song $song): void + { + $this->authorize('access', $song); + $this->authorize('edit', $song); + } + + public function download(Song $song): void + { + $this->authorize('force-download', $song); + } + + public function upload(): void + { + $this->authorize('access', Album::class); + $this->authorize('view', new User()); // User has no policy in Laravel\Policies namespace + } +} + +// ===================== +// Policy Classes (in sub-namespace for convention-based resolution) +// ===================== + +namespace Laravel\Policies; + +class SongPolicy +{ + public function access(object $user, object $song): bool + { + return true; + } + + public function edit(object $user, object $song): bool + { + return true; + } + + public function forceDownload(object $user, object $song): bool + { + return true; + } + + public function unusedAbility(object $user): bool // error: Unused Laravel\Policies\SongPolicy::unusedAbility + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\Policies\SongPolicy::helperMethod + { + } +} + +class AlbumPolicy +{ + public function access(object $user): bool + { + return true; + } + + public function browse(object $user): bool + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\Policies\AlbumPolicy::helperMethod + { + } +} + +class LicenseChecker +{ + public function __construct() + { + } + + public function __invoke(object $user): bool + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\Policies\LicenseChecker::helperMethod + { + } +} From 187569e3a5d59752ee0a939d67c40f32983cb9cb Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 18:32:23 +0100 Subject: [PATCH 05/14] Laravel: replace inline stubs with real laravel/framework dev dependency Other providers (Symfony, Doctrine, Twig, Nette) install real packages as dev dependencies. Laravel was the only one using ~210 lines of inline stubs. Install laravel/framework and use real Illuminate classes instead. --- composer.json | 1 + composer.lock | 8670 ++++++++++++++++++------- tests/Rule/data/providers/laravel.php | 229 +- 3 files changed, 6168 insertions(+), 2732 deletions(-) diff --git a/composer.json b/composer.json index cdaafb2..4adc928 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "doctrine/orm": "^2.19 || ^3.0", "editorconfig-checker/editorconfig-checker": "^10.6.0", "ergebnis/composer-normalize": "^2.48.1", + "laravel/framework": "^11.0 || ^12.0", "nette/application": "^3.1", "nette/component-model": "^3.0", "nette/utils": "^3.0 || ^4.0", diff --git a/composer.lock b/composer.lock index eb5cbca..a2cda26 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "65f40a4ca3b702b8119c1fc37eb88f8b", + "content-hash": "e0b43d4b9f57cc1a3d8298414cf49e9f", "packages": [ { "name": "phpstan/phpstan", @@ -61,6 +61,135 @@ } ], "packages-dev": [ + { + "name": "brick/math", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.13.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-03-29T13:50:30+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, { "name": "composer/semver", "version": "3.4.3", @@ -238,6 +367,81 @@ ], "time": "2025-11-11T04:32:07+00:00" }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, { "name": "doctrine/annotations", "version": "2.0.2", @@ -1069,6 +1273,70 @@ ], "time": "2024-11-01T21:49:07+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": "editorconfig-checker/editorconfig-checker", "version": "10.7.0", @@ -1121,6 +1389,73 @@ }, "time": "2025-03-17T14:59:08+00:00" }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, { "name": "ergebnis/composer-normalize", "version": "2.48.1", @@ -1585,44 +1920,37 @@ "time": "2025-08-19T08:41:00+00:00" }, { - "name": "justinrainbow/json-schema", - "version": "6.5.1", + "name": "fruitcake/php-cors", + "version": "v1.4.0", "source": { "type": "git", - "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "b5ab21e431594897e5bb86343c01f140ba862c26" + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/b5ab21e431594897e5bb86343c01f140ba862c26", - "reference": "b5ab21e431594897e5bb86343c01f140ba862c26", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", "shasum": "" }, "require": { - "ext-json": "*", - "marc-mabe/php-enum": "^4.0", - "php": "^7.2 || ^8.0" + "php": "^8.1", + "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" }, "require-dev": { - "friendsofphp/php-cs-fixer": "3.3.0", - "json-schema/json-schema-test-suite": "^23.2", - "marc-mabe/php-enum-phpstan": "^2.0", - "phpspec/prophecy": "^1.19", - "phpstan/phpstan": "^1.12", - "phpunit/phpunit": "^8.5" + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^4" }, - "bin": [ - "bin/validate-json" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "6.x-dev" + "dev-master": "1.3-dev" } }, "autoload": { "psr-4": { - "JsonSchema\\": "src/JsonSchema/" + "Fruitcake\\Cors\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1631,721 +1959,976 @@ ], "authors": [ { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" }, { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" + "name": "Barryvdh", + "email": "barryvdh@gmail.com" } ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/jsonrainbow/json-schema", + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", "keywords": [ - "json", - "schema" + "cors", + "laravel", + "symfony" ], "support": { - "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.5.1" + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" }, - "time": "2025-08-29T10:58:11+00:00" - }, - { - "name": "localheinz/diff", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/localheinz/diff.git", - "reference": "33bd840935970cda6691c23fc7d94ae764c0734c" + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-12-03T09:33:47+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.4", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/localheinz/diff/zipball/33bd840935970cda6691c23fc7d94ae764c0734c", - "reference": "33bd840935970cda6691c23fc7d94ae764c0734c", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", "shasum": "" }, "require": { - "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.5" }, "require-dev": { - "phpunit/phpunit": "^7.5.0 || ^8.5.23", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" } ], - "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", - "homepage": "https://github.com/localheinz/diff", + "description": "An Implementation Of The Result Type", "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" ], "support": { - "issues": "https://github.com/localheinz/diff/issues", - "source": "https://github.com/localheinz/diff/tree/1.3.0" + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" }, - "time": "2025-08-30T09:44:18+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:43:20+00:00" }, { - "name": "marc-mabe/php-enum", - "version": "v4.7.1", + "name": "guzzlehttp/guzzle", + "version": "7.10.0", "source": { "type": "git", - "url": "https://github.com/marc-mabe/php-enum.git", - "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", - "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { - "ext-reflection": "*", - "php": "^7.1 | ^8.0" + "ext-json": "*", + "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" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { - "phpbench/phpbench": "^0.16.10 || ^1.0.4", - "phpstan/phpstan": "^1.3.1", - "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", - "vimeo/psalm": "^4.17.0 | ^5.26.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { - "branch-alias": { - "dev-3.x": "3.2-dev", - "dev-master": "4.7-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { - "MabeEnum\\": "src/" - }, - "classmap": [ - "stubs/Stringable.php" - ] + "GuzzleHttp\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Marc Bennewitz", - "email": "dev@mabe.berlin", - "homepage": "https://mabe.berlin/", - "role": "Lead" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], - "description": "Simple and fast implementation of enumerations with native PHP", - "homepage": "https://github.com/marc-mabe/php-enum", + "description": "Guzzle is a PHP HTTP client library", "keywords": [ - "enum", - "enum-map", - "enum-set", - "enumeration", - "enumerator", - "enummap", - "enumset", - "map", - "set", - "type", - "type-hint", - "typehint" + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" ], "support": { - "issues": "https://github.com/marc-mabe/php-enum/issues", - "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, - "time": "2024-11-28T04:54:44+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-08-23T22:36:01+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.13.1", + "name": "guzzlehttp/promises", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "url": "https://github.com/guzzle/promises.git", + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "promise" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { - "name": "nette/application", - "version": "v3.2.8", + "name": "guzzlehttp/psr7", + "version": "2.8.0", "source": { "type": "git", - "url": "https://github.com/nette/application.git", - "reference": "aaa18a09a488a2e632162539f77f90b3024c44f8" + "url": "https://github.com/guzzle/psr7.git", + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/application/zipball/aaa18a09a488a2e632162539f77f90b3024c44f8", - "reference": "aaa18a09a488a2e632162539f77f90b3024c44f8", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { - "nette/component-model": "^3.1", - "nette/http": "^3.3.2", - "nette/routing": "^3.1", - "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" }, - "conflict": { - "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.2", - "nette/caching": "<3.2", - "nette/di": "<3.2", - "nette/forms": "<3.2", - "nette/schema": "<1.3", - "tracy/tracy": "<2.9" + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" }, "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", - "latte/latte": "^2.10.2 || ^3.0.18", - "mockery/mockery": "^1.6@stable", - "nette/di": "^3.2", - "nette/forms": "^3.2", - "nette/robot-loader": "^4.0", - "nette/security": "^3.2", - "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.9" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { - "latte/latte": "Allows using Latte in templates", - "nette/forms": "Allows to use Nette\\Application\\UI\\Form" + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.2-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "GuzzleHttp\\Psr7\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" + "MIT" ], "authors": [ { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" }, { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], - "description": "🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.", - "homepage": "https://nette.org", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ - "Forms", - "component-based", - "control", - "framework", - "mvc", - "mvp", - "nette", - "presenter", - "routing", - "seo" + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" ], "support": { - "issues": "https://github.com/nette/application/issues", - "source": "https://github.com/nette/application/tree/v3.2.8" + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, - "time": "2025-11-24T00:10:57+00:00" - }, - { - "name": "nette/component-model", - "version": "v3.1.3", - "source": { + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-08-23T21:21:41+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.5", + "source": { "type": "git", - "url": "https://github.com/nette/component-model.git", - "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2" + "url": "https://github.com/guzzle/uri-template.git", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/component-model/zipball/0d100ba05279a1f4b20acecaa617027fbda8ecb2", - "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { - "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.9" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", + "uri-template/tests": "1.0.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.1-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "GuzzleHttp\\UriTemplate\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" + "MIT" ], "authors": [ { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" }, { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" } ], - "description": "⚛ Nette Component Model", - "homepage": "https://nette.org", + "description": "A polyfill class for uri_template of PHP", "keywords": [ - "components", - "nette" + "guzzlehttp", + "uri-template" ], "support": { - "issues": "https://github.com/nette/component-model/issues", - "source": "https://github.com/nette/component-model/tree/v3.1.3" + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" }, - "time": "2025-11-22T18:56:33+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:27:06+00:00" }, { - "name": "nette/http", - "version": "v3.3.3", + "name": "justinrainbow/json-schema", + "version": "6.5.1", "source": { "type": "git", - "url": "https://github.com/nette/http.git", - "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d" + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "b5ab21e431594897e5bb86343c01f140ba862c26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/http/zipball/c557f21c8cedd621dbfd7990752b1d55ef353f1d", - "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/b5ab21e431594897e5bb86343c01f140ba862c26", + "reference": "b5ab21e431594897e5bb86343c01f140ba862c26", "shasum": "" }, "require": { - "nette/utils": "^4.0.4", - "php": "8.1 - 8.5" - }, - "conflict": { - "nette/di": "<3.0.3", - "nette/schema": "<1.2" + "ext-json": "*", + "marc-mabe/php-enum": "^4.0", + "php": "^7.2 || ^8.0" }, "require-dev": { - "nette/di": "^3.0", - "nette/security": "^3.0", - "nette/tester": "^2.4", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.8" - }, - "suggest": { - "ext-fileinfo": "to detect MIME type of uploaded files by Nette\\Http\\FileUpload", - "ext-gd": "to use image function in Nette\\Http\\FileUpload", - "ext-intl": "to support punycode by Nette\\Http\\Url", - "ext-session": "to use Nette\\Http\\Session" + "friendsofphp/php-cs-fixer": "3.3.0", + "json-schema/json-schema-test-suite": "^23.2", + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" }, + "bin": [ + "bin/validate-json" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "6.x-dev" } }, "autoload": { "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "JsonSchema\\": "src/JsonSchema/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" + "MIT" ], "authors": [ { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" }, { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" } ], - "description": "🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.", - "homepage": "https://nette.org", + "description": "A library to validate a json schema.", + "homepage": "https://github.com/jsonrainbow/json-schema", "keywords": [ - "cookies", - "http", - "nette", - "proxy", - "request", - "response", - "security", - "session", - "url" + "json", + "schema" ], "support": { - "issues": "https://github.com/nette/http/issues", - "source": "https://github.com/nette/http/tree/v3.3.3" + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/6.5.1" }, - "time": "2025-10-30T22:32:24+00:00" + "time": "2025-08-29T10:58:11+00:00" }, { - "name": "nette/routing", - "version": "v3.1.2", + "name": "laravel/framework", + "version": "v12.26.2", "source": { "type": "git", - "url": "https://github.com/nette/routing.git", - "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47" + "url": "https://github.com/laravel/framework.git", + "reference": "56c5fc46cfb1005d0aaa82c7592d63edb776a787" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/routing/zipball/14c466f3383add0d4f78a82074d3c9841f8edf47", - "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47", + "url": "https://api.github.com/repos/laravel/framework/zipball/56c5fc46cfb1005d0aaa82c7592d63edb776a787", + "reference": "56c5fc46cfb1005d0aaa82c7592d63edb776a787", "shasum": "" }, "require": { - "nette/http": "^3.2 || ~4.0.0", - "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "brick/math": "^0.11|^0.12|^0.13", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.31", + "symfony/polyfill-php84": "^1.31", + "symfony/polyfill-php85": "^1.33", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" }, "require-dev": { - "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.9" + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.6.0", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "12.x-dev" } }, "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" + "MIT" ], "authors": [ { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" + "name": "Taylor Otwell", + "email": "taylor@laravel.com" } ], - "description": "Nette Routing: two-ways URL conversion", - "homepage": "https://nette.org", + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", "keywords": [ - "nette" + "framework", + "laravel" ], "support": { - "issues": "https://github.com/nette/routing/issues", - "source": "https://github.com/nette/routing/tree/v3.1.2" + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" }, - "time": "2025-10-31T00:55:27+00:00" + "time": "2025-08-26T18:04:56+00:00" }, { - "name": "nette/schema", - "version": "v1.3.3", + "name": "laravel/prompts", + "version": "v0.3.13", "source": { "type": "git", - "url": "https://github.com/nette/schema.git", - "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" + "url": "https://github.com/laravel/prompts.git", + "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", - "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", + "url": "https://api.github.com/repos/laravel/prompts/zipball/ed8c466571b37e977532fb2fd3c272c784d7050d", + "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d", "shasum": "" }, "require": { - "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0|^8.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { - "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.8" + "illuminate/collections": "^10.0|^11.0|^12.0|^13.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4|^4.0", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-main": "0.3.x-dev" } }, "autoload": { + "files": [ + "src/helpers.php" + ], "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "Laravel\\Prompts\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "📐 Nette Schema: validating data structures against a given Schema.", - "homepage": "https://nette.org", - "keywords": [ - "config", - "nette" + "MIT" ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { - "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.3" + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.13" }, - "time": "2025-10-30T22:57:59+00:00" + "time": "2026-02-06T12:17:10+00:00" }, { - "name": "nette/utils", - "version": "v4.0.9", + "name": "laravel/serializable-closure", + "version": "v2.0.10", "source": { "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "505a30ad386daa5211f08a318e47015b501cad30" + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "870fc81d2f879903dfc5b60bf8a0f94a1609e669" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/505a30ad386daa5211f08a318e47015b501cad30", - "reference": "505a30ad386daa5211f08a318e47015b501cad30", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/870fc81d2f879903dfc5b60bf8a0f94a1609e669", + "reference": "870fc81d2f879903dfc5b60bf8a0f94a1609e669", "shasum": "" }, "require": { - "php": "8.0 - 8.5" - }, - "conflict": { - "nette/finder": "<3", - "nette/schema": "<1.2.2" + "php": "^8.1" }, "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", - "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", - "tracy/tracy": "^2.9" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0|^4.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "Laravel\\SerializableClosure\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" + "MIT" ], "authors": [ { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" + "name": "Taylor Otwell", + "email": "taylor@laravel.com" }, { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" + "name": "Nuno Maduro", + "email": "nuno@laravel.com" } ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" + "closure", + "laravel", + "serializable" ], "support": { - "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.9" + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-10-31T00:45:47+00:00" + "time": "2026-02-20T19:59:49+00:00" }, { - "name": "nikic/php-parser", - "version": "v5.5.0", + "name": "league/commonmark", + "version": "2.8.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "2.9-dev" } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "League\\CommonMark\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2354,52 +2937,87 @@ ], "authors": [ { - "name": "Nikita Popov" + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], - "description": "A PHP parser written in PHP", + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", "keywords": [ - "parser", - "php" + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" }, - "time": "2025-05-31T08:24:38+00:00" + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-11-26T21:48:24+00:00" }, { - "name": "phar-io/manifest", - "version": "2.0.4", + "name": "league/config", + "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "1.2-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "League\\Config\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2407,117 +3025,152 @@ ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" }, "funding": [ { - "url": "https://github.com/theseer", + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", "type": "github" } ], - "time": "2024-03-03T12:33:53+00:00" + "time": "2022-12-11T20:36:23+00:00" }, { - "name": "phar-io/version", - "version": "3.2.1", + "name": "league/flysystem", + "version": "3.32.0", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "254b1595b16b22dbddaaef9ed6ca9fdac4956725" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/254b1595b16b22dbddaaef9ed6ca9fdac4956725", + "reference": "254b1595b16b22dbddaaef9ed6ca9fdac4956725", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "League\\Flysystem\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "Library for handling version information and constraints", + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.32.0" }, - "time": "2022-02-21T01:04:05+00:00" + "time": "2026-02-25T17:01:41+00:00" }, { - "name": "phpbench/container", - "version": "2.2.3", + "name": "league/flysystem-local", + "version": "3.31.0", "source": { "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196" + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196", - "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079", + "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079", "shasum": "" }, "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0" - }, - "require-dev": { - "php-cs-fixer/shim": "^3.89", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, "autoload": { "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" + "League\\Flysystem\\Local\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2526,83 +3179,50 @@ ], "authors": [ { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "Simple, configurable, service container.", + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.3" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0" }, - "time": "2025-11-06T09:05:13+00:00" + "time": "2026-01-23T15:30:45+00:00" }, { - "name": "phpbench/phpbench", - "version": "1.4.2", + "name": "league/mime-type-detection", + "version": "1.16.0", "source": { "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", "shasum": "" }, "require": { - "doctrine/annotations": "^2.0", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^8.1", - "phpbench/container": "^2.2", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^6.1 || ^7.0", - "symfony/filesystem": "^6.1 || ^7.0", - "symfony/finder": "^6.1 || ^7.0", - "symfony/options-resolver": "^6.1 || ^7.0", - "symfony/process": "^6.1 || ^7.0", - "webmozart/glob": "^4.6" + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "dantleech/invoke": "^2.0", - "ergebnis/composer-normalize": "^2.39", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "^1.22", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.4 || ^11.0", - "rector/rector": "^1.2", - "symfony/error-handler": "^6.1 || ^7.0", - "symfony/var-dumper": "^6.1 || ^7.0" + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" + "League\\MimeTypeDetection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2611,919 +3231,1172 @@ ], "authors": [ { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "PHP Benchmarking Framework", - "keywords": [ - "benchmarking", - "optimization", - "performance", - "profiling", - "testing" - ], + "description": "Mime-type detection for Flysystem", "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.2" + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" }, "funding": [ { - "url": "https://github.com/dantleech", + "url": "https://github.com/frankdejonge", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" } ], - "time": "2025-10-26T14:21:59+00:00" + "time": "2024-09-21T08:32:55+00:00" }, { - "name": "phpstan/phpdoc-parser", - "version": "2.3.0", + "name": "league/uri", + "version": "7.8.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + "url": "https://github.com/thephpleague/uri.git", + "reference": "4436c6ec8d458e4244448b069cc572d088230b76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", + "reference": "4436c6ec8d458e4244448b069cc572d088230b76", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "league/uri-interfaces": "^7.8", + "php": "^8.1", + "psr/http-factory": "^1" }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to 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", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, "autoload": { "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "URN", + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc2141", + "rfc3986", + "rfc3987", + "rfc6570", + "rfc8141", + "uri", + "uri-template", + "url", + "ws" + ], "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + "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.8.0" }, - "time": "2025-08-30T15:50:23+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-01-14T17:24:56+00:00" }, { - "name": "phpstan/phpstan-phpunit", - "version": "2.0.6", + "name": "league/uri-interfaces", + "version": "7.8.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "6b92469f8a7995e626da3aa487099617b8dfa260" + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6b92469f8a7995e626da3aa487099617b8dfa260", - "reference": "6b92469f8a7995e626da3aa487099617b8dfa260", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.0.4" - }, - "conflict": { - "phpunit/phpunit": "<7.0" + "ext-filter": "*", + "php": "^8.1", + "psr/http-message": "^1.1 || ^2.0" }, - "require-dev": { - "nikic/php-parser": "^5", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6" + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "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": "phpstan-extension", + "type": "library", "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] + "branch-alias": { + "dev-master": "7.x-dev" } }, "autoload": { "psr-4": { - "PHPStan\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PHPUnit extensions and rules for PHPStan", + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.6" + "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.8.0" }, - "time": "2025-03-26T12:47:06+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-01-15T06:54:53+00:00" }, { - "name": "phpstan/phpstan-strict-rules", - "version": "2.0.4", + "name": "localheinz/diff", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a" + "url": "https://github.com/localheinz/diff.git", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", - "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "url": "https://api.github.com/repos/localheinz/diff/zipball/33bd840935970cda6691c23fc7d94ae764c0734c", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.0.4" + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "rules.neon" - ] - } + "phpunit/phpunit": "^7.5.0 || ^8.5.23", + "symfony/process": "^4.2 || ^5" }, + "type": "library", "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", + "homepage": "https://github.com/localheinz/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" ], - "description": "Extra strict and opinionated rules for PHPStan", "support": { - "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4" + "issues": "https://github.com/localheinz/diff/issues", + "source": "https://github.com/localheinz/diff/tree/1.3.0" }, - "time": "2025-03-18T11:42:40+00:00" + "time": "2025-08-30T09:44:18+00:00" }, { - "name": "phpstan/phpstan-symfony", - "version": "2.0.6", + "name": "marc-mabe/php-enum", + "version": "v4.7.1", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "5005288e07583546ea00b52de4a9ac412eb869d7" + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/5005288e07583546ea00b52de4a9ac412eb869d7", - "reference": "5005288e07583546ea00b52de4a9ac412eb869d7", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", "shasum": "" }, "require": { - "ext-simplexml": "*", - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.13" - }, - "conflict": { - "symfony/framework-bundle": "<3.0" + "ext-reflection": "*", + "php": "^7.1 | ^8.0" }, "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "psr/container": "1.1.2", - "symfony/config": "^5.4 || ^6.1", - "symfony/console": "^5.4 || ^6.1", - "symfony/dependency-injection": "^5.4 || ^6.1", - "symfony/form": "^5.4 || ^6.1", - "symfony/framework-bundle": "^5.4 || ^6.1", - "symfony/http-foundation": "^5.4 || ^6.1", - "symfony/messenger": "^5.4", - "symfony/polyfill-php80": "^1.24", - "symfony/serializer": "^5.4", - "symfony/service-contracts": "^2.2.0" + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" }, - "type": "phpstan-extension", + "type": "library", "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" } }, "autoload": { "psr-4": { - "PHPStan\\": "src/" - } + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Lukáš Unger", - "email": "looky.msc@gmail.com", - "homepage": "https://lookyman.net" + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" } ], - "description": "Symfony Framework extensions and rules for PHPStan", + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], "support": { - "issues": "https://github.com/phpstan/phpstan-symfony/issues", - "source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.6" + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" }, - "time": "2025-05-14T07:00:05+00:00" + "time": "2024-11-28T04:54:44+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "9.2.32", + "name": "monolog/monolog", + "version": "3.10.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + "url": "https://github.com/Seldaek/monolog.git", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-text-template": "^2.0.4", - "sebastian/code-unit-reverse-lookup": "^2.0.3", - "sebastian/complexity": "^2.0.3", - "sebastian/environment": "^5.1.5", - "sebastian/lines-of-code": "^1.0.4", - "sebastian/version": "^3.0.2", - "theseer/tokenizer": "^1.2.3" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8 || ^2.0", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Monolog\\": "src/Monolog" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ - "coverage", - "testing", - "xunit" + "log", + "logging", + "psr-3" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/Seldaek", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" } ], - "time": "2024-08-22T04:23:01+00:00" + "time": "2026-01-02T08:56:05+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "name": "myclabs/deep-copy", + "version": "1.13.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "filesystem", - "iterator" + "clone", + "copy", + "duplicate", + "object", + "object graph" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { - "name": "phpunit/php-invoker", - "version": "3.1.1", + "name": "nesbot/carbon", + "version": "3.11.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "f438fcc98f92babee98381d399c65336f3a3827f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f", + "reference": "f438fcc98f92babee98381d399c65336f3a3827f", "shasum": "" }, "require": { - "php": ">=7.3" + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.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 || ^8.0" }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "provide": { + "psr/clock-implementation": "1.0" }, - "suggest": { - "ext-pcntl": "*" + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.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.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0" }, + "bin": [ + "bin/carbon" + ], "type": "library", "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, "branch-alias": { - "dev-master": "3.1-dev" + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Carbon\\": "src/Carbon/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" } ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbonphp.github.io/carbon/", "keywords": [ - "process" + "date", + "datetime", + "time" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/sponsors/kylekatarnls", "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2026-01-29T09:26:29+00:00" }, { - "name": "phpunit/php-text-template", - "version": "2.0.4", + "name": "nette/application", + "version": "v3.2.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "url": "https://github.com/nette/application.git", + "reference": "aaa18a09a488a2e632162539f77f90b3024c44f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/nette/application/zipball/aaa18a09a488a2e632162539f77f90b3024c44f8", + "reference": "aaa18a09a488a2e632162539f77f90b3024c44f8", "shasum": "" }, "require": { - "php": ">=7.3" + "nette/component-model": "^3.1", + "nette/http": "^3.3.2", + "nette/routing": "^3.1", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.2", + "nette/caching": "<3.2", + "nette/di": "<3.2", + "nette/forms": "<3.2", + "nette/schema": "<1.3", + "tracy/tracy": "<2.9" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "jetbrains/phpstorm-attributes": "^1.2", + "latte/latte": "^2.10.2 || ^3.0.18", + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.2", + "nette/forms": "^3.2", + "nette/robot-loader": "^4.0", + "nette/security": "^3.2", + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "latte/latte": "Allows using Latte in templates", + "nette/forms": "Allows to use Nette\\Application\\UI\\Form" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.", + "homepage": "https://nette.org", "keywords": [ - "template" + "Forms", + "component-based", + "control", + "framework", + "mvc", + "mvp", + "nette", + "presenter", + "routing", + "seo" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "issues": "https://github.com/nette/application/issues", + "source": "https://github.com/nette/application/tree/v3.2.8" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2025-11-24T00:10:57+00:00" }, { - "name": "phpunit/php-timer", - "version": "5.0.3", + "name": "nette/component-model", + "version": "v3.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "url": "https://github.com/nette/component-model.git", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/nette/component-model/zipball/0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2", "shasum": "" }, "require": { - "php": ">=7.3" + "nette/utils": "^4.0", + "php": "8.1 - 8.5" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "⚛ Nette Component Model", + "homepage": "https://nette.org", "keywords": [ - "timer" + "components", + "nette" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "issues": "https://github.com/nette/component-model/issues", + "source": "https://github.com/nette/component-model/tree/v3.1.3" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2025-11-22T18:56:33+00:00" }, { - "name": "phpunit/phpcov", - "version": "8.2.1", + "name": "nette/http", + "version": "v3.3.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpcov.git", - "reference": "8ec45dde34a84914a0ace355fbd6d7af2242c9a4" + "url": "https://github.com/nette/http.git", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpcov/zipball/8ec45dde34a84914a0ace355fbd6d7af2242c9a4", - "reference": "8ec45dde34a84914a0ace355fbd6d7af2242c9a4", + "url": "https://api.github.com/repos/nette/http/zipball/c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d", "shasum": "" }, "require": { - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2", - "phpunit/php-file-iterator": "^3.0", - "phpunit/phpunit": "^9.3", - "sebastian/cli-parser": "^1.0", - "sebastian/diff": "^4.0", - "sebastian/version": "^3.0" + "nette/utils": "^4.0.4", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/di": "<3.0.3", + "nette/schema": "<1.2" + }, + "require-dev": { + "nette/di": "^3.0", + "nette/security": "^3.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "ext-fileinfo": "to detect MIME type of uploaded files by Nette\\Http\\FileUpload", + "ext-gd": "to use image function in Nette\\Http\\FileUpload", + "ext-intl": "to support punycode by Nette\\Http\\Url", + "ext-session": "to use Nette\\Http\\Session" }, - "bin": [ - "phpcov" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "8.2-dev" + "dev-master": "3.3-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "CLI frontend for php-code-coverage", - "homepage": "https://github.com/sebastianbergmann/phpcov", + "description": "🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.", + "homepage": "https://nette.org", + "keywords": [ + "cookies", + "http", + "nette", + "proxy", + "request", + "response", + "security", + "session", + "url" + ], "support": { - "issues": "https://github.com/sebastianbergmann/phpcov/issues", - "source": "https://github.com/sebastianbergmann/phpcov/tree/8.2.1" + "issues": "https://github.com/nette/http/issues", + "source": "https://github.com/nette/http/tree/v3.3.3" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-24T12:07:05+00:00" + "time": "2025-10-30T22:32:24+00:00" }, { - "name": "phpunit/phpunit", - "version": "9.6.23", + "name": "nette/routing", + "version": "v3.1.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + "url": "https://github.com/nette/routing.git", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "url": "https://api.github.com/repos/nette/routing/zipball/14c466f3383add0d4f78a82074d3c9841f8edf47", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.32", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.4", - "phpunit/php-timer": "^5.0.3", - "sebastian/cli-parser": "^1.0.2", - "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.6", - "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", - "sebastian/object-enumerator": "^4.0.4", - "sebastian/resource-operations": "^3.0.4", - "sebastian/type": "^3.2.1", - "sebastian/version": "^3.0.2" + "nette/http": "^3.2 || ~4.0.0", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Nette Routing: two-ways URL conversion", + "homepage": "https://nette.org", "keywords": [ - "phpunit", - "testing", - "xunit" + "nette" ], "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.23" + "issues": "https://github.com/nette/routing/issues", + "source": "https://github.com/nette/routing/tree/v3.1.2" }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "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/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2025-05-02T06:40:34+00:00" + "time": "2025-10-31T00:55:27+00:00" }, { - "name": "psr/cache", - "version": "3.0.0", + "name": "nette/schema", + "version": "v1.3.3", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + "url": "https://github.com/nette/schema.git", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", "shasum": "" }, "require": { - "php": ">=8.0.0" + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.3-dev" } }, "autoload": { "psr-4": { - "Psr\\Cache\\": "src/" - } + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "Common interface for caching libraries", + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", "keywords": [ - "cache", - "psr", - "psr-6" + "config", + "nette" ], "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.3" }, - "time": "2021-02-03T23:26:27+00:00" + "time": "2025-10-30T22:57:59+00:00" }, { - "name": "psr/container", - "version": "2.0.2", + "name": "nette/utils", + "version": "v4.0.9", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/nette/utils.git", + "reference": "505a30ad386daa5211f08a318e47015b501cad30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/nette/utils/zipball/505a30ad386daa5211f08a318e47015b501cad30", + "reference": "505a30ad386daa5211f08a318e47015b501cad30", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": "8.0 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" - } + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.9" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2025-10-31T00:45:47+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "nikic/php-parser", + "version": "v5.5.0", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { - "php": ">=7.2.0" + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Nikita Popov" } ], - "description": "Standard interfaces for event handling.", + "description": "A PHP parser written in PHP", "keywords": [ - "events", - "psr", - "psr-14" + "parser", + "php" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2019-01-08T18:20:26+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { - "name": "psr/log", - "version": "3.0.2", + "name": "nunomaduro/termwind", + "version": "v2.3.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { - "php": ">=8.0.0" + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, "branch-alias": { - "dev-master": "3.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { + "files": [ + "src/Functions.php" + ], "psr-4": { - "Psr\\Log\\": "src" + "Termwind\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3532,46 +4405,65 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Its like Tailwind CSS, but for the console.", "keywords": [ - "log", - "psr", - "psr-3" + "cli", + "console", + "css", + "package", + "php", + "style" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, - "time": "2024-09-11T13:17:53+00:00" + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-05-08T08:14:37+00:00" }, { - "name": "sebastian/cli-parser", - "version": "1.0.2", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "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": "1.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3584,52 +4476,53 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "lead" + "role": "Developer" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/theseer", "type": "github" } ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "sebastian/code-unit", - "version": "1.0.8", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -3640,507 +4533,512 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "lead" + "role": "Developer" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "description": "Library for handling version information and constraints", "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "name": "phpbench/container", + "version": "2.2.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "url": "https://github.com/phpbench/container.git", + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196", + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196", "shasum": "" }, "require": { - "php": ">=7.3" + "psr/container": "^1.0|^2.0", + "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "php-cs-fixer/shim": "^3.89", + "phpstan/phpstan": "^0.12.52", + "phpunit/phpunit": "^8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpBench\\DependencyInjection\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Daniel Leech", + "email": "daniel@dantleech.com" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Simple, configurable, service container.", "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "issues": "https://github.com/phpbench/container/issues", + "source": "https://github.com/phpbench/container/tree/2.2.3" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2025-11-06T09:05:13+00:00" }, { - "name": "sebastian/comparator", - "version": "4.0.8", + "name": "phpbench/phpbench", + "version": "1.4.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "url": "https://github.com/phpbench/phpbench.git", + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "doctrine/annotations": "^2.0", + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "ext-tokenizer": "*", + "php": "^8.1", + "phpbench/container": "^2.2", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "seld/jsonlint": "^1.1", + "symfony/console": "^6.1 || ^7.0", + "symfony/filesystem": "^6.1 || ^7.0", + "symfony/finder": "^6.1 || ^7.0", + "symfony/options-resolver": "^6.1 || ^7.0", + "symfony/process": "^6.1 || ^7.0", + "webmozart/glob": "^4.6" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "dantleech/invoke": "^2.0", + "ergebnis/composer-normalize": "^2.39", + "friendsofphp/php-cs-fixer": "^3.0", + "jangregor/phpstan-prophecy": "^1.0", + "phpspec/prophecy": "^1.22", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^10.4 || ^11.0", + "rector/rector": "^1.2", + "symfony/error-handler": "^6.1 || ^7.0", + "symfony/var-dumper": "^6.1 || ^7.0" + }, + "suggest": { + "ext-xdebug": "For Xdebug profiling extension." }, + "bin": [ + "bin/phpbench" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "1.2-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "lib/Report/Func/functions.php" + ], + "psr-4": { + "PhpBench\\": "lib/", + "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Daniel Leech", + "email": "daniel@dantleech.com" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "PHP Benchmarking Framework", "keywords": [ - "comparator", - "compare", - "equality" + "benchmarking", + "optimization", + "performance", + "profiling", + "testing" ], "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "issues": "https://github.com/phpbench/phpbench/issues", + "source": "https://github.com/phpbench/phpbench/tree/1.4.2" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/dantleech", "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2025-10-26T14:21:59+00:00" }, { - "name": "sebastian/complexity", - "version": "2.0.3", + "name": "phpoption/phpoption", + "version": "1.9.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "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": "2.0-dev" + "dev-master": "1.9-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "Apache-2.0" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/GrahamCampbell", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2025-12-27T19:41:33+00:00" }, { - "name": "sebastian/diff", - "version": "4.0.6", + "name": "phpstan/phpdoc-parser", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" + "MIT" ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2025-08-30T15:50:23+00:00" }, { - "name": "sebastian/environment", - "version": "5.1.5", + "name": "phpstan/phpstan-phpunit", + "version": "2.0.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "6b92469f8a7995e626da3aa487099617b8dfa260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6b92469f8a7995e626da3aa487099617b8dfa260", + "reference": "6b92469f8a7995e626da3aa487099617b8dfa260", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0.4" }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "conflict": { + "phpunit/phpunit": "<7.0" }, - "suggest": { - "ext-posix": "*" + "require-dev": { + "nikic/php-parser": "^5", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" }, - "type": "library", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "5.1-dev" + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" + "MIT" ], + "description": "PHPUnit extensions and rules for PHPStan", "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.6" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2025-03-26T12:47:06+00:00" }, { - "name": "sebastian/exporter", - "version": "4.0.6", + "name": "phpstan/phpstan-strict-rules", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0.4" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" }, - "type": "library", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "4.0-dev" + "phpstan": { + "includes": [ + "rules.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" + "MIT" ], + "description": "Extra strict and opinionated rules for PHPStan", "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-03-18T11:42:40+00:00" }, { - "name": "sebastian/global-state", - "version": "5.0.7", + "name": "phpstan/phpstan-symfony", + "version": "2.0.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "url": "https://github.com/phpstan/phpstan-symfony.git", + "reference": "5005288e07583546ea00b52de4a9ac412eb869d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/5005288e07583546ea00b52de4a9ac412eb869d7", + "reference": "5005288e07583546ea00b52de4a9ac412eb869d7", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "ext-simplexml": "*", + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.13" }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" + "conflict": { + "symfony/framework-bundle": "<3.0" }, - "suggest": { - "ext-uopz": "*" + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "psr/container": "1.1.2", + "symfony/config": "^5.4 || ^6.1", + "symfony/console": "^5.4 || ^6.1", + "symfony/dependency-injection": "^5.4 || ^6.1", + "symfony/form": "^5.4 || ^6.1", + "symfony/framework-bundle": "^5.4 || ^6.1", + "symfony/http-foundation": "^5.4 || ^6.1", + "symfony/messenger": "^5.4", + "symfony/polyfill-php80": "^1.24", + "symfony/serializer": "^5.4", + "symfony/service-contracts": "^2.2.0" }, - "type": "library", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "5.0-dev" + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Lukáš Unger", + "email": "looky.msc@gmail.com", + "homepage": "https://lookyman.net" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], + "description": "Symfony Framework extensions and rules for PHPStan", "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "issues": "https://github.com/phpstan/phpstan-symfony/issues", + "source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.6" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-05-14T07:00:05+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "1.0.4", + "name": "phpunit/php-code-coverage", + "version": "9.2.32", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -4159,11 +5057,17 @@ "role": "lead" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -4171,26 +5075,24 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "4.0.4", + "name": "phpunit/php-file-iterator", + "version": "3.0.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" @@ -4198,7 +5100,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -4213,14 +5115,19 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -4228,32 +5135,36 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "sebastian/object-reflector", - "version": "2.0.4", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { + "ext-pcntl": "*", "phpunit/phpunit": "^9.3" }, + "suggest": { + "ext-pcntl": "*" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4268,14 +5179,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" }, "funding": [ { @@ -4283,20 +5198,20 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2020-09-28T05:58:55+00:00" }, { - "name": "sebastian/recursion-context", - "version": "4.0.5", + "name": "phpunit/php-text-template", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { @@ -4308,7 +5223,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -4323,22 +5238,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, "funding": [ { @@ -4346,32 +5257,32 @@ "type": "github" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2020-10-26T05:33:50+00:00" }, { - "name": "sebastian/resource-operations", - "version": "3.0.4", + "name": "phpunit/php-timer", + "version": "5.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -4386,13 +5297,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { @@ -4400,32 +5316,38 @@ "type": "github" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { - "name": "sebastian/type", - "version": "3.2.1", + "name": "phpunit/phpcov", + "version": "8.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "url": "https://github.com/sebastianbergmann/phpcov.git", + "reference": "8ec45dde34a84914a0ace355fbd6d7af2242c9a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/phpcov/zipball/8ec45dde34a84914a0ace355fbd6d7af2242c9a4", + "reference": "8ec45dde34a84914a0ace355fbd6d7af2242c9a4", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2", + "phpunit/php-file-iterator": "^3.0", + "phpunit/phpunit": "^9.3", + "sebastian/cli-parser": "^1.0", + "sebastian/diff": "^4.0", + "sebastian/version": "^3.0" }, + "bin": [ + "phpcov" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "8.2-dev" } }, "autoload": { @@ -4444,11 +5366,11 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "CLI frontend for php-code-coverage", + "homepage": "https://github.com/sebastianbergmann/phpcov", "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "issues": "https://github.com/sebastianbergmann/phpcov/issues", + "source": "https://github.com/sebastianbergmann/phpcov/tree/8.2.1" }, "funding": [ { @@ -4456,32 +5378,68 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2022-03-24T12:07:05+00:00" }, { - "name": "sebastian/version", - "version": "3.0.2", + "name": "phpunit/phpunit", + "version": "9.6.23", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", "shasum": "" }, "require": { - "php": ">=7.3" + "doctrine/instantiator": "^1.5.0 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "9.6-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -4497,48 +5455,68 @@ "role": "lead" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23" }, "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, { "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/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2025-05-02T06:40:34+00:00" }, { - "name": "seld/jsonlint", - "version": "1.11.0", + "name": "psr/cache", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", - "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", "shasum": "" }, "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.11", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" + "php": ">=8.0.0" }, - "bin": [ - "bin/jsonlint" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" + "Psr\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4547,411 +5525,2035 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "JSON Linter", + "description": "Common interface for caching libraries", "keywords": [ - "json", - "linter", - "parser", - "validator" + "cache", + "psr", + "psr-6" ], "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" + "source": "https://github.com/php-fig/cache/tree/3.0.0" }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2024-07-11T14:55:45+00:00" + "time": "2021-02-03T23:26:27+00:00" }, { - "name": "shipmonk/coding-standard", - "version": "0.2.0", + "name": "psr/clock", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/coding-standard.git", - "reference": "eabe46b1cf541e24692fb6f4700b7b95da3676ec" + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/coding-standard/zipball/eabe46b1cf541e24692fb6f4700b7b95da3676ec", - "reference": "eabe46b1cf541e24692fb6f4700b7b95da3676ec", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "slevomat/coding-standard": "^8.25.0" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.6", - "ergebnis/composer-normalize": "^2.45", - "ext-simplexml": "*", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "shipmonk/composer-dependency-analyser": "^1.8", - "shipmonk/dead-code-detector": "^0.12", - "shipmonk/name-collision-detector": "^2.1", - "shipmonk/phpstan-rules": "^4.1" + "php": "^7.0 || ^8.0" }, - "type": "phpcodesniffer-standard", + "type": "library", "autoload": { "psr-4": { - "ShipMonk\\CodingStandard\\": "ShipMonkCodingStandard/" + "Psr\\Clock\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PHP Coding Standard used in ShipMonk", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], "support": { - "issues": "https://github.com/shipmonk-rnd/coding-standard/issues", - "source": "https://github.com/shipmonk-rnd/coding-standard/tree/0.2.0" + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" }, - "time": "2025-11-25T11:07:36+00:00" + "time": "2022-11-25T14:36:26+00:00" }, { - "name": "shipmonk/composer-dependency-analyser", - "version": "1.8.3", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", - "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/ca6b2725cd4854d97c1ce08e6954a74fbdd25372", - "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.6.0", - "ergebnis/composer-normalize": "^2.19.0", - "ext-dom": "*", - "ext-libxml": "*", - "phpcompatibility/php-compatibility": "^9.3.5", - "phpstan/phpstan": "^1.12.3", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", - "shipmonk/name-collision-detector": "^2.1.1", - "slevomat/coding-standard": "^8.15.0" + "php": ">=7.4.0" }, - "bin": [ - "bin/composer-dependency-analyser" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { - "ShipMonk\\ComposerDependencyAnalyser\\": "src/" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Fast detection of composer dependency issues (dead dependencies, shadow dependencies, misplaced dependencies)", - "keywords": [ - "analyser", - "composer", - "composer dependency", - "dead code", - "dead dependency", - "detector", - "dev", - "misplaced dependency", - "shadow dependency", - "static analysis", - "unused code", - "unused dependency" + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], "support": { - "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", - "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.3" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2025-02-10T13:31:57+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { - "name": "shipmonk/coverage-guard", - "version": "1.0.1", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/coverage-guard.git", - "reference": "def042e97c668d89560ee89507ea016bcd890d08" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/coverage-guard/zipball/def042e97c668d89560ee89507ea016bcd890d08", - "reference": "def042e97c668d89560ee89507ea016bcd890d08", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.19.1 || ^5.0", - "php": "^8.1" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "10.7.0", - "ergebnis/composer-normalize": "2.48.2", - "phpstan/phpstan": "2.1.32", - "phpstan/phpstan-phpunit": "2.0.8", - "phpstan/phpstan-strict-rules": "2.0.7", - "phpunit/php-code-coverage": "^10.1", - "phpunit/phpunit": "~10.5.58", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0", - "shipmonk/coding-standard": "^0.2.0", - "shipmonk/composer-dependency-analyser": "1.8.4", - "shipmonk/dead-code-detector": "0.14.0", - "shipmonk/name-collision-detector": "2.1.1", - "shipmonk/phpstan-rules": "4.3.0" + "php": ">=7.2.0" }, - "bin": [ - "bin/coverage-guard" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "ShipMonk\\CoverageGuard\\": "src/" + "Psr\\EventDispatcher\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Enforce code coverage in your CI. Not by percentage, but target core methods. No more untested Facades, Controllers, or Repositories. Allows you to start enforcing coverage for new code only!", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", "keywords": [ - "code coverage", - "git diff", - "patch", - "phpunit", - "testing" + "events", + "psr", + "psr-14" ], "support": { - "issues": "https://github.com/shipmonk-rnd/coverage-guard/issues", - "source": "https://github.com/shipmonk-rnd/coverage-guard/tree/1.0.1" + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" }, - "time": "2025-12-10T11:45:20+00:00" + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "shipmonk/name-collision-detector", - "version": "2.1.1", + "name": "psr/http-client", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/name-collision-detector.git", - "reference": "e8c8267a9a3774450b64f4cbf0bb035108e78f07" + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/name-collision-detector/zipball/e8c8267a9a3774450b64f4cbf0bb035108e78f07", - "reference": "e8c8267a9a3774450b64f4cbf0bb035108e78f07", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { - "ext-json": "*", - "ext-tokenizer": "*", - "nette/schema": "^1.1.0", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.3.0", - "ergebnis/composer-normalize": "^2.19", - "phpstan/phpstan": "^1.8.7", - "phpstan/phpstan-phpunit": "^1.1.1", - "phpstan/phpstan-strict-rules": "^1.2.3", - "phpunit/phpunit": "^8.5.28 || ^9.5.20", - "shipmonk/composer-dependency-analyser": "^1.0.0", - "slevomat/coding-standard": "^8.0.1" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" }, - "bin": [ - "bin/detect-collisions" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "ShipMonk\\NameCollision\\": "src/" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Simple tool to find ambiguous classes or any other name duplicates within your project.", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ - "ambiguous", - "autoload", - "autoloading", - "classname", - "collision", - "namespace" + "http", + "http-client", + "psr", + "psr-18" ], "support": { - "issues": "https://github.com/shipmonk-rnd/name-collision-detector/issues", - "source": "https://github.com/shipmonk-rnd/name-collision-detector/tree/2.1.1" + "source": "https://github.com/php-fig/http-client" }, - "time": "2024-03-01T13:26:32+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { - "name": "shipmonk/phpstan-dev", - "version": "0.1.4", + "name": "psr/http-factory", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/phpstan-dev.git", - "reference": "d839bcc544d0e8795195d5b0a915eb277cb83a47" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/phpstan-dev/zipball/d839bcc544d0e8795195d5b0a915eb277cb83a47", - "reference": "d839bcc544d0e8795195d5b0a915eb277cb83a47", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.8" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.45.0", - "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpstan/phpstan-phpunit": "^2.0.4", - "phpstan/phpstan-strict-rules": "^2.0.3", - "phpunit/phpunit": "^9.6.22", - "shipmonk/coding-standard": "^0.2.0", - "shipmonk/composer-dependency-analyser": "^1.8.1", - "shipmonk/dead-code-detector": "^0.9.0", - "shipmonk/name-collision-detector": "^2.1.1" - }, - "suggest": { - "phpunit/phpunit": "^9.6.22 for running tests that use RuleTestCase" + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "ShipMonk\\PHPStanDev\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Development utilities for PHPStan rules testing, extracted from shipmonk/phpstan-rules", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ - "PHPStan", - "static analysis", - "testing" + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" ], "support": { - "issues": "https://github.com/shipmonk-rnd/phpstan-dev/issues", - "source": "https://github.com/shipmonk-rnd/phpstan-dev/tree/0.1.4" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2025-12-09T14:01:36+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { - "name": "shipmonk/phpstan-rules", - "version": "4.1.5", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/shipmonk-rnd/phpstan-rules.git", - "reference": "9a2a033d12a516a73056bb215e6e4dec0dd33701" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/phpstan-rules/zipball/9a2a033d12a516a73056bb215e6e4dec0dd33701", - "reference": "9a2a033d12a516a73056bb215e6e4dec0dd33701", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.8" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.6.0", - "ergebnis/composer-normalize": "^2.45.0", - "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpstan/phpstan-phpunit": "^2.0.4", - "phpstan/phpstan-strict-rules": "^2.0.3", - "phpunit/phpunit": "^9.6.22", - "shipmonk/coding-standard": "^0.1.3", - "shipmonk/composer-dependency-analyser": "^1.8.1", - "shipmonk/dead-code-detector": "^0.9.0", - "shipmonk/name-collision-detector": "^2.1.1" + "php": "^7.2 || ^8.0" }, - "type": "phpstan-extension", + "type": "library", "extra": { - "phpstan": { - "includes": [ - "rules.neon" - ] + "branch-alias": { + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "ShipMonk\\PHPStan\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Various extra strict PHPStan rules we found useful in ShipMonk.", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "PHPStan", - "static analysis" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], "support": { - "issues": "https://github.com/shipmonk-rnd/phpstan-rules/issues", - "source": "https://github.com/shipmonk-rnd/phpstan-rules/tree/4.1.5" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2025-07-17T11:41:10+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { - "name": "slevomat/coding-standard", - "version": "8.25.0", + "name": "psr/log", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "3ce4dafb4fe2493715f397f21772988ef2122e20" + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/3ce4dafb4fe2493715f397f21772988ef2122e20", - "reference": "3ce4dafb4fe2493715f397f21772988ef2122e20", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.2.0", - "php": "^7.4 || ^8.0", - "phpstan/phpdoc-parser": "^2.3.0", - "squizlabs/php_codesniffer": "^4.0.1" - }, - "require-dev": { - "phing/phing": "3.0.1|3.1.0", - "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.32", - "phpstan/phpstan-deprecation-rules": "2.0.3", - "phpstan/phpstan-phpunit": "2.0.8", - "phpstan/phpstan-strict-rules": "2.0.7", - "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.4.4" + "php": ">=8.0.0" }, - "type": "phpcodesniffer-standard", + "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.9.2", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "8429c78ca35a09f27565311b98101e2826affde0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", + "reference": "8429c78ca35a09f27565311b98101e2826affde0", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.2" + }, + "time": "2025-12-14T04:43:48+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:33:00+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:35:11+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "seld/jsonlint", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "support": { + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2024-07-11T14:55:45+00:00" + }, + { + "name": "shipmonk/coding-standard", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/coding-standard.git", + "reference": "eabe46b1cf541e24692fb6f4700b7b95da3676ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/coding-standard/zipball/eabe46b1cf541e24692fb6f4700b7b95da3676ec", + "reference": "eabe46b1cf541e24692fb6f4700b7b95da3676ec", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "slevomat/coding-standard": "^8.25.0" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.6", + "ergebnis/composer-normalize": "^2.45", + "ext-simplexml": "*", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "shipmonk/composer-dependency-analyser": "^1.8", + "shipmonk/dead-code-detector": "^0.12", + "shipmonk/name-collision-detector": "^2.1", + "shipmonk/phpstan-rules": "^4.1" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "ShipMonk\\CodingStandard\\": "ShipMonkCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP Coding Standard used in ShipMonk", + "support": { + "issues": "https://github.com/shipmonk-rnd/coding-standard/issues", + "source": "https://github.com/shipmonk-rnd/coding-standard/tree/0.2.0" + }, + "time": "2025-11-25T11:07:36+00:00" + }, + { + "name": "shipmonk/composer-dependency-analyser", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", + "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/ca6b2725cd4854d97c1ce08e6954a74fbdd25372", + "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.6.0", + "ergebnis/composer-normalize": "^2.19.0", + "ext-dom": "*", + "ext-libxml": "*", + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.3", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" + }, + "bin": [ + "bin/composer-dependency-analyser" + ], + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\ComposerDependencyAnalyser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Fast detection of composer dependency issues (dead dependencies, shadow dependencies, misplaced dependencies)", + "keywords": [ + "analyser", + "composer", + "composer dependency", + "dead code", + "dead dependency", + "detector", + "dev", + "misplaced dependency", + "shadow dependency", + "static analysis", + "unused code", + "unused dependency" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", + "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.3" + }, + "time": "2025-02-10T13:31:57+00:00" + }, + { + "name": "shipmonk/coverage-guard", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/coverage-guard.git", + "reference": "def042e97c668d89560ee89507ea016bcd890d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/coverage-guard/zipball/def042e97c668d89560ee89507ea016bcd890d08", + "reference": "def042e97c668d89560ee89507ea016bcd890d08", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.19.1 || ^5.0", + "php": "^8.1" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "10.7.0", + "ergebnis/composer-normalize": "2.48.2", + "phpstan/phpstan": "2.1.32", + "phpstan/phpstan-phpunit": "2.0.8", + "phpstan/phpstan-strict-rules": "2.0.7", + "phpunit/php-code-coverage": "^10.1", + "phpunit/phpunit": "~10.5.58", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "shipmonk/coding-standard": "^0.2.0", + "shipmonk/composer-dependency-analyser": "1.8.4", + "shipmonk/dead-code-detector": "0.14.0", + "shipmonk/name-collision-detector": "2.1.1", + "shipmonk/phpstan-rules": "4.3.0" + }, + "bin": [ + "bin/coverage-guard" + ], + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\CoverageGuard\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Enforce code coverage in your CI. Not by percentage, but target core methods. No more untested Facades, Controllers, or Repositories. Allows you to start enforcing coverage for new code only!", + "keywords": [ + "code coverage", + "git diff", + "patch", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/coverage-guard/issues", + "source": "https://github.com/shipmonk-rnd/coverage-guard/tree/1.0.1" + }, + "time": "2025-12-10T11:45:20+00:00" + }, + { + "name": "shipmonk/name-collision-detector", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/name-collision-detector.git", + "reference": "e8c8267a9a3774450b64f4cbf0bb035108e78f07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/name-collision-detector/zipball/e8c8267a9a3774450b64f4cbf0bb035108e78f07", + "reference": "e8c8267a9a3774450b64f4cbf0bb035108e78f07", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nette/schema": "^1.1.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.3.0", + "ergebnis/composer-normalize": "^2.19", + "phpstan/phpstan": "^1.8.7", + "phpstan/phpstan-phpunit": "^1.1.1", + "phpstan/phpstan-strict-rules": "^1.2.3", + "phpunit/phpunit": "^8.5.28 || ^9.5.20", + "shipmonk/composer-dependency-analyser": "^1.0.0", + "slevomat/coding-standard": "^8.0.1" + }, + "bin": [ + "bin/detect-collisions" + ], + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\NameCollision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Simple tool to find ambiguous classes or any other name duplicates within your project.", + "keywords": [ + "ambiguous", + "autoload", + "autoloading", + "classname", + "collision", + "namespace" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/name-collision-detector/issues", + "source": "https://github.com/shipmonk-rnd/name-collision-detector/tree/2.1.1" + }, + "time": "2024-03-01T13:26:32+00:00" + }, + { + "name": "shipmonk/phpstan-dev", + "version": "0.1.4", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/phpstan-dev.git", + "reference": "d839bcc544d0e8795195d5b0a915eb277cb83a47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/phpstan-dev/zipball/d839bcc544d0e8795195d5b0a915eb277cb83a47", + "reference": "d839bcc544d0e8795195d5b0a915eb277cb83a47", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.8" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.45.0", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.4", + "phpstan/phpstan-strict-rules": "^2.0.3", + "phpunit/phpunit": "^9.6.22", + "shipmonk/coding-standard": "^0.2.0", + "shipmonk/composer-dependency-analyser": "^1.8.1", + "shipmonk/dead-code-detector": "^0.9.0", + "shipmonk/name-collision-detector": "^2.1.1" + }, + "suggest": { + "phpunit/phpunit": "^9.6.22 for running tests that use RuleTestCase" + }, + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\PHPStanDev\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Development utilities for PHPStan rules testing, extracted from shipmonk/phpstan-rules", + "keywords": [ + "PHPStan", + "static analysis", + "testing" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/phpstan-dev/issues", + "source": "https://github.com/shipmonk-rnd/phpstan-dev/tree/0.1.4" + }, + "time": "2025-12-09T14:01:36+00:00" + }, + { + "name": "shipmonk/phpstan-rules", + "version": "4.1.5", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/phpstan-rules.git", + "reference": "9a2a033d12a516a73056bb215e6e4dec0dd33701" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/phpstan-rules/zipball/9a2a033d12a516a73056bb215e6e4dec0dd33701", + "reference": "9a2a033d12a516a73056bb215e6e4dec0dd33701", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.8" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.6.0", + "ergebnis/composer-normalize": "^2.45.0", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.4", + "phpstan/phpstan-strict-rules": "^2.0.3", + "phpunit/phpunit": "^9.6.22", + "shipmonk/coding-standard": "^0.1.3", + "shipmonk/composer-dependency-analyser": "^1.8.1", + "shipmonk/dead-code-detector": "^0.9.0", + "shipmonk/name-collision-detector": "^2.1.1" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "ShipMonk\\PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Various extra strict PHPStan rules we found useful in ShipMonk.", + "keywords": [ + "PHPStan", + "static analysis" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/phpstan-rules/issues", + "source": "https://github.com/shipmonk-rnd/phpstan-rules/tree/4.1.5" + }, + "time": "2025-07-17T11:41:10+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "8.25.0", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "3ce4dafb4fe2493715f397f21772988ef2122e20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/3ce4dafb4fe2493715f397f21772988ef2122e20", + "reference": "3ce4dafb4fe2493715f397f21772988ef2122e20", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.2.0", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.3.0", + "squizlabs/php_codesniffer": "^4.0.1" + }, + "require-dev": { + "phing/phing": "3.0.1|3.1.0", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.32", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpstan/phpstan-phpunit": "2.0.8", + "phpstan/phpstan-strict-rules": "2.0.7", + "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.4.4" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" } }, "autoload": { @@ -4963,163 +7565,931 @@ "license": [ "MIT" ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "keywords": [ - "dev", - "phpcs" + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.25.0" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2025-11-22T10:33:53+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "0525c73950de35ded110cffafb9892946d7771b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5", + "reference": "0525c73950de35ded110cffafb9892946d7771b5", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=7.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-10T16:43:36+00:00" + }, + { + "name": "symfony/cache", + "version": "v7.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "a7a1325a5de2e54ddb45fda002ff528162e48293" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/a7a1325a5de2e54ddb45fda002ff528162e48293", + "reference": "a7a1325a5de2e54ddb45fda002ff528162e48293", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^3.6", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0|^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "ext-redis": "<6.1", + "ext-relay": "<0.12.1", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v7.4.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-11-16T10:14:42+00:00" + }, + { + "name": "symfony/clock", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v8.0.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-11-12T15:46:48+00:00" + }, + { + "name": "symfony/config", + "version": "v7.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "f76c74e93bce2b9285f2dad7fbd06fa8182a7a41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/f76c74e93bce2b9285f2dad7fbd06fa8182a7a41", + "reference": "f76c74e93bce2b9285f2dad7fbd06fa8182a7a41", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^7.1|^8.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "require-dev": { + "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|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "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.4.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-11-27T13:27:24+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T10:34:04+00:00" + }, + { + "name": "symfony/contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "6e489617c52619f6a4f92986dfd19eb52d83de1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/6e489617c52619f6a4f92986dfd19eb52d83de1f", + "reference": "6e489617c52619f6a4f92986dfd19eb52d83de1f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0", + "psr/container": "^1.1|^2.0", + "psr/event-dispatcher": "^1.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "replace": { + "symfony/cache-contracts": "self.version", + "symfony/deprecation-contracts": "self.version", + "symfony/event-dispatcher-contracts": "self.version", + "symfony/http-client-contracts": "self.version", + "symfony/service-contracts": "self.version", + "symfony/translation-contracts": "self.version" + }, + "require-dev": { + "symfony/polyfill-intl-idn": "^1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "Deprecation/function.php" + ], + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "dev", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-01T12:12:53+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v8.0.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "2a178bf80f05dbbe469a337730eba79d61315262" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/2a178bf80f05dbbe469a337730eba79d61315262", + "reference": "2a178bf80f05dbbe469a337730eba79d61315262", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v8.0.6" + }, + "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": "2026-02-17T13:07:04+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "f64a8f3fa7d4ad5e85de1b128a0e03faed02b732" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f64a8f3fa7d4ad5e85de1b128a0e03faed02b732", + "reference": "f64a8f3fa7d4ad5e85de1b128a0e03faed02b732", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^3.5", + "symfony/var-exporter": "^6.4.20|^7.2.5" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<6.4", + "symfony/finder": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "symfony/config": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.25.0" + "source": "https://github.com/symfony/dependency-injection/tree/v7.3.0" }, "funding": [ { - "url": "https://github.com/kukulich", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-11-22T10:33:53+00:00" + "time": "2025-05-19T13:28:56+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "4.0.1", + "name": "symfony/doctrine-bridge", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "0525c73950de35ded110cffafb9892946d7771b5" + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "1df0cb5ce77ddfa0bdbca410009e3822567a6a19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5", - "reference": "0525c73950de35ded110cffafb9892946d7771b5", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/1df0cb5ce77ddfa0bdbca410009e3822567a6a19", + "reference": "1df0cb5ce77ddfa0bdbca410009e3822567a6a19", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=7.2.0" + "doctrine/event-manager": "^2", + "doctrine/persistence": "^3.1|^4", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/collections": "<1.8", + "doctrine/dbal": "<3.6", + "doctrine/lexer": "<1.1", + "doctrine/orm": "<2.15", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/form": "<6.4.6|>=7,<7.0.6", + "symfony/http-foundation": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/lock": "<6.4", + "symfony/messenger": "<6.4", + "symfony/property-info": "<6.4", + "symfony/security-bundle": "<6.4", + "symfony/security-core": "<6.4", + "symfony/validator": "<6.4" }, "require-dev": { - "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" + "doctrine/collections": "^1.8|^2.0", + "doctrine/data-fixtures": "^1.1|^2", + "doctrine/dbal": "^3.6|^4", + "doctrine/orm": "^2.15|^3", + "psr/log": "^1|^2|^3", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/doctrine-messenger": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4.6|^7.0.6", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/type-info": "^7.1", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, - "bin": [ - "bin/phpcbf", - "bin/phpcs" - ], - "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Greg Sherwood", - "role": "Former lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Juliette Reinders Folmer", - "role": "Current lead" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Doctrine with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" + "time": "2025-05-25T10:32:38+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.0" }, "funding": [ { - "url": "https://github.com/PHPCSStandards", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://github.com/jrfnl", + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2025-11-10T16:43:36+00:00" + "time": "2025-05-29T07:19:49+00:00" }, { - "name": "symfony/cache", - "version": "v7.4.0", + "name": "symfony/event-dispatcher", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "a7a1325a5de2e54ddb45fda002ff528162e48293" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a7a1325a5de2e54ddb45fda002ff528162e48293", - "reference": "a7a1325a5de2e54ddb45fda002ff528162e48293", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { "php": ">=8.2", - "psr/cache": "^2.0|^3.0", - "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^3.6", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "doctrine/dbal": "<3.6", - "ext-redis": "<6.1", - "ext-relay": "<0.12.1", "symfony/dependency-injection": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/var-dumper": "<6.4" + "symfony/service-contracts": "<2.5" }, "provide": { - "psr/cache-implementation": "2.0|3.0", - "psr/simple-cache-implementation": "1.0|2.0|3.0", - "symfony/cache-implementation": "1.1|2.0|3.0" + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/filesystem": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "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/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Cache\\": "" + "Symfony\\Component\\EventDispatcher\\": "" }, - "classmap": [ - "Traits/ValueWrapper.php" - ], "exclude-from-classmap": [ "/Tests/" ] @@ -5130,22 +8500,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" }, "funding": [ { @@ -5156,52 +8522,39 @@ "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-11-16T10:14:42+00:00" + "time": "2025-04-22T09:11:45+00:00" }, { - "name": "symfony/config", - "version": "v7.4.0", + "name": "symfony/filesystem", + "version": "v7.3.2", "source": { "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "f76c74e93bce2b9285f2dad7fbd06fa8182a7a41" + "url": "https://github.com/symfony/filesystem.git", + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/f76c74e93bce2b9285f2dad7fbd06fa8182a7a41", - "reference": "f76c74e93bce2b9285f2dad7fbd06fa8182a7a41", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1|^8.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<6.4", - "symfony/service-contracts": "<2.5" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "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|^8.0" + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Config\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5221,10 +8574,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.4.0" + "source": "https://github.com/symfony/filesystem/tree/v7.3.2" }, "funding": [ { @@ -5244,56 +8597,32 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2025-07-07T08:17:47+00:00" }, { - "name": "symfony/console", - "version": "v7.3.0", + "name": "symfony/finder", + "version": "v7.3.5", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + "url": "https://github.com/symfony/finder.git", + "reference": "9f696d2f1e340484b4683f7853b273abff94421f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", + "reference": "9f696d2f1e340484b4683f7853b273abff94421f", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "php": ">=8.2" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5313,16 +8642,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", + "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.0" + "source": "https://github.com/symfony/finder/tree/v7.3.5" }, "funding": [ { @@ -5333,62 +8656,134 @@ "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-05-24T10:34:04+00:00" + "time": "2025-10-15T18:45:57+00:00" }, { - "name": "symfony/contracts", - "version": "v3.6.0", + "name": "symfony/framework-bundle", + "version": "v7.3.6", "source": { "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "6e489617c52619f6a4f92986dfd19eb52d83de1f" + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/6e489617c52619f6a4f92986dfd19eb52d83de1f", - "reference": "6e489617c52619f6a4f92986dfd19eb52d83de1f", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/cabfdfa82bc4f75d693a329fe263d96937636b77", + "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/cache": "^3.0", - "psr/container": "^1.1|^2.0", - "psr/event-dispatcher": "^1.0" + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.2", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^7.3", + "symfony/dependency-injection": "^7.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^7.3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/filesystem": "^7.1", + "symfony/finder": "^6.4|^7.0", + "symfony/http-foundation": "^7.3", + "symfony/http-kernel": "^7.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^6.4|^7.0" }, "conflict": { - "ext-psr": "<1.1|>=2" - }, - "replace": { - "symfony/cache-contracts": "self.version", - "symfony/deprecation-contracts": "self.version", - "symfony/event-dispatcher-contracts": "self.version", - "symfony/http-client-contracts": "self.version", - "symfony/service-contracts": "self.version", - "symfony/translation-contracts": "self.version" + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/asset": "<6.4", + "symfony/asset-mapper": "<6.4", + "symfony/clock": "<6.4", + "symfony/console": "<6.4", + "symfony/dom-crawler": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/json-streamer": ">=7.4", + "symfony/lock": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/object-mapper": ">=7.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", + "symfony/security-core": "<6.4", + "symfony/security-csrf": "<7.2", + "symfony/serializer": "<7.2.5", + "symfony/stopwatch": "<6.4", + "symfony/translation": "<7.3", + "symfony/twig-bridge": "<6.4", + "symfony/twig-bundle": "<6.4", + "symfony/validator": "<6.4", + "symfony/web-profiler-bundle": "<6.4", + "symfony/webhook": "<7.2", + "symfony/workflow": "<7.3.0-beta2" }, "require-dev": { - "symfony/polyfill-intl-idn": "^1.10" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.6-dev" - } + "doctrine/persistence": "^1.3|^2|^3", + "dragonmantank/cron-expression": "^3.1", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "seld/jsonlint": "^1.10", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/dotenv": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/json-streamer": "7.3.*", + "symfony/lock": "^6.4|^7.0", + "symfony/mailer": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/notifier": "^6.4|^7.0", + "symfony/object-mapper": "^v7.3.0-beta2", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", + "symfony/security-bundle": "^6.4|^7.0", + "symfony/semaphore": "^6.4|^7.0", + "symfony/serializer": "^7.2.5", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^7.3", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/type-info": "^7.1.8", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/webhook": "^7.2", + "symfony/workflow": "^7.3", + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.12" }, + "type": "symfony-bundle", "autoload": { - "files": [ - "Deprecation/function.php" - ], "psr-4": { - "Symfony\\Contracts\\": "" + "Symfony\\Bundle\\FrameworkBundle\\": "" }, "exclude-from-classmap": [ - "**/Tests/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5397,27 +8792,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "A set of abstractions extracted out of the Symfony components", + "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "dev", - "interfaces", - "interoperability", - "standards" - ], "support": { - "source": "https://github.com/symfony/contracts/tree/v3.6.0" + "source": "https://github.com/symfony/framework-bundle/tree/v7.3.6" }, "funding": [ { @@ -5428,53 +8814,56 @@ "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-05-01T12:12:53+00:00" + "time": "2025-10-30T09:42:24+00:00" }, { - "name": "symfony/dependency-injection", + "name": "symfony/http-foundation", "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f64a8f3fa7d4ad5e85de1b128a0e03faed02b732" + "url": "https://github.com/symfony/http-foundation.git", + "reference": "4236baf01609667d53b20371486228231eb135fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f64a8f3fa7d4ad5e85de1b128a0e03faed02b732", - "reference": "f64a8f3fa7d4ad5e85de1b128a0e03faed02b732", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", + "reference": "4236baf01609667d53b20371486228231eb135fd", "shasum": "" }, "require": { "php": ">=8.2", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^3.5", - "symfony/var-exporter": "^6.4.20|^7.2.5" + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" }, "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.4", - "symfony/finder": "<6.4", - "symfony/yaml": "<6.4" - }, - "provide": { - "psr/container-implementation": "1.1|2.0", - "symfony/service-implementation": "1.1|2.0|3.0" + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { - "symfony/config": "^6.4|^7.0", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" + "Symfony\\Component\\HttpFoundation\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5494,10 +8883,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.3.0" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" }, "funding": [ { @@ -5513,77 +8902,82 @@ "type": "tidelift" } ], - "time": "2025-05-19T13:28:56+00:00" + "time": "2025-05-12T14:48:23+00:00" }, { - "name": "symfony/doctrine-bridge", + "name": "symfony/http-kernel", "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "1df0cb5ce77ddfa0bdbca410009e3822567a6a19" + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/1df0cb5ce77ddfa0bdbca410009e3822567a6a19", - "reference": "1df0cb5ce77ddfa0bdbca410009e3822567a6a19", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", "shasum": "" }, "require": { - "doctrine/event-manager": "^2", - "doctrine/persistence": "^3.1|^4", "php": ">=8.2", + "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3" + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "doctrine/collections": "<1.8", - "doctrine/dbal": "<3.6", - "doctrine/lexer": "<1.1", - "doctrine/orm": "<2.15", + "symfony/browser-kit": "<6.4", "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", - "symfony/form": "<6.4.6|>=7,<7.0.6", - "symfony/http-foundation": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/lock": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", "symfony/messenger": "<6.4", - "symfony/property-info": "<6.4", - "symfony/security-bundle": "<6.4", - "symfony/security-core": "<6.4", - "symfony/validator": "<6.4" + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "doctrine/collections": "^1.8|^2.0", - "doctrine/data-fixtures": "^1.1|^2", - "doctrine/dbal": "^3.6|^4", - "doctrine/orm": "^2.15|^3", - "psr/log": "^1|^2|^3", - "symfony/cache": "^6.4|^7.0", + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", - "symfony/doctrine-messenger": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4.6|^7.0.6", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", "symfony/stopwatch": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", - "symfony/type-info": "^7.1", + "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" }, - "type": "symfony-bridge", + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bridge\\Doctrine\\": "" + "Symfony\\Component\\HttpKernel\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5603,10 +8997,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides integration for Doctrine with various Symfony components", + "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" }, "funding": [ { @@ -5622,45 +9016,48 @@ "type": "tidelift" } ], - "time": "2025-05-25T10:32:38+00:00" + "time": "2025-05-29T07:47:32+00:00" }, { - "name": "symfony/error-handler", - "version": "v7.3.0", + "name": "symfony/mailer", + "version": "v7.4.6", "source": { "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" + "url": "https://github.com/symfony/mailer.git", + "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", - "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b02726f39a20bc65e30364f5c750c4ddbf1f58e9", + "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9", "shasum": "" }, "require": { + "egulias/email-validator": "^2.1.10|^3|^4", "php": ">=8.2", + "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.2|^8.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/webpack-encore-bundle": "^1.0|^2.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" }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" + "Symfony\\Component\\Mailer\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5680,10 +9077,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides tools to manage errors and ease debugging PHP code", + "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.3.0" + "source": "https://github.com/symfony/mailer/tree/v7.4.6" }, "funding": [ { @@ -5694,53 +9091,58 @@ "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-05-29T07:19:49+00:00" + "time": "2026-02-25T16:50:00+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v7.3.0", + "name": "symfony/mime", + "version": "v7.4.6", "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "url": "https://api.github.com/repos/symfony/mime/zipball/9fc881d95feae4c6c48678cb6372bd8a7ba04f5f", + "reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/event-dispatcher-contracts": "^2.5|^3" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" + "egulias/email-validator": "~3.0.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": { - "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/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "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": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" + "Symfony\\Component\\Mime\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5760,10 +9162,14 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "description": "Allows manipulating MIME messages", "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + "source": "https://github.com/symfony/mime/tree/v7.4.6" }, "funding": [ { @@ -5774,39 +9180,39 @@ "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-02-05T15:57:06+00:00" }, { - "name": "symfony/filesystem", - "version": "v7.3.2", + "name": "symfony/options-resolver", + "version": "v7.3.3", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + "url": "https://github.com/symfony/options-resolver.git", + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0" + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\OptionsResolver\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5826,10 +9232,15 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides basic utilities for the filesystem", + "description": "Provides an improved replacement for the array_replace PHP function", "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" }, "funding": [ { @@ -5849,36 +9260,45 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:47+00:00" + "time": "2025-08-05T10:16:07+00:00" }, { - "name": "symfony/finder", - "version": "v7.3.5", + "name": "symfony/polyfill-ctype", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=7.2" }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5886,18 +9306,24 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Finds files and directories via an intuitive fluent interface", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.5" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -5908,135 +9334,126 @@ "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-10-15T18:45:57+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/framework-bundle", - "version": "v7.3.6", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/cabfdfa82bc4f75d693a329fe263d96937636b77", - "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.2", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^7.3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/filesystem": "^7.1", - "symfony/finder": "^6.4|^7.0", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^6.4|^7.0" + "php": ">=7.2" }, - "conflict": { - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<6.4", - "symfony/asset-mapper": "<6.4", - "symfony/clock": "<6.4", - "symfony/console": "<6.4", - "symfony/dom-crawler": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/json-streamer": ">=7.4", - "symfony/lock": "<6.4", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/mime": "<6.4", - "symfony/object-mapper": ">=7.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", - "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/security-core": "<6.4", - "symfony/security-csrf": "<7.2", - "symfony/serializer": "<7.2.5", - "symfony/stopwatch": "<6.4", - "symfony/translation": "<7.3", - "symfony/twig-bridge": "<6.4", - "symfony/twig-bundle": "<6.4", - "symfony/validator": "<6.4", - "symfony/web-profiler-bundle": "<6.4", - "symfony/webhook": "<7.2", - "symfony/workflow": "<7.3.0-beta2" + "suggest": { + "ext-intl": "For best performance" }, - "require-dev": { - "doctrine/persistence": "^1.3|^2|^3", - "dragonmantank/cron-expression": "^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "seld/jsonlint": "^1.10", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/dotenv": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/json-streamer": "7.3.*", - "symfony/lock": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/notifier": "^6.4|^7.0", - "symfony/object-mapper": "^v7.3.0-beta2", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4.4|^7.0.4", - "symfony/security-bundle": "^6.4|^7.0", - "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^7.2.5", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^7.3", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/webhook": "^7.2", - "symfony/workflow": "^7.3", - "symfony/yaml": "^6.4|^7.0", - "twig/twig": "^3.12" + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } }, - "type": "symfony-bundle", "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6044,18 +9461,30 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.3.6" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -6075,50 +9504,44 @@ "type": "tidelift" } ], - "time": "2025-10-30T09:42:24+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { - "name": "symfony/http-foundation", - "version": "v7.3.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "4236baf01609667d53b20371486228231eb135fd" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", - "reference": "4236baf01609667d53b20371486228231eb135fd", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" - }, - "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + "php": ">=7.2" }, - "require-dev": { - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/clock": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "suggest": { + "ext-intl": "For best performance" }, "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -6127,18 +9550,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Defines an object-oriented layer for the HTTP specification", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -6154,86 +9585,46 @@ "type": "tidelift" } ], - "time": "2025-05-12T14:48:23+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/http-kernel", - "version": "v7.3.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", - "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "ext-mbstring": "*" }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.12" + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6241,18 +9632,25 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a structured process for converting a Request into a Response", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -6268,33 +9666,41 @@ "type": "tidelift" } ], - "time": "2025-05-29T07:47:32+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/options-resolver", - "version": "v7.3.3", + "name": "symfony/polyfill-php80", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=7.2" }, "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -6303,23 +9709,28 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an improved replacement for the array_replace PHP function", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ - "config", - "configuration", - "options" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -6339,31 +9750,25 @@ "type": "tidelift" } ], - "time": "2025-08-05T10:16:07+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/polyfill-ctype", + "name": "symfony/polyfill-php83", "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { "php": ">=7.2" }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, "type": "library", "extra": { "thanks": { @@ -6376,8 +9781,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6385,24 +9793,24 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "ctype", "polyfill", - "portable" + "portable", + "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -6421,25 +9829,22 @@ "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", + "name": "symfony/polyfill-php84", "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "000df7860439609837bbe28670b0be15783b7fbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/000df7860439609837bbe28670b0be15783b7fbf", + "reference": "000df7860439609837bbe28670b0be15783b7fbf", "shasum": "" }, "require": { "php": ">=7.2" }, - "suggest": { - "ext-intl": "For best performance" - }, "type": "library", "extra": { "thanks": { @@ -6452,8 +9857,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6469,18 +9877,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's grapheme_* functions", + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "grapheme", - "intl", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.32.0" }, "funding": [ { @@ -6496,28 +9902,25 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-02-20T12:04:08+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "name": "symfony/polyfill-php85", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", "shasum": "" }, "require": { "php": ">=7.2" }, - "suggest": { - "ext-intl": "For best performance" - }, "type": "library", "extra": { "thanks": { @@ -6530,7 +9933,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + "Symfony\\Polyfill\\Php85\\": "" }, "classmap": [ "Resources/stubs" @@ -6550,18 +9953,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "intl", - "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" }, "funding": [ { @@ -6572,36 +9973,39 @@ "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-09T11:45:10+00:00" + "time": "2025-06-23T16:12:55+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "name": "symfony/polyfill-uuid", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "ext-iconv": "*", "php": ">=7.2" }, "provide": { - "ext-mbstring": "*" + "ext-uuid": "*" }, "suggest": { - "ext-mbstring": "For best performance" + "ext-uuid": "For best performance" }, "type": "library", "extra": { @@ -6615,7 +10019,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Polyfill\\Uuid\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -6624,25 +10028,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for uuid functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", - "shim" + "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" }, "funding": [ { @@ -6653,46 +10056,41 @@ "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-12-23T08:48:59+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php83", - "version": "v1.32.0", + "name": "symfony/process", + "version": "v7.3.4", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "url": "https://github.com/symfony/process.git", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.2" }, "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" + "Symfony\\Component\\Process\\": "" }, - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -6701,24 +10099,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + "source": "https://github.com/symfony/process/tree/v7.3.4" }, "funding": [ { @@ -6729,46 +10121,55 @@ "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-09T11:45:10+00:00" + "time": "2025-09-11T10:12:26+00:00" }, { - "name": "symfony/polyfill-php84", - "version": "v1.32.0", + "name": "symfony/routing", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "000df7860439609837bbe28670b0be15783b7fbf" + "url": "https://github.com/symfony/routing.git", + "reference": "8e213820c5fea844ecea29203d2a308019007c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/000df7860439609837bbe28670b0be15783b7fbf", - "reference": "000df7860439609837bbe28670b0be15783b7fbf", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, + "type": "library", "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Php84\\": "" + "Symfony\\Component\\Routing\\": "" }, - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -6777,24 +10178,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "description": "Maps an HTTP request to a set of configuration variables", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "router", + "routing", + "uri", + "url" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.32.0" + "source": "https://github.com/symfony/routing/tree/v7.3.0" }, "funding": [ { @@ -6810,29 +10211,47 @@ "type": "tidelift" } ], - "time": "2025-02-20T12:04:08+00:00" + "time": "2025-05-24T20:43:28+00:00" }, { - "name": "symfony/process", - "version": "v7.3.4", + "name": "symfony/string", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + "url": "https://github.com/symfony/string.git", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, - "require": { - "php": ">=8.2" + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -6844,18 +10263,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Executes commands in sub-processes", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], "support": { - "source": "https://github.com/symfony/process/tree/v7.3.4" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -6866,52 +10293,69 @@ "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-09-11T10:12:26+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { - "name": "symfony/routing", - "version": "v7.3.0", + "name": "symfony/translation", + "version": "v7.4.6", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "8e213820c5fea844ecea29203d2a308019007c15" + "url": "https://github.com/symfony/translation.git", + "reference": "1888cf064399868af3784b9e043240f1d89d25ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", - "reference": "8e213820c5fea844ecea29203d2a308019007c15", + "url": "https://api.github.com/repos/symfony/translation/zipball/1888cf064399868af3784b9e043240f1d89d25ce", + "reference": "1888cf064399868af3784b9e043240f1d89d25ce", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5.3|^3.3" }, "conflict": { + "nikic/php-parser": "<5.0", "symfony/config": "<6.4", + "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", "symfony/yaml": "<6.4" }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, "require-dev": { + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/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|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Routing\\": "" + "Symfony\\Component\\Translation\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -6931,16 +10375,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Maps an HTTP request to a set of configuration variables", + "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.0" + "source": "https://github.com/symfony/translation/tree/v7.4.6" }, "funding": [ { @@ -6951,52 +10389,42 @@ "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-05-24T20:43:28+00:00" + "time": "2026-02-17T07:53:42+00:00" }, { - "name": "symfony/string", - "version": "v7.3.0", + "name": "symfony/uid", + "version": "v7.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + "url": "https://github.com/symfony/uid.git", + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/polyfill-uuid": "^1.15" }, "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/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], "psr-4": { - "Symfony\\Component\\String\\": "" + "Symfony\\Component\\Uid\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -7007,6 +10435,10 @@ "MIT" ], "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -7016,18 +10448,15 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "description": "Provides an object-oriented API to generate and represent UIDs", "homepage": "https://symfony.com", "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" + "UID", + "ulid", + "uuid" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.0" + "source": "https://github.com/symfony/uid/tree/v7.4.4" }, "funding": [ { @@ -7038,12 +10467,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-20T20:19:01+00:00" + "time": "2026-01-03T23:30:35+00:00" }, { "name": "symfony/validator", @@ -7354,6 +10787,61 @@ ], "time": "2024-03-03T12:36:25+00:00" }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41", + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0" + }, + "time": "2025-12-02T11:56:42+00:00" + }, { "name": "twig/twig", "version": "v3.21.1", @@ -7433,6 +10921,164 @@ ], "time": "2025-05-03T07:21:55+00:00" }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.3", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "955e7815d677a3eaa7075231212f2110983adecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.4", + "php": "^7.2.5 || ^8.0", + "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", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:49:13+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, { "name": "webmozart/glob", "version": "4.7.0", diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 4ac7613..03110e8 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -1,218 +1,5 @@ $attributes */ - public function __construct(array $attributes = []) {} - - /** @param class-string|list $classes */ - public static function observe(string|array $classes): void {} -} - -namespace Illuminate\Database\Eloquent\Relations; - -abstract class Relation -{ -} - -class HasMany extends Relation -{ -} - -class BelongsTo extends Relation -{ -} - -class BelongsToMany extends Relation -{ -} - -namespace Illuminate\Database\Eloquent\Casts; - -class Attribute -{ -} - -namespace Illuminate\Database\Eloquent\Factories; - -abstract class Factory -{ -} - -namespace Illuminate\Console; - -class Command -{ -} - -namespace Illuminate\Contracts\Queue; - -interface ShouldQueue -{ -} - -namespace Illuminate\Foundation\Bus; - -trait Dispatchable -{ -} - -namespace Illuminate\Support; - -abstract class ServiceProvider -{ - public function __construct($app) {} -} - -namespace Illuminate\Http; - -class Request -{ -} - -namespace Illuminate\Notifications; - -class Notification -{ -} - -trait RoutesNotifications -{ -} - -trait Notifiable -{ - use RoutesNotifications; -} - -namespace Illuminate\Foundation\Http; - -class FormRequest -{ -} - -namespace Illuminate\Database; - -class Seeder -{ -} - -namespace Illuminate\Database\Migrations; - -abstract class Migration -{ -} - -namespace Illuminate\Database\Eloquent\Attributes; - -use Attribute; - -#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] -class ObservedBy -{ - /** @param class-string|list $classes */ - public function __construct(string|array $classes) {} -} - -namespace Illuminate\Mail; - -class Mailable -{ -} - -namespace Illuminate\Contracts\Broadcasting; - -interface ShouldBroadcast -{ -} - -namespace Illuminate\Http\Resources\Json; - -class JsonResource -{ -} - -namespace Illuminate\Contracts\Validation; - -interface ValidationRule -{ -} - -interface Rule -{ -} - -namespace Illuminate\Foundation\Auth\Access; - -trait AuthorizesRequests -{ - /** @param mixed ...$arguments */ - public function authorize(string $ability, ...$arguments): void {} -} - -namespace Illuminate\Support\Facades; - -class Route -{ - /** @param mixed $action */ - public static function get(string $uri, $action): void {} - /** @param mixed $action */ - public static function post(string $uri, $action): void {} - /** @param mixed $action */ - public static function put(string $uri, $action): void {} - /** @param mixed $action */ - public static function patch(string $uri, $action): void {} - /** @param mixed $action */ - public static function delete(string $uri, $action): void {} - /** @param mixed $action */ - public static function any(string $uri, $action): void {} - /** - * @param list $methods - * @param mixed $action - */ - public static function match(array $methods, string $uri, $action): void {} - public static function resource(string $name, string $controller): void {} - public static function apiResource(string $name, string $controller): void {} -} - -class Event -{ - /** @param mixed $event */ - public static function listen($event, string $listener): void {} - public static function subscribe(string $subscriber): void {} -} - -class Schedule -{ - public static function job(string $job): void {} -} - -class Gate -{ - /** @param mixed $callback */ - public static function define(string $ability, $callback): void {} - public static function policy(string $model, string $policy): void {} -} - -// ===================== -// Test Classes -// ===================== - namespace Laravel; use Illuminate\Console\Command; @@ -241,6 +28,7 @@ public static function policy(string $model, string $policy): void {} use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Schedule; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\ServiceProvider; // --- Controllers (AST-based via Route:: calls) --- @@ -393,17 +181,17 @@ public function scopeActive(object $query): object public function posts(): HasMany { - return new HasMany(); + throw new \RuntimeException('stub'); } public function company(): BelongsTo { - return new BelongsTo(); + throw new \RuntimeException('stub'); } public function roles(): BelongsToMany { - return new BelongsToMany(); + throw new \RuntimeException('stub'); } protected function firstName(): Attribute @@ -853,10 +641,9 @@ public function with(object $request): array return []; } - /** @return array */ - public function additional(object $request): array + public function additional(array $data): static { - return []; + return $this; } /** @return array */ @@ -885,7 +672,7 @@ private function helperMethod(): void // error: Unused Laravel\UppercaseRule::he class OldValidationRule implements ValidationRuleOld { - public function passes(string $attribute, mixed $value): bool + public function passes($attribute, $value): bool { return true; } @@ -1044,6 +831,8 @@ function registerPolicies(): void class SongController extends Controller { + use AuthorizesRequests; + public function show(Song $song): void { $this->authorize('access', $song); From 17fcd5bf5009af2b3e1d9e5e87286b0030efcdd9 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 18:56:28 +0100 Subject: [PATCH 06/14] Laravel: allow ^10.0 to support PHP 8.1 Laravel 11+ requires PHP ^8.2, which breaks CI on PHP 8.1. Laravel 10 requires PHP ^8.1 and all tests pass with it. --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4adc928..fefe6c3 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "doctrine/orm": "^2.19 || ^3.0", "editorconfig-checker/editorconfig-checker": "^10.6.0", "ergebnis/composer-normalize": "^2.48.1", - "laravel/framework": "^11.0 || ^12.0", + "laravel/framework": "^10.0 || ^11.0 || ^12.0", "nette/application": "^3.1", "nette/component-model": "^3.0", "nette/utils": "^3.0 || ^4.0", diff --git a/composer.lock b/composer.lock index a2cda26..f6f6afc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e0b43d4b9f57cc1a3d8298414cf49e9f", + "content-hash": "2e0aa22150b58969f3f1ea2d639143f6", "packages": [ { "name": "phpstan/phpstan", From caf227cfb6781c92b6d0e90618368441728f1855 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:18:53 +0100 Subject: [PATCH 07/14] Extract EloquentUsageProvider from LaravelUsageProvider Eloquent (illuminate/database) can be used standalone without laravel/framework. The new EloquentUsageProvider auto-enables when illuminate/database is installed, covering Model methods, Factory, Seeder, Migration, and Observer detection. --- rules.neon | 12 + src/Provider/EloquentUsageProvider.php | 328 +++++++++++++++++++++++++ src/Provider/LaravelUsageProvider.php | 223 +---------------- tests/Rule/DeadCodeRuleTest.php | 5 + tests/Rule/data/providers/eloquent.php | 191 ++++++++++++++ tests/Rule/data/providers/laravel.php | 182 -------------- 6 files changed, 537 insertions(+), 404 deletions(-) create mode 100644 src/Provider/EloquentUsageProvider.php create mode 100644 tests/Rule/data/providers/eloquent.php diff --git a/rules.neon b/rules.neon index 3215dee..11e0467 100644 --- a/rules.neon +++ b/rules.neon @@ -101,6 +101,13 @@ services: arguments: enabled: %shipmonkDeadCode.usageProviders.phpstan.enabled% + - + class: ShipMonk\PHPStan\DeadCode\Provider\EloquentUsageProvider + tags: + - shipmonk.deadCode.memberUsageProvider + arguments: + enabled: %shipmonkDeadCode.usageProviders.eloquent.enabled% + - class: ShipMonk\PHPStan\DeadCode\Provider\LaravelUsageProvider tags: @@ -235,6 +242,8 @@ parameters: enabled: null doctrine: enabled: null + eloquent: + enabled: null laravel: enabled: null nette: @@ -304,6 +313,9 @@ parametersSchema: doctrine: structure([ enabled: schema(bool(), nullable()) ]) + eloquent: structure([ + enabled: schema(bool(), nullable()) + ]) laravel: structure([ enabled: schema(bool(), nullable()) ]) diff --git a/src/Provider/EloquentUsageProvider.php b/src/Provider/EloquentUsageProvider.php new file mode 100644 index 0000000..e30b135 --- /dev/null +++ b/src/Provider/EloquentUsageProvider.php @@ -0,0 +1,328 @@ +enabled = $enabled ?? InstalledVersions::isInstalled('illuminate/database'); + } + + public function getUsages( + Node $node, + Scope $scope + ): array + { + if (!$this->enabled) { + return []; + } + + $usages = []; + + if ($node instanceof InClassNode) { // @phpstan-ignore phpstanApi.instanceofAssumption + $usages = [...$usages, ...$this->getMethodUsagesFromReflection($node)]; + $usages = [...$usages, ...$this->getObserverUsagesFromModelAttribute($node)]; + } + + if ($node instanceof StaticCall) { + $usages = [...$usages, ...$this->getUsagesFromObserveCall($node, $scope)]; + } + + return $usages; + } + + /** + * @return list + */ + private function getMethodUsagesFromReflection(InClassNode $node): array + { + $classReflection = $node->getClassReflection(); + $nativeReflection = $classReflection->getNativeReflection(); + + $usages = []; + + foreach ($nativeReflection->getMethods() as $method) { + if ($method->getDeclaringClass()->getName() !== $nativeReflection->getName()) { + continue; + } + + $note = $this->shouldMarkAsUsed($method, $classReflection); + + if ($note !== null) { + $usages[] = $this->createUsage($classReflection->getNativeMethod($method->getName()), $note); + } + } + + return $usages; + } + + /** + * @return list + */ + private function getUsagesFromObserveCall( + StaticCall $node, + Scope $scope + ): array + { + if (!$node->name instanceof Identifier || $node->name->name !== 'observe') { + return []; + } + + $callerType = $node->class instanceof Expr + ? $scope->getType($node->class) + : $scope->resolveTypeByName($node->class); + + if (!(new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf($callerType)->yes()) { + return []; + } + + $arg = $node->getArgs()[0] ?? null; + + if ($arg === null) { + return []; + } + + $argType = $scope->getType($arg->value); + $observerClassNames = []; + + foreach ($argType->getConstantStrings() as $stringType) { + $observerClassNames[] = $stringType->getValue(); + } + + foreach ($argType->getConstantArrays() as $arrayType) { + foreach ($arrayType->getValueTypes() as $valueType) { + foreach ($valueType->getConstantStrings() as $stringType) { + $observerClassNames[] = $stringType->getValue(); + } + } + } + + $usages = []; + + foreach ($observerClassNames as $observerClassName) { + foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($observerClassName, $method, false), + ); + } + } + + return $usages; + } + + /** + * @return list + */ + private function getObserverUsagesFromModelAttribute(InClassNode $node): array + { + $classReflection = $node->getClassReflection(); + + if (!(new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf(new ObjectType($classReflection->getName()))->yes()) { + return []; + } + + $nativeReflection = $classReflection->getNativeReflection(); + $attributes = $nativeReflection->getAttributes('Illuminate\Database\Eloquent\Attributes\ObservedBy'); + + $usages = []; + + foreach ($attributes as $attribute) { + $args = $attribute->getArguments(); + + foreach ($args as $arg) { + $classNames = is_array($arg) ? $arg : [$arg]; + + foreach ($classNames as $className) { + if (!is_string($className)) { + continue; + } + + foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createVirtual($this, VirtualUsageData::withNote('Eloquent observer via #[ObservedBy]')), + new ClassMethodRef($className, $method, false), + ); + } + } + } + } + + return $usages; + } + + private function shouldMarkAsUsed( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + return $this->isEloquentModelMethod($method, $classReflection) + ?? $this->isFactoryMethod($method, $classReflection) + ?? $this->isSeederMethod($method, $classReflection) + ?? $this->isMigrationMethod($method, $classReflection); + } + + private function isEloquentModelMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Eloquent\Model')) { + return null; + } + + $methodName = $method->getName(); + + if ($method->isConstructor()) { + return 'Eloquent model constructor'; + } + + if (in_array($methodName, ['boot', 'booted', 'casts', 'newFactory'], true)) { + return 'Eloquent lifecycle/framework method'; + } + + if (strpos($methodName, 'scope') === 0 && $methodName !== 'scope') { + return 'Eloquent query scope'; + } + + if ($this->methodReturnsType($method, 'Illuminate\Database\Eloquent\Relations')) { + return 'Eloquent relationship'; + } + + if ($this->methodReturnsExactType($method, 'Illuminate\Database\Eloquent\Casts\Attribute')) { + return 'Eloquent attribute accessor'; + } + + return null; + } + + private function isFactoryMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Eloquent\Factories\Factory')) { + return null; + } + + if (in_array($method->getName(), ['definition', 'configure'], true)) { + return 'Eloquent factory method'; + } + + return null; + } + + private function isSeederMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Seeder')) { + return null; + } + + if ($method->getName() === 'run') { + return 'Eloquent seeder method'; + } + + return null; + } + + private function isMigrationMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + if (!$classReflection->is('Illuminate\Database\Migrations\Migration')) { + return null; + } + + if (in_array($method->getName(), ['up', 'down'], true)) { + return 'Eloquent migration method'; + } + + return null; + } + + /** + * Checks if the method return type starts with the given prefix (for namespace matching). + */ + private function methodReturnsType( + ReflectionMethod $method, + string $typePrefix + ): bool + { + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + return false; + } + + return strpos($returnType->getName(), $typePrefix) === 0; + } + + /** + * Checks if the method return type exactly matches the given type. + */ + private function methodReturnsExactType( + ReflectionMethod $method, + string $type + ): bool + { + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + return false; + } + + return $returnType->getName() === $type; + } + + private function createUsage( + ExtendedMethodReflection $methodReflection, + string $reason + ): ClassMethodUsage + { + return new ClassMethodUsage( + UsageOrigin::createVirtual($this, VirtualUsageData::withNote($reason)), + new ClassMethodRef( + $methodReflection->getDeclaringClass()->getName(), + $methodReflection->getName(), + false, + ), + ); + } + +} diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 86c608e..0b05d43 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -15,15 +15,12 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ReflectionProvider; -use PHPStan\Type\ObjectType; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef; use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage; use ShipMonk\PHPStan\DeadCode\Graph\UsageOrigin; use function array_map; use function count; use function in_array; -use function is_array; -use function is_string; use function lcfirst; use function str_replace; use function strpos; @@ -34,12 +31,6 @@ final class LaravelUsageProvider implements MemberUsageProvider { - private const OBSERVER_EVENT_METHODS = [ - 'creating', 'created', 'updating', 'updated', 'saving', 'saved', - 'deleting', 'deleted', 'restoring', 'restored', 'replicating', - 'retrieved', 'forceDeleting', 'forceDeleted', 'trashed', - ]; - private ReflectionProvider $reflectionProvider; private bool $enabled; @@ -66,7 +57,6 @@ public function getUsages( if ($node instanceof InClassNode) { // @phpstan-ignore phpstanApi.instanceofAssumption $usages = [...$usages, ...$this->getMethodUsagesFromReflection($node)]; - $usages = [...$usages, ...$this->getObserverUsagesFromModelAttribute($node)]; } if ($node instanceof StaticCall) { @@ -139,14 +129,6 @@ private function getUsagesFromStaticCall( } } - if ( - $node->name instanceof Identifier - && $node->name->name === 'observe' - && (new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf($callerType)->yes() - ) { - $usages = [...$usages, ...$this->getUsagesFromObserveCall($node, $scope)]; - } - return $usages; } @@ -522,89 +504,6 @@ private function kebabToCamelCase(string $string): string ); } - /** - * @return list - */ - private function getUsagesFromObserveCall( - StaticCall $node, - Scope $scope - ): array - { - $arg = $node->getArgs()[0] ?? null; - - if ($arg === null) { - return []; - } - - $argType = $scope->getType($arg->value); - $observerClassNames = []; - - foreach ($argType->getConstantStrings() as $stringType) { - $observerClassNames[] = $stringType->getValue(); - } - - foreach ($argType->getConstantArrays() as $arrayType) { - foreach ($arrayType->getValueTypes() as $valueType) { - foreach ($valueType->getConstantStrings() as $stringType) { - $observerClassNames[] = $stringType->getValue(); - } - } - } - - $usages = []; - - foreach ($observerClassNames as $observerClassName) { - foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { - $usages[] = new ClassMethodUsage( - UsageOrigin::createRegular($node, $scope), - new ClassMethodRef($observerClassName, $method, false), - ); - } - } - - return $usages; - } - - /** - * @return list - */ - private function getObserverUsagesFromModelAttribute(InClassNode $node): array - { - $classReflection = $node->getClassReflection(); - - if (!(new ObjectType('Illuminate\Database\Eloquent\Model'))->isSuperTypeOf(new ObjectType($classReflection->getName()))->yes()) { - return []; - } - - $nativeReflection = $classReflection->getNativeReflection(); - $attributes = $nativeReflection->getAttributes('Illuminate\Database\Eloquent\Attributes\ObservedBy'); - - $usages = []; - - foreach ($attributes as $attribute) { - $args = $attribute->getArguments(); - - foreach ($args as $arg) { - $classNames = is_array($arg) ? $arg : [$arg]; - - foreach ($classNames as $className) { - if (!is_string($className)) { - continue; - } - - foreach ([...self::OBSERVER_EVENT_METHODS, '__construct'] as $method) { - $usages[] = new ClassMethodUsage( - UsageOrigin::createVirtual($this, VirtualUsageData::withNote('Laravel observer via #[ObservedBy]')), - new ClassMethodRef($className, $method, false), - ); - } - } - } - } - - return $usages; - } - /** * Extracts [class, method] pairs from a callable array argument like [Controller::class, 'method']. * @@ -681,16 +580,12 @@ private function shouldMarkAsUsed( ClassReflection $classReflection ): ?string { - return $this->isEloquentModelMethod($method, $classReflection) - ?? $this->isCommandMethod($method, $classReflection) + return $this->isCommandMethod($method, $classReflection) ?? $this->isJobMethod($method, $classReflection) ?? $this->isServiceProviderMethod($method, $classReflection) ?? $this->isMiddlewareMethod($method, $classReflection) ?? $this->isNotificationMethod($method, $classReflection) ?? $this->isFormRequestMethod($method, $classReflection) - ?? $this->isFactoryMethod($method, $classReflection) - ?? $this->isSeederMethod($method, $classReflection) - ?? $this->isMigrationMethod($method, $classReflection) ?? $this->isPolicyMethod($method, $classReflection) ?? $this->isMailableMethod($method, $classReflection) ?? $this->isBroadcastEventMethod($method, $classReflection) @@ -699,40 +594,6 @@ private function shouldMarkAsUsed( ?? $this->isNotifiableMethod($method, $classReflection); } - private function isEloquentModelMethod( - ReflectionMethod $method, - ClassReflection $classReflection - ): ?string - { - if (!$classReflection->is('Illuminate\Database\Eloquent\Model')) { - return null; - } - - $methodName = $method->getName(); - - if ($method->isConstructor()) { - return 'Laravel Eloquent model constructor'; - } - - if (in_array($methodName, ['boot', 'booted', 'casts', 'newFactory'], true)) { - return 'Laravel Eloquent lifecycle/framework method'; - } - - if (strpos($methodName, 'scope') === 0 && $methodName !== 'scope') { - return 'Laravel Eloquent query scope'; - } - - if ($this->methodReturnsType($method, 'Illuminate\Database\Eloquent\Relations')) { - return 'Laravel Eloquent relationship'; - } - - if ($this->methodReturnsExactType($method, 'Illuminate\Database\Eloquent\Casts\Attribute')) { - return 'Laravel Eloquent attribute accessor'; - } - - return null; - } - private function isCommandMethod( ReflectionMethod $method, ClassReflection $classReflection @@ -867,54 +728,6 @@ private function isFormRequestMethod( return null; } - private function isFactoryMethod( - ReflectionMethod $method, - ClassReflection $classReflection - ): ?string - { - if (!$classReflection->is('Illuminate\Database\Eloquent\Factories\Factory')) { - return null; - } - - if (in_array($method->getName(), ['definition', 'configure'], true)) { - return 'Laravel factory method'; - } - - return null; - } - - private function isSeederMethod( - ReflectionMethod $method, - ClassReflection $classReflection - ): ?string - { - if (!$classReflection->is('Illuminate\Database\Seeder')) { - return null; - } - - if ($method->getName() === 'run') { - return 'Laravel seeder method'; - } - - return null; - } - - private function isMigrationMethod( - ReflectionMethod $method, - ClassReflection $classReflection - ): ?string - { - if (!$classReflection->is('Illuminate\Database\Migrations\Migration')) { - return null; - } - - if (in_array($method->getName(), ['up', 'down'], true)) { - return 'Laravel migration method'; - } - - return null; - } - private function isPolicyMethod( ReflectionMethod $method, ClassReflection $classReflection @@ -1033,40 +846,6 @@ private function isNotifiableMethod( return null; } - /** - * Checks if the method return type starts with the given prefix (for namespace matching). - */ - private function methodReturnsType( - ReflectionMethod $method, - string $typePrefix - ): bool - { - $returnType = $method->getReturnType(); - - if (!$returnType instanceof ReflectionNamedType) { - return false; - } - - return strpos($returnType->getName(), $typePrefix) === 0; - } - - /** - * Checks if the method return type exactly matches the given type. - */ - private function methodReturnsExactType( - ReflectionMethod $method, - string $type - ): bool - { - $returnType = $method->getReturnType(); - - if (!$returnType instanceof ReflectionNamedType) { - return false; - } - - return $returnType->getName() === $type; - } - private function createUsage( ExtendedMethodReflection $methodReflection, string $reason diff --git a/tests/Rule/DeadCodeRuleTest.php b/tests/Rule/DeadCodeRuleTest.php index 8bf2cce..f2f0762 100644 --- a/tests/Rule/DeadCodeRuleTest.php +++ b/tests/Rule/DeadCodeRuleTest.php @@ -43,6 +43,7 @@ use ShipMonk\PHPStan\DeadCode\Provider\BehatUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\BuiltinUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\DoctrineUsageProvider; +use ShipMonk\PHPStan\DeadCode\Provider\EloquentUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\EnumUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\LaravelUsageProvider; use ShipMonk\PHPStan\DeadCode\Provider\MemberUsageProvider; @@ -930,6 +931,7 @@ public static function provideFiles(): Traversable yield 'provider-behat' => [__DIR__ . '/data/providers/behat.php', self::requiresPhp(8_00_00)]; yield 'provider-doctrine' => [__DIR__ . '/data/providers/doctrine.php', self::requiresPhp(8_01_00)]; yield 'provider-phpstan' => [__DIR__ . '/data/providers/phpstan.php']; + yield 'provider-eloquent' => [__DIR__ . '/data/providers/eloquent.php', self::requiresPhp(8_01_00)]; yield 'provider-laravel' => [__DIR__ . '/data/providers/laravel.php', self::requiresPhp(8_01_00)]; yield 'provider-nette' => [__DIR__ . '/data/providers/nette.php']; yield 'provider-apiphpdoc' => [__DIR__ . '/data/providers/api-phpdoc.php', self::requiresPhp(8_01_00)]; @@ -1118,6 +1120,9 @@ private function getMemberUsageProviders(): array $this->providersEnabled, $this->createPhpStanContainerMock(), ), + new EloquentUsageProvider( + $this->providersEnabled, + ), new LaravelUsageProvider( self::getContainer()->getByType(ReflectionProvider::class), $this->providersEnabled, diff --git a/tests/Rule/data/providers/eloquent.php b/tests/Rule/data/providers/eloquent.php new file mode 100644 index 0000000..758395d --- /dev/null +++ b/tests/Rule/data/providers/eloquent.php @@ -0,0 +1,191 @@ + */ + protected function casts(): array + { + return []; + } + + protected static function newFactory(): Factory + { + return new UserFactory(); + } + + public function scopeActive(object $query): object + { + return $query; + } + + public function posts(): HasMany + { + throw new \RuntimeException('stub'); + } + + public function company(): BelongsTo + { + throw new \RuntimeException('stub'); + } + + public function roles(): BelongsToMany + { + throw new \RuntimeException('stub'); + } + + protected function firstName(): Attribute + { + return new Attribute(); + } + + private function notAFrameworkMethod(): void // error: Unused Eloquent\User::notAFrameworkMethod + { + } +} + +// --- Factories --- + +class UserFactory extends Factory +{ + /** @return array */ + public function definition(): array + { + return []; + } + + public function configure(): static + { + return $this; + } + + private function helperMethod(): void // error: Unused Eloquent\UserFactory::helperMethod + { + } +} + +// --- Seeders --- + +class DatabaseSeeder extends Seeder +{ + public function run(): void + { + } + + private function helperMethod(): void // error: Unused Eloquent\DatabaseSeeder::helperMethod + { + } +} + +// --- Migrations --- + +class CreateUsersTable extends Migration +{ + public function up(): void + { + } + + public function down(): void + { + } + + private function helperMethod(): void // error: Unused Eloquent\CreateUsersTable::helperMethod + { + } +} + +// --- Observers --- + +class UserObserver +{ + public function __construct() + { + } + + public function creating(object $user): void + { + } + + public function updated(object $user): void + { + } + + public function helperMethod(): void // error: Unused Eloquent\UserObserver::helperMethod + { + } +} + +#[ObservedBy(PostObserver::class)] +class ObservedPost extends Model +{ +} + +class PostObserver +{ + public function __construct() + { + } + + public function saving(object $post): void + { + } + + public function deleted(object $post): void + { + } + + public function helperMethod(): void // error: Unused Eloquent\PostObserver::helperMethod + { + } +} + +class AuditObserver +{ + public function __construct() + { + } + + public function created(object $model): void + { + } + + public function helperMethod(): void // error: Unused Eloquent\AuditObserver::helperMethod + { + } +} + +// ===================== +// Observer Registrations (AST-based detection) +// ===================== + +function registerObservers(): void +{ + User::observe(UserObserver::class); + User::observe([AuditObserver::class]); +} diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 03110e8..67db6b4 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -7,15 +7,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Validation\Rule as ValidationRuleOld; use Illuminate\Contracts\Validation\ValidationRule; -use Illuminate\Database\Eloquent\Attributes\ObservedBy; -use Illuminate\Database\Eloquent\Casts\Attribute; -use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Migrations\Migration; -use Illuminate\Database\Seeder; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Request; @@ -146,64 +138,6 @@ public function unusedMethod(): void // error: Unused Laravel\CleanupJob::unused } } -// --- Eloquent Models --- - -class User extends Model -{ - public function __construct(array $attributes = []) - { - parent::__construct($attributes); - } - - public static function boot(): void - { - } - - public static function booted(): void - { - } - - /** @return array */ - protected function casts(): array - { - return []; - } - - protected static function newFactory(): Factory - { - return new UserFactory(); - } - - public function scopeActive(object $query): object - { - return $query; - } - - public function posts(): HasMany - { - throw new \RuntimeException('stub'); - } - - public function company(): BelongsTo - { - throw new \RuntimeException('stub'); - } - - public function roles(): BelongsToMany - { - throw new \RuntimeException('stub'); - } - - protected function firstName(): Attribute - { - return new Attribute(); - } - - private function notAFrameworkMethod(): void // error: Unused Laravel\User::notAFrameworkMethod - { - } -} - // Model with notification routing (routeNotificationFor* belongs on the notifiable model, not Notification) class NotifiableUser extends Model { @@ -467,39 +401,6 @@ private function helperMethod(): void // error: Unused Laravel\StoreUserRequest: } } -// --- Factories --- - -class UserFactory extends Factory -{ - /** @return array */ - public function definition(): array - { - return []; - } - - public function configure(): static - { - return $this; - } - - private function helperMethod(): void // error: Unused Laravel\UserFactory::helperMethod - { - } -} - -// --- Seeders --- - -class DatabaseSeeder extends Seeder -{ - public function run(): void - { - } - - private function helperMethod(): void // error: Unused Laravel\DatabaseSeeder::helperMethod - { - } -} - // --- Policies --- class PostPolicy @@ -687,83 +588,6 @@ private function helperMethod(): void // error: Unused Laravel\OldValidationRule } } -// --- Migrations --- - -class CreateUsersTable extends Migration -{ - public function up(): void - { - } - - public function down(): void - { - } - - private function helperMethod(): void // error: Unused Laravel\CreateUsersTable::helperMethod - { - } -} - -// --- Observers --- - -class UserObserver -{ - public function __construct() - { - } - - public function creating(object $user): void - { - } - - public function updated(object $user): void - { - } - - public function helperMethod(): void // error: Unused Laravel\UserObserver::helperMethod - { - } -} - -#[ObservedBy(PostObserver::class)] -class ObservedPost extends Model -{ -} - -class PostObserver -{ - public function __construct() - { - } - - public function saving(object $post): void - { - } - - public function deleted(object $post): void - { - } - - public function helperMethod(): void // error: Unused Laravel\PostObserver::helperMethod - { - } -} - -class AuditObserver -{ - public function __construct() - { - } - - public function created(object $model): void - { - } - - public function helperMethod(): void // error: Unused Laravel\AuditObserver::helperMethod - { - } -} - // --- Middleware with constructor --- class ThrottleMiddleware @@ -811,12 +635,6 @@ function registerSchedule(): void Schedule::job(CleanupJob::class); } -function registerObservers(): void -{ - User::observe(UserObserver::class); - User::observe([AuditObserver::class]); -} - function registerPolicies(): void { Gate::policy(Album::class, \Laravel\Policies\AlbumPolicy::class); From 54e41d4c50c0626821dafa8f64ce8fcf604672b7 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:31:12 +0100 Subject: [PATCH 08/14] Remove Laravel provider checks redundant with VendorUsageProvider Methods declared in vendor interfaces/parent classes are already handled by VendorUsageProvider, so the Laravel provider doesn't need to mark them: - broadcastOn: declared in ShouldBroadcast interface - toArray, with, additional: declared in JsonResource parent class - validate: declared in ValidationRule interface - passes, message: declared in Rule interface The remaining checks cover methods called via method_exists() magic (broadcastWith, broadcastAs, broadcastWhen, paginationInformation) which VendorUsageProvider cannot detect. --- src/Provider/LaravelUsageProvider.php | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 0b05d43..ee0aba2 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -590,7 +590,6 @@ private function shouldMarkAsUsed( ?? $this->isMailableMethod($method, $classReflection) ?? $this->isBroadcastEventMethod($method, $classReflection) ?? $this->isJsonResourceMethod($method, $classReflection) - ?? $this->isValidationRuleMethod($method, $classReflection) ?? $this->isNotifiableMethod($method, $classReflection); } @@ -779,7 +778,7 @@ private function isBroadcastEventMethod( return null; } - $broadcastMethods = ['broadcastOn', 'broadcastWith', 'broadcastAs', 'broadcastWhen']; + $broadcastMethods = ['broadcastWith', 'broadcastAs', 'broadcastWhen']; if (in_array($method->getName(), $broadcastMethods, true)) { return 'Laravel broadcast event method'; @@ -797,7 +796,7 @@ private function isJsonResourceMethod( return null; } - $resourceMethods = ['toArray', 'with', 'additional', 'paginationInformation']; + $resourceMethods = ['paginationInformation']; if (in_array($method->getName(), $resourceMethods, true)) { return 'Laravel JSON resource method'; @@ -806,27 +805,6 @@ private function isJsonResourceMethod( return null; } - private function isValidationRuleMethod( - ReflectionMethod $method, - ClassReflection $classReflection - ): ?string - { - if ( - !$classReflection->is('Illuminate\Contracts\Validation\ValidationRule') - && !$classReflection->is('Illuminate\Contracts\Validation\Rule') - ) { - return null; - } - - $ruleMethods = ['validate', 'passes', 'message']; - - if (in_array($method->getName(), $ruleMethods, true)) { - return 'Laravel validation rule method'; - } - - return null; - } - private function isNotifiableMethod( ReflectionMethod $method, ClassReflection $classReflection From 73189169457afb52a8cee479d165a6fb8f346971 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:36:19 +0100 Subject: [PATCH 09/14] Laravel: require \Policies\ namespace for policy method heuristic The isPolicyMethod() fallback previously matched any class ending in "Policy" (e.g. RetentionPolicy, CachePolicy), which could suppress legitimate dead code warnings on non-authorization classes that happen to have methods named view, create, update, delete, etc. Laravel's own guessPolicyName() always generates candidates within a \Policies\ namespace segment. Policies registered outside that convention (via Gate::policy() or #[UsePolicy]) are already handled by the precise detection layer. So we can safely require \Policies\ in the class name for the heuristic fallback. --- src/Provider/LaravelUsageProvider.php | 5 ++ tests/Rule/data/providers/laravel.php | 96 +++++++++++++-------------- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index ee0aba2..726d209 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -733,6 +733,11 @@ private function isPolicyMethod( ): ?string { $className = $classReflection->getName(); + + if (strpos($className, '\\Policies\\') === false) { + return null; + } + $lastSeparator = strrpos($className, '\\'); $shortName = $lastSeparator !== false ? substr($className, $lastSeparator + 1) : $className; diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 67db6b4..961d0cd 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -401,55 +401,6 @@ private function helperMethod(): void // error: Unused Laravel\StoreUserRequest: } } -// --- Policies --- - -class PostPolicy -{ - public function before(object $user): ?bool - { - return null; - } - - public function viewAny(object $user): bool - { - return true; - } - - public function view(object $user, object $post): bool - { - return true; - } - - public function create(object $user): bool - { - return true; - } - - public function update(object $user, object $post): bool - { - return true; - } - - public function delete(object $user, object $post): bool - { - return true; - } - - public function restore(object $user, object $post): bool - { - return true; - } - - public function forceDelete(object $user, object $post): bool - { - return true; - } - - private function helperMethod(): void // error: Unused Laravel\PostPolicy::helperMethod - { - } -} - // --- Policy with custom abilities (detected via authorize() and Gate::policy()) --- class Song extends Model @@ -675,6 +626,53 @@ public function upload(): void namespace Laravel\Policies; +class PostPolicy +{ + public function before(object $user): ?bool + { + return null; + } + + public function viewAny(object $user): bool + { + return true; + } + + public function view(object $user, object $post): bool + { + return true; + } + + public function create(object $user): bool + { + return true; + } + + public function update(object $user, object $post): bool + { + return true; + } + + public function delete(object $user, object $post): bool + { + return true; + } + + public function restore(object $user, object $post): bool + { + return true; + } + + public function forceDelete(object $user, object $post): bool + { + return true; + } + + private function helperMethod(): void // error: Unused Laravel\Policies\PostPolicy::helperMethod + { + } +} + class SongPolicy { public function access(object $user, object $song): bool From f10fc5017361c5d31d88103e91227ffa47067d1e Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:39:11 +0100 Subject: [PATCH 10/14] Add missing test coverage for Laravel/Eloquent provider features - Route::match with invokable controller (class string at arg index 2) - Job methods uniqueVia and displayName - FormRequest methods failedValidation and failedAuthorization - #[ObservedBy] with array syntax --- tests/Rule/data/providers/eloquent.php | 20 +++++++++++++++ tests/Rule/data/providers/laravel.php | 34 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/tests/Rule/data/providers/eloquent.php b/tests/Rule/data/providers/eloquent.php index 758395d..726cb7a 100644 --- a/tests/Rule/data/providers/eloquent.php +++ b/tests/Rule/data/providers/eloquent.php @@ -146,6 +146,26 @@ class ObservedPost extends Model { } +#[ObservedBy([CommentObserver::class])] +class ObservedComment extends Model +{ +} + +class CommentObserver +{ + public function __construct() + { + } + + public function updating(object $comment): void + { + } + + public function helperMethod(): void // error: Unused Eloquent\CommentObserver::helperMethod + { + } +} + class PostObserver { public function __construct() diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 961d0cd..401f1a7 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -85,6 +85,21 @@ public function unusedAction(): void // error: Unused Laravel\InvokableControlle } } +class MatchInvokableController extends Controller +{ + public function __construct() + { + } + + public function __invoke(): void + { + } + + public function unusedAction(): void // error: Unused Laravel\MatchInvokableController::unusedAction + { + } +} + // --- Event Listeners --- class OrderCreatedEvent @@ -222,6 +237,16 @@ public function backoff(): array return []; } + public function uniqueVia(): object + { + return new \stdClass(); + } + + public function displayName(): string + { + return ''; + } + private function notAJobMethod(): void // error: Unused Laravel\SendEmailJob::notAJobMethod { } @@ -396,6 +421,14 @@ protected function passedValidation(): void { } + protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator): void + { + } + + protected function failedAuthorization(): void + { + } + private function helperMethod(): void // error: Unused Laravel\StoreUserRequest::helperMethod { } @@ -570,6 +603,7 @@ function registerRoutes(): void Route::delete('/users/{id}', [UserController::class, 'index']); Route::any('/any', [UserController::class, 'show']); Route::match(['GET', 'POST'], '/match', [UserController::class, 'index']); + Route::match(['GET'], '/match-invokable', MatchInvokableController::class); Route::get('/invokable', InvokableController::class); Route::resource('posts', PostController::class); Route::apiResource('comments', CommentController::class); From c5e494dbad8aa655d21ee6dbcd1179f41d76180c Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:42:03 +0100 Subject: [PATCH 11/14] Fix policy class resolution for models in nested namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation only checked {rootNamespace}\Policies\{Model}Policy, which missed models in sub-namespaces (e.g. App\Models\Admin\User would only try App\Policies\UserPolicy, missing App\Policies\Admin\UserPolicy). Now mirrors Laravel's Gate::guessPolicyName() candidate list: - \Models\ → \Models\Policies\ replacement - \Models\ → \Policies\ replacement - Segment-based candidates from most to least specific All existing candidates where the class exists are emitted as usages, rather than just the first match. --- src/Provider/LaravelUsageProvider.php | 56 ++++++++++++++++----------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 726d209..8739b4b 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -19,7 +19,10 @@ use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage; use ShipMonk\PHPStan\DeadCode\Graph\UsageOrigin; use function array_map; +use function array_slice; use function count; +use function explode; +use function implode; use function in_array; use function lcfirst; use function str_replace; @@ -402,19 +405,11 @@ private function getUsagesFromAuthorizeCall( $modelType = $scope->getType($modelArg->value); foreach ($modelType->getObjectClassNames() as $modelClassName) { - $policyClassName = $this->resolvePolicyClassName($modelClassName); - - if ($policyClassName !== null) { - $policyClassNames[] = $policyClassName; - } + $policyClassNames = [...$policyClassNames, ...$this->resolvePolicyClassNames($modelClassName)]; } foreach ($modelType->getConstantStrings() as $modelStringType) { - $policyClassName = $this->resolvePolicyClassName($modelStringType->getValue()); - - if ($policyClassName !== null) { - $policyClassNames[] = $policyClassName; - } + $policyClassNames = [...$policyClassNames, ...$this->resolvePolicyClassNames($modelStringType->getValue())]; } } @@ -432,29 +427,46 @@ private function getUsagesFromAuthorizeCall( return $usages; } - private function resolvePolicyClassName(string $modelClassName): ?string + /** + * @return list + * + * @see \Illuminate\Auth\Access\Gate::guessPolicyName() + */ + private function resolvePolicyClassNames(string $modelClassName): array { $lastSeparator = strrpos($modelClassName, '\\'); if ($lastSeparator === false) { - return null; + return []; } - $namespace = substr($modelClassName, 0, $lastSeparator); - $shortName = substr($modelClassName, $lastSeparator + 1); + $classDirname = substr($modelClassName, 0, $lastSeparator); + $classBasename = substr($modelClassName, $lastSeparator + 1); + $policyBasename = $classBasename . 'Policy'; - $firstSeparator = strpos($namespace, '\\'); - $rootNamespace = $firstSeparator !== false - ? substr($namespace, 0, $firstSeparator) - : $namespace; + $segments = explode('\\', $classDirname); + $segmentCount = count($segments); - $policyClassName = $rootNamespace . '\\Policies\\' . $shortName . 'Policy'; + $candidates = []; - if ($this->reflectionProvider->hasClass($policyClassName)) { - return $policyClassName; + if (strpos($classDirname, '\\Models\\') !== false) { + $candidates[] = str_replace('\\Models\\', '\\Models\\Policies\\', $classDirname) . '\\' . $policyBasename; + $candidates[] = str_replace('\\Models\\', '\\Policies\\', $classDirname) . '\\' . $policyBasename; } - return null; + for ($i = $segmentCount; $i >= 1; $i--) { + $candidates[] = implode('\\', array_slice($segments, 0, $i)) . '\\Policies\\' . $policyBasename; + } + + $result = []; + + foreach ($candidates as $candidate) { + if ($this->reflectionProvider->hasClass($candidate)) { + $result[] = $candidate; + } + } + + return $result; } /** From 55282d9d1b841f69f8a34d2c3a6c13038ed1267f Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 19:55:39 +0100 Subject: [PATCH 12/14] Eloquent: detect legacy get*Attribute/set*Attribute accessors/mutators --- src/Provider/EloquentUsageProvider.php | 23 +++++++++++++++++++++++ tests/Rule/data/providers/eloquent.php | 16 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Provider/EloquentUsageProvider.php b/src/Provider/EloquentUsageProvider.php index e30b135..d56be73 100644 --- a/src/Provider/EloquentUsageProvider.php +++ b/src/Provider/EloquentUsageProvider.php @@ -20,7 +20,9 @@ use function in_array; use function is_array; use function is_string; +use function strlen; use function strpos; +use function substr; final class EloquentUsageProvider implements MemberUsageProvider { @@ -225,9 +227,30 @@ private function isEloquentModelMethod( return 'Eloquent attribute accessor'; } + if ($this->isLegacyAccessorOrMutator($methodName)) { + return 'Eloquent legacy accessor/mutator'; + } + return null; } + /** + * Legacy get{Name}Attribute() / set{Name}Attribute() convention (pre-Laravel 9). + * Still supported in Laravel 10+ alongside the modern Attribute return-type approach. + */ + private function isLegacyAccessorOrMutator(string $methodName): bool + { + $length = strlen($methodName); + + // Minimum: get + X + Attribute = 13 chars, same for set + if ($length <= 12 || substr($methodName, -9) !== 'Attribute') { + return false; + } + + return strpos($methodName, 'get') === 0 + || strpos($methodName, 'set') === 0; + } + private function isFactoryMethod( ReflectionMethod $method, ClassReflection $classReflection diff --git a/tests/Rule/data/providers/eloquent.php b/tests/Rule/data/providers/eloquent.php index 726cb7a..0afb44b 100644 --- a/tests/Rule/data/providers/eloquent.php +++ b/tests/Rule/data/providers/eloquent.php @@ -65,6 +65,22 @@ protected function firstName(): Attribute return new Attribute(); } + // Legacy accessors/mutators (pre-Laravel 9, still supported) + public function getLastNameAttribute(): string + { + return ''; + } + + public function setLastNameAttribute(string $value): void + { + } + + // These should NOT be detected as legacy accessors/mutators + public function getSomethingElse(): string // error: Unused Eloquent\User::getSomethingElse + { + return ''; + } + private function notAFrameworkMethod(): void // error: Unused Eloquent\User::notAFrameworkMethod { } From 0269db2be50c1815a931cbd48bb65de217a11b00 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 20:11:03 +0100 Subject: [PATCH 13/14] Add support for legacy Controller@method string route syntax Laravel supports 'Controller@method' strings in route definitions. Parse these alongside array callables and class-string invokables in Route::get/post/put/patch/delete/any and Route::match calls. --- src/Provider/LaravelUsageProvider.php | 54 +++++++++++++++++++++++++++ tests/Rule/data/providers/laravel.php | 24 ++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 8739b4b..92b7eda 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -160,6 +160,16 @@ private function getUsagesFromRouteCall( } } + // String syntax: Route::get('/path', 'Controller@method') + foreach ($this->extractControllerAtMethodFromArg($node, $scope, 1) as [$className, $method]) { + foreach ([$method, '__construct'] as $usedMethod) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $usedMethod, false), + ); + } + } + // Invokable controllers: Route::get('/path', Controller::class) foreach ($this->extractClassNamesFromArg($node, $scope, 1) as $className) { foreach (['__invoke', '__construct'] as $method) { @@ -181,6 +191,16 @@ private function getUsagesFromRouteCall( } } + // String syntax: Route::match(['GET'], '/path', 'Controller@method') + foreach ($this->extractControllerAtMethodFromArg($node, $scope, 2) as [$className, $method]) { + foreach ([$method, '__construct'] as $usedMethod) { + $usages[] = new ClassMethodUsage( + UsageOrigin::createRegular($node, $scope), + new ClassMethodRef($className, $usedMethod, false), + ); + } + } + // Invokable controllers: Route::match(['GET'], '/path', Controller::class) foreach ($this->extractClassNamesFromArg($node, $scope, 2) as $className) { foreach (['__invoke', '__construct'] as $method) { @@ -587,6 +607,40 @@ private function extractClassNamesFromArg( return $classNames; } + /** + * Extracts [class, method] pairs from a 'Controller@method' string argument. + * + * @return list + */ + private function extractControllerAtMethodFromArg( + StaticCall $node, + Scope $scope, + int $argIndex + ): array + { + $arg = $node->getArgs()[$argIndex] ?? null; + + if ($arg === null) { + return []; + } + + $argType = $scope->getType($arg->value); + $callables = []; + + foreach ($argType->getConstantStrings() as $stringType) { + $value = $stringType->getValue(); + $atPos = strpos($value, '@'); + + if ($atPos !== false) { + $className = substr($value, 0, $atPos); + $methodName = substr($value, $atPos + 1); + $callables[] = [$className, $methodName]; + } + } + + return $callables; + } + private function shouldMarkAsUsed( ReflectionMethod $method, ClassReflection $classReflection diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 401f1a7..40603e5 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -100,6 +100,25 @@ public function unusedAction(): void // error: Unused Laravel\MatchInvokableCont } } +class StringRouteController extends Controller +{ + public function __construct() + { + } + + public function index(): void + { + } + + public function store(): void + { + } + + public function unusedAction(): void // error: Unused Laravel\StringRouteController::unusedAction + { + } +} + // --- Event Listeners --- class OrderCreatedEvent @@ -607,6 +626,11 @@ function registerRoutes(): void Route::get('/invokable', InvokableController::class); Route::resource('posts', PostController::class); Route::apiResource('comments', CommentController::class); + + // String syntax: 'Controller@method' + Route::get('/string-route', 'Laravel\StringRouteController@index'); + Route::post('/string-route', 'Laravel\StringRouteController@store'); + Route::match(['GET'], '/string-match', 'Laravel\StringRouteController@index'); } function registerEvents(): void From 896a79c19ec33504254d46fa371c73024b912525 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Sun, 1 Mar 2026 20:37:02 +0100 Subject: [PATCH 14/14] Detect auto-discovered event listener methods as used Laravel automatically discovers event listeners by scanning the Listeners directory for classes with public handle*/__invoke methods that have a class-typed first parameter (the event). This happens without any explicit Event::listen() registration. Previously, only explicitly registered listeners (via Event::listen AST calls) had their handle() marked as used. Auto-discovered listeners would be falsely reported as dead code. The detection mirrors Laravel's DiscoverEvents logic: - Public methods matching handle* or __invoke - First parameter must have a non-builtin class type-hint - Union types (e.g. EventA|EventB) are supported - Constructor is also marked when the class qualifies Placed last in the shouldMarkAsUsed chain so it only triggers for classes not already identified as Commands, Jobs, Middleware, etc. --- src/Provider/LaravelUsageProvider.php | 67 ++++++++++++++++++++- tests/Rule/data/providers/laravel.php | 87 +++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/src/Provider/LaravelUsageProvider.php b/src/Provider/LaravelUsageProvider.php index 92b7eda..d74fcf7 100644 --- a/src/Provider/LaravelUsageProvider.php +++ b/src/Provider/LaravelUsageProvider.php @@ -656,7 +656,8 @@ private function shouldMarkAsUsed( ?? $this->isMailableMethod($method, $classReflection) ?? $this->isBroadcastEventMethod($method, $classReflection) ?? $this->isJsonResourceMethod($method, $classReflection) - ?? $this->isNotifiableMethod($method, $classReflection); + ?? $this->isNotifiableMethod($method, $classReflection) + ?? $this->isEventListenerMethod($method, $classReflection); } private function isCommandMethod( @@ -895,6 +896,70 @@ private function isNotifiableMethod( return null; } + private function isEventListenerMethod( + ReflectionMethod $method, + ClassReflection $classReflection + ): ?string + { + $methodName = $method->getName(); + + if ($method->isPublic() && (strpos($methodName, 'handle') === 0 || $methodName === '__invoke')) { + if ($this->firstParamHasClassType($methodName, $classReflection)) { + return 'Laravel auto-discovered event listener method'; + } + + return null; + } + + if ($method->isConstructor() && $this->hasAutoDiscoveredListenerMethod($classReflection)) { + return 'Laravel auto-discovered event listener method'; + } + + return null; + } + + private function hasAutoDiscoveredListenerMethod(ClassReflection $classReflection): bool + { + foreach ($classReflection->getNativeReflection()->getMethods() as $classMethod) { + if (!$classMethod->isPublic()) { + continue; + } + + $name = $classMethod->getName(); + + if (strpos($name, 'handle') !== 0 && $name !== '__invoke') { + continue; + } + + if ($this->firstParamHasClassType($name, $classReflection)) { + return true; + } + } + + return false; + } + + /** + * @see \Illuminate\Support\Reflector::getParameterClassNames() + */ + private function firstParamHasClassType( + string $methodName, + ClassReflection $classReflection + ): bool + { + foreach ($classReflection->getNativeMethod($methodName)->getVariants() as $variant) { + $params = $variant->getParameters(); + + if ($params === []) { + return false; + } + + return $params[0]->getType()->getObjectClassNames() !== []; + } + + return false; + } + private function createUsage( ExtendedMethodReflection $methodReflection, string $reason diff --git a/tests/Rule/data/providers/laravel.php b/tests/Rule/data/providers/laravel.php index 40603e5..798ee52 100644 --- a/tests/Rule/data/providers/laravel.php +++ b/tests/Rule/data/providers/laravel.php @@ -155,6 +155,93 @@ public function unusedMethod(): void // error: Unused Laravel\OrderEventSubscrib } } +// --- Auto-discovered Event Listeners (reflection-based) --- + +class OrderShippedEvent +{ +} + +class AutoDiscoveredListener +{ + public function __construct() + { + } + + public function handle(OrderCreatedEvent $event): void + { + } + + public function unusedMethod(): void // error: Unused Laravel\AutoDiscoveredListener::unusedMethod + { + } +} + +class MultiHandlerListener +{ + public function __construct() + { + } + + public function handleOrderCreated(OrderCreatedEvent $event): void + { + } + + public function handleOrderShipped(OrderShippedEvent $event): void + { + } + + public function unusedMethod(): void // error: Unused Laravel\MultiHandlerListener::unusedMethod + { + } +} + +class InvokableListener +{ + public function __construct() + { + } + + public function __invoke(OrderCreatedEvent $event): void + { + } +} + +// Auto-discovered with union type parameter + +class UnionTypeListener +{ + public function handle(OrderCreatedEvent|OrderShippedEvent $event): void + { + } +} + +// Not auto-discovered: private handle method + +class NotListenerPrivateHandle +{ + private function handle(OrderCreatedEvent $event): void // error: Unused Laravel\NotListenerPrivateHandle::handle + { + } +} + +// Not auto-discovered: no params (handle without type-hinted event) + +class NotListenerNoParams +{ + public function handle(): void // error: Unused Laravel\NotListenerNoParams::handle + { + } +} + +// Not auto-discovered: first param is built-in type + +class NotListenerBuiltinParam +{ + public function handle(string $eventId): void // error: Unused Laravel\NotListenerBuiltinParam::handle + { + } +} + // --- Scheduled Jobs (AST-based via Schedule:: calls) --- class CleanupJob