From b69f96902bf59b201a5b0ade452acf2dd21dd1fe Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 16 Jul 2022 19:13:59 +0100 Subject: [PATCH 01/16] chore: setup phpstan infrastructure Signed-off-by: Sami Mazouz --- composer.json | 3 +- php-packages/phpstan/composer.json | 3 +- php-packages/phpstan/extension.neon | 290 +----------- php-packages/phpstan/larastan-extension.neon | 439 +++++++++++++++++++ phpstan.neon | 13 + 5 files changed, 457 insertions(+), 291 deletions(-) create mode 100644 php-packages/phpstan/larastan-extension.neon create mode 100644 phpstan.neon diff --git a/composer.json b/composer.json index 0564a66fc6..8262c55a08 100644 --- a/composer.json +++ b/composer.json @@ -141,7 +141,8 @@ "mockery/mockery": "^1.4", "phpunit/phpunit": "^9.0", "phpstan/phpstan-php-parser": "^1.0", - "phpstan/phpstan": "^1.2" + "phpstan/phpstan": "^1.2", + "nunomaduro/larastan": "^1.0" }, "config": { "sort-packages": true diff --git a/php-packages/phpstan/composer.json b/php-packages/phpstan/composer.json index 225023e2fb..ce23184452 100644 --- a/php-packages/phpstan/composer.json +++ b/php-packages/phpstan/composer.json @@ -5,7 +5,8 @@ "license": "MIT", "require": { "phpstan/phpstan-php-parser": "^1.0", - "phpstan/phpstan": "^1.2" + "phpstan/phpstan": "^1.2", + "nunomaduro/larastan": "^1.0" }, "autoload": { "psr-4": { diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 7ff7961578..2bdfe14075 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -1,291 +1,3 @@ includes: - vendor/phpstan/phpstan-php-parser/extension.neon -parameters: - stubFiles: - - stubs/Illuminate/Enumerable.stub - - stubs/Illuminate/Database/EloquentBuilder.stub - - stubs/Illuminate/Collection.stub - - stubs/Illuminate/Database/EloquentCollection.stub - - stubs/Illuminate/Database/Factory.stub - - stubs/Illuminate/Database/Model.stub - - stubs/Illuminate/Database/Gate.stub - - stubs/Illuminate/Database/Relation.stub - - stubs/Illuminate/Database/BelongsTo.stub - - stubs/Illuminate/Database/BelongsToMany.stub - - stubs/Illuminate/Database/HasOneOrMany.stub - - stubs/Illuminate/Database/HasMany.stub - - stubs/Illuminate/Database/HasOne.stub - - stubs/Illuminate/Database/HasOneThrough.stub - - stubs/Illuminate/Database/HasManyThrough.stub - - stubs/Illuminate/Database/MorphTo.stub - - stubs/Illuminate/Database/MorphToMany.stub - - stubs/Illuminate/Database/MorphMany.stub - - stubs/Illuminate/Database/MorphOne.stub - - stubs/Illuminate/Database/MorphOneOrMany.stub - - stubs/Illuminate/HigherOrderProxies.stub - - stubs/Illuminate/Database/QueryBuilder.stub - - stubs/Illuminate/EnumeratesValues.stub - - stubs/Contracts/Support.stub - universalObjectCratesClasses: - - Illuminate\Http\Request - mixinExcludeClasses: - - Eloquent - earlyTerminatingFunctionCalls: - - abort - - dd - excludePaths: - - *.blade.php - checkGenericClassInNonGenericObjectType: false - checkModelProperties: false - databaseMigrationsPath: [] - -parametersSchema: - databaseMigrationsPath: listOf(string()) - checkModelProperties: bool() - -services: - - - class: Flarum\PHPStan\Methods\RelationForwardsCallsExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\ModelForwardsCallsExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\EloquentBuilderForwardsCallsExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\HigherOrderTapProxyExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\HigherOrderCollectionProxyExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\StorageMethodsClassReflectionExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Methods\Extension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - class: Flarum\PHPStan\Methods\ModelFactoryMethodsClassReflectionExtension - tags: - - phpstan.broker.methodsClassReflectionExtension - - - - class: Flarum\PHPStan\Properties\ModelAccessorExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - - class: Flarum\PHPStan\Properties\ModelPropertyExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - - class: Flarum\PHPStan\Properties\HigherOrderCollectionProxyPropertyExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - - class: Flarum\PHPStan\Types\RelationDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\Types\ModelRelationsDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\HigherOrderTapProxyExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - className: Illuminate\Contracts\Container\Container - - - class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - className: Illuminate\Container\Container - - - class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - className: Illuminate\Foundation\Application - - - class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - className: Illuminate\Contracts\Foundation\Application - - - - class: Flarum\PHPStan\Properties\ModelRelationsExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - - class: Flarum\PHPStan\ReturnTypes\ModelFactoryDynamicStaticMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\ModelExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\RequestExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\EloquentBuilderExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\RelationFindExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\RelationCollectionExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\ModelFindExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\BuilderModelFindExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\TestCaseExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\CollectionMakeDynamicStaticMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: Flarum\PHPStan\Support\CollectionHelper - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\CollectExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\TransExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\ValidatorExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\CollectionFilterDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - arguments: - methodName: 'abort' - negate: false - - - - class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - arguments: - methodName: 'abort' - negate: true - - - - class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - arguments: - methodName: throw - negate: false - - - - class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - arguments: - methodName: throw - negate: true - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\AppExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\ValueExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\Helpers\TapExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: Flarum\PHPStan\ReturnTypes\StorageDynamicStaticMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: Flarum\PHPStan\Types\GenericEloquentCollectionTypeNodeResolverExtension - tags: - - phpstan.phpDoc.typeNodeResolverExtension - - - - class: Flarum\PHPStan\Types\ViewStringTypeNodeResolverExtension - tags: - - phpstan.phpDoc.typeNodeResolverExtension - - - class: Flarum\PHPStan\Methods\BuilderHelper - arguments: - checkProperties: %checkModelProperties% - - - class: Flarum\PHPStan\Properties\MigrationHelper - arguments: - databaseMigrationPath: %databaseMigrationsPath% - parser: @currentPhpVersionSimpleDirectParser - - - class: Flarum\PHPStan\Types\RelationParserHelper - arguments: - parser: @currentPhpVersionSimpleDirectParser + - larastan-extension.neon diff --git a/php-packages/phpstan/larastan-extension.neon b/php-packages/phpstan/larastan-extension.neon new file mode 100644 index 0000000000..78661d126d --- /dev/null +++ b/php-packages/phpstan/larastan-extension.neon @@ -0,0 +1,439 @@ +parameters: + stubFiles: + - vendor/nunomaduro/larastan/stubs/Enumerable.stub + - vendor/nunomaduro/larastan/stubs/EloquentBuilder.stub + - vendor/nunomaduro/larastan/stubs/Collection.stub + - vendor/nunomaduro/larastan/stubs/EloquentCollection.stub + - vendor/nunomaduro/larastan/stubs/Factory.stub + - vendor/nunomaduro/larastan/stubs/Model.stub + - vendor/nunomaduro/larastan/stubs/Gate.stub + - vendor/nunomaduro/larastan/stubs/Relation.stub + - vendor/nunomaduro/larastan/stubs/BelongsTo.stub + - vendor/nunomaduro/larastan/stubs/BelongsToMany.stub + - vendor/nunomaduro/larastan/stubs/HasOneOrMany.stub + - vendor/nunomaduro/larastan/stubs/HasMany.stub + - vendor/nunomaduro/larastan/stubs/HasOne.stub + - vendor/nunomaduro/larastan/stubs/HasOneThrough.stub + - vendor/nunomaduro/larastan/stubs/HasManyThrough.stub + - vendor/nunomaduro/larastan/stubs/Mailable.stub + - vendor/nunomaduro/larastan/stubs/MorphOne.stub + - vendor/nunomaduro/larastan/stubs/MorphOneOrMany.stub + - vendor/nunomaduro/larastan/stubs/MorphTo.stub + - vendor/nunomaduro/larastan/stubs/MorphToMany.stub + - vendor/nunomaduro/larastan/stubs/MorphMany.stub + - vendor/nunomaduro/larastan/stubs/Helpers.stub + - vendor/nunomaduro/larastan/stubs/HigherOrderProxies.stub + - vendor/nunomaduro/larastan/stubs/QueryBuilder.stub + - vendor/nunomaduro/larastan/stubs/Facades.stub + - vendor/nunomaduro/larastan/stubs/Pagination.stub + - vendor/nunomaduro/larastan/stubs/Contracts/Pagination.stub + - vendor/nunomaduro/larastan/stubs/Contracts/Support.stub + - vendor/nunomaduro/larastan/stubs/Redis/Connection.stub + - vendor/nunomaduro/larastan/stubs/Logger.stub + - vendor/nunomaduro/larastan/stubs/EnumeratesValues.stub + universalObjectCratesClasses: + - Illuminate\Http\Request + earlyTerminatingFunctionCalls: + - abort + - dd + excludePaths: + - *.blade.php + mixinExcludeClasses: + - Eloquent +# bootstrapFiles: +# - bootstrap.php + checkGenericClassInNonGenericObjectType: false + checkOctaneCompatibility: false + noModelMake: true + noUnnecessaryCollectionCall: true + noUnnecessaryCollectionCallOnly: [] + noUnnecessaryCollectionCallExcept: [] + databaseMigrationsPath: [] + checkModelProperties: false + checkPhpDocMissingReturn: false + +parametersSchema: + checkOctaneCompatibility: bool() + noModelMake: bool() + noUnnecessaryCollectionCall: bool() + noUnnecessaryCollectionCallOnly: listOf(string()) + noUnnecessaryCollectionCallExcept: listOf(string()) + databaseMigrationsPath: listOf(string()) + checkModelProperties: bool() + +conditionalTags: + NunoMaduro\Larastan\Rules\NoModelMakeRule: + phpstan.rules.rule: %noModelMake% + NunoMaduro\Larastan\Rules\NoUnnecessaryCollectionCallRule: + phpstan.rules.rule: %noUnnecessaryCollectionCall% + NunoMaduro\Larastan\Rules\OctaneCompatibilityRule: + phpstan.rules.rule: %checkOctaneCompatibility% + NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyRule: + phpstan.rules.rule: %checkModelProperties% + NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyStaticCallRule: + phpstan.rules.rule: %checkModelProperties% + +services: + - + class: NunoMaduro\Larastan\Methods\RelationForwardsCallsExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\ModelForwardsCallsExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\EloquentBuilderForwardsCallsExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\HigherOrderTapProxyExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\HigherOrderCollectionProxyExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\StorageMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Methods\Extension + tags: + - phpstan.broker.methodsClassReflectionExtension + - + class: NunoMaduro\Larastan\Methods\ModelFactoryMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + - + class: NunoMaduro\Larastan\Methods\RedirectResponseMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + + - + class: NunoMaduro\Larastan\Properties\ModelAccessorExtension + tags: + - phpstan.broker.propertiesClassReflectionExtension + + - + class: NunoMaduro\Larastan\Properties\ModelPropertyExtension + tags: + - phpstan.broker.propertiesClassReflectionExtension + + - + class: NunoMaduro\Larastan\Properties\HigherOrderCollectionProxyPropertyExtension + tags: + - phpstan.broker.propertiesClassReflectionExtension + + - + class: NunoMaduro\Larastan\Types\RelationDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\Types\ModelRelationsDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\HigherOrderTapProxyExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + - + class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + className: Illuminate\Contracts\Container\Container + - + class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + className: Illuminate\Container\Container + - + class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + className: Illuminate\Foundation\Application + - + class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + className: Illuminate\Contracts\Foundation\Application + + - + class: NunoMaduro\Larastan\Properties\ModelRelationsExtension + tags: + - phpstan.broker.propertiesClassReflectionExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\ModelFactoryDynamicStaticMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\ModelExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\AuthExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\GuardDynamicStaticMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\AuthManagerExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\GuardExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\RequestExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\EloquentBuilderExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\RelationFindExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\RelationCollectionExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\ModelFindExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\BuilderModelFindExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\TestCaseExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\CollectionMakeDynamicStaticMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\Support\CollectionHelper + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\AuthExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\CollectExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\CookieExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\ResponseExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\RequestExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\RedirectExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\UrlExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\ViewExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\TransExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\ValidatorExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\CollectionFilterDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + arguments: + methodName: 'abort' + negate: false + + - + class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + arguments: + methodName: 'abort' + negate: true + + - + class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + arguments: + methodName: throw + negate: false + + - + class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + arguments: + methodName: throw + negate: true + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\AppExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\ValueExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\Helpers\TapExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: NunoMaduro\Larastan\ReturnTypes\StorageDynamicStaticMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: NunoMaduro\Larastan\Types\GenericEloquentCollectionTypeNodeResolverExtension + tags: + - phpstan.phpDoc.typeNodeResolverExtension + + - + class: NunoMaduro\Larastan\Types\ViewStringTypeNodeResolverExtension + tags: + - phpstan.phpDoc.typeNodeResolverExtension + + - + class: NunoMaduro\Larastan\Rules\OctaneCompatibilityRule + + - + class: NunoMaduro\Larastan\Rules\NoModelMakeRule + + - + class: NunoMaduro\Larastan\Rules\NoUnnecessaryCollectionCallRule + arguments: + onlyMethods: %noUnnecessaryCollectionCallOnly% + excludeMethods: %noUnnecessaryCollectionCallExcept% + + - + class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyRule + + - + class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyStaticCallRule + + - + class: NunoMaduro\Larastan\Types\GenericEloquentBuilderTypeNodeResolverExtension + tags: + - phpstan.phpDoc.typeNodeResolverExtension + + - + class: NunoMaduro\Larastan\Types\ModelProperty\ModelPropertyTypeNodeResolverExtension + tags: + - phpstan.phpDoc.typeNodeResolverExtension + arguments: + active: %checkModelProperties% + + - + class: NunoMaduro\Larastan\Types\RelationParserHelper + arguments: + parser: @currentPhpVersionSimpleDirectParser + + - + class: NunoMaduro\Larastan\Properties\MigrationHelper + arguments: + databaseMigrationPath: %databaseMigrationsPath% + parser: @currentPhpVersionSimpleDirectParser + + - + class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertiesRuleHelper + + - + class: NunoMaduro\Larastan\Rules\ModelRuleHelper + + - + class: NunoMaduro\Larastan\Methods\BuilderHelper + arguments: + checkProperties: %checkModelProperties% + + - + class: NunoMaduro\Larastan\Rules\RelationExistenceRule + tags: + - phpstan.rule + + - + class: NunoMaduro\Larastan\Rules\CheckDispatchArgumentTypesCompatibleWithClassConstructorRule + arguments: + dispatchableClass: Illuminate\Foundation\Bus\Dispatchable + tags: + - phpstan.rules.rule + - + class: NunoMaduro\Larastan\Rules\CheckDispatchArgumentTypesCompatibleWithClassConstructorRule + arguments: + dispatchableClass: Illuminate\Foundation\Events\Dispatchable + tags: + - phpstan.rules.rule +rules: + - NunoMaduro\Larastan\Rules\RelationExistenceRule diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000000..7fec5052ae --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,13 @@ +includes: + - php-packages/phpstan/extension.neon + +parameters: + level: 4 + paths: + - framework/core/src + ignoreErrors: + - '#PHPDoc tag @var#' + excludePaths: + - *.blade.php + checkMissingIterableValueType: false + databaseMigrationsPath: ['framework/core/migrations'] From c5d8f0a46e0797ff7acb1fa2a2b565583c8aeee5 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sun, 17 Jul 2022 21:10:43 +0100 Subject: [PATCH 02/16] chore: level 4 phpstan Signed-off-by: Sami Mazouz --- .../core/src/Admin/Content/AdminPayload.php | 5 + framework/core/src/Api/Client.php | 7 +- .../ListNotificationsController.php | 6 +- .../src/Api/Serializer/AbstractSerializer.php | 8 +- .../Serializer/ExtensionReadmeSerializer.php | 3 +- .../src/Api/Serializer/ForumSerializer.php | 10 +- framework/core/src/Console/Schedule.php | 7 +- framework/core/src/Database/AbstractModel.php | 4 +- .../Database/Console/GenerateDumpCommand.php | 3 +- .../Database/DatabaseMigrationRepository.php | 5 +- framework/core/src/Database/Migrator.php | 10 +- .../Discussion/Access/DiscussionPolicy.php | 6 +- framework/core/src/Discussion/Discussion.php | 20 +- .../src/Discussion/DiscussionRepository.php | 25 +- .../IdWithTransliteratedSlugDriver.php | 6 + .../Search/Gambit/FulltextGambit.php | 2 + framework/core/src/Extend/ErrorHandling.php | 2 +- framework/core/src/Extend/Frontend.php | 2 +- framework/core/src/Extend/LanguagePack.php | 4 +- framework/core/src/Extend/Middleware.php | 6 +- framework/core/src/Extend/View.php | 2 +- framework/core/src/Extension/Extension.php | 6 +- .../core/src/Extension/ExtensionManager.php | 4 +- .../core/src/Filter/AbstractFilterer.php | 2 +- framework/core/src/Filter/FilterInterface.php | 3 - framework/core/src/Formatter/Formatter.php | 18 +- framework/core/src/Foundation/Application.php | 6 +- .../src/Foundation/Console/InfoCommand.php | 7 +- .../Foundation/ErrorHandling/HandledError.php | 2 +- .../core/src/Foundation/InstalledSite.php | 2 +- framework/core/src/Foundation/Paths.php | 8 +- .../src/Frontend/Compiler/FileVersioner.php | 8 +- .../core/src/Frontend/Compiler/JsCompiler.php | 7 +- .../src/Frontend/Compiler/LessCompiler.php | 4 +- .../Frontend/Compiler/RevisionCompiler.php | 19 +- framework/core/src/Frontend/Document.php | 7 +- framework/core/src/Group/GroupRepository.php | 14 +- framework/core/src/Http/AccessToken.php | 4 +- framework/core/src/Http/CookieFactory.php | 2 +- .../core/src/Http/Middleware/ResolveRoute.php | 6 +- framework/core/src/Http/Server.php | 11 +- .../core/src/Http/SlugDriverInterface.php | 9 + framework/core/src/Http/SlugManager.php | 5 + .../Install/Controller/IndexController.php | 5 - .../Install/Steps/EnableBundledExtensions.php | 7 +- .../Driver/EmailNotificationDriver.php | 2 +- .../core/src/Notification/Event/Read.php | 2 +- .../core/src/Notification/Event/ReadAll.php | 2 +- .../core/src/Notification/Notification.php | 6 +- .../src/Notification/NotificationMailer.php | 7 +- framework/core/src/Post/Post.php | 6 +- framework/core/src/Post/PostRepository.php | 10 +- framework/core/src/Queue/ExceptionHandler.php | 4 +- framework/core/src/Queue/QueueFactory.php | 2 +- .../core/src/Queue/QueueServiceProvider.php | 7 +- .../core/src/Search/AbstractRegexGambit.php | 4 +- .../core/src/Search/AbstractSearcher.php | 1 - framework/core/src/Search/GambitManager.php | 3 - .../src/Update/Controller/IndexController.php | 4 - .../core/src/User/Access/AbstractPolicy.php | 8 +- .../src/User/Command/RegisterUserHandler.php | 6 - framework/core/src/User/EmailToken.php | 4 +- framework/core/src/User/IdSlugDriver.php | 11 +- framework/core/src/User/RegistrationToken.php | 2 +- .../src/User/Search/Gambit/FulltextGambit.php | 2 + framework/core/src/User/User.php | 25 +- framework/core/src/User/UserRepository.php | 26 +- .../core/src/User/UserServiceProvider.php | 4 + framework/core/src/User/UserValidator.php | 2 +- .../core/src/User/UsernameSlugDriver.php | 9 + framework/core/src/helpers.php | 6 +- php-packages/phpstan/extension.neon | 8 + php-packages/phpstan/phpstan-baseline.neon | 4 + .../phpstan/src/Concerns/HasContainer.php | 72 - .../phpstan/src/Concerns/LoadsAuthModel.php | 31 - .../Contracts/Methods/PassableContract.php | 96 -- .../Contracts/Methods/Pipes/PipeContract.php | 28 - .../src/Contracts/Types/PassableContract.php | 29 - .../Contracts/Types/Pipes/PipeContract.php | 28 - .../phpstan/src/Methods/BuilderHelper.php | 241 --- .../EloquentBuilderForwardsCallsExtension.php | 161 -- .../phpstan/src/Methods/Extension.php | 64 - .../HigherOrderCollectionProxyExtension.php | 149 -- .../Methods/HigherOrderTapProxyExtension.php | 56 - php-packages/phpstan/src/Methods/Kernel.php | 79 - php-packages/phpstan/src/Methods/Macro.php | 265 --- ...FactoryMethodsClassReflectionExtension.php | 166 -- .../Methods/ModelForwardsCallsExtension.php | 219 --- .../phpstan/src/Methods/ModelTypeHelper.php | 38 - php-packages/phpstan/src/Methods/Passable.php | 224 --- .../phpstan/src/Methods/Pipes/Auths.php | 68 - .../phpstan/src/Methods/Pipes/Contracts.php | 67 - .../phpstan/src/Methods/Pipes/Facades.php | 66 - .../phpstan/src/Methods/Pipes/Macros.php | 105 -- .../phpstan/src/Methods/Pipes/Managers.php | 63 - .../phpstan/src/Methods/Pipes/SelfClass.php | 35 - .../RelationForwardsCallsExtension.php | 150 -- ...StorageMethodsClassReflectionExtension.php | 67 - ...rOrderCollectionProxyPropertyExtension.php | 124 -- .../src/Properties/MigrationHelper.php | 102 -- .../src/Properties/ModelAccessorExtension.php | 46 - .../phpstan/src/Properties/ModelProperty.php | 105 -- .../src/Properties/ModelPropertyExtension.php | 274 ---- .../Properties/ModelRelationsExtension.php | 124 -- .../Properties/ReflectionTypeContainer.php | 67 - .../src/Properties/SchemaAggregator.php | 439 ----- .../phpstan/src/Properties/SchemaColumn.php | 52 - .../phpstan/src/Properties/SchemaTable.php | 54 - ...notationScopeMethodParameterReflection.php | 77 - .../AnnotationScopeMethodReflection.php | 140 -- .../DynamicWhereParameterReflection.php | 50 - .../EloquentBuilderMethodReflection.php | 161 -- .../Reflection/ModelScopeMethodReflection.php | 127 -- .../src/Reflection/ReflectionHelper.php | 35 - .../src/Reflection/StaticMethodReflection.php | 99 -- .../ReturnTypes/BuilderModelFindExtension.php | 119 -- ...ectionFilterDynamicReturnTypeExtension.php | 119 -- ...DynamicStaticMethodReturnTypeExtension.php | 58 - ...AccessDynamicMethodReturnTypeExtension.php | 80 - .../ReturnTypes/EloquentBuilderExtension.php | 93 -- .../src/ReturnTypes/Helpers/AppExtension.php | 72 - .../ReturnTypes/Helpers/CollectExtension.php | 52 - .../src/ReturnTypes/Helpers/TapExtension.php | 56 - .../ReturnTypes/Helpers/TransExtension.php | 47 - .../Helpers/ValidatorExtension.php | 47 - .../ReturnTypes/Helpers/ValueExtension.php | 63 - .../HigherOrderTapProxyExtension.php | 63 - .../src/ReturnTypes/ModelExtension.php | 111 -- ...DynamicStaticMethodReturnTypeExtension.php | 64 - .../src/ReturnTypes/ModelFindExtension.php | 115 -- .../RelationCollectionExtension.php | 93 -- .../src/ReturnTypes/RelationFindExtension.php | 106 -- .../src/ReturnTypes/RequestExtension.php | 68 - ...DynamicStaticMethodReturnTypeExtension.php | 45 - .../src/ReturnTypes/TestCaseExtension.php | 60 - .../phpstan/src/Support/CollectionHelper.php | 106 -- .../HigherOrderCollectionProxyHelper.php | 141 -- ...AbortIfFunctionTypeSpecifyingExtension.php | 67 - ...oquentBuilderTypeNodeResolverExtension.php | 63 - ...entCollectionTypeNodeResolverExtension.php | 91 -- .../GenericModelPropertyType.php | 126 -- .../Types/ModelProperty/ModelPropertyType.php | 27 - ...ModelPropertyTypeNodeResolverExtension.php | 74 - ...ationsDynamicMethodReturnTypeExtension.php | 115 -- php-packages/phpstan/src/Types/Passable.php | 52 - ...lationDynamicMethodReturnTypeExtension.php | 72 - .../src/Types/RelationParserHelper.php | 139 -- .../phpstan/src/Types/ViewStringType.php | 87 - .../ViewStringTypeNodeResolverExtension.php | 33 - .../phpstan/stubs/Contracts/Container.stub | 16 - .../phpstan/stubs/Contracts/Pagination.stub | 17 - .../phpstan/stubs/Contracts/Support.stub | 19 - php-packages/phpstan/stubs/Flarum/User.stub | 31 - .../phpstan/stubs/Illuminate/Collection.stub | 148 -- .../Contracts/Container/Container.stub | 7 + .../stubs/Illuminate/Database/BelongsTo.stub | 27 - .../Illuminate/Database/BelongsToMany.stub | 112 -- .../Illuminate/Database/EloquentBuilder.stub | 454 ------ .../Database/EloquentCollection.stub | 43 - .../stubs/Illuminate/Database/Factory.stub | 81 - .../stubs/Illuminate/Database/Gate.stub | 31 - .../stubs/Illuminate/Database/HasMany.stub | 17 - .../Illuminate/Database/HasManyThrough.stub | 17 - .../stubs/Illuminate/Database/HasOne.stub | 17 - .../Illuminate/Database/HasOneOrMany.stub | 86 - .../Illuminate/Database/HasOneThrough.stub | 24 - .../stubs/Illuminate/Database/Model.stub | 28 - .../stubs/Illuminate/Database/MorphMany.stub | 24 - .../stubs/Illuminate/Database/MorphOne.stub | 17 - .../Illuminate/Database/MorphOneOrMany.stub | 17 - .../stubs/Illuminate/Database/MorphTo.stub | 11 - .../Illuminate/Database/MorphToMany.stub | 11 - .../Illuminate/Database/QueryBuilder.stub | 1440 ----------------- .../stubs/Illuminate/Database/Relation.stub | 24 - .../phpstan/stubs/Illuminate/Enumerable.stub | 58 - .../stubs/Illuminate/EnumeratesValues.stub | 36 - .../phpstan/stubs/Illuminate/Facades.stub | 30 - .../Illuminate/Filesystem/Filesystem.stub | 15 + .../phpstan/stubs/Illuminate/Helpers.stub | 48 - .../stubs/Illuminate/HigherOrderProxies.stub | 24 - .../phpstan/stubs/Illuminate/Logger.stub | 14 - .../phpstan/stubs/Illuminate/Mailable.stub | 22 - .../phpstan/stubs/Illuminate/Pagination.stub | 23 - .../Illuminate/Queue/ListenerOptions.stub | 13 + .../Illuminate/Support/ServiceProvider.stub | 15 + 185 files changed, 318 insertions(+), 10552 deletions(-) create mode 100644 php-packages/phpstan/phpstan-baseline.neon delete mode 100644 php-packages/phpstan/src/Concerns/HasContainer.php delete mode 100644 php-packages/phpstan/src/Concerns/LoadsAuthModel.php delete mode 100644 php-packages/phpstan/src/Contracts/Methods/PassableContract.php delete mode 100644 php-packages/phpstan/src/Contracts/Methods/Pipes/PipeContract.php delete mode 100644 php-packages/phpstan/src/Contracts/Types/PassableContract.php delete mode 100644 php-packages/phpstan/src/Contracts/Types/Pipes/PipeContract.php delete mode 100644 php-packages/phpstan/src/Methods/BuilderHelper.php delete mode 100644 php-packages/phpstan/src/Methods/EloquentBuilderForwardsCallsExtension.php delete mode 100644 php-packages/phpstan/src/Methods/Extension.php delete mode 100644 php-packages/phpstan/src/Methods/HigherOrderCollectionProxyExtension.php delete mode 100644 php-packages/phpstan/src/Methods/HigherOrderTapProxyExtension.php delete mode 100644 php-packages/phpstan/src/Methods/Kernel.php delete mode 100644 php-packages/phpstan/src/Methods/Macro.php delete mode 100644 php-packages/phpstan/src/Methods/ModelFactoryMethodsClassReflectionExtension.php delete mode 100644 php-packages/phpstan/src/Methods/ModelForwardsCallsExtension.php delete mode 100644 php-packages/phpstan/src/Methods/ModelTypeHelper.php delete mode 100644 php-packages/phpstan/src/Methods/Passable.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/Auths.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/Contracts.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/Facades.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/Macros.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/Managers.php delete mode 100644 php-packages/phpstan/src/Methods/Pipes/SelfClass.php delete mode 100644 php-packages/phpstan/src/Methods/RelationForwardsCallsExtension.php delete mode 100644 php-packages/phpstan/src/Methods/StorageMethodsClassReflectionExtension.php delete mode 100644 php-packages/phpstan/src/Properties/HigherOrderCollectionProxyPropertyExtension.php delete mode 100644 php-packages/phpstan/src/Properties/MigrationHelper.php delete mode 100644 php-packages/phpstan/src/Properties/ModelAccessorExtension.php delete mode 100644 php-packages/phpstan/src/Properties/ModelProperty.php delete mode 100644 php-packages/phpstan/src/Properties/ModelPropertyExtension.php delete mode 100644 php-packages/phpstan/src/Properties/ModelRelationsExtension.php delete mode 100644 php-packages/phpstan/src/Properties/ReflectionTypeContainer.php delete mode 100644 php-packages/phpstan/src/Properties/SchemaAggregator.php delete mode 100644 php-packages/phpstan/src/Properties/SchemaColumn.php delete mode 100644 php-packages/phpstan/src/Properties/SchemaTable.php delete mode 100644 php-packages/phpstan/src/Reflection/AnnotationScopeMethodParameterReflection.php delete mode 100644 php-packages/phpstan/src/Reflection/AnnotationScopeMethodReflection.php delete mode 100644 php-packages/phpstan/src/Reflection/DynamicWhereParameterReflection.php delete mode 100644 php-packages/phpstan/src/Reflection/EloquentBuilderMethodReflection.php delete mode 100644 php-packages/phpstan/src/Reflection/ModelScopeMethodReflection.php delete mode 100644 php-packages/phpstan/src/Reflection/ReflectionHelper.php delete mode 100644 php-packages/phpstan/src/Reflection/StaticMethodReflection.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/BuilderModelFindExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/CollectionFilterDynamicReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/CollectionMakeDynamicStaticMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/ContainerArrayAccessDynamicMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/EloquentBuilderExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/AppExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/CollectExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/TapExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/TransExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/ValidatorExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/Helpers/ValueExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/HigherOrderTapProxyExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/ModelExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/ModelFactoryDynamicStaticMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/ModelFindExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/RelationCollectionExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/RelationFindExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/RequestExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/StorageDynamicStaticMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/ReturnTypes/TestCaseExtension.php delete mode 100644 php-packages/phpstan/src/Support/CollectionHelper.php delete mode 100644 php-packages/phpstan/src/Support/HigherOrderCollectionProxyHelper.php delete mode 100644 php-packages/phpstan/src/Types/AbortIfFunctionTypeSpecifyingExtension.php delete mode 100644 php-packages/phpstan/src/Types/GenericEloquentBuilderTypeNodeResolverExtension.php delete mode 100644 php-packages/phpstan/src/Types/GenericEloquentCollectionTypeNodeResolverExtension.php delete mode 100644 php-packages/phpstan/src/Types/ModelProperty/GenericModelPropertyType.php delete mode 100644 php-packages/phpstan/src/Types/ModelProperty/ModelPropertyType.php delete mode 100644 php-packages/phpstan/src/Types/ModelProperty/ModelPropertyTypeNodeResolverExtension.php delete mode 100644 php-packages/phpstan/src/Types/ModelRelationsDynamicMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/Types/Passable.php delete mode 100644 php-packages/phpstan/src/Types/RelationDynamicMethodReturnTypeExtension.php delete mode 100644 php-packages/phpstan/src/Types/RelationParserHelper.php delete mode 100644 php-packages/phpstan/src/Types/ViewStringType.php delete mode 100644 php-packages/phpstan/src/Types/ViewStringTypeNodeResolverExtension.php delete mode 100644 php-packages/phpstan/stubs/Contracts/Container.stub delete mode 100644 php-packages/phpstan/stubs/Contracts/Pagination.stub delete mode 100644 php-packages/phpstan/stubs/Contracts/Support.stub delete mode 100644 php-packages/phpstan/stubs/Flarum/User.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Collection.stub create mode 100644 php-packages/phpstan/stubs/Illuminate/Contracts/Container/Container.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/BelongsTo.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/BelongsToMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/EloquentBuilder.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/EloquentCollection.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/Factory.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/Gate.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/HasMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/HasManyThrough.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/HasOne.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/HasOneOrMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/HasOneThrough.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/Model.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/MorphMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/MorphOne.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/MorphOneOrMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/MorphTo.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/MorphToMany.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/QueryBuilder.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Database/Relation.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Enumerable.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/EnumeratesValues.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Facades.stub create mode 100644 php-packages/phpstan/stubs/Illuminate/Filesystem/Filesystem.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Helpers.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/HigherOrderProxies.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Logger.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Mailable.stub delete mode 100644 php-packages/phpstan/stubs/Illuminate/Pagination.stub create mode 100644 php-packages/phpstan/stubs/Illuminate/Queue/ListenerOptions.stub create mode 100644 php-packages/phpstan/stubs/Illuminate/Support/ServiceProvider.stub diff --git a/framework/core/src/Admin/Content/AdminPayload.php b/framework/core/src/Admin/Content/AdminPayload.php index 8c4237c8ee..0eb4736aab 100644 --- a/framework/core/src/Admin/Content/AdminPayload.php +++ b/framework/core/src/Admin/Content/AdminPayload.php @@ -42,6 +42,11 @@ class AdminPayload */ protected $db; + /** + * @var Dispatcher + */ + protected $events; + /** * @param Container $container * @param SettingsRepositoryInterface $settings diff --git a/framework/core/src/Api/Client.php b/framework/core/src/Api/Client.php index 457ec41acc..a65fd06db4 100644 --- a/framework/core/src/Api/Client.php +++ b/framework/core/src/Api/Client.php @@ -26,12 +26,12 @@ class Client protected $pipe; /** - * @var User + * @var User|null */ protected $actor; /** - * @var ServerRequestInterface + * @var ServerRequestInterface|null */ protected $parent; @@ -45,9 +45,6 @@ class Client */ protected $body = []; - /** - * @param Container $container - */ public function __construct(MiddlewarePipeInterface $pipe) { $this->pipe = $pipe; diff --git a/framework/core/src/Api/Controller/ListNotificationsController.php b/framework/core/src/Api/Controller/ListNotificationsController.php index aff1f54d6d..12fc3b9271 100644 --- a/framework/core/src/Api/Controller/ListNotificationsController.php +++ b/framework/core/src/Api/Controller/ListNotificationsController.php @@ -113,15 +113,15 @@ private function loadSubjectDiscussions(array $notifications) $ids = []; foreach ($notifications as $notification) { - if ($notification->subject && $notification->subject->discussion_id) { + if ($notification->subject && isset($notification->subject->discussion_id)) { $ids[] = $notification->subject->discussion_id; } } - $discussions = Discussion::find(array_unique($ids)); + $discussions = Discussion::query()->find(array_unique($ids)); foreach ($notifications as $notification) { - if ($notification->subject && $notification->subject->discussion_id) { + if ($notification->subject && isset($notification->subject->discussion_id)) { $notification->subject->setRelation('discussion', $discussions->find($notification->subject->discussion_id)); } } diff --git a/framework/core/src/Api/Serializer/AbstractSerializer.php b/framework/core/src/Api/Serializer/AbstractSerializer.php index a6892f129f..ce707f18ed 100644 --- a/framework/core/src/Api/Serializer/AbstractSerializer.php +++ b/framework/core/src/Api/Serializer/AbstractSerializer.php @@ -42,12 +42,12 @@ abstract class AbstractSerializer extends BaseAbstractSerializer protected static $container; /** - * @var callable[] + * @var array */ protected static $attributeMutators = []; /** - * @var array + * @var array> */ protected static $customRelations = []; @@ -189,7 +189,7 @@ public function hasMany($model, $serializer, $relation = null) * @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer * @param string|null $relation * @param bool $many - * @return Relationship + * @return Relationship|null */ protected function buildRelationship($model, $serializer, $relation = null, $many = false) { @@ -210,6 +210,8 @@ protected function buildRelationship($model, $serializer, $relation = null, $man return new Relationship($element); } + + return null; } /** diff --git a/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php b/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php index e59e4f74f4..7f40eebef7 100644 --- a/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php +++ b/framework/core/src/Api/Serializer/ExtensionReadmeSerializer.php @@ -12,7 +12,8 @@ class ExtensionReadmeSerializer extends AbstractSerializer { /** - * {@inheritdoc} + * @param \Flarum\Extension\Extension $extension + * @return array */ protected function getDefaultAttributes($extension) { diff --git a/framework/core/src/Api/Serializer/ForumSerializer.php b/framework/core/src/Api/Serializer/ForumSerializer.php index 346f968f73..c61f365010 100644 --- a/framework/core/src/Api/Serializer/ForumSerializer.php +++ b/framework/core/src/Api/Serializer/ForumSerializer.php @@ -15,6 +15,7 @@ use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Filesystem\Cloud; use Illuminate\Contracts\Filesystem\Factory; +use Illuminate\Contracts\Filesystem\Filesystem; class ForumSerializer extends AbstractSerializer { @@ -39,7 +40,7 @@ class ForumSerializer extends AbstractSerializer protected $url; /** - * @var Cloud + * @var Filesystem */ protected $assetsFilesystem; @@ -62,7 +63,7 @@ public function __construct(Config $config, Factory $filesystemFactory, Settings */ public function getId($model) { - return 1; + return '1'; } /** @@ -132,6 +133,9 @@ protected function getFaviconUrl() public function getAssetUrl($assetPath): string { - return $this->assetsFilesystem->url($assetPath); + /** @var Cloud $assetsFilesystem */ + $assetsFilesystem = $this->assetsFilesystem; + + return $assetsFilesystem->url($assetPath); } } diff --git a/framework/core/src/Console/Schedule.php b/framework/core/src/Console/Schedule.php index 6deba8eb09..e59e571693 100644 --- a/framework/core/src/Console/Schedule.php +++ b/framework/core/src/Console/Schedule.php @@ -18,17 +18,20 @@ class Schedule extends LaravelSchedule public function dueEvents($container) { return (new Collection($this->events))->filter->isDue(new class($container) { + /** @var Config */ + protected $config; + public function __construct($container) { $this->config = $container->make(Config::class); } - public function isDownForMaintenance() + public function isDownForMaintenance(): bool { return $this->config->inMaintenanceMode(); } - public function environment() + public function environment(): string { return ''; } diff --git a/framework/core/src/Database/AbstractModel.php b/framework/core/src/Database/AbstractModel.php index 6da46666a7..e926bcf60d 100644 --- a/framework/core/src/Database/AbstractModel.php +++ b/framework/core/src/Database/AbstractModel.php @@ -20,6 +20,8 @@ * Adds the ability for custom relations to be added to a model during runtime. * These relations behave in the same way that you would expect; they can be * queried, eager loaded, and accessed as an attribute. + * + * @property-read int|null $id */ abstract class AbstractModel extends Eloquent { @@ -82,7 +84,7 @@ public static function boot() /** * {@inheritdoc} */ - public function __construct(array $attributes = []) + final public function __construct(array $attributes = []) { $this->attributes = []; diff --git a/framework/core/src/Database/Console/GenerateDumpCommand.php b/framework/core/src/Database/Console/GenerateDumpCommand.php index 84bfd5d50f..eb958792e9 100644 --- a/framework/core/src/Database/Console/GenerateDumpCommand.php +++ b/framework/core/src/Database/Console/GenerateDumpCommand.php @@ -12,6 +12,7 @@ use Flarum\Console\AbstractCommand; use Flarum\Foundation\Paths; use Illuminate\Database\Connection; +use Illuminate\Database\MySqlConnection; class GenerateDumpCommand extends AbstractCommand { @@ -53,7 +54,7 @@ protected function configure() protected function fire() { $dumpPath = __DIR__.'/../../../migrations/install.dump'; - /** @var Connection */ + /** @var Connection&MySqlConnection */ $connection = resolve('db.connection'); $connection diff --git a/framework/core/src/Database/DatabaseMigrationRepository.php b/framework/core/src/Database/DatabaseMigrationRepository.php index 7b781210b7..4a880d0eff 100644 --- a/framework/core/src/Database/DatabaseMigrationRepository.php +++ b/framework/core/src/Database/DatabaseMigrationRepository.php @@ -9,6 +9,7 @@ namespace Flarum\Database; +use Illuminate\Database\Connection; use Illuminate\Database\ConnectionInterface; class DatabaseMigrationRepository implements MigrationRepositoryInterface @@ -16,7 +17,7 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface /** * The name of the database connection to use. * - * @var ConnectionInterface + * @var Connection */ protected $connection; @@ -30,7 +31,7 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface /** * Create a new database migration repository instance. * - * @param \Illuminate\Database\ConnectionInterface $connection + * @param Connection $connection * @param string $table */ public function __construct(ConnectionInterface $connection, $table) diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 03b0dde1ae..34ed0355d3 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -11,6 +11,7 @@ use Exception; use Flarum\Extension\Extension; +use Illuminate\Database\Connection; use Illuminate\Database\ConnectionInterface; use Illuminate\Database\MySqlConnection; use Illuminate\Filesystem\Filesystem; @@ -39,11 +40,12 @@ class Migrator /** * The output interface implementation. * - * @var OutputInterface + * @var OutputInterface|null */ protected $output; + /** - * @var ConnectionInterface|MySqlConnection + * @var Connection|MySqlConnection */ protected $connection; @@ -51,7 +53,7 @@ class Migrator * Create a new migrator instance. * * @param MigrationRepositoryInterface $repository - * @param ConnectionInterface $connection + * @param Connection $connection * @param Filesystem $files */ public function __construct( @@ -245,6 +247,8 @@ public function resolve($path, $file) if ($this->files->exists($migration)) { return $this->files->getRequire($migration); } + + return []; } /** diff --git a/framework/core/src/Discussion/Access/DiscussionPolicy.php b/framework/core/src/Discussion/Access/DiscussionPolicy.php index 1f98151025..202d9a49ee 100644 --- a/framework/core/src/Discussion/Access/DiscussionPolicy.php +++ b/framework/core/src/Discussion/Access/DiscussionPolicy.php @@ -22,10 +22,6 @@ class DiscussionPolicy extends AbstractPolicy */ protected $settings; - /** - * @param SettingsRepositoryInterface $settings - * @param Dispatcher $events - */ public function __construct(SettingsRepositoryInterface $settings) { $this->settings = $settings; @@ -34,7 +30,7 @@ public function __construct(SettingsRepositoryInterface $settings) /** * @param User $actor * @param string $ability - * @return bool|null + * @return string|void */ public function can(User $actor, $ability) { diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index e813422964..cebefb13d3 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -23,6 +23,7 @@ use Flarum\Post\Post; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Support\Str; /** @@ -83,7 +84,7 @@ class Discussion extends AbstractModel /** * The user for which the state relationship should be loaded. * - * @var User + * @var User|null */ protected static $stateUser; @@ -395,11 +396,8 @@ public function readers() * relation), then the static `$stateUser` property is used. * * @see Discussion::setStateUser() - * - * @param User|null $user - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function state(User $user = null) + public function state(User $user = null): HasOne { $user = $user ?: static::$stateUser; @@ -409,12 +407,10 @@ public function state(User $user = null) /** * Get the state model for a user, or instantiate a new one if it does not * exist. - * - * @param User $user - * @return \Flarum\Discussion\UserState */ - public function stateFor(User $user) + public function stateFor(User $user): UserState { + /** @var UserState|null $state */ $state = $this->state($user)->first(); if (! $state) { @@ -428,8 +424,6 @@ public function stateFor(User $user) /** * Set the user for which the state relationship should be loaded. - * - * @param User $user */ public static function setStateUser(User $user) { @@ -440,10 +434,8 @@ public static function setStateUser(User $user) * Set the discussion title. * * This automatically creates a matching slug for the discussion. - * - * @param string $title */ - protected function setTitleAttribute($title) + protected function setTitleAttribute(string $title) { $this->attributes['title'] = $title; $this->slug = Str::slug( diff --git a/framework/core/src/Discussion/DiscussionRepository.php b/framework/core/src/Discussion/DiscussionRepository.php index a50ec55378..2619bc9fcd 100644 --- a/framework/core/src/Discussion/DiscussionRepository.php +++ b/framework/core/src/Discussion/DiscussionRepository.php @@ -17,7 +17,7 @@ class DiscussionRepository /** * Get a new query builder for the discussions table. * - * @return Builder + * @return Builder */ public function query() { @@ -29,12 +29,12 @@ public function query() * certain user, or throw an exception. * * @param int $id - * @param User $user + * @param User|null $user * @return \Flarum\Discussion\Discussion */ public function findOrFail($id, User $user = null) { - $query = Discussion::where('id', $id); + $query = $this->query()->where('id', $id); return $this->scopeVisibleTo($query, $user)->firstOrFail(); } @@ -42,26 +42,25 @@ public function findOrFail($id, User $user = null) /** * Get the IDs of discussions which a user has read completely. * - * @deprecated 1.3 Use `getReadIdsQuery` instead - * * @param User $user - * @return array + * @return \Illuminate\Database\Eloquent\Collection + * @deprecated 1.3 Use `getReadIdsQuery` instead */ public function getReadIds(User $user) { - return $this->getReadIdsQuery($user) - ->all(); + return $this->getReadIdsQuery($user)->get(); } /** * Get a query containing the IDs of discussions which a user has read completely. * * @param User $user - * @return Builder + * @return Builder */ public function getReadIdsQuery(User $user): Builder { - return Discussion::leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id') + return Discussion::query() + ->leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id') ->where('discussion_user.user_id', $user->id) ->whereColumn('last_read_post_number', '>=', 'last_post_number') ->select('id'); @@ -70,9 +69,9 @@ public function getReadIdsQuery(User $user): Builder /** * Scope a query to only include records that are visible to a user. * - * @param Builder $query - * @param User $user - * @return Builder + * @param Builder $query + * @param User|null $user + * @return Builder */ protected function scopeVisibleTo(Builder $query, User $user = null) { diff --git a/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php b/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php index 3a1cb58efc..2f55220f7e 100644 --- a/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php +++ b/framework/core/src/Discussion/IdWithTransliteratedSlugDriver.php @@ -13,6 +13,9 @@ use Flarum\Http\SlugDriverInterface; use Flarum\User\User; +/** + * @implements SlugDriverInterface + */ class IdWithTransliteratedSlugDriver implements SlugDriverInterface { /** @@ -25,6 +28,9 @@ public function __construct(DiscussionRepository $discussions) $this->discussions = $discussions; } + /** + * @param Discussion $instance + */ public function toSlug(AbstractModel $instance): string { return $instance->id.(trim($instance->slug) ? '-'.$instance->slug : ''); diff --git a/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php b/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php index ed0b16f2a4..20cd7227ed 100644 --- a/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php +++ b/framework/core/src/Discussion/Search/Gambit/FulltextGambit.php @@ -65,5 +65,7 @@ public function apply(SearchState $search, $bit) $query->orderByRaw('MATCH('.$grammar->wrap('discussions.title').') AGAINST (?) desc', [$bit]); $query->orderBy('posts_ft.score', 'desc'); }); + + return true; } } diff --git a/framework/core/src/Extend/ErrorHandling.php b/framework/core/src/Extend/ErrorHandling.php index 7d75465d4a..135c795e59 100644 --- a/framework/core/src/Extend/ErrorHandling.php +++ b/framework/core/src/Extend/ErrorHandling.php @@ -76,7 +76,7 @@ public function type(string $exceptionClass, string $errorType): self * contain "details" - arbitrary data with more context for to the error. * * @param string $exceptionClass: The ::class attribute of the exception class. - * @param string $errorType: The ::class attribute of the handler class. + * @param string $handlerClass: The ::class attribute of the handler class. * @return self */ public function handler(string $exceptionClass, string $handlerClass): self diff --git a/framework/core/src/Extend/Frontend.php b/framework/core/src/Extend/Frontend.php index f44d2ee433..1bab3522db 100644 --- a/framework/core/src/Extend/Frontend.php +++ b/framework/core/src/Extend/Frontend.php @@ -110,7 +110,7 @@ public function removeRoute(string $name): self /** * Modify the content of the frontend. * - * @param callable|string|null $content + * @param callable|string|null $callback * * The content can be a closure or an invokable class, and should accept: * - \Flarum\Frontend\Document $document diff --git a/framework/core/src/Extend/LanguagePack.php b/framework/core/src/Extend/LanguagePack.php index 9807ce9780..96cc87503c 100644 --- a/framework/core/src/Extend/LanguagePack.php +++ b/framework/core/src/Extend/LanguagePack.php @@ -31,7 +31,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface /** * LanguagePack constructor. * - * @param string|null $path: Path to yaml language files. + * @param string $path: Path to yaml language files. */ public function __construct(string $path = '/locale') { @@ -115,7 +115,7 @@ private function shouldLoad(SplFileInfo $file, Container $container) return true; } - /** @var ExtensionManager $extensions */ + /** @var ExtensionManager|null $extensions */ static $extensions; $extensions = $extensions ?? $container->make(ExtensionManager::class); diff --git a/framework/core/src/Extend/Middleware.php b/framework/core/src/Extend/Middleware.php index e7fe119bee..e22f3e4587 100644 --- a/framework/core/src/Extend/Middleware.php +++ b/framework/core/src/Extend/Middleware.php @@ -48,7 +48,7 @@ public function add(string $middleware): self * * @param string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $middleware: ::class attribute of the middleware class. + * @param string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -77,7 +77,7 @@ public function remove(string $middleware): self * * @param string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $middleware: ::class attribute of the middleware class. + * @param string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ @@ -93,7 +93,7 @@ public function insertBefore(string $originalMiddleware, string $newMiddleware): * * @param string $originalMiddleware: ::class attribute of the original middleware class. * Or container binding name. - * @param string $middleware: ::class attribute of the middleware class. + * @param string $newMiddleware: ::class attribute of the middleware class. * Must implement \Psr\Http\Server\MiddlewareInterface. * @return self */ diff --git a/framework/core/src/Extend/View.php b/framework/core/src/Extend/View.php index b40b410751..3d42fb4897 100644 --- a/framework/core/src/Extend/View.php +++ b/framework/core/src/Extend/View.php @@ -65,7 +65,7 @@ public function extendNamespace(string $namespace, $hints): self public function extend(Container $container, Extension $extension = null) { - $container->resolving(Factory::class, function (Factory $view) { + $container->resolving(Factory::class, function (\Illuminate\View\Factory $view) { foreach ($this->namespaces as $namespace => $hints) { $view->addNamespace($namespace, $hints); } diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index d841a2f3e1..dfe664d22b 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -214,9 +214,6 @@ public function setVersion($version) * @param array $extensionSet: An associative array where keys are the composer package names * of installed extensions. Used to figure out which dependencies * are flarum extensions. - * @param array $enabledIds: An associative array where keys are the composer package names - * of enabled extensions. Used to figure out optional dependencies. - * * @internal */ public function calculateDependencies($extensionSet) @@ -489,6 +486,7 @@ public function hasMigrations() } /** + * @return int|void * @internal */ public function migrate(Migrator $migrator, $direction = 'up') @@ -498,7 +496,7 @@ public function migrate(Migrator $migrator, $direction = 'up') } if ($direction == 'up') { - return $migrator->run($this->getPath().'/migrations', $this); + $migrator->run($this->getPath().'/migrations', $this); } else { return $migrator->reset($this->getPath().'/migrations', $this); } diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php index d958e9d177..e368a65dc2 100644 --- a/framework/core/src/Extension/ExtensionManager.php +++ b/framework/core/src/Extension/ExtensionManager.php @@ -333,13 +333,13 @@ public function migrate(Extension $extension, $direction = 'up') * Runs the database migrations to reset the database to its old state. * * @param Extension $extension - * @return array Notes from the migrator. + * @return void * * @internal */ public function migrateDown(Extension $extension) { - return $this->migrate($extension, 'down'); + $this->migrate($extension, 'down'); } /** diff --git a/framework/core/src/Filter/AbstractFilterer.php b/framework/core/src/Filter/AbstractFilterer.php index 7e216f4686..db18b21ecc 100644 --- a/framework/core/src/Filter/AbstractFilterer.php +++ b/framework/core/src/Filter/AbstractFilterer.php @@ -39,7 +39,7 @@ abstract protected function getQuery(User $actor): Builder; /** * @param QueryCriteria $criteria - * @param mixed|null $limit + * @param int|null $limit * @param int $offset * * @return QueryResults diff --git a/framework/core/src/Filter/FilterInterface.php b/framework/core/src/Filter/FilterInterface.php index a5853c4bd7..edfdf5ce8a 100644 --- a/framework/core/src/Filter/FilterInterface.php +++ b/framework/core/src/Filter/FilterInterface.php @@ -18,9 +18,6 @@ public function getFilterKey(): string; /** * Filters a query. - * - * @param FilterState $filter - * @param string $value The value of the requested filter */ public function filter(FilterState $filterState, string $filterValue, bool $negate); } diff --git a/framework/core/src/Formatter/Formatter.php b/framework/core/src/Formatter/Formatter.php index 7cd872401c..46958d0e96 100644 --- a/framework/core/src/Formatter/Formatter.php +++ b/framework/core/src/Formatter/Formatter.php @@ -9,8 +9,6 @@ namespace Flarum\Formatter; -use DOMDocument; -use DOMElement; use Illuminate\Contracts\Cache\Repository; use Psr\Http\Message\ServerRequestInterface; use s9e\TextFormatter\Configurator; @@ -152,8 +150,8 @@ protected function getConfigurator() $configurator->rootRules->enableAutoLineBreaks(); - $configurator->rendering->engine = 'PHP'; - $configurator->rendering->engine->cacheDir = $this->cacheDir; + $configurator->rendering->setEngine('PHP'); + $configurator->rendering->getEngine()->cacheDir = $this->cacheDir; // @phpstan-ignore-line $configurator->enableJavaScript(); $configurator->javascript->exports = ['preview']; @@ -161,9 +159,9 @@ protected function getConfigurator() $configurator->javascript->setMinifier('MatthiasMullieMinify') ->keepGoing = true; - $configurator->Escaper; - $configurator->Autoemail; - $configurator->Autolink; + $configurator->Escaper; /** @phpstan-ignore-line */ + $configurator->Autoemail; /** @phpstan-ignore-line */ + $configurator->Autolink; /** @phpstan-ignore-line */ $configurator->tags->onDuplicate('replace'); foreach ($this->configurationCallbacks as $callback) { @@ -180,11 +178,13 @@ protected function getConfigurator() */ protected function configureExternalLinks(Configurator $configurator) { - /** @var DOMDocument $dom */ + /** + * @var Configurator\Items\TemplateDocument $dom + */ $dom = $configurator->tags['URL']->template->asDOM(); - /** @var DOMElement $a */ foreach ($dom->getElementsByTagName('a') as $a) { + /** @var \s9e\SweetDOM\Element $a */ $a->prependXslCopyOf('@target'); $a->prependXslCopyOf('@rel'); } diff --git a/framework/core/src/Foundation/Application.php b/framework/core/src/Foundation/Application.php index dff5fc8a8d..a4b81a12aa 100644 --- a/framework/core/src/Foundation/Application.php +++ b/framework/core/src/Foundation/Application.php @@ -140,10 +140,10 @@ protected function registerBaseBindings() * Use container inside flarum instead. */ $this->container->instance('app', $this->container); - $this->container->alias('app', \Illluminate\Container\Container::class); + $this->container->alias('app', \Illuminate\Container\Container::class); $this->container->instance('container', $this->container); - $this->container->alias('container', \Illluminate\Container\Container::class); + $this->container->alias('container', \Illuminate\Container\Container::class); $this->container->instance('flarum', $this); $this->container->alias('flarum', self::class); @@ -170,7 +170,7 @@ protected function registerBaseServiceProviders() */ public function register($provider, $options = [], $force = false) { - if ($registered = $this->getProvider($provider) && ! $force) { + if (($registered = $this->getProvider($provider)) && ! $force) { return $registered; } diff --git a/framework/core/src/Foundation/Console/InfoCommand.php b/framework/core/src/Foundation/Console/InfoCommand.php index 52a49502ce..a8c8dea70f 100644 --- a/framework/core/src/Foundation/Console/InfoCommand.php +++ b/framework/core/src/Foundation/Console/InfoCommand.php @@ -15,6 +15,7 @@ use Flarum\Foundation\Config; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Queue\Queue; +use Illuminate\Database\Connection; use Illuminate\Database\ConnectionInterface; use Illuminate\Support\Str; use PDO; @@ -39,14 +40,18 @@ class InfoCommand extends AbstractCommand protected $settings; /** - * @var ConnectionInterface + * @var Connection */ protected $db; + /** * @var Queue */ private $queue; + /** + * @param Connection $db + */ public function __construct( ExtensionManager $extensions, Config $config, diff --git a/framework/core/src/Foundation/ErrorHandling/HandledError.php b/framework/core/src/Foundation/ErrorHandling/HandledError.php index 026d1b13e6..8ef07a6d5c 100644 --- a/framework/core/src/Foundation/ErrorHandling/HandledError.php +++ b/framework/core/src/Foundation/ErrorHandling/HandledError.php @@ -28,7 +28,7 @@ class HandledError public static function unknown(Throwable $error) { - return new static($error, 'unknown', 500); + return new self($error, 'unknown', 500); } public function __construct(Throwable $error, $type, $statusCode) diff --git a/framework/core/src/Foundation/InstalledSite.php b/framework/core/src/Foundation/InstalledSite.php index 790066a7c3..6ccc248f1c 100644 --- a/framework/core/src/Foundation/InstalledSite.php +++ b/framework/core/src/Foundation/InstalledSite.php @@ -104,7 +104,7 @@ protected function bootLaravel(): Container $container->instance('flarum.config', $this->config); $container->alias('flarum.config', Config::class); $container->instance('flarum.debug', $this->config->inDebugMode()); - $container->instance('config', $config = $this->getIlluminateConfig($laravel)); + $container->instance('config', $config = $this->getIlluminateConfig()); $container->instance('flarum.maintenance.handler', new MaintenanceModeHandler); $this->registerLogger($container); diff --git a/framework/core/src/Foundation/Paths.php b/framework/core/src/Foundation/Paths.php index b527cd50bb..a873123f85 100644 --- a/framework/core/src/Foundation/Paths.php +++ b/framework/core/src/Foundation/Paths.php @@ -12,10 +12,10 @@ use InvalidArgumentException; /** - * @property-read string base - * @property-read string public - * @property-read string storage - * @property-read string vendor + * @property-read string $base + * @property-read string $public + * @property-read string $storage + * @property-read string $vendor */ class Paths { diff --git a/framework/core/src/Frontend/Compiler/FileVersioner.php b/framework/core/src/Frontend/Compiler/FileVersioner.php index de2766c206..7c03df2c29 100644 --- a/framework/core/src/Frontend/Compiler/FileVersioner.php +++ b/framework/core/src/Frontend/Compiler/FileVersioner.php @@ -27,8 +27,8 @@ public function __construct(Filesystem $filesystem) public function putRevision(string $file, ?string $revision) { - if ($this->filesystem->has(static::REV_MANIFEST)) { - $manifest = json_decode($this->filesystem->read(static::REV_MANIFEST), true); + if ($this->filesystem->exists(static::REV_MANIFEST)) { + $manifest = json_decode($this->filesystem->get(static::REV_MANIFEST), true); } else { $manifest = []; } @@ -44,8 +44,8 @@ public function putRevision(string $file, ?string $revision) public function getRevision(string $file): ?string { - if ($this->filesystem->has(static::REV_MANIFEST)) { - $manifest = json_decode($this->filesystem->read(static::REV_MANIFEST), true); + if ($this->filesystem->exists(static::REV_MANIFEST)) { + $manifest = json_decode($this->filesystem->get(static::REV_MANIFEST), true); return Arr::get($manifest, $file); } diff --git a/framework/core/src/Frontend/Compiler/JsCompiler.php b/framework/core/src/Frontend/Compiler/JsCompiler.php index a092f6af0b..ddb3b0bc88 100644 --- a/framework/core/src/Frontend/Compiler/JsCompiler.php +++ b/framework/core/src/Frontend/Compiler/JsCompiler.php @@ -49,10 +49,13 @@ protected function save(string $file, array $sources): bool $line += substr_count($content, "\n") + 1; } + /** @var \Illuminate\Contracts\Filesystem\Cloud $assetsDir */ + $assetsDir = $this->assetsDir; + // Add a comment to the end of our file to point to the sourcemap // we just constructed. We will then store the JS file and the map // in our asset directory. - $output[] = '//# sourceMappingURL='.$this->assetsDir->url($mapFile); + $output[] = '//# sourceMappingURL='.$assetsDir->url($mapFile); $this->assetsDir->put($file, implode("\n", $output)); $this->assetsDir->put($mapFile, json_encode($map, JSON_UNESCAPED_SLASHES)); @@ -72,7 +75,7 @@ protected function delete(string $file) { parent::delete($file); - if ($this->assetsDir->has($mapFile = $file.'.map')) { + if ($this->assetsDir->exists($mapFile = $file.'.map')) { $this->assetsDir->delete($mapFile); } } diff --git a/framework/core/src/Frontend/Compiler/LessCompiler.php b/framework/core/src/Frontend/Compiler/LessCompiler.php index e6c92c928c..9e070205c8 100644 --- a/framework/core/src/Frontend/Compiler/LessCompiler.php +++ b/framework/core/src/Frontend/Compiler/LessCompiler.php @@ -35,12 +35,12 @@ class LessCompiler extends RevisionCompiler protected $customFunctions = []; /** - * @var Collection + * @var Collection|null */ protected $lessImportOverrides; /** - * @var Collection + * @var Collection|null */ protected $fileSourceOverrides; diff --git a/framework/core/src/Frontend/Compiler/RevisionCompiler.php b/framework/core/src/Frontend/Compiler/RevisionCompiler.php index edb88bafcf..c7b5229b43 100644 --- a/framework/core/src/Frontend/Compiler/RevisionCompiler.php +++ b/framework/core/src/Frontend/Compiler/RevisionCompiler.php @@ -24,6 +24,7 @@ class RevisionCompiler implements CompilerInterface * @var Filesystem */ protected $assetsDir; + /** * @var VersionerInterface */ @@ -71,7 +72,7 @@ public function commit(bool $force = false) // In case the previous and current revisions do not match // Or no file was written yet, let's save the file to disk. - if ($force || $oldRevision !== $newRevision || ! $this->assetsDir->has($this->filename)) { + if ($force || $oldRevision !== $newRevision || ! $this->assetsDir->exists($this->filename)) { if (! $this->save($this->filename, $sources)) { // If no file was written (because the sources were empty), we // will set the revision to a special value so that we can tell @@ -120,7 +121,10 @@ public function getUrl(): ?string return null; } - $url = $this->assetsDir->url($this->filename); + /** @var \Illuminate\Contracts\Filesystem\Cloud $assetDir */ + $assetDir = $this->assetsDir; + + $url = $assetDir->url($this->filename); // Append revision as GET param to signify that there's been // a change to the file and it should be refreshed. @@ -145,7 +149,6 @@ protected function save(string $file, array $sources): bool /** * @param SourceInterface[] $sources - * @return string */ protected function compile(array $sources): string { @@ -158,10 +161,6 @@ protected function compile(array $sources): string return $output; } - /** - * @param string $string - * @return string - */ protected function format(string $string): string { return $string; @@ -169,7 +168,6 @@ protected function format(string $string): string /** * @param SourceInterface[] $sources - * @return string */ protected function calculateRevision(array $sources): string { @@ -196,12 +194,9 @@ public function flush() } } - /** - * @param string $file - */ protected function delete(string $file) { - if ($this->assetsDir->has($file)) { + if ($this->assetsDir->exists($file)) { $this->assetsDir->delete($file); } } diff --git a/framework/core/src/Frontend/Document.php b/framework/core/src/Frontend/Document.php index b839fca195..4b947059cc 100644 --- a/framework/core/src/Frontend/Document.php +++ b/framework/core/src/Frontend/Document.php @@ -221,14 +221,13 @@ protected function makeTitle(): string return resolve(TitleDriverInterface::class)->makeTitle($this, $this->request, $this->forumApiDocument); } - /** - * @return View - */ - protected function makeLayout(): View + protected function makeLayout(): ?View { if ($this->layoutView) { return $this->view->make($this->layoutView)->with('content', $this->makeContent()); } + + return null; } /** diff --git a/framework/core/src/Group/GroupRepository.php b/framework/core/src/Group/GroupRepository.php index 769e0d606d..50aa2708d8 100644 --- a/framework/core/src/Group/GroupRepository.php +++ b/framework/core/src/Group/GroupRepository.php @@ -17,7 +17,7 @@ class GroupRepository /** * Get a new query builder for the groups table. * - * @return Builder + * @return Builder */ public function query() { @@ -29,14 +29,14 @@ public function query() * user, or throw an exception. * * @param int $id - * @param User $actor - * @return \Flarum\Group\Group + * @param User|null $actor + * @return Group * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ public function findOrFail($id, User $actor = null) { - $query = Group::where('id', $id); + $query = $this->query()->where('id', $id); return $this->scopeVisibleTo($query, $actor)->firstOrFail(); } @@ -44,9 +44,9 @@ public function findOrFail($id, User $actor = null) /** * Scope a query to only include records that are visible to a user. * - * @param Builder $query - * @param User $actor - * @return Builder + * @param Builder $query + * @param User|null $actor + * @return Builder */ protected function scopeVisibleTo(Builder $query, User $actor = null) { diff --git a/framework/core/src/Http/AccessToken.php b/framework/core/src/Http/AccessToken.php index 40357838b3..41b3e60bf6 100644 --- a/framework/core/src/Http/AccessToken.php +++ b/framework/core/src/Http/AccessToken.php @@ -25,8 +25,8 @@ * @property Carbon|null $last_activity_at * @property string $type * @property string $title - * @property string $last_ip_address - * @property string $last_user_agent + * @property string|null $last_ip_address + * @property string|null $last_user_agent * @property \Flarum\User\User|null $user */ class AccessToken extends AbstractModel diff --git a/framework/core/src/Http/CookieFactory.php b/framework/core/src/Http/CookieFactory.php index b0ee9fd609..fb5f72a69a 100644 --- a/framework/core/src/Http/CookieFactory.php +++ b/framework/core/src/Http/CookieFactory.php @@ -46,7 +46,7 @@ class CookieFactory /** * Same Site cookie value. * - * @var string + * @var string|null */ protected $samesite; diff --git a/framework/core/src/Http/Middleware/ResolveRoute.php b/framework/core/src/Http/Middleware/ResolveRoute.php index cc203a0b70..dc27027fd7 100644 --- a/framework/core/src/Http/Middleware/ResolveRoute.php +++ b/framework/core/src/Http/Middleware/ResolveRoute.php @@ -26,7 +26,7 @@ class ResolveRoute implements Middleware protected $routes; /** - * @var Dispatcher + * @var Dispatcher|null */ protected $dispatcher; @@ -43,6 +43,8 @@ public function __construct(RouteCollection $routes) /** * Resolve the given request from our route collection. * + * @return Response + * * @throws MethodNotAllowedException * @throws RouteNotFoundException */ @@ -58,7 +60,7 @@ public function process(Request $request, Handler $handler): Response throw new RouteNotFoundException($uri); case Dispatcher::METHOD_NOT_ALLOWED: throw new MethodNotAllowedException($method); - case Dispatcher::FOUND: + default: $request = $request ->withAttribute('routeName', $routeInfo[1]['name']) ->withAttribute('routeHandler', $routeInfo[1]['handler']) diff --git a/framework/core/src/Http/Server.php b/framework/core/src/Http/Server.php index e7faf3b17a..278caba66b 100644 --- a/framework/core/src/Http/Server.php +++ b/framework/core/src/Http/Server.php @@ -11,6 +11,7 @@ use Flarum\Foundation\ErrorHandling\LogReporter; use Flarum\Foundation\SiteInterface; +use Illuminate\Contracts\Container\Container; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; @@ -50,7 +51,7 @@ function (Throwable $e) { * We catch all exceptions happening during this process and format them to * prevent exposure of sensitive information. * - * @return \Psr\Http\Server\RequestHandlerInterface + * @return \Psr\Http\Server\RequestHandlerInterface|void */ private function safelyBootAndGetHandler() { @@ -80,7 +81,9 @@ private function safelyBootAndGetHandler() */ private function cleanBootExceptionLog(Throwable $error) { - if (app()->has('flarum.config') && app('flarum.config')->inDebugMode()) { + $container = resolve(Container::class); + + if ($container->has('flarum.config') && resolve('flarum.config')->inDebugMode()) { // If the application booted far enough for the config to be available, we will check for debug mode // Since the config is loaded very early, it is very likely to be available from the container $message = $error->getMessage(); @@ -96,12 +99,12 @@ private function cleanBootExceptionLog(Throwable $error)
$error
ERROR; exit(1); - } elseif (app()->has(LoggerInterface::class)) { + } elseif ($container->has(LoggerInterface::class)) { // If the application booted far enough for the logger to be available, we will log the error there // Considering most boot errors are related to database or extensions, the logger should already be loaded // We check for LoggerInterface binding because it's a constructor dependency of LogReporter, // then instantiate LogReporter through the container for automatic dependency injection - app(LogReporter::class)->report($error); + resolve(LogReporter::class)->report($error); echo 'Flarum encountered a boot error. Details have been logged to the Flarum log file.'; exit(1); diff --git a/framework/core/src/Http/SlugDriverInterface.php b/framework/core/src/Http/SlugDriverInterface.php index 84d3a621e1..40c3a277dc 100644 --- a/framework/core/src/Http/SlugDriverInterface.php +++ b/framework/core/src/Http/SlugDriverInterface.php @@ -12,9 +12,18 @@ use Flarum\Database\AbstractModel; use Flarum\User\User; +/** + * @template T of AbstractModel + */ interface SlugDriverInterface { + /** + * @param T $instance + */ public function toSlug(AbstractModel $instance): string; + /** + * @return T + */ public function fromSlug(string $slug, User $actor): AbstractModel; } diff --git a/framework/core/src/Http/SlugManager.php b/framework/core/src/Http/SlugManager.php index 71ec28a857..3aa510e3d9 100644 --- a/framework/core/src/Http/SlugManager.php +++ b/framework/core/src/Http/SlugManager.php @@ -20,6 +20,11 @@ public function __construct(array $drivers) $this->drivers = $drivers; } + /** + * @template T of \Flarum\Database\AbstractModel + * @param class-string $resourceName + * @return SlugDriverInterface + */ public function forResource(string $resourceName): SlugDriverInterface { return Arr::get($this->drivers, $resourceName, null); diff --git a/framework/core/src/Install/Controller/IndexController.php b/framework/core/src/Install/Controller/IndexController.php index 886e7a52a8..6422642917 100644 --- a/framework/core/src/Install/Controller/IndexController.php +++ b/framework/core/src/Install/Controller/IndexController.php @@ -26,10 +26,6 @@ class IndexController extends AbstractHtmlController */ protected $installation; - /** - * @param Factory $view - * @param Installation $installation - */ public function __construct(Factory $view, Installation $installation) { $this->view = $view; @@ -37,7 +33,6 @@ public function __construct(Factory $view, Installation $installation) } /** - * @param Request $request * @return \Illuminate\Contracts\Support\Renderable */ public function render(Request $request) diff --git a/framework/core/src/Install/Steps/EnableBundledExtensions.php b/framework/core/src/Install/Steps/EnableBundledExtensions.php index d77a6109fa..5abcdf14e8 100644 --- a/framework/core/src/Install/Steps/EnableBundledExtensions.php +++ b/framework/core/src/Install/Steps/EnableBundledExtensions.php @@ -60,6 +60,11 @@ class EnableBundledExtensions implements Step */ private $enabledExtensions; + /** + * @var Migrator|null + */ + private $migrator; + public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null) { $this->database = $database; @@ -124,7 +129,7 @@ private function loadExtensions() }); } - private function getMigrator() + private function getMigrator(): Migrator { return $this->migrator = $this->migrator ?? new Migrator( new DatabaseMigrationRepository($this->database, 'migrations'), diff --git a/framework/core/src/Notification/Driver/EmailNotificationDriver.php b/framework/core/src/Notification/Driver/EmailNotificationDriver.php index 1a4870380d..d256209534 100644 --- a/framework/core/src/Notification/Driver/EmailNotificationDriver.php +++ b/framework/core/src/Notification/Driver/EmailNotificationDriver.php @@ -41,7 +41,7 @@ public function send(BlueprintInterface $blueprint, array $users): void /** * Mail a notification to a list of users. * - * @param MailableInterface $blueprint + * @param MailableInterface&BlueprintInterface $blueprint * @param User[] $recipients */ protected function mailNotifications(MailableInterface $blueprint, array $recipients) diff --git a/framework/core/src/Notification/Event/Read.php b/framework/core/src/Notification/Event/Read.php index eb0510f597..00618e4cd7 100644 --- a/framework/core/src/Notification/Event/Read.php +++ b/framework/core/src/Notification/Event/Read.php @@ -32,7 +32,7 @@ class Read public function __construct(User $user, Notification $notification, DateTime $timestamp) { - $this->user = $user; + $this->actor = $user; $this->notification = $notification; $this->timestamp = $timestamp; } diff --git a/framework/core/src/Notification/Event/ReadAll.php b/framework/core/src/Notification/Event/ReadAll.php index e2bfa72fec..6cb7b5fe23 100644 --- a/framework/core/src/Notification/Event/ReadAll.php +++ b/framework/core/src/Notification/Event/ReadAll.php @@ -26,7 +26,7 @@ class ReadAll public function __construct(User $user, DateTime $timestamp) { - $this->user = $user; + $this->actor = $user; $this->timestamp = $timestamp; } } diff --git a/framework/core/src/Notification/Notification.php b/framework/core/src/Notification/Notification.php index 4d81e5dbeb..765a1ef25d 100644 --- a/framework/core/src/Notification/Notification.php +++ b/framework/core/src/Notification/Notification.php @@ -41,7 +41,7 @@ * @property \Carbon\Carbon $deleted_at * @property \Flarum\User\User|null $user * @property \Flarum\User\User|null $fromUser - * @property \Flarum\Database\AbstractModel|null $subject + * @property \Flarum\Database\AbstractModel|\Flarum\Post\Post|\Flarum\Discussion\Discussion|null $subject */ class Notification extends AbstractModel { @@ -209,7 +209,7 @@ public function scopeWhereSubjectModel(Builder $query, string $class) */ public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $blueprint) { - return $query->where(static::getBlueprintAttributes($blueprint)); + return $query->where(self::getBlueprintAttributes($blueprint)); } /** @@ -220,7 +220,7 @@ public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $bluep */ public static function notify(array $recipients, BlueprintInterface $blueprint) { - $attributes = static::getBlueprintAttributes($blueprint); + $attributes = self::getBlueprintAttributes($blueprint); $now = Carbon::now()->toDateTimeString(); static::insert( diff --git a/framework/core/src/Notification/NotificationMailer.php b/framework/core/src/Notification/NotificationMailer.php index 5bdcbca6c1..7b5a1ee627 100644 --- a/framework/core/src/Notification/NotificationMailer.php +++ b/framework/core/src/Notification/NotificationMailer.php @@ -12,6 +12,7 @@ use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; use Illuminate\Contracts\Mail\Mailer; +use Illuminate\Contracts\Translation\Translator; use Illuminate\Mail\Message; use Symfony\Contracts\Translation\TranslatorInterface; @@ -23,7 +24,7 @@ class NotificationMailer protected $mailer; /** - * @var TranslatorInterface + * @var TranslatorInterface&Translator */ protected $translator; @@ -33,9 +34,7 @@ class NotificationMailer protected $settings; /** - * @param Mailer $mailer - * @param TranslatorInterface $translator - * @param SettingsRepositoryInterface $settings + * @param TranslatorInterface&Translator $translator */ public function __construct(Mailer $mailer, TranslatorInterface $translator, SettingsRepositoryInterface $settings) { diff --git a/framework/core/src/Post/Post.php b/framework/core/src/Post/Post.php index 8a0ba4ab51..9866bfe493 100644 --- a/framework/core/src/Post/Post.php +++ b/framework/core/src/Post/Post.php @@ -16,14 +16,14 @@ use Flarum\Notification\Notification; use Flarum\Post\Event\Deleted; use Flarum\User\User; -use Illuminate\Database\ConnectionInterface; +use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Expression; /** * @property int $id * @property int $discussion_id - * @property int $number + * @property int|Expression $number * @property \Carbon\Carbon $created_at * @property int|null $user_id * @property string|null $type @@ -94,7 +94,7 @@ public static function boot() static::creating(function (self $post) { $post->type = $post::$type; - /** @var ConnectionInterface $db */ + /** @var Connection $db */ $db = static::getConnectionResolver(); $post->number = new Expression('('. $db->table('posts', 'pn') diff --git a/framework/core/src/Post/PostRepository.php b/framework/core/src/Post/PostRepository.php index 2b8f7829b2..96ccba0b5e 100644 --- a/framework/core/src/Post/PostRepository.php +++ b/framework/core/src/Post/PostRepository.php @@ -18,7 +18,7 @@ class PostRepository /** * Get a new query builder for the posts table. * - * @return Builder + * @return Builder */ public function query() { @@ -27,7 +27,7 @@ public function query() /** * @param User|null $user - * @return Builder + * @return Builder */ protected function queryVisibleTo(User $user = null) { @@ -45,8 +45,8 @@ protected function queryVisibleTo(User $user = null) * user, or throw an exception. * * @param int $id - * @param \Flarum\User\User $actor - * @return \Flarum\Post\Post + * @param \Flarum\User\User|null $actor + * @return Post * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ @@ -126,7 +126,7 @@ public function getIndexForNumber($discussionId, $number, User $actor = null) /** * @param array $ids * @param User|null $actor - * @return Builder + * @return Builder */ protected function queryIds(array $ids, User $actor = null) { diff --git a/framework/core/src/Queue/ExceptionHandler.php b/framework/core/src/Queue/ExceptionHandler.php index d311370b12..2870ac942d 100644 --- a/framework/core/src/Queue/ExceptionHandler.php +++ b/framework/core/src/Queue/ExceptionHandler.php @@ -42,9 +42,9 @@ public function report(Throwable $e) * * @param \Illuminate\Http\Request $request * @param Throwable $e - * @return \Symfony\Component\HttpFoundation\Response + * @return void */ - public function render($request, Throwable $e) + public function render($request, Throwable $e) /** @phpstan-ignore-line */ { // TODO: Implement render() method. } diff --git a/framework/core/src/Queue/QueueFactory.php b/framework/core/src/Queue/QueueFactory.php index d975f4477b..cb6ae9c502 100644 --- a/framework/core/src/Queue/QueueFactory.php +++ b/framework/core/src/Queue/QueueFactory.php @@ -21,7 +21,7 @@ class QueueFactory implements Factory /** * The cached queue instance. * - * @var \Illuminate\Contracts\Queue\Queue + * @var \Illuminate\Contracts\Queue\Queue|null */ private $queue; diff --git a/framework/core/src/Queue/QueueServiceProvider.php b/framework/core/src/Queue/QueueServiceProvider.php index 19377e4301..fd3bd6c2b5 100644 --- a/framework/core/src/Queue/QueueServiceProvider.php +++ b/framework/core/src/Queue/QueueServiceProvider.php @@ -90,7 +90,12 @@ function () use ($config) { // Bind a simple cache manager that returns the cache store. $this->container->singleton('cache', function (Container $container) { return new class($container) implements CacheFactory { - public function __construct($container) + /** + * @var Container $container + */ + private $container; + + public function __construct(Container $container) { $this->container = $container; } diff --git a/framework/core/src/Search/AbstractRegexGambit.php b/framework/core/src/Search/AbstractRegexGambit.php index 5787a02c83..fa5fae5e8f 100644 --- a/framework/core/src/Search/AbstractRegexGambit.php +++ b/framework/core/src/Search/AbstractRegexGambit.php @@ -34,13 +34,15 @@ public function apply(SearchState $search, $bit) * Match the bit against this gambit. * * @param string $bit - * @return array + * @return array|null */ protected function match($bit) { if (preg_match('/^(-?)'.$this->getGambitPattern().'$/i', $bit, $matches)) { return $matches; } + + return null; } /** diff --git a/framework/core/src/Search/AbstractSearcher.php b/framework/core/src/Search/AbstractSearcher.php index 49978975e6..a5fbb244b2 100644 --- a/framework/core/src/Search/AbstractSearcher.php +++ b/framework/core/src/Search/AbstractSearcher.php @@ -43,7 +43,6 @@ abstract protected function getQuery(User $actor): Builder; * @param int $offset * * @return QueryResults - * @throws InvalidArgumentException */ public function search(QueryCriteria $criteria, $limit = null, $offset = 0): QueryResults { diff --git a/framework/core/src/Search/GambitManager.php b/framework/core/src/Search/GambitManager.php index 928bd1257d..9429d03c19 100644 --- a/framework/core/src/Search/GambitManager.php +++ b/framework/core/src/Search/GambitManager.php @@ -26,9 +26,6 @@ class GambitManager */ protected $fulltextGambit; - /** - * @param GambitInterface $gambit - */ public function __construct(GambitInterface $fulltextGambit) { $this->fulltextGambit = $fulltextGambit; diff --git a/framework/core/src/Update/Controller/IndexController.php b/framework/core/src/Update/Controller/IndexController.php index f8fe1edf22..d499e2c227 100644 --- a/framework/core/src/Update/Controller/IndexController.php +++ b/framework/core/src/Update/Controller/IndexController.php @@ -28,10 +28,6 @@ public function __construct(Factory $view) $this->view = $view; } - /** - * @param Request $request - * @return \Psr\Http\Message\ResponseInterface - */ public function render(Request $request) { $view = $this->view->make('flarum.update::app')->with('title', 'Update Flarum'); diff --git a/framework/core/src/User/Access/AbstractPolicy.php b/framework/core/src/User/Access/AbstractPolicy.php index 3b4579d744..c9d1880859 100644 --- a/framework/core/src/User/Access/AbstractPolicy.php +++ b/framework/core/src/User/Access/AbstractPolicy.php @@ -40,13 +40,11 @@ protected function forceDeny() } /** - * @param User $user - * @param string $ability - * @param $instance * @return string|void */ public function checkAbility(User $actor, string $ability, $instance) - { // If a specific method for this ability is defined, + { + // If a specific method for this ability is defined, // call that and return any non-null results if (method_exists($this, $ability)) { $result = $this->sanitizeResult(call_user_func_array([$this, $ability], [$actor, $instance])); @@ -73,7 +71,7 @@ public function checkAbility(User $actor, string $ability, $instance) * `return SOME_BOOLEAN_LOGIC; * * @param mixed $result - * @return string|void + * @return string|void|null */ public function sanitizeResult($result) { diff --git a/framework/core/src/User/Command/RegisterUserHandler.php b/framework/core/src/User/Command/RegisterUserHandler.php index a9c9a872bc..c8b0670106 100644 --- a/framework/core/src/User/Command/RegisterUserHandler.php +++ b/framework/core/src/User/Command/RegisterUserHandler.php @@ -54,12 +54,6 @@ class RegisterUserHandler */ protected $imageManager; - /** - * @param Dispatcher $events - * @param SettingsRepositoryInterface $settings - * @param UserValidator $validator - * @param AvatarUploader $avatarUploader - */ public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator, ImageManager $imageManager) { $this->events = $events; diff --git a/framework/core/src/User/EmailToken.php b/framework/core/src/User/EmailToken.php index f118621897..77dd3a7523 100644 --- a/framework/core/src/User/EmailToken.php +++ b/framework/core/src/User/EmailToken.php @@ -76,12 +76,12 @@ public function user() * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $id - * @return static + * @return self * @throws InvalidConfirmationTokenException */ public function scopeValidOrFail($query, $id) { - /** @var EmailToken $token */ + /** @var EmailToken|null $token */ $token = $query->find($id); if (! $token || $token->created_at->diffInDays() >= 1) { diff --git a/framework/core/src/User/IdSlugDriver.php b/framework/core/src/User/IdSlugDriver.php index 2a71a508cc..59fa738571 100644 --- a/framework/core/src/User/IdSlugDriver.php +++ b/framework/core/src/User/IdSlugDriver.php @@ -12,6 +12,9 @@ use Flarum\Database\AbstractModel; use Flarum\Http\SlugDriverInterface; +/** + * @implements SlugDriverInterface + */ class IdSlugDriver implements SlugDriverInterface { /** @@ -24,11 +27,17 @@ public function __construct(UserRepository $users) $this->users = $users; } + /** + * @param User $instance + */ public function toSlug(AbstractModel $instance): string { - return $instance->id; + return (string) $instance->id; } + /** + * @return User + */ public function fromSlug(string $slug, User $actor): AbstractModel { return $this->users->findOrFail($slug, $actor); diff --git a/framework/core/src/User/RegistrationToken.php b/framework/core/src/User/RegistrationToken.php index fdb696abce..05951be7c7 100644 --- a/framework/core/src/User/RegistrationToken.php +++ b/framework/core/src/User/RegistrationToken.php @@ -83,7 +83,7 @@ public static function generate(string $provider, string $identifier, array $att */ public function scopeValidOrFail($query, string $token) { - /** @var RegistrationToken $token */ + /** @var RegistrationToken|null $token */ $token = $query->find($token); if (! $token || $token->created_at->lessThan(Carbon::now()->subDay())) { diff --git a/framework/core/src/User/Search/Gambit/FulltextGambit.php b/framework/core/src/User/Search/Gambit/FulltextGambit.php index 0522e76d26..47180a0436 100644 --- a/framework/core/src/User/Search/Gambit/FulltextGambit.php +++ b/framework/core/src/User/Search/Gambit/FulltextGambit.php @@ -50,5 +50,7 @@ public function apply(SearchState $search, $searchValue) 'id', $this->getUserSearchSubQuery($searchValue) ); + + return true; } } diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index 05ee35394b..5af55a839c 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -109,7 +109,7 @@ class User extends AbstractModel /** * The access gate. * - * @var Gate + * @var Access\Gate */ protected static $gate; @@ -172,7 +172,7 @@ public static function register($username, $email, $password) } /** - * @param Gate $gate + * @param Access\Gate $gate */ public static function setGate($gate) { @@ -311,14 +311,16 @@ public function changeAvatarPath($path) /** * Get the URL of the user's avatar. * - * @todo Allow different storage locations to be used * @param string|null $value * @return string */ public function getAvatarUrlAttribute(string $value = null) { if ($value && strpos($value, '://') === false) { - return resolve(Factory::class)->disk('flarum-avatars')->url($value); + /** @var \Illuminate\Contracts\Filesystem\Cloud $disk */ + $disk = resolve(Factory::class)->disk('flarum-avatars'); + + return $disk->url($value); } return $value; @@ -410,15 +412,6 @@ public function hasPermissionLike($match) return false; } - private function checkForDeprecatedPermissions($permission) - { - foreach (['viewDiscussions', 'viewUserList'] as $deprecated) { - if (strpos($permission, $deprecated) !== false) { - trigger_error('The `viewDiscussions` and `viewUserList` permissions have been renamed to `viewForum` and `searchUsers` respectively. Please use those instead.', E_USER_DEPRECATED); - } - } - } - /** * Get the notification types that should be alerted to this user, according * to their preferences. @@ -479,7 +472,7 @@ public function getNewNotificationCount() * Get the values of all registered preferences for this user, by * transforming their stored preferences and merging them with the defaults. * - * @param string $value + * @param string|null $value * @return array */ public function getPreferencesAttribute($value) @@ -676,7 +669,7 @@ public function discussions() /** * Define the relationship with the user's read discussions. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ public function read() { @@ -825,7 +818,7 @@ public static function registerPreference($key, callable $transformer = null, $d * Register a callback that processes a user's list of groups. * * @param callable $callback - * @return array $groupIds + * @return void * * @internal */ diff --git a/framework/core/src/User/UserRepository.php b/framework/core/src/User/UserRepository.php index eb828e37a8..1a898d7b82 100644 --- a/framework/core/src/User/UserRepository.php +++ b/framework/core/src/User/UserRepository.php @@ -16,7 +16,7 @@ class UserRepository /** * Get a new query builder for the users table. * - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ public function query() { @@ -28,14 +28,14 @@ public function query() * user, or throw an exception. * * @param int $id - * @param User $actor + * @param User|null $actor * @return User * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ public function findOrFail($id, User $actor = null) { - $query = User::where('id', $id); + $query = $this->query()->where('id', $id); return $this->scopeVisibleTo($query, $actor)->firstOrFail(); } @@ -44,15 +44,15 @@ public function findOrFail($id, User $actor = null) * Find a user by username, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param int $id - * @param User $actor + * @param string $username + * @param User|null $actor * @return User * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException */ public function findOrFailByUsername($username, User $actor = null) { - $query = User::where('username', $username); + $query = $this->query()->where('username', $username); return $this->scopeVisibleTo($query, $actor)->firstOrFail(); } @@ -67,7 +67,7 @@ public function findByIdentification($identification) { $field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; - return User::where($field, $identification)->first(); + return $this->query()->where($field, $identification)->first(); } /** @@ -78,7 +78,7 @@ public function findByIdentification($identification) */ public function findByEmail($email) { - return User::where('email', $email)->first(); + return $this->query()->where('email', $email)->first(); } /** @@ -90,7 +90,7 @@ public function findByEmail($email) */ public function getIdForUsername($username, User $actor = null) { - $query = User::where('username', $username); + $query = $this->query()->where('username', $username); return $this->scopeVisibleTo($query, $actor)->value('id'); } @@ -107,7 +107,7 @@ public function getIdsForUsername($string, User $actor = null) { $string = $this->escapeLikeString($string); - $query = User::where('username', 'like', '%'.$string.'%') + $query = $this->query()->where('username', 'like', '%'.$string.'%') ->orderByRaw('username = ? desc', [$string]) ->orderByRaw('username like ? desc', [$string.'%']); @@ -117,9 +117,9 @@ public function getIdsForUsername($string, User $actor = null) /** * Scope a query to only include records that are visible to a user. * - * @param Builder $query - * @param User $actor - * @return Builder + * @param Builder $query + * @param User|null $actor + * @return Builder */ protected function scopeVisibleTo(Builder $query, User $actor = null) { diff --git a/framework/core/src/User/UserServiceProvider.php b/framework/core/src/User/UserServiceProvider.php index 6e3160d60b..d796def1b7 100644 --- a/framework/core/src/User/UserServiceProvider.php +++ b/framework/core/src/User/UserServiceProvider.php @@ -98,6 +98,10 @@ public function boot(Container $container, Dispatcher $events) User::addGroupProcessor(ContainerUtil::wrapCallback($callback, $container)); } + /** + * @var \Illuminate\Container\Container $container + */ + User::setHasher($container->make('hash')); User::setPasswordCheckers($container->make('flarum.user.password_checkers')); User::setGate($container->makeWith(Access\Gate::class, ['policyClasses' => $container->make('flarum.policies')])); diff --git a/framework/core/src/User/UserValidator.php b/framework/core/src/User/UserValidator.php index ea9624cbc8..bd24ec34d7 100644 --- a/framework/core/src/User/UserValidator.php +++ b/framework/core/src/User/UserValidator.php @@ -14,7 +14,7 @@ class UserValidator extends AbstractValidator { /** - * @var User + * @var User|null */ protected $user; diff --git a/framework/core/src/User/UsernameSlugDriver.php b/framework/core/src/User/UsernameSlugDriver.php index 9bacf3740d..ad18a11181 100644 --- a/framework/core/src/User/UsernameSlugDriver.php +++ b/framework/core/src/User/UsernameSlugDriver.php @@ -12,6 +12,9 @@ use Flarum\Database\AbstractModel; use Flarum\Http\SlugDriverInterface; +/** + * @implements SlugDriverInterface + */ class UsernameSlugDriver implements SlugDriverInterface { /** @@ -24,11 +27,17 @@ public function __construct(UserRepository $users) $this->users = $users; } + /** + * @param User $instance + */ public function toSlug(AbstractModel $instance): string { return $instance->username; } + /** + * @return User + */ public function fromSlug(string $slug, User $actor): AbstractModel { return $this->users->findOrFailByUsername($slug, $actor); diff --git a/framework/core/src/helpers.php b/framework/core/src/helpers.php index 9033587ca0..565e911e3a 100644 --- a/framework/core/src/helpers.php +++ b/framework/core/src/helpers.php @@ -16,11 +16,11 @@ * Resolve a service from the container. * * @template T - * @param class-string|string $name - * @param array $parameters + * @param class-string $name + * @param array $parameters * @return T|mixed */ - function resolve($name, $parameters = []) + function resolve(string $name, array $parameters = []) { return Container::getInstance()->make($name, $parameters); } diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 2bdfe14075..7478bc370e 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -1,3 +1,11 @@ includes: - vendor/phpstan/phpstan-php-parser/extension.neon - larastan-extension.neon + - phpstan-baseline.neon + +parameters: + stubFiles: + - stubs/Illuminate/Contracts/Container/Container.stub + - stubs/Illuminate/Queue/ListenerOptions.stub + - stubs/Illuminate/Support/ServiceProvider.stub + - stubs/Illuminate/Filesystem/Filesystem.stub diff --git a/php-packages/phpstan/phpstan-baseline.neon b/php-packages/phpstan/phpstan-baseline.neon new file mode 100644 index 0000000000..a883f5569a --- /dev/null +++ b/php-packages/phpstan/phpstan-baseline.neon @@ -0,0 +1,4 @@ +parameters: + ignoreErrors: +# Remove with larastan 2.0 + - "#Relation '[A-z_-]+' is not found in [A-z\_]+ model.#" diff --git a/php-packages/phpstan/src/Concerns/HasContainer.php b/php-packages/phpstan/src/Concerns/HasContainer.php deleted file mode 100644 index 8625b638c2..0000000000 --- a/php-packages/phpstan/src/Concerns/HasContainer.php +++ /dev/null @@ -1,72 +0,0 @@ -container = $container; - } - - /** - * Returns the current broker. - * - * @return \Illuminate\Contracts\Container\Container - */ - public function getContainer(): ContainerContract - { - return $this->container ?? Container::getInstance(); - } - - /** - * Resolve the given type from the container. - * - * @param string $abstract - * @return mixed - */ - public function resolve(string $abstract) - { - $concrete = null; - - try { - $concrete = $this->getContainer() - ->make($abstract); - } catch (ReflectionException $exception) { - // .. - } catch (BindingResolutionException $exception) { - // .. - } catch (NotFoundExceptionInterface $exception) { - // .. - } - - return $concrete; - } -} diff --git a/php-packages/phpstan/src/Concerns/LoadsAuthModel.php b/php-packages/phpstan/src/Concerns/LoadsAuthModel.php deleted file mode 100644 index 300f5c161c..0000000000 --- a/php-packages/phpstan/src/Concerns/LoadsAuthModel.php +++ /dev/null @@ -1,31 +0,0 @@ -get('auth.defaults.guard'))) || - ! ($provider = $config->get('auth.guards.'.$guard.'.provider')) || - ! ($authModel = $config->get('auth.providers.'.$provider.'.model')) - ) { - return null; - } - - return $authModel; - } -} diff --git a/php-packages/phpstan/src/Contracts/Methods/PassableContract.php b/php-packages/phpstan/src/Contracts/Methods/PassableContract.php deleted file mode 100644 index 4a71387cfa..0000000000 --- a/php-packages/phpstan/src/Contracts/Methods/PassableContract.php +++ /dev/null @@ -1,96 +0,0 @@ -reflectionProvider = $reflectionProvider; - $this->checkProperties = $checkProperties; - } - - public function dynamicWhere( - string $methodName, - Type $returnObject - ): ?EloquentBuilderMethodReflection { - if (! Str::startsWith($methodName, 'where')) { - return null; - } - - if ($returnObject instanceof GenericObjectType && $this->checkProperties) { - $returnClassReflection = $returnObject->getClassReflection(); - - if ($returnClassReflection !== null) { - $modelType = $returnClassReflection->getActiveTemplateTypeMap()->getType('TModelClass'); - - if ($modelType === null) { - $modelType = $returnClassReflection->getActiveTemplateTypeMap()->getType('TRelatedModel'); - } - - if ($modelType !== null) { - $finder = substr($methodName, 5); - - $segments = preg_split( - '/(And|Or)(?=[A-Z])/', - $finder, - -1, - PREG_SPLIT_DELIM_CAPTURE - ); - - if ($segments !== false) { - $trinaryLogic = TrinaryLogic::createYes(); - - foreach ($segments as $segment) { - if ($segment !== 'And' && $segment !== 'Or') { - $trinaryLogic = $trinaryLogic->and($modelType->hasProperty(Str::snake($segment))); - } - } - - if (! $trinaryLogic->yes()) { - return null; - } - } - } - } - } - - $classReflection = $this->reflectionProvider->getClass(QueryBuilder::class); - - $methodReflection = $classReflection->getNativeMethod('dynamicWhere'); - - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $methodReflection, - [new DynamicWhereParameterReflection], - $returnObject, - true - ); - } - - /** - * This method mimics the `EloquentBuilder::__call` method. - * Does not handle the case where $methodName exists in `EloquentBuilder`, - * that should be checked by caller before calling this method. - * - * @param ClassReflection $eloquentBuilder Can be `EloquentBuilder` or a custom builder extending it. - * @param string $methodName - * @param ClassReflection $model - * @return MethodReflection|null - * - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - public function searchOnEloquentBuilder(ClassReflection $eloquentBuilder, string $methodName, ClassReflection $model): ?MethodReflection - { - // Check for local query scopes - if (array_key_exists('scope'.ucfirst($methodName), $model->getMethodTags())) { - $methodTag = $model->getMethodTags()['scope'.ucfirst($methodName)]; - - $parameters = []; - foreach ($methodTag->getParameters() as $parameterName => $parameterTag) { - $parameters[] = new AnnotationScopeMethodParameterReflection($parameterName, $parameterTag->getType(), $parameterTag->passedByReference(), $parameterTag->isOptional(), $parameterTag->isVariadic(), $parameterTag->getDefaultValue()); - } - - // We shift the parameters, - // because first parameter is the Builder - array_shift($parameters); - - return new EloquentBuilderMethodReflection( - 'scope'.ucfirst($methodName), - $model, - new AnnotationScopeMethodReflection('scope'.ucfirst($methodName), $model, $methodTag->getReturnType(), $parameters, $methodTag->isStatic(), false), - $parameters, - $methodTag->getReturnType() - ); - } - - if ($model->hasNativeMethod('scope'.ucfirst($methodName))) { - $methodReflection = $model->getNativeMethod('scope'.ucfirst($methodName)); - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()); - - $parameters = $parametersAcceptor->getParameters(); - // We shift the parameters, - // because first parameter is the Builder - array_shift($parameters); - - $returnType = $parametersAcceptor->getReturnType(); - - return new EloquentBuilderMethodReflection( - 'scope'.ucfirst($methodName), - $methodReflection->getDeclaringClass(), - $methodReflection, - $parameters, - $returnType, - $parametersAcceptor->isVariadic() - ); - } - - $queryBuilderReflection = $this->reflectionProvider->getClass(QueryBuilder::class); - - if (in_array($methodName, $this->passthru, true)) { - return $queryBuilderReflection->getNativeMethod($methodName); - } - - if ($queryBuilderReflection->hasNativeMethod($methodName)) { - return $queryBuilderReflection->getNativeMethod($methodName); - } - - return $this->dynamicWhere($methodName, new GenericObjectType($eloquentBuilder->getName(), [new ObjectType($model->getName())])); - } - - /** - * @param string $modelClassName - * @return string - * - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - public function determineBuilderName(string $modelClassName): string - { - $method = $this->reflectionProvider->getClass($modelClassName)->getNativeMethod('newEloquentBuilder'); - - $returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType(); - - if (in_array(EloquentBuilder::class, $returnType->getReferencedClasses(), true)) { - return EloquentBuilder::class; - } - - if ($returnType instanceof ObjectType) { - return $returnType->getClassName(); - } - - return $returnType->describe(VerbosityLevel::value()); - } - - /** - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - public function determineCollectionClassName(string $modelClassName): string - { - $newCollectionMethod = $this->reflectionProvider->getClass($modelClassName)->getNativeMethod('newCollection'); - - $returnType = ParametersAcceptorSelector::selectSingle($newCollectionMethod->getVariants())->getReturnType(); - - if ($returnType instanceof ObjectType) { - return $returnType->getClassName(); - } - - return $returnType->describe(VerbosityLevel::value()); - } -} diff --git a/php-packages/phpstan/src/Methods/EloquentBuilderForwardsCallsExtension.php b/php-packages/phpstan/src/Methods/EloquentBuilderForwardsCallsExtension.php deleted file mode 100644 index 6e532269f1..0000000000 --- a/php-packages/phpstan/src/Methods/EloquentBuilderForwardsCallsExtension.php +++ /dev/null @@ -1,161 +0,0 @@ - */ - private $cache = []; - - /** @var BuilderHelper */ - private $builderHelper; - - /** @var ReflectionProvider */ - private $reflectionProvider; - - public function __construct(BuilderHelper $builderHelper, ReflectionProvider $reflectionProvider) - { - $this->builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - } - - /** - * @throws ShouldNotHappenException - * @throws MissingMethodFromReflectionException - */ - public function hasMethod(ClassReflection $classReflection, string $methodName): bool - { - if (array_key_exists($classReflection->getCacheKey().'-'.$methodName, $this->cache)) { - return true; - } - - $methodReflection = $this->findMethod($classReflection, $methodName); - - if ($methodReflection !== null && $classReflection->isGeneric()) { - $this->cache[$classReflection->getCacheKey().'-'.$methodName] = $methodReflection; - - return true; - } - - return false; - } - - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection - { - return $this->cache[$classReflection->getCacheKey().'-'.$methodName]; - } - - /** - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - private function findMethod(ClassReflection $classReflection, string $methodName): ?MethodReflection - { - if ($classReflection->getName() !== EloquentBuilder::class && ! $classReflection->isSubclassOf(EloquentBuilder::class)) { - return null; - } - - /** @var Type|TemplateMixedType|null $modelType */ - $modelType = $classReflection->getActiveTemplateTypeMap()->getType('TModelClass'); - - // Generic type is not specified - if ($modelType === null) { - return null; - } - - if ($modelType instanceof TemplateObjectType) { - $modelType = $modelType->getBound(); - - if ($modelType->equals(new ObjectType(Model::class))) { - return null; - } - } - - if ($modelType instanceof TypeWithClassName) { - $modelReflection = $modelType->getClassReflection(); - } else { - $modelReflection = $this->reflectionProvider->getClass(Model::class); - } - - if ($modelReflection === null) { - return null; - } - - $ref = $this->builderHelper->searchOnEloquentBuilder($classReflection, $methodName, $modelReflection); - - if ($ref === null) { - // Special case for `SoftDeletes` trait - if ( - in_array($methodName, ['withTrashed', 'onlyTrashed', 'withoutTrashed'], true) && - in_array(SoftDeletes::class, array_keys($modelReflection->getTraits(true))) - ) { - $ref = $this->reflectionProvider->getClass(SoftDeletes::class)->getMethod($methodName, new OutOfClassScope()); - - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $ref, - ParametersAcceptorSelector::selectSingle($ref->getVariants())->getParameters(), - new GenericObjectType($classReflection->getName(), [$modelType]), - ParametersAcceptorSelector::selectSingle($ref->getVariants())->isVariadic() - ); - } - - return null; - } - - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($ref->getVariants()); - - if (in_array($methodName, $this->builderHelper->passthru, true)) { - $returnType = $parametersAcceptor->getReturnType(); - - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $ref, - $parametersAcceptor->getParameters(), - $returnType, - $parametersAcceptor->isVariadic() - ); - } - - // Returning custom reflection - // to ensure return type is always `EloquentBuilder` - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $ref, - $parametersAcceptor->getParameters(), - new GenericObjectType($classReflection->getName(), [$modelType]), - $parametersAcceptor->isVariadic() - ); - } -} diff --git a/php-packages/phpstan/src/Methods/Extension.php b/php-packages/phpstan/src/Methods/Extension.php deleted file mode 100644 index cb6ff82d1e..0000000000 --- a/php-packages/phpstan/src/Methods/Extension.php +++ /dev/null @@ -1,64 +0,0 @@ -kernel = $kernel ?? new Kernel($methodReflectionFactory, $reflectionProvider); - } - - public function hasMethod(ClassReflection $classReflection, string $methodName): bool - { - if ($classReflection->getName() === Model::class) { - return false; - } - - if (array_key_exists($methodName.'-'.$classReflection->getName(), $this->methodReflections)) { - return true; - } - - $passable = $this->kernel->handle($classReflection, $methodName); - - $found = $passable->hasFound(); - - if ($found) { - $this->methodReflections[$methodName.'-'.$classReflection->getName()] = $passable->getMethodReflection(); - } - - return $found; - } - - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection - { - return $this->methodReflections[$methodName.'-'.$classReflection->getName()]; - } -} diff --git a/php-packages/phpstan/src/Methods/HigherOrderCollectionProxyExtension.php b/php-packages/phpstan/src/Methods/HigherOrderCollectionProxyExtension.php deleted file mode 100644 index 9663764a89..0000000000 --- a/php-packages/phpstan/src/Methods/HigherOrderCollectionProxyExtension.php +++ /dev/null @@ -1,149 +0,0 @@ -getActiveTemplateTypeMap(); - - /** @var Type\Constant\ConstantStringType $methodType */ - $methodType = $activeTemplateTypeMap->getType('T'); - - /** @var Type\ObjectType $valueType */ - $valueType = $activeTemplateTypeMap->getType('TValue'); - - $modelMethodReflection = $valueType->getMethod($methodName, new OutOfClassScope()); - - $modelMethodReturnType = ParametersAcceptorSelector::selectSingle($modelMethodReflection->getVariants())->getReturnType(); - - $returnType = HigherOrderCollectionProxyHelper::determineReturnType($methodType->getValue(), $valueType, $modelMethodReturnType); - - return new class($classReflection, $methodName, $modelMethodReflection, $returnType) implements MethodReflection { - /** @var ClassReflection */ - private $classReflection; - - /** @var string */ - private $methodName; - - /** @var MethodReflection */ - private $modelMethodReflection; - - /** @var Type\Type */ - private $returnType; - - public function __construct(ClassReflection $classReflection, string $methodName, MethodReflection $modelMethodReflection, Type\Type $returnType) - { - $this->classReflection = $classReflection; - $this->methodName = $methodName; - $this->modelMethodReflection = $modelMethodReflection; - $this->returnType = $returnType; - } - - public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return null; - } - - public function getName(): string - { - return $this->methodName; - } - - public function getPrototype(): \PHPStan\Reflection\ClassMemberReflection - { - return $this; - } - - public function getVariants(): array - { - return [ - new FunctionVariant( - ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getTemplateTypeMap(), - ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getResolvedTemplateTypeMap(), - ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getParameters(), - ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->isVariadic(), - $this->returnType - ), - ]; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?\PHPStan\Type\Type - { - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } - }; - } -} diff --git a/php-packages/phpstan/src/Methods/HigherOrderTapProxyExtension.php b/php-packages/phpstan/src/Methods/HigherOrderTapProxyExtension.php deleted file mode 100644 index a356235a0e..0000000000 --- a/php-packages/phpstan/src/Methods/HigherOrderTapProxyExtension.php +++ /dev/null @@ -1,56 +0,0 @@ -getName() !== HigherOrderTapProxy::class) { - return false; - } - - $templateTypeMap = $classReflection->getActiveTemplateTypeMap(); - - $templateType = $templateTypeMap->getType('TClass'); - - if (! $templateType instanceof ObjectType) { - return false; - } - - if ($templateType->getClassReflection() === null) { - return false; - } - - return $templateType->hasMethod($methodName)->yes(); - } - - public function getMethod( - ClassReflection $classReflection, - string $methodName - ): MethodReflection { - /** @var ObjectType $templateType */ - $templateType = $classReflection->getActiveTemplateTypeMap()->getType('TClass'); - - /** @var ClassReflection $reflection */ - $reflection = $templateType->getClassReflection(); - - return $reflection->getMethod($methodName, new OutOfClassScope()); - } -} diff --git a/php-packages/phpstan/src/Methods/Kernel.php b/php-packages/phpstan/src/Methods/Kernel.php deleted file mode 100644 index b10d79330d..0000000000 --- a/php-packages/phpstan/src/Methods/Kernel.php +++ /dev/null @@ -1,79 +0,0 @@ -methodReflectionFactory = $methodReflectionFactory; - $this->reflectionProvider = $reflectionProvider; - } - - /** - * @param ClassReflection $classReflection - * @param string $methodName - * @return PassableContract - */ - public function handle(ClassReflection $classReflection, string $methodName): PassableContract - { - $pipeline = new Pipeline($this->getContainer()); - - $passable = new Passable($this->methodReflectionFactory, $this->reflectionProvider, $pipeline, $classReflection, $methodName); - - $pipeline->send($passable) - ->through( - [ - Pipes\SelfClass::class, - Pipes\Macros::class, - Pipes\Contracts::class, - Pipes\Facades::class, - Pipes\Managers::class, - Pipes\Auths::class, - ] - ) - ->then( - function ($method) { - } - ); - - return $passable; - } -} diff --git a/php-packages/phpstan/src/Methods/Macro.php b/php-packages/phpstan/src/Methods/Macro.php deleted file mode 100644 index deff8ace4e..0000000000 --- a/php-packages/phpstan/src/Methods/Macro.php +++ /dev/null @@ -1,265 +0,0 @@ - ValidationException::class, - 'validateWithBag' => ValidationException::class, - ]; - - public function __construct(ClassReflection $classReflection, string $methodName, ReflectionFunction $reflectionFunction) - { - $this->classReflection = $classReflection; - $this->methodName = $methodName; - $this->reflectionFunction = $reflectionFunction; - $this->parameters = $this->reflectionFunction->getParameters(); - - if ($this->reflectionFunction->isClosure()) { - try { - /** @var Closure $closure */ - $closure = $this->reflectionFunction->getClosure(); - Closure::bind($closure, new stdClass); - // The closure can be bound so it was not explicitly marked as static - } catch (ErrorException $e) { - // The closure was explicitly marked as static - $this->isStatic = true; - } - } - } - - public function getDeclaringClass(): ClassReflection - { - return $this->classReflection; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isStatic(): bool - { - return $this->isStatic; - } - - /** - * Set the is static value. - * - * @param bool $isStatic - * @return void - */ - public function setIsStatic(bool $isStatic): void - { - $this->isStatic = $isStatic; - } - - /** - * {@inheritdoc} - */ - public function getDocComment(): ?string - { - return $this->reflectionFunction->getDocComment() ?: null; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return $this->methodName; - } - - /** @return ParameterReflection[] */ - public function getParameters(): array - { - return array_map(function (ReflectionParameter $reflection): ParameterReflection { - return new class($reflection) implements ParameterReflection { - /** - * @var ReflectionParameter - */ - private $reflection; - - public function __construct(ReflectionParameter $reflection) - { - $this->reflection = $reflection; - } - - public function getName(): string - { - return $this->reflection->getName(); - } - - public function isOptional(): bool - { - return $this->reflection->isOptional(); - } - - public function getType(): Type - { - $type = $this->reflection->getType(); - - if ($type === null) { - return new MixedType(); - } - - return TypehintHelper::decideTypeFromReflection($this->reflection->getType()); - } - - public function passedByReference(): PassedByReference - { - return PassedByReference::createNo(); - } - - public function isVariadic(): bool - { - return $this->reflection->isVariadic(); - } - - public function getDefaultValue(): ?Type - { - return null; - } - }; - }, $this->parameters); - } - - /** - * Set the parameters value. - * - * @param ReflectionParameter[] $parameters - * @return void - */ - public function setParameters(array $parameters): void - { - $this->parameters = $parameters; - } - - public function getReturnType(): ?ReflectionType - { - return $this->reflectionFunction->getReturnType(); - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->reflectionFunction->isDeprecated()); - } - - public function getPrototype(): ClassMemberReflection - { - return $this; - } - - /** - * @inheritDoc - */ - public function getVariants(): array - { - return [ - new FunctionVariant(TemplateTypeMap::createEmpty(), null, $this->getParameters(), $this->reflectionFunction->isVariadic(), TypehintHelper::decideTypeFromReflection($this->getReturnType())), - ]; - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function getThrowType(): ?Type - { - if (array_key_exists($this->methodName, $this->methodThrowTypeMap)) { - return new ObjectType($this->methodThrowTypeMap[$this->methodName]); - } - - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } -} diff --git a/php-packages/phpstan/src/Methods/ModelFactoryMethodsClassReflectionExtension.php b/php-packages/phpstan/src/Methods/ModelFactoryMethodsClassReflectionExtension.php deleted file mode 100644 index 8ed0ca1241..0000000000 --- a/php-packages/phpstan/src/Methods/ModelFactoryMethodsClassReflectionExtension.php +++ /dev/null @@ -1,166 +0,0 @@ -isSubclassOf(Factory::class)) { - return false; - } - - if (! Str::startsWith($methodName, ['for', 'has'])) { - return false; - } - - $relationship = Str::camel(Str::substr($methodName, 3)); - - $parent = $classReflection->getParentClass(); - - if ($parent === null) { - return false; - } - - $modelType = $parent->getActiveTemplateTypeMap()->getType('TModel'); - - if ($modelType === null) { - return false; - } - - return $modelType->hasMethod($relationship)->yes(); - } - - public function getMethod( - ClassReflection $classReflection, - string $methodName - ): MethodReflection { - return new class($classReflection, $methodName) implements MethodReflection { - /** @var ClassReflection */ - private $classReflection; - - /** @var string */ - private $methodName; - - public function __construct(ClassReflection $classReflection, string $methodName) - { - $this->classReflection = $classReflection; - $this->methodName = $methodName; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return null; - } - - public function getName(): string - { - return $this->methodName; - } - - public function getPrototype(): ClassMemberReflection - { - return $this; - } - - public function getVariants(): array - { - $returnType = new ObjectType($this->classReflection->getName()); - $stateParameter = ParametersAcceptorSelector::selectSingle($this->classReflection->getMethod('state', new OutOfClassScope())->getVariants())->getParameters()[0]; - $countParameter = ParametersAcceptorSelector::selectSingle($this->classReflection->getMethod('count', new OutOfClassScope())->getVariants())->getParameters()[0]; - - $variants = [ - new FunctionVariant(TemplateTypeMap::createEmpty(), null, [], false, $returnType), - ]; - - if (Str::startsWith($this->methodName, 'for')) { - $variants[] = new FunctionVariant(TemplateTypeMap::createEmpty(), null, [$stateParameter], false, $returnType); - } else { - $variants[] = new FunctionVariant(TemplateTypeMap::createEmpty(), null, [$countParameter], false, $returnType); - $variants[] = new FunctionVariant(TemplateTypeMap::createEmpty(), null, [$stateParameter], false, $returnType); - $variants[] = new FunctionVariant(TemplateTypeMap::createEmpty(), null, [$countParameter, $stateParameter], false, $returnType); - } - - return $variants; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?Type - { - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } - }; - } -} diff --git a/php-packages/phpstan/src/Methods/ModelForwardsCallsExtension.php b/php-packages/phpstan/src/Methods/ModelForwardsCallsExtension.php deleted file mode 100644 index a9d60885eb..0000000000 --- a/php-packages/phpstan/src/Methods/ModelForwardsCallsExtension.php +++ /dev/null @@ -1,219 +0,0 @@ - */ - private $cache = []; - - public function __construct(BuilderHelper $builderHelper, ReflectionProvider $reflectionProvider, EloquentBuilderForwardsCallsExtension $eloquentBuilderForwardsCallsExtension) - { - $this->builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - $this->eloquentBuilderForwardsCallsExtension = $eloquentBuilderForwardsCallsExtension; - } - - /** - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - public function hasMethod(ClassReflection $classReflection, string $methodName): bool - { - if (array_key_exists($classReflection->getCacheKey().'-'.$methodName, $this->cache)) { - return true; - } - - $methodReflection = $this->findMethod($classReflection, $methodName); - - if ($methodReflection !== null) { - $this->cache[$classReflection->getCacheKey().'-'.$methodName] = $methodReflection; - - return true; - } - - return false; - } - - /** - * @param ClassReflection $classReflection - * @param string $methodName - * @return MethodReflection - */ - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection - { - return $this->cache[$classReflection->getCacheKey().'-'.$methodName]; - } - - /** - * @throws ShouldNotHappenException - * @throws MissingMethodFromReflectionException - */ - private function findMethod(ClassReflection $classReflection, string $methodName): ?MethodReflection - { - if ($classReflection->getName() !== Model::class && ! $classReflection->isSubclassOf(Model::class)) { - return null; - } - - $builderName = $this->builderHelper->determineBuilderName($classReflection->getName()); - - if (in_array($methodName, ['increment', 'decrement'], true)) { - $methodReflection = $classReflection->getNativeMethod($methodName); - - return new class($classReflection, $methodName, $methodReflection) implements MethodReflection { - /** @var ClassReflection */ - private $classReflection; - - /** @var string */ - private $methodName; - - /** @var MethodReflection */ - private $methodReflection; - - public function __construct(ClassReflection $classReflection, string $methodName, MethodReflection $methodReflection) - { - $this->classReflection = $classReflection; - $this->methodName = $methodName; - $this->methodReflection = $methodReflection; - } - - public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return null; - } - - public function getName(): string - { - return $this->methodName; - } - - public function getPrototype(): \PHPStan\Reflection\ClassMemberReflection - { - return $this; - } - - public function getVariants(): array - { - return $this->methodReflection->getVariants(); - } - - public function isDeprecated(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?\PHPStan\Type\Type - { - return null; - } - - public function hasSideEffects(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createYes(); - } - }; - } - - $builderReflection = $this->reflectionProvider->getClass($builderName)->withTypes([new ObjectType($classReflection->getName())]); - $genericBuilderAndModelType = new GenericObjectType($builderName, [new ObjectType($classReflection->getName())]); - - if ($builderReflection->hasNativeMethod($methodName)) { - $reflection = $builderReflection->getNativeMethod($methodName); - - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($reflection->getVariants()); - - $returnType = TypeTraverser::map($parametersAcceptor->getReturnType(), static function (Type $type, callable $traverse) use ($genericBuilderAndModelType) { - if ($type instanceof TypeWithClassName && $type->getClassName() === Builder::class) { - return $genericBuilderAndModelType; - } - - return $traverse($type); - }); - - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $reflection, - $parametersAcceptor->getParameters(), - $returnType, - $parametersAcceptor->isVariadic() - ); - } - - if ($this->eloquentBuilderForwardsCallsExtension->hasMethod($builderReflection, $methodName)) { - return $this->eloquentBuilderForwardsCallsExtension->getMethod($builderReflection, $methodName); - } - - return null; - } -} diff --git a/php-packages/phpstan/src/Methods/ModelTypeHelper.php b/php-packages/phpstan/src/Methods/ModelTypeHelper.php deleted file mode 100644 index 8b122dbd6d..0000000000 --- a/php-packages/phpstan/src/Methods/ModelTypeHelper.php +++ /dev/null @@ -1,38 +0,0 @@ -getClassName() === Model::class) { - return new ObjectType($modelClass); - } - - return $traverse($type); - }); - } -} diff --git a/php-packages/phpstan/src/Methods/Passable.php b/php-packages/phpstan/src/Methods/Passable.php deleted file mode 100644 index 503dd60096..0000000000 --- a/php-packages/phpstan/src/Methods/Passable.php +++ /dev/null @@ -1,224 +0,0 @@ -methodReflectionFactory = $methodReflectionFactory; - $this->reflectionProvider = $reflectionProvider; - $this->pipeline = $pipeline; - $this->classReflection = $classReflection; - $this->methodName = $methodName; - } - - /** - * {@inheritdoc} - */ - public function getClassReflection(): ClassReflection - { - return $this->classReflection; - } - - /** - * {@inheritdoc} - */ - public function setClassReflection(ClassReflection $classReflection): PassableContract - { - $this->classReflection = $classReflection; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getMethodName(): string - { - return $this->methodName; - } - - /** - * {@inheritdoc} - */ - public function hasFound(): bool - { - return $this->methodReflection !== null; - } - - /** - * {@inheritdoc} - */ - public function searchOn(string $class): bool - { - $classReflection = $this->reflectionProvider->getClass($class); - - $found = $classReflection->hasNativeMethod($this->methodName); - - if ($found) { - $this->setMethodReflection($classReflection->getNativeMethod($this->methodName)); - } - - return $found; - } - - /** - * {@inheritdoc} - */ - public function getMethodReflection(): MethodReflection - { - if ($this->methodReflection === null) { - throw new LogicException("MethodReflection doesn't exist"); - } - - return $this->methodReflection; - } - - /** - * {@inheritdoc} - */ - public function setMethodReflection(MethodReflection $methodReflection): void - { - $this->methodReflection = $methodReflection; - } - - /** - * {@inheritdoc} - */ - public function setStaticAllowed(bool $staticAllowed): void - { - $this->staticAllowed = $staticAllowed; - } - - /** - * {@inheritdoc} - */ - public function isStaticAllowed(): bool - { - return $this->staticAllowed; - } - - /** - * {@inheritdoc} - */ - public function sendToPipeline(string $class, $staticAllowed = false): bool - { - $classReflection = $this->reflectionProvider->getClass($class); - - $this->setStaticAllowed($this->staticAllowed ?: $staticAllowed); - - $originalClassReflection = $this->classReflection; - $this->pipeline->send($this->setClassReflection($classReflection)) - ->then( - function (PassableContract $passable) use ($originalClassReflection) { - if ($passable->hasFound()) { - $this->setMethodReflection($passable->getMethodReflection()); - $this->setStaticAllowed($passable->isStaticAllowed()); - } - - $this->setClassReflection($originalClassReflection); - } - ); - - if ($result = $this->hasFound()) { - $methodReflection = $this->getMethodReflection(); - if (get_class($methodReflection) === PhpMethodReflection::class) { - $methodReflection = Mockery::mock($methodReflection); - $methodReflection->shouldReceive('isStatic') - ->andReturn($this->isStaticAllowed()); - } - - $this->setMethodReflection($methodReflection); - } - - return $result; - } - - public function getReflectionProvider(): ReflectionProvider - { - return $this->reflectionProvider; - } - - /** - * {@inheritdoc} - */ - public function getMethodReflectionFactory(): PhpMethodReflectionFactory - { - return $this->methodReflectionFactory; - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/Auths.php b/php-packages/phpstan/src/Methods/Pipes/Auths.php deleted file mode 100644 index 3176ad5ee4..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/Auths.php +++ /dev/null @@ -1,68 +0,0 @@ -getClassReflection() - ->getName(); - - $found = false; - - $config = $this->resolve('config'); - - if ($config !== null && in_array($classReflectionName, $this->classes, true)) { - $authModel = $this->getAuthModel($config); - - if ($authModel !== null) { - $found = $passable->sendToPipeline($authModel); - } - } elseif ($classReflectionName === \Illuminate\Contracts\Auth\Factory::class || $classReflectionName === \Illuminate\Auth\AuthManager::class) { - $found = $passable->sendToPipeline( - \Illuminate\Contracts\Auth\Guard::class - ); - } - - if (! $found) { - $next($passable); - } - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/Contracts.php b/php-packages/phpstan/src/Methods/Pipes/Contracts.php deleted file mode 100644 index a82ce20ba3..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/Contracts.php +++ /dev/null @@ -1,67 +0,0 @@ -concretes($passable->getClassReflection()) as $concrete) { - if ($found = $passable->sendToPipeline($concrete)) { - break; - } - } - - if (! $found) { - $next($passable); - } - } - - /** - * @param \PHPStan\Reflection\ClassReflection $classReflection - * @return class-string[] - */ - private function concretes(ClassReflection $classReflection): array - { - if ($classReflection->isInterface() && Str::startsWith($classReflection->getName(), 'Illuminate\Contracts')) { - $concrete = $this->resolve($classReflection->getName()); - - if ($concrete !== null) { - $class = get_class($concrete); - - if ($class) { - return [$class]; - } - } - } - - return []; - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/Facades.php b/php-packages/phpstan/src/Methods/Pipes/Facades.php deleted file mode 100644 index c98987bc99..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/Facades.php +++ /dev/null @@ -1,66 +0,0 @@ -getClassReflection(); - - $found = false; - - if ($classReflection->isSubclassOf(Facade::class)) { - $facadeClass = $classReflection->getName(); - - if ($concrete = $facadeClass::getFacadeRoot()) { - $class = get_class($concrete); - - if ($class) { - $found = $passable->sendToPipeline($class, true); - } - } - - if (! $found && Str::startsWith($passable->getMethodName(), 'assert')) { - $fakeFacadeClass = $this->getFake($facadeClass); - - if ($passable->getReflectionProvider()->hasClass($fakeFacadeClass)) { - assert(class_exists($fakeFacadeClass)); - $found = $passable->sendToPipeline($fakeFacadeClass, true); - } - } - } - - if (! $found) { - $next($passable); - } - } - - private function getFake(string $facade): string - { - $shortClassName = substr($facade, strrpos($facade, '\\') + 1); - - return sprintf('\\Illuminate\\Support\\Testing\\Fakes\\%sFake', $shortClassName); - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/Macros.php b/php-packages/phpstan/src/Methods/Pipes/Macros.php deleted file mode 100644 index 8dbabd83b3..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/Macros.php +++ /dev/null @@ -1,105 +0,0 @@ -getTraits() as $trait) { - if ($this->hasIndirectTraitUse($trait, $traitName)) { - return true; - } - } - - return $class->hasTraitUse($traitName); - } - - /** - * {@inheritdoc} - */ - public function handle(PassableContract $passable, Closure $next): void - { - $classReflection = $passable->getClassReflection(); - - /** @var class-string $className */ - $className = null; - $found = false; - $macroTraitProperty = null; - - if ($classReflection->isInterface() && Str::startsWith($classReflection->getName(), 'Illuminate\Contracts')) { - /** @var object|null $concrete */ - $concrete = $this->resolve($classReflection->getName()); - - if ($concrete !== null) { - $className = get_class($concrete); - - if ($className && $passable->getReflectionProvider() - ->getClass($className) - ->hasTraitUse(Macroable::class)) { - $macroTraitProperty = 'macros'; - } - } - } elseif ($classReflection->hasTraitUse(Macroable::class) || $classReflection->getName() === Builder::class) { - $className = $classReflection->getName(); - $macroTraitProperty = 'macros'; - } elseif ($this->hasIndirectTraitUse($classReflection, CarbonMacro::class)) { - $className = $classReflection->getName(); - $macroTraitProperty = 'globalMacros'; - } - - if ($className !== null && $macroTraitProperty) { - $classReflection = $passable->getReflectionProvider()->getClass($className); - $refObject = new \ReflectionClass($className); - $refProperty = $refObject->getProperty($macroTraitProperty); - $refProperty->setAccessible(true); - - $found = $className === Builder::class - ? $className::hasGlobalMacro($passable->getMethodName()) - : $className::hasMacro($passable->getMethodName()); - - if ($found) { - $reflectionFunction = new \ReflectionFunction($refProperty->getValue()[$passable->getMethodName()]); - - $methodReflection = new Macro( - $classReflection, - $passable->getMethodName(), - $reflectionFunction - ); - - $methodReflection->setIsStatic(true); - - $passable->setMethodReflection($methodReflection); - } - } - - if (! $found) { - $next($passable); - } - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/Managers.php b/php-packages/phpstan/src/Methods/Pipes/Managers.php deleted file mode 100644 index 6e66e66faa..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/Managers.php +++ /dev/null @@ -1,63 +0,0 @@ -getClassReflection(); - - $found = false; - - if ($classReflection->isSubclassOf(Manager::class)) { - $driver = null; - - $concrete = $this->resolve( - $classReflection->getName() - ); - - try { - $driver = $concrete->driver(); - } catch (InvalidArgumentException $exception) { - // .. - } - - if ($driver !== null) { - $class = get_class($driver); - - if ($class) { - $found = $passable->sendToPipeline($class); - } - } - } - - if (! $found) { - $next($passable); - } - } -} diff --git a/php-packages/phpstan/src/Methods/Pipes/SelfClass.php b/php-packages/phpstan/src/Methods/Pipes/SelfClass.php deleted file mode 100644 index ccff37108e..0000000000 --- a/php-packages/phpstan/src/Methods/Pipes/SelfClass.php +++ /dev/null @@ -1,35 +0,0 @@ -getClassReflection() - ->getName(); - - if (! $passable->searchOn($className)) { - $next($passable); - } - } -} diff --git a/php-packages/phpstan/src/Methods/RelationForwardsCallsExtension.php b/php-packages/phpstan/src/Methods/RelationForwardsCallsExtension.php deleted file mode 100644 index 61aee24f28..0000000000 --- a/php-packages/phpstan/src/Methods/RelationForwardsCallsExtension.php +++ /dev/null @@ -1,150 +0,0 @@ - */ - private $cache = []; - - /** @var ReflectionProvider */ - private $reflectionProvider; - - /** @var EloquentBuilderForwardsCallsExtension */ - private $eloquentBuilderForwardsCallsExtension; - - public function __construct(BuilderHelper $builderHelper, ReflectionProvider $reflectionProvider, EloquentBuilderForwardsCallsExtension $eloquentBuilderForwardsCallsExtension) - { - $this->builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - $this->eloquentBuilderForwardsCallsExtension = $eloquentBuilderForwardsCallsExtension; - } - - public function hasMethod(ClassReflection $classReflection, string $methodName): bool - { - if (array_key_exists($classReflection->getCacheKey().'-'.$methodName, $this->cache)) { - return true; - } - - $methodReflection = $this->findMethod($classReflection, $methodName); - - if ($methodReflection !== null) { - $this->cache[$classReflection->getCacheKey().'-'.$methodName] = $methodReflection; - - return true; - } - - return false; - } - - public function getMethod( - ClassReflection $classReflection, - string $methodName - ): MethodReflection { - return $this->cache[$classReflection->getCacheKey().'-'.$methodName]; - } - - /** - * @throws MissingMethodFromReflectionException - * @throws ShouldNotHappenException - */ - private function findMethod(ClassReflection $classReflection, string $methodName): ?MethodReflection - { - if (! $classReflection->isSubclassOf(Relation::class)) { - return null; - } - - /** @var Type|TemplateMixedType|null $relatedModel */ - $relatedModel = $classReflection->getActiveTemplateTypeMap()->getType('TRelatedModel'); - - if ($relatedModel === null) { - return null; - } - - if ($relatedModel instanceof TypeWithClassName) { - $modelReflection = $relatedModel->getClassReflection(); - } else { - $modelReflection = $this->reflectionProvider->getClass(Model::class); - } - - if ($modelReflection === null) { - return null; - } - - $builderName = $this->builderHelper->determineBuilderName($modelReflection->getName()); - - $builderReflection = $this->reflectionProvider->getClass($builderName)->withTypes([$relatedModel]); - - if ($builderReflection->hasNativeMethod($methodName)) { - $reflection = $builderReflection->getNativeMethod($methodName); - } elseif ($this->eloquentBuilderForwardsCallsExtension->hasMethod($builderReflection, $methodName)) { - $reflection = $this->eloquentBuilderForwardsCallsExtension->getMethod($builderReflection, $methodName); - } else { - return null; - } - - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($reflection->getVariants()); - $returnType = $parametersAcceptor->getReturnType(); - - $types = [$relatedModel]; - - // BelongsTo relation needs second generic type - if ($classReflection->getName() === BelongsTo::class) { - $childType = $classReflection->getActiveTemplateTypeMap()->getType('TChildModel'); - - if ($childType !== null) { - $types[] = $childType; - } - } - - if ((new ObjectType(Builder::class))->isSuperTypeOf($returnType)->yes()) { - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $reflection, - $parametersAcceptor->getParameters(), - new GenericObjectType($classReflection->getName(), $types), - $parametersAcceptor->isVariadic() - ); - } - - return new EloquentBuilderMethodReflection( - $methodName, - $classReflection, - $reflection, - $parametersAcceptor->getParameters(), - $returnType, - $parametersAcceptor->isVariadic() - ); - } -} diff --git a/php-packages/phpstan/src/Methods/StorageMethodsClassReflectionExtension.php b/php-packages/phpstan/src/Methods/StorageMethodsClassReflectionExtension.php deleted file mode 100644 index b46979d97b..0000000000 --- a/php-packages/phpstan/src/Methods/StorageMethodsClassReflectionExtension.php +++ /dev/null @@ -1,67 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - - public function hasMethod(ClassReflection $classReflection, string $methodName): bool - { - if ($classReflection->getName() !== Storage::class) { - return false; - } - - if ($this->reflectionProvider->getClass(FilesystemManager::class)->hasMethod($methodName)) { - return true; - } - - if ($this->reflectionProvider->getClass(FilesystemAdapter::class)->hasMethod($methodName)) { - return true; - } - - return false; - } - - public function getMethod( - ClassReflection $classReflection, - string $methodName - ): MethodReflection { - if ($this->reflectionProvider->getClass(FilesystemManager::class)->hasMethod($methodName)) { - return new StaticMethodReflection( - $this->reflectionProvider->getClass(FilesystemManager::class)->getMethod($methodName, new OutOfClassScope()) - ); - } - - return new StaticMethodReflection( - $this->reflectionProvider->getClass(FilesystemAdapter::class)->getMethod($methodName, new OutOfClassScope()) - ); - } -} diff --git a/php-packages/phpstan/src/Properties/HigherOrderCollectionProxyPropertyExtension.php b/php-packages/phpstan/src/Properties/HigherOrderCollectionProxyPropertyExtension.php deleted file mode 100644 index 2d9d8670c7..0000000000 --- a/php-packages/phpstan/src/Properties/HigherOrderCollectionProxyPropertyExtension.php +++ /dev/null @@ -1,124 +0,0 @@ -getActiveTemplateTypeMap(); - - /** @var Type\Constant\ConstantStringType $methodType */ - $methodType = $activeTemplateTypeMap->getType('T'); - - /** @var Type\ObjectType $modelType */ - $modelType = $activeTemplateTypeMap->getType('TValue'); - - $propertyType = $modelType->getProperty($propertyName, new OutOfClassScope())->getReadableType(); - - $returnType = HigherOrderCollectionProxyHelper::determineReturnType($methodType->getValue(), $modelType, $propertyType); - - return new class($classReflection, $returnType) implements PropertyReflection { - /** @var ClassReflection */ - private $classReflection; - - /** @var Type\Type */ - private $returnType; - - public function __construct(ClassReflection $classReflection, Type\Type $returnType) - { - $this->classReflection = $classReflection; - $this->returnType = $returnType; - } - - public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return null; - } - - public function getReadableType(): Type\Type - { - return $this->returnType; - } - - public function getWritableType(): Type\Type - { - return $this->returnType; - } - - public function canChangeTypeAfterAssignment(): bool - { - return false; - } - - public function isReadable(): bool - { - return true; - } - - public function isWritable(): bool - { - return false; - } - - public function isDeprecated(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isInternal(): \PHPStan\TrinaryLogic - { - return TrinaryLogic::createNo(); - } - }; - } -} diff --git a/php-packages/phpstan/src/Properties/MigrationHelper.php b/php-packages/phpstan/src/Properties/MigrationHelper.php deleted file mode 100644 index 870053a7ac..0000000000 --- a/php-packages/phpstan/src/Properties/MigrationHelper.php +++ /dev/null @@ -1,102 +0,0 @@ -parser = $parser; - $this->databaseMigrationPath = $databaseMigrationPath; - $this->fileHelper = $fileHelper; - } - - /** - * @return array - */ - public function initializeTables(): array - { - if (empty($this->databaseMigrationPath)) { - $this->databaseMigrationPath = [database_path('migrations')]; - } - - $schemaAggregator = new SchemaAggregator(); - $filesArray = $this->getMigrationFiles(); - - if (empty($filesArray)) { - return []; - } - - ksort($filesArray); - - $this->requireFiles($filesArray); - - foreach ($filesArray as $file) { - $schemaAggregator->addStatements($this->parser->parseFile($file->getPathname())); - } - - return $schemaAggregator->tables; - } - - /** - * @return SplFileInfo[] - */ - private function getMigrationFiles(): array - { - /** @var SplFileInfo[] $migrationFiles */ - $migrationFiles = []; - - foreach ($this->databaseMigrationPath as $additionalPath) { - $absolutePath = $this->fileHelper->absolutizePath($additionalPath); - - if (is_dir($absolutePath)) { - $migrationFiles += iterator_to_array( - new RegexIterator( - new RecursiveIteratorIterator(new RecursiveDirectoryIterator($absolutePath)), - '/\.php$/i' - ) - ); - } - } - - return $migrationFiles; - } - - /** - * @param SplFileInfo[] $files - */ - private function requireFiles(array $files): void - { - foreach ($files as $file) { - require_once $file; - } - } -} diff --git a/php-packages/phpstan/src/Properties/ModelAccessorExtension.php b/php-packages/phpstan/src/Properties/ModelAccessorExtension.php deleted file mode 100644 index c889972a74..0000000000 --- a/php-packages/phpstan/src/Properties/ModelAccessorExtension.php +++ /dev/null @@ -1,46 +0,0 @@ -isSubclassOf(Model::class)) { - return false; - } - - return $classReflection->hasNativeMethod('get'.Str::studly($propertyName).'Attribute'); - } - - public function getProperty( - ClassReflection $classReflection, - string $propertyName - ): PropertyReflection { - $method = $classReflection->getNativeMethod('get'.Str::studly($propertyName).'Attribute'); - - return new ModelProperty( - $classReflection, - $method->getVariants()[0]->getReturnType(), - $method->getVariants()[0]->getReturnType() - ); - } -} diff --git a/php-packages/phpstan/src/Properties/ModelProperty.php b/php-packages/phpstan/src/Properties/ModelProperty.php deleted file mode 100644 index e6515478b3..0000000000 --- a/php-packages/phpstan/src/Properties/ModelProperty.php +++ /dev/null @@ -1,105 +0,0 @@ -declaringClass = $declaringClass; - $this->readableType = $readableType; - $this->writableType = $writableType; - $this->writeable = $writeable; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->declaringClass; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function isReadable(): bool - { - return true; - } - - public function isWritable(): bool - { - return $this->writeable; - } - - public function getDocComment(): ?string - { - return null; - } - - public function getReadableType(): Type - { - return $this->readableType; - } - - public function getWritableType(): Type - { - return $this->writableType; - } - - public function canChangeTypeAfterAssignment(): bool - { - return false; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } -} diff --git a/php-packages/phpstan/src/Properties/ModelPropertyExtension.php b/php-packages/phpstan/src/Properties/ModelPropertyExtension.php deleted file mode 100644 index 55fd433c91..0000000000 --- a/php-packages/phpstan/src/Properties/ModelPropertyExtension.php +++ /dev/null @@ -1,274 +0,0 @@ - */ - private $tables = []; - - /** @var TypeStringResolver */ - private $stringResolver; - - /** @var string */ - private $dateClass; - - /** @var MigrationHelper */ - private $migrationHelper; - - public function __construct(TypeStringResolver $stringResolver, MigrationHelper $migrationHelper) - { - $this->stringResolver = $stringResolver; - $this->migrationHelper = $migrationHelper; - } - - public function hasProperty(ClassReflection $classReflection, string $propertyName): bool - { - if (! $classReflection->isSubclassOf(Model::class)) { - return false; - } - - if ($classReflection->isAbstract()) { - return false; - } - - if ($classReflection->hasNativeMethod('get'.Str::studly($propertyName).'Attribute')) { - return false; - } - - if (ReflectionHelper::hasPropertyTag($classReflection, $propertyName)) { - return false; - } - - if (count($this->tables) === 0) { - $this->tables = $this->migrationHelper->initializeTables(); - } - - if ($propertyName === 'id') { - return true; - } - - $modelName = $classReflection->getNativeReflection()->getName(); - - try { - $reflect = new \ReflectionClass($modelName); - - /** @var Model $modelInstance */ - $modelInstance = $reflect->newInstanceWithoutConstructor(); - - $tableName = $modelInstance->getTable(); - } catch (\ReflectionException $e) { - return false; - } - - if (! array_key_exists($tableName, $this->tables)) { - return false; - } - - if (! array_key_exists($propertyName, $this->tables[$tableName]->columns)) { - return false; - } - - $this->castPropertiesType($modelInstance); - - $column = $this->tables[$tableName]->columns[$propertyName]; - - [$readableType, $writableType] = $this->getReadableAndWritableTypes($column, $modelInstance); - - $column->readableType = $readableType; - $column->writeableType = $writableType; - - $this->tables[$tableName]->columns[$propertyName] = $column; - - return true; - } - - public function getProperty( - ClassReflection $classReflection, - string $propertyName - ): PropertyReflection { - $modelName = $classReflection->getNativeReflection()->getName(); - - try { - $reflect = new \ReflectionClass($modelName); - - /** @var Model $modelInstance */ - $modelInstance = $reflect->newInstanceWithoutConstructor(); - - $tableName = $modelInstance->getTable(); - } catch (\ReflectionException $e) { - // `hasProperty` should return false if there was a reflection exception. - // so this should never happen - throw new ShouldNotHappenException(); - } - - if ( - ( - ! array_key_exists($tableName, $this->tables) - || ! array_key_exists($propertyName, $this->tables[$tableName]->columns) - ) - && $propertyName === 'id' - ) { - return new ModelProperty( - $classReflection, - new IntegerType(), - new IntegerType() - ); - } - - $column = $this->tables[$tableName]->columns[$propertyName]; - - return new ModelProperty( - $classReflection, - $this->stringResolver->resolve($column->readableType), - $this->stringResolver->resolve($column->writeableType) - ); - } - - private function getDateClass(): string - { - if (! $this->dateClass) { - $this->dateClass = class_exists(\Illuminate\Support\Facades\Date::class) - ? '\\'.get_class(\Illuminate\Support\Facades\Date::now()) - : '\Illuminate\Support\Carbon'; - - $this->dateClass .= '|\Carbon\Carbon'; - } - - return $this->dateClass; - } - - /** - * @param SchemaColumn $column - * @param Model $modelInstance - * @return string[] - * @phpstan-return array - */ - private function getReadableAndWritableTypes(SchemaColumn $column, Model $modelInstance): array - { - $readableType = $column->readableType; - $writableType = $column->writeableType; - - if (in_array($column->name, $modelInstance->getDates(), true)) { - return [$this->getDateClass().($column->nullable ? '|null' : ''), $this->getDateClass().'|string'.($column->nullable ? '|null' : '')]; - } - - switch ($column->readableType) { - case 'string': - case 'int': - case 'float': - $readableType = $writableType = $column->readableType.($column->nullable ? '|null' : ''); - break; - - case 'boolean': - case 'bool': - switch ((string) config('database.default')) { - case 'sqlite': - case 'mysql': - $writableType = '0|1|bool'; - $readableType = 'bool'; - break; - default: - $readableType = $writableType = 'bool'; - break; - } - break; - case 'enum': - if (! $column->options) { - $readableType = $writableType = 'string'; - } else { - $readableType = $writableType = '\''.implode('\'|\'', $column->options).'\''; - } - - break; - - default: - break; - } - - return [$readableType, $writableType]; - } - - private function castPropertiesType(Model $modelInstance): void - { - $casts = $modelInstance->getCasts(); - foreach ($casts as $name => $type) { - if (! array_key_exists($name, $this->tables[$modelInstance->getTable()]->columns)) { - continue; - } - - switch ($type) { - case 'boolean': - case 'bool': - $realType = 'boolean'; - break; - case 'string': - $realType = 'string'; - break; - case 'array': - case 'json': - $realType = 'array'; - break; - case 'object': - $realType = 'object'; - break; - case 'int': - case 'integer': - case 'timestamp': - $realType = 'integer'; - break; - case 'real': - case 'double': - case 'float': - $realType = 'float'; - break; - case 'date': - case 'datetime': - $realType = $this->getDateClass(); - break; - case 'collection': - $realType = '\Illuminate\Support\Collection'; - break; - case 'Illuminate\Database\Eloquent\Casts\AsArrayObject': - $realType = ArrayObject::class; - break; - case 'Illuminate\Database\Eloquent\Casts\AsCollection': - $realType = '\Illuminate\Support\Collection'; - break; - default: - $realType = class_exists($type) ? ('\\'.$type) : 'mixed'; - break; - } - - if ($this->tables[$modelInstance->getTable()]->columns[$name]->nullable) { - $realType .= '|null'; - } - - $this->tables[$modelInstance->getTable()]->columns[$name]->readableType = $realType; - $this->tables[$modelInstance->getTable()]->columns[$name]->writeableType = $realType; - } - } -} diff --git a/php-packages/phpstan/src/Properties/ModelRelationsExtension.php b/php-packages/phpstan/src/Properties/ModelRelationsExtension.php deleted file mode 100644 index 9364860c8d..0000000000 --- a/php-packages/phpstan/src/Properties/ModelRelationsExtension.php +++ /dev/null @@ -1,124 +0,0 @@ -relationParserHelper = $relationParserHelper; - $this->builderHelper = $builderHelper; - } - - public function hasProperty(ClassReflection $classReflection, string $propertyName): bool - { - if (! $classReflection->isSubclassOf(Model::class)) { - return false; - } - - if (ReflectionHelper::hasPropertyTag($classReflection, $propertyName)) { - return false; - } - - $hasNativeMethod = $classReflection->hasNativeMethod($propertyName); - - if (! $hasNativeMethod) { - return false; - } - - $returnType = ParametersAcceptorSelector::selectSingle($classReflection->getNativeMethod($propertyName)->getVariants())->getReturnType(); - - if (! (new ObjectType(Relation::class))->isSuperTypeOf($returnType)->yes()) { - return false; - } - - return true; - } - - public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection - { - $method = $classReflection->getMethod($propertyName, new OutOfClassScope()); - - /** @var ObjectType $returnType */ - $returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType(); - - if ($returnType instanceof GenericObjectType) { - /** @var ObjectType $relatedModelType */ - $relatedModelType = $returnType->getTypes()[0]; - $relatedModelClassName = $relatedModelType->getClassName(); - } else { - $relatedModelClassName = $this - ->relationParserHelper - ->findRelatedModelInRelationMethod($method); - } - - if ($relatedModelClassName === null) { - $relatedModelClassName = Model::class; - } - - $relatedModel = new ObjectType($relatedModelClassName); - $collectionClass = $this->builderHelper->determineCollectionClassName($relatedModelClassName); - - if (Str::contains($returnType->getClassName(), 'Many')) { - return new ModelProperty( - $classReflection, - new GenericObjectType($collectionClass, [$relatedModel]), - new NeverType(), - false - ); - } - - if (Str::endsWith($returnType->getClassName(), 'MorphTo')) { - return new ModelProperty($classReflection, new UnionType([ - new ObjectType(Model::class), - new MixedType(), - ]), new NeverType(), false); - } - - return new ModelProperty($classReflection, new UnionType([ - $relatedModel, - new NullType(), - ]), new NeverType(), false); - } -} diff --git a/php-packages/phpstan/src/Properties/ReflectionTypeContainer.php b/php-packages/phpstan/src/Properties/ReflectionTypeContainer.php deleted file mode 100644 index f4b7daea81..0000000000 --- a/php-packages/phpstan/src/Properties/ReflectionTypeContainer.php +++ /dev/null @@ -1,67 +0,0 @@ -type = $type; - } - - /** - * {@inheritdoc} - */ - public function allowsNull(): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isBuiltin(): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return $this->getName(); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return $this->type; - } -} diff --git a/php-packages/phpstan/src/Properties/SchemaAggregator.php b/php-packages/phpstan/src/Properties/SchemaAggregator.php deleted file mode 100644 index 0d9a5ee753..0000000000 --- a/php-packages/phpstan/src/Properties/SchemaAggregator.php +++ /dev/null @@ -1,439 +0,0 @@ - */ - public $tables = []; - - /** - * @param array $stmts - */ - public function addStatements(array $stmts): void - { - $nodeFinder = new NodeFinder(); - - /** @var PhpParser\Node\Stmt\Class_[] $classes */ - $classes = $nodeFinder->findInstanceOf($stmts, PhpParser\Node\Stmt\Class_::class); - - foreach ($classes as $stmt) { - $this->addClassStatements($stmt->stmts); - } - } - - /** - * @param array $stmts - */ - private function addClassStatements(array $stmts): void - { - foreach ($stmts as $stmt) { - if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod - && $stmt->name->name !== 'down' - && $stmt->stmts - ) { - $this->addUpMethodStatements($stmt->stmts); - } - } - } - - /** - * @param PhpParser\Node\Stmt[] $stmts - */ - private function addUpMethodStatements(array $stmts): void - { - $nodeFinder = new NodeFinder(); - $methods = $nodeFinder->findInstanceOf($stmts, PhpParser\Node\Stmt\Expression::class); - - foreach ($methods as $stmt) { - if ($stmt instanceof PhpParser\Node\Stmt\Expression - && $stmt->expr instanceof PhpParser\Node\Expr\StaticCall - && ($stmt->expr->class instanceof PhpParser\Node\Name) - && $stmt->expr->name instanceof PhpParser\Node\Identifier - && ($stmt->expr->class->toCodeString() === '\Illuminate\Support\Facades\Schema' || $stmt->expr->class->toCodeString() === '\Schema') - ) { - switch ($stmt->expr->name->name) { - case 'create': - $this->alterTable($stmt->expr, true); - break; - - case 'table': - $this->alterTable($stmt->expr, false); - break; - - case 'drop': - case 'dropIfExists': - $this->dropTable($stmt->expr); - break; - - case 'rename': - $this->renameTable($stmt->expr); - } - } - } - } - - private function alterTable(PhpParser\Node\Expr\StaticCall $call, bool $creating): void - { - if (! isset($call->args[0]) - || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ - ) { - return; - } - - $tableName = $call->getArgs()[0]->value->value; - - if ($creating) { - $this->tables[$tableName] = new SchemaTable($tableName); - } - - if (! isset($call->args[1]) - || ! $call->getArgs()[1]->value instanceof PhpParser\Node\Expr\Closure - || count($call->getArgs()[1]->value->params) < 1 - || ($call->getArgs()[1]->value->params[0]->type instanceof PhpParser\Node\Name - && $call->getArgs()[1]->value->params[0]->type->toCodeString() - !== '\\Illuminate\Database\Schema\Blueprint') - ) { - return; - } - - $updateClosure = $call->getArgs()[1]->value; - - if ($call->getArgs()[1]->value->params[0]->var instanceof PhpParser\Node\Expr\Variable - && is_string($call->getArgs()[1]->value->params[0]->var->name) - ) { - $argName = $call->getArgs()[1]->value->params[0]->var->name; - - $this->processColumnUpdates($tableName, $argName, $updateClosure->stmts); - } - } - - /** - * @param string $tableName - * @param string $argName - * @param PhpParser\Node\Stmt[] $stmts - * - * @throws \Exception - */ - private function processColumnUpdates(string $tableName, string $argName, array $stmts): void - { - if (! isset($this->tables[$tableName])) { - return; - } - - $table = $this->tables[$tableName]; - - foreach ($stmts as $stmt) { - if ($stmt instanceof PhpParser\Node\Stmt\Expression - && $stmt->expr instanceof PhpParser\Node\Expr\MethodCall - && $stmt->expr->name instanceof PhpParser\Node\Identifier - ) { - $rootVar = $stmt->expr; - - $firstMethodCall = $rootVar; - - $nullable = false; - - while ($rootVar instanceof PhpParser\Node\Expr\MethodCall) { - if ($rootVar->name instanceof PhpParser\Node\Identifier - && $rootVar->name->name === 'nullable' - ) { - $nullable = true; - } - - $firstMethodCall = $rootVar; - $rootVar = $rootVar->var; - } - - if ($rootVar instanceof PhpParser\Node\Expr\Variable - && $rootVar->name === $argName - && $firstMethodCall->name instanceof PhpParser\Node\Identifier - ) { - $firstArg = $firstMethodCall->getArgs()[0]->value ?? null; - $secondArg = $firstMethodCall->getArgs()[1]->value ?? null; - - if ($firstMethodCall->name->name === 'foreignIdFor') { - if ($firstArg instanceof PhpParser\Node\Expr\ClassConstFetch - && $firstArg->class instanceof PhpParser\Node\Name - ) { - $modelClass = $firstArg->class->toCodeString(); - } elseif ($firstArg instanceof PhpParser\Node\Scalar\String_) { - $modelClass = $firstArg->value; - } else { - continue; - } - - $columnName = Str::snake(class_basename($modelClass)).'_id'; - if ($secondArg instanceof PhpParser\Node\Scalar\String_) { - $columnName = $secondArg->value; - } - - $table->setColumn(new SchemaColumn($columnName, 'int', $nullable)); - - continue; - } - - if (! $firstArg instanceof PhpParser\Node\Scalar\String_) { - if ($firstMethodCall->name->name === 'timestamps' - || $firstMethodCall->name->name === 'timestampsTz' - || $firstMethodCall->name->name === 'nullableTimestamps' - || $firstMethodCall->name->name === 'nullableTimestampsTz' - || $firstMethodCall->name->name === 'rememberToken' - ) { - switch (strtolower($firstMethodCall->name->name)) { - case 'droptimestamps': - case 'droptimestampstz': - $table->dropColumn('created_at'); - $table->dropColumn('updated_at'); - break; - - case 'remembertoken': - $table->setColumn(new SchemaColumn('remember_token', 'string', $nullable)); - break; - - case 'dropremembertoken': - $table->dropColumn('remember_token'); - break; - - case 'timestamps': - case 'timestampstz': - case 'nullabletimestamps': - $table->setColumn(new SchemaColumn('created_at', 'string', true)); - $table->setColumn(new SchemaColumn('updated_at', 'string', true)); - break; - } - - continue; - } - - if ($firstMethodCall->name->name === 'softDeletes' - || $firstMethodCall->name->name === 'softDeletesTz' - || $firstMethodCall->name->name === 'dropSoftDeletes' - || $firstMethodCall->name->name === 'dropSoftDeletesTz' - ) { - $columnName = 'deleted_at'; - } else { - continue; - } - } else { - $columnName = $firstArg->value; - } - - $secondArgArray = null; - - if ($secondArg instanceof PhpParser\Node\Expr\Array_) { - $secondArgArray = []; - - foreach ($secondArg->items as $array_item) { - if ($array_item !== null && $array_item->value instanceof PhpParser\Node\Scalar\String_) { - $secondArgArray[] = $array_item->value->value; - } - } - } - - switch (strtolower($firstMethodCall->name->name)) { - case 'biginteger': - case 'increments': - case 'integer': - case 'integerincrements': - case 'mediumincrements': - case 'mediuminteger': - case 'smallincrements': - case 'smallinteger': - case 'tinyincrements': - case 'tinyinteger': - case 'unsignedbiginteger': - case 'unsignedinteger': - case 'unsignedmediuminteger': - case 'unsignedsmallinteger': - case 'unsignedtinyinteger': - case 'bigincrements': - $table->setColumn(new SchemaColumn($columnName, 'int', $nullable)); - break; - - case 'char': - case 'datetimetz': - case 'date': - case 'datetime': - case 'ipaddress': - case 'json': - case 'jsonb': - case 'linestring': - case 'longtext': - case 'macaddress': - case 'mediumtext': - case 'multilinestring': - case 'string': - case 'text': - case 'time': - case 'timestamp': - case 'uuid': - case 'binary': - $table->setColumn(new SchemaColumn($columnName, 'string', $nullable)); - break; - - case 'boolean': - $table->setColumn(new SchemaColumn($columnName, 'bool', $nullable)); - break; - - case 'geometry': - case 'geometrycollection': - case 'multipoint': - case 'multipolygon': - case 'multipolygonz': - case 'point': - case 'polygon': - case 'computed': - $table->setColumn(new SchemaColumn($columnName, 'mixed', $nullable)); - break; - - case 'double': - case 'float': - case 'unsigneddecimal': - case 'decimal': - $table->setColumn(new SchemaColumn($columnName, 'float', $nullable)); - break; - - case 'after': - if ($secondArg instanceof PhpParser\Node\Expr\Closure - && $secondArg->params[0]->var instanceof PhpParser\Node\Expr\Variable - && ! ($secondArg->params[0]->var->name instanceof PhpParser\Node\Expr)) { - $argName = $secondArg->params[0]->var->name; - $this->processColumnUpdates($tableName, $argName, $secondArg->stmts); - } - break; - - case 'dropcolumn': - case 'dropifexists': - case 'dropsoftdeletes': - case 'dropsoftdeletestz': - case 'removecolumn': - case 'drop': - $table->dropColumn($columnName); - break; - - case 'dropforeign': - case 'dropindex': - case 'dropprimary': - case 'dropunique': - case 'foreign': - case 'index': - case 'primary': - case 'renameindex': - case 'spatialIndex': - case 'unique': - case 'dropspatialindex': - break; - - case 'dropmorphs': - $table->dropColumn($columnName.'_type'); - $table->dropColumn($columnName.'_id'); - break; - - case 'enum': - $table->setColumn(new SchemaColumn($columnName, 'enum', $nullable, $secondArgArray)); - break; - - case 'morphs': - $table->setColumn(new SchemaColumn($columnName.'_type', 'string', $nullable)); - $table->setColumn(new SchemaColumn($columnName.'_id', 'int', $nullable)); - break; - - case 'nullablemorphs': - $table->setColumn(new SchemaColumn($columnName.'_type', 'string', true)); - $table->setColumn(new SchemaColumn($columnName.'_id', 'int', true)); - break; - - case 'nullableuuidmorphs': - $table->setColumn(new SchemaColumn($columnName.'_type', 'string', true)); - $table->setColumn(new SchemaColumn($columnName.'_id', 'string', true)); - break; - - case 'rename': - case 'renamecolumn': - if ($secondArg instanceof PhpParser\Node\Scalar\String_) { - $table->renameColumn($columnName, $secondArg->value); - } - break; - - case 'set': - $table->setColumn(new SchemaColumn($columnName, 'set', $nullable, $secondArgArray)); - break; - - case 'softdeletestz': - case 'timestamptz': - case 'timetz': - case 'year': - case 'softdeletes': - $table->setColumn(new SchemaColumn($columnName, 'string', true)); - break; - - case 'uuidmorphs': - $table->setColumn(new SchemaColumn($columnName.'_type', 'string', $nullable)); - $table->setColumn(new SchemaColumn($columnName.'_id', 'string', $nullable)); - break; - - default: - // We know a property exists with a name, we just don't know its type. - $table->setColumn(new SchemaColumn($columnName, 'mixed', $nullable)); - break; - } - } - } - } - } - - private function dropTable(PhpParser\Node\Expr\StaticCall $call): void - { - if (! isset($call->args[0]) - || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ - ) { - return; - } - - $tableName = $call->getArgs()[0]->value->value; - - unset($this->tables[$tableName]); - } - - private function renameTable(PhpParser\Node\Expr\StaticCall $call): void - { - if (! isset($call->args[0], $call->args[1]) - || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ - || ! $call->getArgs()[1]->value instanceof PhpParser\Node\Scalar\String_ - ) { - return; - } - - $oldTableName = $call->getArgs()[0]->value->value; - $newTableName = $call->getArgs()[1]->value->value; - - if (! isset($this->tables[$oldTableName])) { - return; - } - - $table = $this->tables[$oldTableName]; - - unset($this->tables[$oldTableName]); - - $table->name = $newTableName; - - $this->tables[$newTableName] = $table; - } -} diff --git a/php-packages/phpstan/src/Properties/SchemaColumn.php b/php-packages/phpstan/src/Properties/SchemaColumn.php deleted file mode 100644 index 8cba2c2cdc..0000000000 --- a/php-packages/phpstan/src/Properties/SchemaColumn.php +++ /dev/null @@ -1,52 +0,0 @@ - */ - public $options; - - /** - * @param string $name - * @param string $readableType - * @param bool $nullable - * @param string[]|null $options - */ - public function __construct( - string $name, - string $readableType, - bool $nullable = false, - ?array $options = null - ) { - $this->name = $name; - $this->readableType = $readableType; - $this->writeableType = $readableType; - $this->nullable = $nullable; - $this->options = $options; - } -} diff --git a/php-packages/phpstan/src/Properties/SchemaTable.php b/php-packages/phpstan/src/Properties/SchemaTable.php deleted file mode 100644 index 7033381893..0000000000 --- a/php-packages/phpstan/src/Properties/SchemaTable.php +++ /dev/null @@ -1,54 +0,0 @@ -name = $name; - } - - public function setColumn(SchemaColumn $column): void - { - $this->columns[$column->name] = $column; - } - - public function renameColumn(string $oldName, string $newName): void - { - if (! isset($this->columns[$oldName])) { - return; - } - - $oldColumn = $this->columns[$oldName]; - - unset($this->columns[$oldName]); - - $oldColumn->name = $newName; - - $this->columns[$newName] = $oldColumn; - } - - public function dropColumn(string $columnName): void - { - unset($this->columns[$columnName]); - } -} diff --git a/php-packages/phpstan/src/Reflection/AnnotationScopeMethodParameterReflection.php b/php-packages/phpstan/src/Reflection/AnnotationScopeMethodParameterReflection.php deleted file mode 100644 index 6c11545937..0000000000 --- a/php-packages/phpstan/src/Reflection/AnnotationScopeMethodParameterReflection.php +++ /dev/null @@ -1,77 +0,0 @@ -name = $name; - $this->type = $type; - $this->passedByReference = $passedByReference; - $this->isOptional = $isOptional; - $this->isVariadic = $isVariadic; - $this->defaultValue = $defaultValue; - } - - public function getName(): string - { - return $this->name; - } - - public function isOptional(): bool - { - return $this->isOptional; - } - - public function getType(): Type - { - return $this->type; - } - - public function passedByReference(): PassedByReference - { - return $this->passedByReference; - } - - public function isVariadic(): bool - { - return $this->isVariadic; - } - - public function getDefaultValue(): ?Type - { - return $this->defaultValue; - } -} diff --git a/php-packages/phpstan/src/Reflection/AnnotationScopeMethodReflection.php b/php-packages/phpstan/src/Reflection/AnnotationScopeMethodReflection.php deleted file mode 100644 index 604c7f4a2e..0000000000 --- a/php-packages/phpstan/src/Reflection/AnnotationScopeMethodReflection.php +++ /dev/null @@ -1,140 +0,0 @@ -name = $name; - $this->declaringClass = $declaringClass; - $this->returnType = $returnType; - $this->parameters = $parameters; - $this->isStatic = $isStatic; - $this->isVariadic = $isVariadic; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->declaringClass; - } - - public function getPrototype(): ClassMemberReflection - { - return $this; - } - - public function isStatic(): bool - { - return $this->isStatic; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getName(): string - { - return $this->name; - } - - /** - * @return ParametersAcceptor[] - */ - public function getVariants(): array - { - if ($this->variants === null) { - $this->variants = [new FunctionVariant(TemplateTypeMap::createEmpty(), null, $this->parameters, $this->isVariadic, $this->returnType)]; - } - - return $this->variants; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?Type - { - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } - - public function getDocComment(): ?string - { - return null; - } -} diff --git a/php-packages/phpstan/src/Reflection/DynamicWhereParameterReflection.php b/php-packages/phpstan/src/Reflection/DynamicWhereParameterReflection.php deleted file mode 100644 index f3c77e2bbf..0000000000 --- a/php-packages/phpstan/src/Reflection/DynamicWhereParameterReflection.php +++ /dev/null @@ -1,50 +0,0 @@ -methodName = $methodName; - $this->classReflection = $classReflection; - $this->originalMethodReflection = $originalMethodReflection; - $this->parameters = $parameters; - $this->returnType = $returnType ?? new ObjectType(Builder::class); - $this->isVariadic = $isVariadic; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return true; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getName(): string - { - return $this->methodName; - } - - public function getPrototype(): ClassMemberReflection - { - return $this; - } - - /** - * {@inheritdoc} - */ - public function getVariants(): array - { - return [ - new FunctionVariant( - TemplateTypeMap::createEmpty(), - null, - $this->parameters, - $this->isVariadic, - $this->returnType - ), - ]; - } - - public function getDocComment(): ?string - { - return null; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?Type - { - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } - - /** - * @return MethodReflection - */ - public function getOriginalMethodReflection(): MethodReflection - { - return $this->originalMethodReflection; - } -} diff --git a/php-packages/phpstan/src/Reflection/ModelScopeMethodReflection.php b/php-packages/phpstan/src/Reflection/ModelScopeMethodReflection.php deleted file mode 100644 index 45ff9e2f91..0000000000 --- a/php-packages/phpstan/src/Reflection/ModelScopeMethodReflection.php +++ /dev/null @@ -1,127 +0,0 @@ -methodName = $methodName; - $this->classReflection = $classReflection; - $this->relation = $relation; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->classReflection; - } - - public function isStatic(): bool - { - return false; - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getName(): string - { - return $this->methodName; - } - - public function getPrototype(): ClassMemberReflection - { - return $this; - } - - /** - * {@inheritdoc} - */ - public function getVariants(): array - { - return [ - new FunctionVariant( - TemplateTypeMap::createEmpty(), - null, - [], - false, - new ObjectType($this->relation->getName()) - ), - ]; - } - - public function getDocComment(): ?string - { - return null; - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getDeprecatedDescription(): ?string - { - return null; - } - - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getThrowType(): ?Type - { - return null; - } - - public function hasSideEffects(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } -} diff --git a/php-packages/phpstan/src/Reflection/ReflectionHelper.php b/php-packages/phpstan/src/Reflection/ReflectionHelper.php deleted file mode 100644 index a593540a36..0000000000 --- a/php-packages/phpstan/src/Reflection/ReflectionHelper.php +++ /dev/null @@ -1,35 +0,0 @@ -getPropertyTags())) { - return true; - } - - foreach ($classReflection->getAncestors() as $ancestor) { - if (array_key_exists($propertyName, $ancestor->getPropertyTags())) { - return true; - } - } - - return false; - } -} diff --git a/php-packages/phpstan/src/Reflection/StaticMethodReflection.php b/php-packages/phpstan/src/Reflection/StaticMethodReflection.php deleted file mode 100644 index dc37f8c887..0000000000 --- a/php-packages/phpstan/src/Reflection/StaticMethodReflection.php +++ /dev/null @@ -1,99 +0,0 @@ -methodReflection = $methodReflection; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->methodReflection->getDeclaringClass(); - } - - public function isStatic(): bool - { - return true; - } - - public function isPrivate(): bool - { - return $this->methodReflection->isPrivate(); - } - - public function isPublic(): bool - { - return $this->methodReflection->isPublic(); - } - - public function getDocComment(): ?string - { - return $this->methodReflection->getDocComment(); - } - - public function getName(): string - { - return $this->methodReflection->getName(); - } - - public function getPrototype(): ClassMemberReflection - { - return $this->methodReflection->getPrototype(); - } - - public function getVariants(): array - { - return $this->methodReflection->getVariants(); - } - - public function isDeprecated(): TrinaryLogic - { - return $this->methodReflection->isDeprecated(); - } - - public function getDeprecatedDescription(): ?string - { - return $this->methodReflection->getDeprecatedDescription(); - } - - public function isFinal(): TrinaryLogic - { - return $this->methodReflection->isFinal(); - } - - public function isInternal(): TrinaryLogic - { - return $this->methodReflection->isInternal(); - } - - public function getThrowType(): ?Type - { - return $this->methodReflection->getThrowType(); - } - - public function hasSideEffects(): TrinaryLogic - { - return $this->methodReflection->hasSideEffects(); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/BuilderModelFindExtension.php b/php-packages/phpstan/src/ReturnTypes/BuilderModelFindExtension.php deleted file mode 100644 index 6caf7eb56f..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/BuilderModelFindExtension.php +++ /dev/null @@ -1,119 +0,0 @@ -builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - } - - /** - * {@inheritdoc} - */ - public function getClass(): string - { - return Builder::class; - } - - /** - * {@inheritdoc} - */ - public function isMethodSupported(MethodReflection $methodReflection): bool - { - $methodName = $methodReflection->getName(); - - if (! Str::startsWith($methodName, 'find')) { - return false; - } - - $model = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TModelClass'); - - if ($model === null || ! $model instanceof ObjectType) { - return false; - } - - if (! $this->reflectionProvider->getClass(Builder::class)->hasNativeMethod($methodName) && - ! $this->reflectionProvider->getClass(QueryBuilder::class)->hasNativeMethod($methodName)) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - /** @var ObjectType $model */ - $model = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TModelClass'); - $returnType = $methodReflection->getVariants()[0]->getReturnType(); - $argType = $scope->getType($methodCall->getArgs()[0]->value); - - $returnType = ModelTypeHelper::replaceStaticTypeWithModel($returnType, $model->getClassName()); - - if ($argType->isIterable()->yes()) { - if (in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($model->getClassName()); - - return new GenericObjectType($collectionClassName, [$model]); - } - - return TypeCombinator::remove($returnType, $model); - } - - if ($argType instanceof MixedType) { - return $returnType; - } - - return TypeCombinator::remove( - TypeCombinator::remove( - $returnType, - new ArrayType(new MixedType(), $model) - ), - new ObjectType(Collection::class) - ); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/CollectionFilterDynamicReturnTypeExtension.php b/php-packages/phpstan/src/ReturnTypes/CollectionFilterDynamicReturnTypeExtension.php deleted file mode 100644 index b017ef6e6b..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/CollectionFilterDynamicReturnTypeExtension.php +++ /dev/null @@ -1,119 +0,0 @@ -getName() === 'filter'; - } - - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - $calledOnType = $scope->getType($methodCall->var); - - if (! $calledOnType instanceof \PHPStan\Type\Generic\GenericObjectType) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - } - - $keyType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TKey'); - $valueType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TValue'); - - if ($keyType === null || $valueType === null) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - } - - if (count($methodCall->getArgs()) < 1) { - $falseyTypes = $this->getFalseyTypes(); - - $nonFalseyTypes = TypeCombinator::remove($valueType, $falseyTypes); - - if ((new ObjectType(Collection::class))->isSuperTypeOf($calledOnType)->yes()) { - return new GenericObjectType($calledOnType->getClassName(), [$nonFalseyTypes]); - } - - return new GenericObjectType($calledOnType->getClassName(), [$keyType, $nonFalseyTypes]); - } - - $callbackArg = $methodCall->getArgs()[0]->value; - - $var = null; - $expr = null; - - if ($callbackArg instanceof Closure && count($callbackArg->stmts) === 1 && count($callbackArg->params) > 0) { - $statement = $callbackArg->stmts[0]; - if ($statement instanceof Return_ && $statement->expr !== null) { - $var = $callbackArg->params[0]->var; - $expr = $statement->expr; - } - } elseif ($callbackArg instanceof ArrowFunction && count($callbackArg->params) > 0) { - $var = $callbackArg->params[0]->var; - $expr = $callbackArg->expr; - } - - if ($var !== null && $expr !== null) { - if (! $var instanceof Variable || ! is_string($var->name)) { - throw new \PHPStan\ShouldNotHappenException(); - } - - $itemVariableName = $var->name; - - // @phpstan-ignore-next-line - $scope = $scope->assignVariable($itemVariableName, $valueType); - $scope = $scope->filterByTruthyValue($expr); - $valueType = $scope->getVariableType($itemVariableName); - } - - if ((new ObjectType(Collection::class))->isSuperTypeOf($calledOnType)->yes()) { - return new GenericObjectType($calledOnType->getClassName(), [$valueType]); - } - - return new GenericObjectType($calledOnType->getClassName(), [$keyType, $valueType]); - } - - private function getFalseyTypes(): UnionType - { - return new UnionType([new NullType(), new ConstantBooleanType(false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType(''), new ConstantStringType('0'), new ConstantArrayType([], [])]); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/CollectionMakeDynamicStaticMethodReturnTypeExtension.php b/php-packages/phpstan/src/ReturnTypes/CollectionMakeDynamicStaticMethodReturnTypeExtension.php deleted file mode 100644 index 2cca6a0d9d..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/CollectionMakeDynamicStaticMethodReturnTypeExtension.php +++ /dev/null @@ -1,58 +0,0 @@ -collectionHelper = $collectionHelper; - } - - public function getClass(): string - { - return Collection::class; - } - - public function isStaticMethodSupported(MethodReflection $methodReflection): bool - { - return $methodReflection->getName() === 'make'; - } - - public function getTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope - ): Type { - if (count($methodCall->getArgs()) < 1) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - } - - $valueType = $scope->getType($methodCall->getArgs()[0]->value); - - return $this->collectionHelper->determineGenericCollectionTypeFromType($valueType); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/ContainerArrayAccessDynamicMethodReturnTypeExtension.php b/php-packages/phpstan/src/ReturnTypes/ContainerArrayAccessDynamicMethodReturnTypeExtension.php deleted file mode 100644 index 9121ac6f50..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/ContainerArrayAccessDynamicMethodReturnTypeExtension.php +++ /dev/null @@ -1,80 +0,0 @@ -className = $className; - } - - public function getClass(): string - { - return $this->className; - } - - public function isMethodSupported(MethodReflection $methodReflection): bool - { - return $methodReflection->getName() === 'offsetGet'; - } - - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - $args = $methodCall->getArgs(); - - if (count($args) === 0) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - } - - $argType = $scope->getType($args[0]->value); - - if (! $argType instanceof ConstantStringType) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - } - - $resolvedValue = $this->resolve($argType->getValue()); - - if ($resolvedValue === null) { - return new ErrorType(); - } - - if (is_object($resolvedValue)) { - $class = get_class($resolvedValue); - - return new ObjectType($class); - } - - return $scope->getTypeFromValue($resolvedValue); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/EloquentBuilderExtension.php b/php-packages/phpstan/src/ReturnTypes/EloquentBuilderExtension.php deleted file mode 100644 index 902a5ceb27..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/EloquentBuilderExtension.php +++ /dev/null @@ -1,93 +0,0 @@ -builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - } - - public function getClass(): string - { - return EloquentBuilder::class; - } - - public function isMethodSupported(MethodReflection $methodReflection): bool - { - $builderReflection = $this->reflectionProvider->getClass(EloquentBuilder::class); - - // Don't handle dynamic wheres - if (Str::startsWith($methodReflection->getName(), 'where') && - ! $builderReflection->hasNativeMethod($methodReflection->getName()) - ) { - return false; - } - - if (Str::startsWith($methodReflection->getName(), 'find') && - $builderReflection->hasNativeMethod($methodReflection->getName()) - ) { - return false; - } - - $templateTypeMap = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap(); - - if (! $templateTypeMap->getType('TModelClass') instanceof ObjectType) { - return false; - } - - return $builderReflection->hasNativeMethod($methodReflection->getName()); - } - - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $methodReflection->getVariants())->getReturnType(); - $templateTypeMap = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap(); - - /** @var Type|ObjectType|TemplateMixedType $modelType */ - $modelType = $templateTypeMap->getType('TModelClass'); - - if ($modelType instanceof ObjectType && in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($modelType->getClassName()); - - return new GenericObjectType($collectionClassName, [$modelType]); - } - - return $returnType; - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/AppExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/AppExtension.php deleted file mode 100644 index 89b659f2e8..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/AppExtension.php +++ /dev/null @@ -1,72 +0,0 @@ -getName() === 'app' || $functionReflection->getName() === 'resolve'; - } - - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - if (count($functionCall->getArgs()) === 0) { - return new ObjectType(Application::class); - } - - /** @var Expr $expr */ - $expr = $functionCall->getArgs()[0]->value; - - if ($expr instanceof String_) { - try { - /** @var object|null $resolved */ - $resolved = $this->resolve($expr->value); - - if ($resolved === null) { - return new ErrorType(); - } - - return new ObjectType(get_class($resolved)); - } catch (Throwable $exception) { - return new ErrorType(); - } - } - - if ($expr instanceof ClassConstFetch && $expr->class instanceof FullyQualified) { - return new ObjectType($expr->class->toString()); - } - - return new NeverType(); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/CollectExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/CollectExtension.php deleted file mode 100644 index 499b394876..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/CollectExtension.php +++ /dev/null @@ -1,52 +0,0 @@ -collectionHelper = $collectionHelper; - } - - public function isFunctionSupported(FunctionReflection $functionReflection): bool - { - return $functionReflection->getName() === 'collect'; - } - - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - if (count($functionCall->getArgs()) < 1) { - return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); - } - - $valueType = $scope->getType($functionCall->getArgs()[0]->value); - - return $this->collectionHelper->determineGenericCollectionTypeFromType($valueType); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/TapExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/TapExtension.php deleted file mode 100644 index ad6e59e992..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/TapExtension.php +++ /dev/null @@ -1,56 +0,0 @@ -getName() === 'tap'; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - if (count($functionCall->getArgs()) === 1) { - $type = $scope->getType($functionCall->getArgs()[0]->value); - - return new GenericObjectType(HigherOrderTapProxy::class, [ - $type instanceof ThisType ? $type->getStaticObjectType() : $type, - ]); - } - - if (count($functionCall->getArgs()) === 2) { - return $scope->getType($functionCall->getArgs()[0]->value); - } - - return new NeverType(); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/TransExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/TransExtension.php deleted file mode 100644 index 66bde450b9..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/TransExtension.php +++ /dev/null @@ -1,47 +0,0 @@ -getName() === 'trans'; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - // No path provided, so it returns a Translator instance - if (count($functionCall->getArgs()) === 0) { - return new ObjectType(\Illuminate\Contracts\Translation\Translator::class); - } - - return new MixedType(); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/ValidatorExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/ValidatorExtension.php deleted file mode 100644 index 71e7de08fd..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/ValidatorExtension.php +++ /dev/null @@ -1,47 +0,0 @@ -getName() === 'validator'; - } - - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - if (count($functionCall->getArgs()) === 0) { - return new ObjectType(\Illuminate\Contracts\Validation\Factory::class); - } - - return new IntersectionType([ - new ObjectType(\Illuminate\Validation\Validator::class), - new ObjectType(\Illuminate\Contracts\Validation\Validator::class), - ]); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/Helpers/ValueExtension.php b/php-packages/phpstan/src/ReturnTypes/Helpers/ValueExtension.php deleted file mode 100644 index f4e8e630b2..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/Helpers/ValueExtension.php +++ /dev/null @@ -1,63 +0,0 @@ -getName() === 'value'; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromFunctionCall( - FunctionReflection $functionReflection, - FuncCall $functionCall, - Scope $scope - ): Type { - if (count($functionCall->getArgs()) === 0) { - return new NeverType(); - } - - $arg = $functionCall->getArgs()[0]->value; - if ($arg instanceof Closure) { - $callbackType = $scope->getType($arg); - $callbackReturnType = ParametersAcceptorSelector::selectFromArgs( - $scope, - $functionCall->getArgs(), - $callbackType->getCallableParametersAcceptors($scope) - )->getReturnType(); - - return $callbackReturnType; - } - - return $scope->getType($arg); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/HigherOrderTapProxyExtension.php b/php-packages/phpstan/src/ReturnTypes/HigherOrderTapProxyExtension.php deleted file mode 100644 index a60e7a54e7..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/HigherOrderTapProxyExtension.php +++ /dev/null @@ -1,63 +0,0 @@ -getType($methodCall->var); - if ($type instanceof GenericObjectType) { - $types = $type->getTypes(); - if (count($types) === 1 && $types[0] instanceof ObjectType) { - return $types[0]; - } - } - - return new MixedType(); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/ModelExtension.php b/php-packages/phpstan/src/ReturnTypes/ModelExtension.php deleted file mode 100644 index 4e1b2dba42..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/ModelExtension.php +++ /dev/null @@ -1,111 +0,0 @@ -builderHelper = $builderHelper; - } - - /** - * {@inheritdoc} - */ - public function getClass(): string - { - return Model::class; - } - - /** - * {@inheritdoc} - */ - public function isStaticMethodSupported(MethodReflection $methodReflection): bool - { - $name = $methodReflection->getName(); - if ($name === '__construct') { - return false; - } - - if (in_array($name, ['get', 'hydrate', 'fromQuery'], true)) { - return true; - } - - if (! $methodReflection->getDeclaringClass()->hasNativeMethod($name)) { - return false; - } - - $method = $methodReflection->getDeclaringClass()->getNativeMethod($methodReflection->getName()); - - $returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType(); - - return (count(array_intersect([EloquentBuilder::class, QueryBuilder::class, Collection::class], $returnType->getReferencedClasses()))) > 0; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope - ): Type { - $method = $methodReflection->getDeclaringClass() - ->getMethod($methodReflection->getName(), $scope); - - $returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType(); - - if ((count(array_intersect([EloquentBuilder::class, QueryBuilder::class], $returnType->getReferencedClasses())) > 0) - && $methodCall->class instanceof \PhpParser\Node\Name - ) { - $returnType = new GenericObjectType( - $this->builderHelper->determineBuilderName($scope->resolveName($methodCall->class)), - [new ObjectType($scope->resolveName($methodCall->class))] - ); - } - - if ( - $methodCall->class instanceof \PhpParser\Node\Name - && in_array(Collection::class, $returnType->getReferencedClasses(), true) - && in_array($methodReflection->getName(), ['get', 'hydrate', 'fromQuery', 'all', 'findMany'], true) - ) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($scope->resolveName($methodCall->class)); - - return new GenericObjectType($collectionClassName, [new ObjectType($scope->resolveName($methodCall->class))]); - } - - return $returnType; - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/ModelFactoryDynamicStaticMethodReturnTypeExtension.php b/php-packages/phpstan/src/ReturnTypes/ModelFactoryDynamicStaticMethodReturnTypeExtension.php deleted file mode 100644 index 910731ff1f..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/ModelFactoryDynamicStaticMethodReturnTypeExtension.php +++ /dev/null @@ -1,64 +0,0 @@ -getName() !== 'factory') { - return false; - } - - // Class only available on Laravel 8 - if (! class_exists('\Illuminate\Database\Eloquent\Factories\Factory')) { - return false; - } - - return true; - } - - public function getTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope - ): Type { - $class = $methodCall->class; - - if (! $class instanceof Name) { - return new ErrorType(); - } - - $modelName = basename(str_replace('\\', '/', $class->toCodeString())); - - if (! class_exists('Database\\Factories\\'.$modelName.'Factory')) { - return new ErrorType(); - } - - return new ObjectType('Database\\Factories\\'.$modelName.'Factory'); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/ModelFindExtension.php b/php-packages/phpstan/src/ReturnTypes/ModelFindExtension.php deleted file mode 100644 index 4a1db41ab6..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/ModelFindExtension.php +++ /dev/null @@ -1,115 +0,0 @@ -builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - } - - /** - * {@inheritdoc} - */ - public function getClass(): string - { - return Model::class; - } - - /** - * {@inheritdoc} - */ - public function isStaticMethodSupported(MethodReflection $methodReflection): bool - { - $methodName = $methodReflection->getName(); - - if (! Str::startsWith($methodName, 'find')) { - return false; - } - - if (! $this->reflectionProvider->getClass(Builder::class)->hasNativeMethod($methodName) && - ! $this->reflectionProvider->getClass(QueryBuilder::class)->hasNativeMethod($methodName)) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope - ): Type { - if (count($methodCall->getArgs()) < 1) { - return new ErrorType(); - } - - $modelName = $methodReflection->getDeclaringClass()->getName(); - $returnType = $methodReflection->getVariants()[0]->getReturnType(); - $argType = $scope->getType($methodCall->getArgs()[0]->value); - - if ($argType->isIterable()->yes()) { - if (in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($modelName); - - return new GenericObjectType($collectionClassName, [new ObjectType($modelName)]); - } - - return TypeCombinator::remove($returnType, new ObjectType($modelName)); - } - - if ($argType instanceof MixedType) { - return $returnType; - } - - return TypeCombinator::remove( - TypeCombinator::remove( - $returnType, - new ArrayType(new MixedType(), new ObjectType($modelName)) - ), - new ObjectType(Collection::class) - ); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/RelationCollectionExtension.php b/php-packages/phpstan/src/ReturnTypes/RelationCollectionExtension.php deleted file mode 100644 index c9caa3fafe..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/RelationCollectionExtension.php +++ /dev/null @@ -1,93 +0,0 @@ -builderHelper = $builderHelper; - } - - /** - * {@inheritdoc} - */ - public function getClass(): string - { - return Relation::class; - } - - /** - * {@inheritdoc} - */ - public function isMethodSupported(MethodReflection $methodReflection): bool - { - if (Str::startsWith($methodReflection->getName(), 'find')) { - return false; - } - - $modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel'); - - if (! $modelType instanceof ObjectType) { - return false; - } - - $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - - if (! in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - return false; - } - - return $methodReflection->getDeclaringClass()->hasNativeMethod($methodReflection->getName()); - } - - /** - * {@inheritdoc} - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - /** @var ObjectType $modelType */ - $modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel'); - - $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - - if (in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($modelType->getClassname()); - - return new GenericObjectType($collectionClassName, [$modelType]); - } - - return $returnType; - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/RelationFindExtension.php b/php-packages/phpstan/src/ReturnTypes/RelationFindExtension.php deleted file mode 100644 index 9ff1ed7ea8..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/RelationFindExtension.php +++ /dev/null @@ -1,106 +0,0 @@ -builderHelper = $builderHelper; - $this->reflectionProvider = $reflectionProvider; - } - - /** - * {@inheritdoc} - */ - public function getClass(): string - { - return Relation::class; - } - - /** - * {@inheritdoc} - */ - public function isMethodSupported(MethodReflection $methodReflection): bool - { - if (! Str::startsWith($methodReflection->getName(), 'find')) { - return false; - } - - $modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel'); - - if (! $modelType instanceof ObjectType) { - return false; - } - - return $methodReflection->getDeclaringClass()->hasNativeMethod($methodReflection->getName()) || - $this->reflectionProvider->getClass(Builder::class)->hasNativeMethod($methodReflection->getName()) || - $this->reflectionProvider->getClass(QueryBuilder::class)->hasNativeMethod($methodReflection->getName()); - } - - /** - * {@inheritdoc} - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - /** @var ObjectType $modelType */ - $modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel'); - - $argType = $scope->getType($methodCall->getArgs()[0]->value); - - $returnType = $methodReflection->getVariants()[0]->getReturnType(); - - if (in_array(Collection::class, $returnType->getReferencedClasses(), true)) { - if ($argType->isIterable()->yes()) { - $collectionClassName = $this->builderHelper->determineCollectionClassName($modelType->getClassname()); - - return new GenericObjectType($collectionClassName, [$modelType]); - } - - $returnType = TypeCombinator::remove($returnType, new ObjectType(Collection::class)); - - return TypeCombinator::remove($returnType, new ArrayType(new MixedType(), $modelType)); - } - - return $returnType; - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/RequestExtension.php b/php-packages/phpstan/src/ReturnTypes/RequestExtension.php deleted file mode 100644 index 155b20a7b6..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/RequestExtension.php +++ /dev/null @@ -1,68 +0,0 @@ -getName() === 'file'; - } - - /** - * {@inheritdoc} - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - $uploadedFileType = new ObjectType(UploadedFile::class); - $uploadedFileArrayType = new ArrayType(new IntegerType(), $uploadedFileType); - - if (count($methodCall->getArgs()) === 0) { - return new ArrayType(new IntegerType(), $uploadedFileType); - } - - if (count($methodCall->getArgs()) === 1) { - return TypeCombinator::union($uploadedFileArrayType, TypeCombinator::addNull($uploadedFileType)); - } - - return TypeCombinator::union(TypeCombinator::union($uploadedFileArrayType, $uploadedFileType), $scope->getType($methodCall->getArgs()[1]->value)); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/StorageDynamicStaticMethodReturnTypeExtension.php b/php-packages/phpstan/src/ReturnTypes/StorageDynamicStaticMethodReturnTypeExtension.php deleted file mode 100644 index 8ed27c8d31..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/StorageDynamicStaticMethodReturnTypeExtension.php +++ /dev/null @@ -1,45 +0,0 @@ -getName() === 'disk'; - } - - public function getTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope - ): Type { - return new ObjectType(FilesystemAdapter::class); - } -} diff --git a/php-packages/phpstan/src/ReturnTypes/TestCaseExtension.php b/php-packages/phpstan/src/ReturnTypes/TestCaseExtension.php deleted file mode 100644 index c80ad78981..0000000000 --- a/php-packages/phpstan/src/ReturnTypes/TestCaseExtension.php +++ /dev/null @@ -1,60 +0,0 @@ -getName(), [ - 'mock', - 'partialMock', - 'spy', - ], true); - } - - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - $defaultReturnType = new ObjectType('Mockery\\MockInterface'); - - $classType = $scope->getType($methodCall->getArgs()[0]->value); - - if (! $classType instanceof ConstantStringType) { - return $defaultReturnType; - } - - $objectType = new ObjectType($classType->getValue()); - - return TypeCombinator::intersect($defaultReturnType, $objectType); - } -} diff --git a/php-packages/phpstan/src/Support/CollectionHelper.php b/php-packages/phpstan/src/Support/CollectionHelper.php deleted file mode 100644 index 1b6061ca5c..0000000000 --- a/php-packages/phpstan/src/Support/CollectionHelper.php +++ /dev/null @@ -1,106 +0,0 @@ -isSuperTypeOf($type)->yes()) { - return $this->getTypeFromEloquentCollection($type); - } - - if ( - (new ObjectType(Traversable::class))->isSuperTypeOf($type)->yes() || - (new ObjectType(IteratorAggregate::class))->isSuperTypeOf($type)->yes() || - (new ObjectType(Iterator::class))->isSuperTypeOf($type)->yes() - ) { - return $this->getTypeFromIterator($type); - } - } - - if (! $type->isArray()->yes()) { - return new GenericObjectType(Collection::class, [$type->toArray()->getIterableKeyType(), $type->toArray()->getIterableValueType()]); - } - - if ($type->isIterableAtLeastOnce()->no()) { - return new GenericObjectType(Collection::class, [$keyType, new MixedType()]); - } - - return new GenericObjectType(Collection::class, [ - TypeUtils::generalizeType($type->getIterableKeyType(), GeneralizePrecision::lessSpecific()), - TypeUtils::generalizeType($type->getIterableValueType(), GeneralizePrecision::lessSpecific()), - ]); - } - - private function getTypeFromEloquentCollection(TypeWithClassName $valueType): GenericObjectType - { - $keyType = TypeCombinator::union(new IntegerType(), new StringType()); - - $classReflection = $valueType->getClassReflection(); - - if ($classReflection === null) { - return new GenericObjectType(Collection::class, [$keyType, new MixedType()]); - } - - $innerValueType = $classReflection->getActiveTemplateTypeMap()->getType('TValue'); - - if ($classReflection->getName() === EloquentCollection::class || $classReflection->isSubclassOf(EloquentCollection::class)) { - $keyType = new IntegerType(); - } - - if ($innerValueType !== null) { - return new GenericObjectType(Collection::class, [$keyType, $innerValueType]); - } - - return new GenericObjectType(Collection::class, [$keyType, new MixedType()]); - } - - private function getTypeFromIterator(TypeWithClassName $valueType): GenericObjectType - { - $keyType = TypeCombinator::union(new IntegerType(), new StringType()); - - $classReflection = $valueType->getClassReflection(); - - if ($classReflection === null) { - return new GenericObjectType(Collection::class, [$keyType, new MixedType()]); - } - - $templateTypes = array_values($classReflection->getActiveTemplateTypeMap()->getTypes()); - - if (count($templateTypes) === 1) { - return new GenericObjectType(Collection::class, [$keyType, $templateTypes[0]]); - } - - return new GenericObjectType(Collection::class, $templateTypes); - } -} diff --git a/php-packages/phpstan/src/Support/HigherOrderCollectionProxyHelper.php b/php-packages/phpstan/src/Support/HigherOrderCollectionProxyHelper.php deleted file mode 100644 index 99a6cb0864..0000000000 --- a/php-packages/phpstan/src/Support/HigherOrderCollectionProxyHelper.php +++ /dev/null @@ -1,141 +0,0 @@ -getName() !== HigherOrderCollectionProxy::class) { - return false; - } - - $activeTemplateTypeMap = $classReflection->getActiveTemplateTypeMap(); - - if ($activeTemplateTypeMap->count() !== 2) { - return false; - } - - $methodType = $activeTemplateTypeMap->getType('T'); - $valueType = $activeTemplateTypeMap->getType('TValue'); - - if (($methodType === null) || ($valueType === null)) { - return false; - } - - if (! $methodType instanceof Type\Constant\ConstantStringType) { - return false; - } - - if (! $valueType->canCallMethods()->yes()) { - return false; - } - - if ($propertyOrMethod === 'method') { - return $valueType->hasMethod($name)->yes(); - } - - return $valueType->hasProperty($name)->yes(); - } - - public static function determineReturnType(string $name, Type\Type $valueType, Type\Type $methodOrPropertyReturnType): Type\Type - { - if ((new Type\ObjectType(Model::class))->isSuperTypeOf($valueType)->yes()) { - $collectionType = Collection::class; - $types = [$valueType]; - } else { - $collectionType = SupportCollection::class; - $types = [new Type\IntegerType(), $valueType]; - } - switch ($name) { - case 'average': - case 'avg': - $returnType = new Type\FloatType(); - break; - case 'contains': - case 'every': - case 'some': - $returnType = new Type\BooleanType(); - break; - case 'each': - case 'filter': - case 'reject': - case 'skipUntil': - case 'skipWhile': - case 'sortBy': - case 'sortByDesc': - case 'takeUntil': - case 'takeWhile': - case 'unique': - $returnType = new Type\Generic\GenericObjectType($collectionType, $types); - break; - case 'keyBy': - if ($collectionType === SupportCollection::class) { - $returnType = new Type\Generic\GenericObjectType($collectionType, [$methodOrPropertyReturnType, $valueType]); - } else { - $returnType = new Type\Generic\GenericObjectType($collectionType, $types); - } - break; - case 'first': - $returnType = Type\TypeCombinator::addNull($valueType); - break; - case 'flatMap': - $returnType = new Type\Generic\GenericObjectType(SupportCollection::class, [new Type\IntegerType(), new Type\MixedType()]); - break; - case 'groupBy': - case 'partition': - $innerTypes = [ - new Type\Generic\GenericObjectType($collectionType, $types), - ]; - - if ($collectionType === SupportCollection::class) { - array_unshift($innerTypes, new Type\IntegerType()); - } - - $returnType = new Type\Generic\GenericObjectType($collectionType, $innerTypes); - break; - case 'map': - $returnType = new Type\Generic\GenericObjectType(SupportCollection::class, [ - new Type\IntegerType(), - $methodOrPropertyReturnType, - ]); - break; - case 'max': - case 'min': - $returnType = $methodOrPropertyReturnType; - break; - case 'sum': - if ($methodOrPropertyReturnType->accepts(new Type\IntegerType(), true)->yes()) { - $returnType = new Type\IntegerType(); - } else { - $returnType = new Type\ErrorType(); - } - - break; - default: - $returnType = new Type\ErrorType(); - break; - } - - return $returnType; - } -} diff --git a/php-packages/phpstan/src/Types/AbortIfFunctionTypeSpecifyingExtension.php b/php-packages/phpstan/src/Types/AbortIfFunctionTypeSpecifyingExtension.php deleted file mode 100644 index 075d854cd4..0000000000 --- a/php-packages/phpstan/src/Types/AbortIfFunctionTypeSpecifyingExtension.php +++ /dev/null @@ -1,67 +0,0 @@ -negate = $negate; - $this->methodName = $methodName.'_'.($negate === false ? 'if' : 'unless'); - } - - public function isFunctionSupported( - FunctionReflection $functionReflection, - FuncCall $node, - TypeSpecifierContext $context - ): bool { - return $functionReflection->getName() === $this->methodName && $context->null(); - } - - public function specifyTypes( - FunctionReflection $functionReflection, - FuncCall $node, - Scope $scope, - TypeSpecifierContext $context - ): SpecifiedTypes { - if (count($node->args) < 2) { - return new SpecifiedTypes(); - } - - $context = $this->negate === false ? TypeSpecifierContext::createFalsey() : TypeSpecifierContext::createTruthy(); - - return $this->typeSpecifier->specifyTypesInCondition($scope, $node->getArgs()[0]->value, $context); - } - - public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void - { - $this->typeSpecifier = $typeSpecifier; - } -} diff --git a/php-packages/phpstan/src/Types/GenericEloquentBuilderTypeNodeResolverExtension.php b/php-packages/phpstan/src/Types/GenericEloquentBuilderTypeNodeResolverExtension.php deleted file mode 100644 index 5fc7f202f4..0000000000 --- a/php-packages/phpstan/src/Types/GenericEloquentBuilderTypeNodeResolverExtension.php +++ /dev/null @@ -1,63 +0,0 @@ -types) !== 2) { - return null; - } - - $modelTypeNode = null; - $builderTypeNode = null; - foreach ($typeNode->types as $innerTypeNode) { - if ($innerTypeNode instanceof IdentifierTypeNode - && is_subclass_of($nameScope->resolveStringName($innerTypeNode->name), Model::class) - ) { - $modelTypeNode = $innerTypeNode; - continue; - } - - if ( - $innerTypeNode instanceof IdentifierTypeNode - && ($nameScope->resolveStringName($innerTypeNode->name) === Builder::class || is_subclass_of($nameScope->resolveStringName($innerTypeNode->name), Builder::class)) - ) { - $builderTypeNode = $innerTypeNode; - } - } - - if ($modelTypeNode === null || $builderTypeNode === null) { - return null; - } - - $builderTypeName = $nameScope->resolveStringName($builderTypeNode->name); - $modelTypeName = $nameScope->resolveStringName($modelTypeNode->name); - - return new GenericObjectType($builderTypeName, [ - new ObjectType($modelTypeName), - ]); - } -} diff --git a/php-packages/phpstan/src/Types/GenericEloquentCollectionTypeNodeResolverExtension.php b/php-packages/phpstan/src/Types/GenericEloquentCollectionTypeNodeResolverExtension.php deleted file mode 100644 index 0108eab48a..0000000000 --- a/php-packages/phpstan/src/Types/GenericEloquentCollectionTypeNodeResolverExtension.php +++ /dev/null @@ -1,91 +0,0 @@ - $accounts - * - * Now IDE's can benefit from auto-completion, and we can benefit from the correct type passed to the generic collection - */ -class GenericEloquentCollectionTypeNodeResolverExtension implements TypeNodeResolverExtension -{ - /** - * @var TypeNodeResolver - */ - private $typeNodeResolver; - - public function __construct(TypeNodeResolver $typeNodeResolver) - { - $this->typeNodeResolver = $typeNodeResolver; - } - - public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type - { - if (! $typeNode instanceof UnionTypeNode || count($typeNode->types) !== 2) { - return null; - } - - $arrayTypeNode = null; - $identifierTypeNode = null; - foreach ($typeNode->types as $innerTypeNode) { - if ($innerTypeNode instanceof ArrayTypeNode) { - $arrayTypeNode = $innerTypeNode; - continue; - } - - if ($innerTypeNode instanceof IdentifierTypeNode) { - $identifierTypeNode = $innerTypeNode; - } - } - - if ($arrayTypeNode === null || $identifierTypeNode === null) { - return null; - } - - $identifierTypeName = $nameScope->resolveStringName($identifierTypeNode->name); - if ($identifierTypeName !== Collection::class) { - return null; - } - - $innerArrayTypeNode = $arrayTypeNode->type; - if (! $innerArrayTypeNode instanceof IdentifierTypeNode) { - return null; - } - - $resolvedInnerArrayType = $this->typeNodeResolver->resolve($innerArrayTypeNode, $nameScope); - - return new GenericObjectType($identifierTypeName, [ - $resolvedInnerArrayType, - ]); - } -} diff --git a/php-packages/phpstan/src/Types/ModelProperty/GenericModelPropertyType.php b/php-packages/phpstan/src/Types/ModelProperty/GenericModelPropertyType.php deleted file mode 100644 index 6018b12120..0000000000 --- a/php-packages/phpstan/src/Types/ModelProperty/GenericModelPropertyType.php +++ /dev/null @@ -1,126 +0,0 @@ -type = $type; - } - - public function getReferencedClasses(): array - { - return $this->getGenericType()->getReferencedClasses(); - } - - public function getGenericType(): Type - { - return $this->type; - } - - public function isSuperTypeOf(Type $type): TrinaryLogic - { - if ($type instanceof ConstantStringType) { - return $this->getGenericType()->hasProperty($type->getValue()); - } - - if ($type instanceof self) { - return TrinaryLogic::createYes(); - } - - if ($type instanceof parent) { - return TrinaryLogic::createMaybe(); - } - - if ($type instanceof CompoundType) { - return $type->isSubTypeOf($this); - } - - return TrinaryLogic::createNo(); - } - - public function traverse(callable $cb): Type - { - $newType = $cb($this->getGenericType()); - - if ($newType === $this->getGenericType()) { - return $this; - } - - return new self($newType); - } - - public function inferTemplateTypes(Type $receivedType): TemplateTypeMap - { - if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { - return $receivedType->inferTemplateTypesOn($this); - } - - if ($receivedType instanceof ConstantStringType) { - $typeToInfer = new ObjectType($receivedType->getValue()); - } elseif ($receivedType instanceof self) { - $typeToInfer = $receivedType->type; - } elseif ($receivedType instanceof ClassStringType) { - $typeToInfer = $this->getGenericType(); - - if ($typeToInfer instanceof TemplateType) { - $typeToInfer = $typeToInfer->getBound(); - } - - $typeToInfer = TypeCombinator::intersect($typeToInfer, new ObjectWithoutClassType()); - } else { - return TemplateTypeMap::createEmpty(); - } - - if (! $this->getGenericType()->isSuperTypeOf($typeToInfer)->no()) { - return $this->getGenericType()->inferTemplateTypes($typeToInfer); - } - - return TemplateTypeMap::createEmpty(); - } - - public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array - { - $variance = $positionVariance->compose(TemplateTypeVariance::createCovariant()); - - return $this->getGenericType()->getReferencedTemplateTypes($variance); - } - - /** - * @param mixed[] $properties - * @return Type - */ - public static function __set_state(array $properties): Type - { - return new self($properties['type']); - } -} diff --git a/php-packages/phpstan/src/Types/ModelProperty/ModelPropertyType.php b/php-packages/phpstan/src/Types/ModelProperty/ModelPropertyType.php deleted file mode 100644 index 7da7bb3005..0000000000 --- a/php-packages/phpstan/src/Types/ModelProperty/ModelPropertyType.php +++ /dev/null @@ -1,27 +0,0 @@ -baseResolver = $baseResolver; - $this->active = $active; - } - - public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type - { - if ($typeNode instanceof IdentifierTypeNode && $typeNode->name === 'model-property') { - return $this->active ? new ModelPropertyType() : new StringType(); - } - - if ($typeNode instanceof GenericTypeNode && $typeNode->type->name === 'model-property') { - if (! $this->active) { - return new StringType(); - } - - if (count($typeNode->genericTypes) !== 1) { - return new ErrorType(); - } - - $genericType = $this->baseResolver->resolve($typeNode->genericTypes[0], $nameScope); - - if ((new ObjectType(Model::class))->isSuperTypeOf($genericType)->no()) { - return new ErrorType(); - } - - if ($genericType instanceof NeverType) { - return new ErrorType(); - } - - return new GenericModelPropertyType($genericType); - } - - return null; - } -} diff --git a/php-packages/phpstan/src/Types/ModelRelationsDynamicMethodReturnTypeExtension.php b/php-packages/phpstan/src/Types/ModelRelationsDynamicMethodReturnTypeExtension.php deleted file mode 100644 index 3c18af086d..0000000000 --- a/php-packages/phpstan/src/Types/ModelRelationsDynamicMethodReturnTypeExtension.php +++ /dev/null @@ -1,115 +0,0 @@ -relationParserHelper = $relationParserHelper; - } - - public function getClass(): string - { - return Model::class; - } - - public function isMethodSupported(MethodReflection $methodReflection): bool - { - $variants = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()); - - $returnType = $variants->getReturnType(); - - if (! $returnType instanceof ObjectType) { - return false; - } - - if (! (new ObjectType(Relation::class))->isSuperTypeOf($returnType)->yes()) { - return false; - } - - if (! $methodReflection->getDeclaringClass()->hasNativeMethod($methodReflection->getName())) { - return false; - } - - if (count($variants->getParameters()) !== 0) { - return false; - } - - if (in_array($methodReflection->getName(), [ - 'hasOne', 'hasOneThrough', 'morphOne', - 'belongsTo', 'morphTo', - 'hasMany', 'hasManyThrough', 'morphMany', - 'belongsToMany', 'morphToMany', 'morphedByMany', - ], true)) { - return false; - } - - $relatedModel = $this - ->relationParserHelper - ->findRelatedModelInRelationMethod($methodReflection); - - return $relatedModel !== null; - } - - /** - * @param MethodReflection $methodReflection - * @param MethodCall $methodCall - * @param Scope $scope - * @return Type - * - * @throws ShouldNotHappenException - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - /** @var ObjectType $returnType */ - $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); - - /** @var string $relatedModelClassName */ - $relatedModelClassName = $this - ->relationParserHelper - ->findRelatedModelInRelationMethod($methodReflection); - - $classReflection = $methodReflection->getDeclaringClass(); - - if ($returnType->isInstanceOf(BelongsTo::class)->yes()) { - return new GenericObjectType($returnType->getClassName(), [ - new ObjectType($relatedModelClassName), - new ObjectType($classReflection->getName()), - ]); - } - - return new GenericObjectType($returnType->getClassName(), [new ObjectType($relatedModelClassName)]); - } -} diff --git a/php-packages/phpstan/src/Types/Passable.php b/php-packages/phpstan/src/Types/Passable.php deleted file mode 100644 index 47cab20a01..0000000000 --- a/php-packages/phpstan/src/Types/Passable.php +++ /dev/null @@ -1,52 +0,0 @@ -type = $type; - } - - /** - * @return \PHPStan\Type\Type - */ - public function getType(): Type - { - return $this->type; - } - - /** - * @param \PHPStan\Type\Type $type - */ - public function setType(Type $type): void - { - $this->type = $type; - } -} diff --git a/php-packages/phpstan/src/Types/RelationDynamicMethodReturnTypeExtension.php b/php-packages/phpstan/src/Types/RelationDynamicMethodReturnTypeExtension.php deleted file mode 100644 index 054bafbe7c..0000000000 --- a/php-packages/phpstan/src/Types/RelationDynamicMethodReturnTypeExtension.php +++ /dev/null @@ -1,72 +0,0 @@ -getName(), [ - 'hasOne', 'hasOneThrough', 'morphOne', - 'belongsTo', 'morphTo', - 'hasMany', 'hasManyThrough', 'morphMany', - 'belongsToMany', 'morphToMany', 'morphedByMany', - ], true); - } - - /** - * @throws ShouldNotHappenException - */ - public function getTypeFromMethodCall( - MethodReflection $methodReflection, - MethodCall $methodCall, - Scope $scope - ): Type { - /** @var FunctionVariant $functionVariant */ - $functionVariant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()); - $returnType = $functionVariant->getReturnType(); - - if (count($methodCall->getArgs()) === 0) { - return $returnType; - } - - $argType = $scope->getType($methodCall->getArgs()[0]->value); - - if (! $argType instanceof ConstantStringType) { - return $returnType; - } - - if (! $returnType instanceof ObjectType) { - return $returnType; - } - - return new GenericObjectType($returnType->getClassName(), [new ObjectType($argType->getValue())]); - } -} diff --git a/php-packages/phpstan/src/Types/RelationParserHelper.php b/php-packages/phpstan/src/Types/RelationParserHelper.php deleted file mode 100644 index f059f8afec..0000000000 --- a/php-packages/phpstan/src/Types/RelationParserHelper.php +++ /dev/null @@ -1,139 +0,0 @@ -parser = $parser; - $this->scopeFactory = $scopeFactory; - $this->reflectionProvider = $reflectionProvider; - } - - public function findRelatedModelInRelationMethod( - MethodReflection $methodReflection - ): ?string { - $fileName = $methodReflection - ->getDeclaringClass() - ->getNativeReflection() - ->getMethod($methodReflection->getName()) - ->getFileName(); - - if ($fileName === false) { - return null; - } - - $fileStmts = $this->parser->parseFile($fileName); - - /** @var Node\Stmt\ClassMethod|null $relationMethod */ - $relationMethod = $this->findMethod($methodReflection->getName(), $fileStmts); - - if ($relationMethod === null) { - return null; - } - - /** @var Node\Stmt\Return_|null $returnStmt */ - $returnStmt = $this->findReturn($relationMethod); - - if ($returnStmt === null || ! $returnStmt->expr instanceof MethodCall) { - return null; - } - - $methodCall = $returnStmt->expr; - - while ($methodCall->var instanceof MethodCall) { - $methodCall = $methodCall->var; - } - - if (count($methodCall->getArgs()) < 1) { - return null; - } - - $scope = $this->scopeFactory->create( - ScopeContext::create($fileName), - false, - [], - $methodReflection - ); - - $methodScope = $scope - ->enterClass($methodReflection->getDeclaringClass()) - ->enterClassMethod($relationMethod, TemplateTypeMap::createEmpty(), [], null, null, null, false, false, false); - - $argType = $methodScope->getType($methodCall->getArgs()[0]->value); - $returnClass = null; - - if ($argType instanceof ConstantStringType) { - $returnClass = $argType->getValue(); - } - - if ($argType instanceof GenericClassStringType) { - $modelType = $argType->getGenericType(); - - if (! $modelType instanceof ObjectType) { - return null; - } - - $returnClass = $modelType->getClassName(); - } - - if ($returnClass === null) { - return null; - } - - return $this->reflectionProvider->hasClass($returnClass) ? $returnClass : null; - } - - /** - * @param string $method - * @param mixed $statements - * @return Node|null - */ - private function findMethod(string $method, $statements): ?Node - { - return (new NodeFinder)->findFirst($statements, static function (Node $node) use ($method) { - return $node instanceof Node\Stmt\ClassMethod - && $node->name->toString() === $method; - }); - } - - private function findReturn(Node\Stmt\ClassMethod $relationMethod): ?Node - { - /** @var Node[] $statements */ - $statements = $relationMethod->stmts; - - return (new NodeFinder)->findFirstInstanceOf($statements, Node\Stmt\Return_::class); - } -} diff --git a/php-packages/phpstan/src/Types/ViewStringType.php b/php-packages/phpstan/src/Types/ViewStringType.php deleted file mode 100644 index 0b84a916d1..0000000000 --- a/php-packages/phpstan/src/Types/ViewStringType.php +++ /dev/null @@ -1,87 +0,0 @@ -exists($string) test is a valid view-string type. - */ -class ViewStringType extends StringType -{ - public function describe(\PHPStan\Type\VerbosityLevel $level): string - { - return 'view-string'; - } - - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - if ($type instanceof CompoundType) { - return $type->isAcceptedBy($this, $strictTypes); - } - - if ($type instanceof ConstantStringType) { - /** @var \Illuminate\View\Factory $view */ - $view = view(); - - return TrinaryLogic::createFromBoolean($view->exists($type->getValue())); - } - - if ($type instanceof self) { - return TrinaryLogic::createYes(); - } - - if ($type instanceof StringType) { - return TrinaryLogic::createMaybe(); - } - - return TrinaryLogic::createNo(); - } - - public function isSuperTypeOf(Type $type): TrinaryLogic - { - if ($type instanceof ConstantStringType) { - /** @var \Illuminate\View\Factory $view */ - $view = view(); - - return TrinaryLogic::createFromBoolean($view->exists($type->getValue())); - } - - if ($type instanceof self) { - return TrinaryLogic::createYes(); - } - - if ($type instanceof parent) { - return TrinaryLogic::createMaybe(); - } - - if ($type instanceof CompoundType) { - return $type->isSubTypeOf($this); - } - - return TrinaryLogic::createNo(); - } - - /** - * @param mixed[] $properties - * @return Type - */ - public static function __set_state(array $properties): Type - { - return new self(); - } -} diff --git a/php-packages/phpstan/src/Types/ViewStringTypeNodeResolverExtension.php b/php-packages/phpstan/src/Types/ViewStringTypeNodeResolverExtension.php deleted file mode 100644 index eff6526add..0000000000 --- a/php-packages/phpstan/src/Types/ViewStringTypeNodeResolverExtension.php +++ /dev/null @@ -1,33 +0,0 @@ -__toString() === 'view-string') { - return new ViewStringType(); - } - - return null; - } -} diff --git a/php-packages/phpstan/stubs/Contracts/Container.stub b/php-packages/phpstan/stubs/Contracts/Container.stub deleted file mode 100644 index 78ed9c6327..0000000000 --- a/php-packages/phpstan/stubs/Contracts/Container.stub +++ /dev/null @@ -1,16 +0,0 @@ - */ -interface Container extends \ArrayAccess -{ - -} - -namespace Illuminate\Contracts\Foundation; - -interface Application extends \Illuminate\Contracts\Container\Container -{ - -} diff --git a/php-packages/phpstan/stubs/Contracts/Pagination.stub b/php-packages/phpstan/stubs/Contracts/Pagination.stub deleted file mode 100644 index f23beab128..0000000000 --- a/php-packages/phpstan/stubs/Contracts/Pagination.stub +++ /dev/null @@ -1,17 +0,0 @@ - - */ - public function toArray(); -} - -interface Jsonable -{} diff --git a/php-packages/phpstan/stubs/Flarum/User.stub b/php-packages/phpstan/stubs/Flarum/User.stub deleted file mode 100644 index 4ce9aecb5a..0000000000 --- a/php-packages/phpstan/stubs/Flarum/User.stub +++ /dev/null @@ -1,31 +0,0 @@ - - * @implements Enumerable - */ -class Collection implements \ArrayAccess, Enumerable -{ - /** - * @param callable|null $callback - * @param mixed $default - * @return TValue|null - */ - public function first(callable $callback = null, $default = null){} - - /** - * @param callable|null $callback - * @param mixed $default - * @return TValue|null - */ - public function last(callable $callback = null, $default = null){} - - - /** - * @param mixed $key - * @param mixed $default - * @return TValue|null - */ - public function get($key, $default = null) {} - - /** - * @return TValue|null - */ - public function pop() {} - - /** - * @param mixed $key - * @param mixed $default - * @return TValue|null - */ - public function pull($key, $default = null) {} - - /** - * @param mixed $value - * @param bool $strict - * @return TKey|false - */ - public function search($value, $strict = false) {} - - /** - * @return TValue|null - */ - public function shift() {} - - /** - * @param callable(TValue, TKey): (void|bool) $callable - * @return static - */ - public function each($callable) {} - - /** - * @template TReturn - * @param callable(TValue, TKey): TReturn $callable - * @return static - */ - public function map($callable) {} - - /** - * Run a grouping map over the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapToGroupsKey of array-key - * @template TMapToGroupsValue - * - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToGroups(callable $callback) {} - - /** - * @param array|string|callable(TValue, TKey): mixed $groupBy - * @param bool $preserveKeys - * @return static> - */ - public function groupBy($groupBy, $preserveKeys = false); - - /** - * @template TClass - * @param class-string $class - * @return static - */ - public function mapInto($class); - - /** - * @template TReturn - * @param callable(TValue, TKey): (array|\Illuminate\Support\Enumerable) $callback - * @return static - */ - public function flatMap(callable $callback) {} - - /** - * @template TReturn - * @param callable(TValue ...$values): TReturn $callback - * @return static - */ - public function mapSpread(callable $callback) {} - - /** - * @param int $number - * @param null|callable(int, int): mixed $callback - * @return static - */ - public static function times($number, callable $callback = null) {} - - /** - * @param string|array $value - * @param string|null $key - * @return static - */ - public function pluck($value, $key = null) {} - - /** - * @return TValue - */ - public function pop() {} - - /** - * Push one or more items onto the end of the collection. - * - * @param TValue ...$values - * @return static - */ - public function push(...$values) {} - - /** - * Put an item in the collection by key. - * - * @param TKey $key - * @param TValue $value - * @return static - */ - public function put($key, $value) {} -} diff --git a/php-packages/phpstan/stubs/Illuminate/Contracts/Container/Container.stub b/php-packages/phpstan/stubs/Illuminate/Contracts/Container/Container.stub new file mode 100644 index 0000000000..6e07ef1163 --- /dev/null +++ b/php-packages/phpstan/stubs/Illuminate/Contracts/Container/Container.stub @@ -0,0 +1,7 @@ + - */ -class BelongsTo extends Relation -{ - /** @phpstan-return TChildModel */ - public function associate(); - - /** @phpstan-return TChildModel */ - public function dissociate(); - - /** @phpstan-return TChildModel */ - public function getChild(); - - /** - * Get the results of the relationship. - * - * @phpstan-return ?TRelatedModel - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/BelongsToMany.stub b/php-packages/phpstan/stubs/Illuminate/Database/BelongsToMany.stub deleted file mode 100644 index 22484d0ba1..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/BelongsToMany.stub +++ /dev/null @@ -1,112 +0,0 @@ - - */ -class BelongsToMany extends Relation -{ - /** - * Find a related model by its primary key or return new instance of the related model. - * - * @param mixed $id - * @param array $columns - * @return \Illuminate\Support\Collection|TRelatedModel - */ - public function findOrNew($id, $columns = ['*']); - - /** - * Get the first related model record matching the attributes or instantiate it. - * - * @param array $attributes - * @return TRelatedModel - */ - public function firstOrNew(array $attributes); - - /** - * Get the first related record matching the attributes or create it. - * - * @param array $attributes - * @param array $joining - * @param bool $touch - * @return TRelatedModel - */ - public function firstOrCreate(array $attributes, array $joining = [], $touch = true); - - /** - * Create or update a related record matching the attributes, and fill it with values. - * - * @param array $attributes - * @param array $values - * @param array $joining - * @param bool $touch - * @return TRelatedModel - */ - public function updateOrCreate(array $attributes, array $values = [], array $joining = [], $touch = true); - - /** - * Find a related model by its primary key. - * - * @param mixed $id - * @param array $columns - * @return TRelatedModel|\Illuminate\Database\Eloquent\Collection|null - */ - public function find($id, $columns = ['*']); - - /** - * Find multiple related models by their primary keys. - * - * @param \Illuminate\Contracts\Support\Arrayable|int[] $ids - * @param array $columns - * @return \Illuminate\Database\Eloquent\Collection - */ - public function findMany($ids, $columns = ['*']); - - /** - * Find a related model by its primary key or throw an exception. - * - * @param mixed $id - * @param array $columns - * @return TRelatedModel|\Illuminate\Database\Eloquent\Collection - * - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function findOrFail($id, $columns = ['*']); - - /** - * Execute the query and get the first result. - * - * @param array $columns - * @return TRelatedModel|null - */ - public function first($columns = ['*']); - - /** - * Execute the query and get the first result or throw an exception. - * - * @param array $columns - * @return TRelatedModel - * - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function firstOrFail($columns = ['*']); - - /** - * Create a new instance of the related model. - * - * @param array, mixed> $attributes - * @param mixed[] $joining - * @param bool $touch - * @return TRelatedModel - */ - public function create(array $attributes = [], array $joining = [], $touch = true); - - /** - * Get the results of the relationship. - * - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/EloquentBuilder.stub b/php-packages/phpstan/stubs/Illuminate/Database/EloquentBuilder.stub deleted file mode 100644 index 039dd8e3c8..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/EloquentBuilder.stub +++ /dev/null @@ -1,454 +0,0 @@ - $orWhere - */ -class Builder -{ - /** - * Create and return an un-saved model instance. - * - * @phpstan-param array, mixed> $attributes - * @phpstan-return TModelClass - */ - public function make(array $attributes = []); - - /** - * Register a new global scope. - * - * @param string $identifier - * @param \Illuminate\Database\Eloquent\Scope|\Closure $scope - * @return static - */ - public function withGlobalScope($identifier, $scope); - - /** - * Remove a registered global scope. - * - * @param \Illuminate\Database\Eloquent\Scope|string $scope - * @return static - */ - public function withoutGlobalScope($scope); - - /** @phpstan-return TModelClass */ - public function getModel(); - - /** - * @phpstan-param array, mixed> $attributes - * @phpstan-return TModelClass - */ - public function create(array $attributes = []); - - /** - * Create a collection of models from plain arrays. - * - * @param array $items - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function hydrate(array $items); - - /** - * Create a collection of models from a raw query. - * - * @param string $query - * @param array $bindings - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function fromQuery($query, $bindings = []); - - /** - * Find a model by its primary key. - * - * @param mixed $id - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass|\Illuminate\Database\Eloquent\Collection|null - */ - public function find($id, $columns = ['*']); - - /** - * Find multiple models by their primary keys. - * - * @param \Illuminate\Contracts\Support\Arrayable|array $ids - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function findMany($ids, $columns = ['*']); - - /** - * Find a model by its primary key or throw an exception. - * - * @param mixed $id - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass|\Illuminate\Database\Eloquent\Collection - * - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function findOrFail($id, $columns = ['*']); - - /** - * Find a model by its primary key or return fresh model instance. - * - * @param mixed $id - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass - */ - public function findOrNew($id, $columns = ['*']); - - /** - * Execute the query and get the first result. - * - * @param array|int, mixed>|string $columns - * @return TModelClass|null - */ - public function first($columns = ['*']); - - /** - * Get the first record matching the attributes or instantiate it. - * - * @param array, mixed> $attributes - * @param array, mixed> $values - * @phpstan-return TModelClass - */ - public function firstOrNew(array $attributes = [], array $values = []); - - /** - * Get the first record matching the attributes or create it. - * - * @param array, mixed> $attributes - * @param array, mixed> $values - * @phpstan-return TModelClass - */ - public function firstOrCreate(array $attributes, array $values = []); - - /** - * Create or update a record matching the attributes, and fill it with values. - * - * @param array, mixed> $attributes - * @param array, mixed> $values - * @phpstan-return TModelClass - */ - public function updateOrCreate(array $attributes, array $values = []); - - /** - * @param array, mixed> $attributes - * @phpstan-return TModelClass - */ - public function forceCreate(array $attributes); - - /** - * @param array, mixed> $values - * @return int - */ - public function update(array $values); - - /** - * Execute the query and get the first result or throw an exception. - * - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass - * - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException - */ - public function firstOrFail($columns = ['*']); - - /** - * Execute the query and get the first result if it's the sole matching record. - * - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass - */ - public function sole($columns = ['*']); - - /** - * Execute the query and get the first result or call a callback. - * - * @param \Closure|array|'*')> $columns - * @param \Closure|null $callback - * @phpstan-return TModelClass|mixed - */ - public function firstOr($columns = ['*'], \Closure $callback = null); - - /** - * Add a basic where clause to the query. - * - * @param \Closure|model-property|array|int, mixed>|\Illuminate\Database\Query\Expression $column - * @param mixed $operator - * @param mixed $value - * @param string $boolean - * @return static - */ - public function where($column, $operator = null, $value = null, $boolean = 'and'); - - /** - * Add an "or where" clause to the query. - * - * @param \Closure|model-property|array|int, mixed>|\Illuminate\Database\Query\Expression $column - * @param mixed $operator - * @param mixed $value - * @return static - */ - public function orWhere($column, $operator = null, $value = null); - - /** - * Add a relationship count / exists condition to the query. - * - * @template TRelatedModel of Model - * @param \Illuminate\Database\Eloquent\Relations\Relation|string $relation - * @param string $operator - * @param int $count - * @param string $boolean - * @param \Closure|null $callback - * @return static - * - * @throws \RuntimeException - */ - public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', \Closure $callback = null); - - /** - * Add a relationship count / exists condition to the query with an "or". - * - * @param string $relation - * @param string $operator - * @param int $count - * @return static - */ - public function orHas($relation, $operator = '>=', $count = 1); - - /** - * Add a relationship count / exists condition to the query. - * - * @param string $relation - * @param string $boolean - * @param \Closure|null $callback - * @return static - */ - public function doesntHave($relation, $boolean = 'and', \Closure $callback = null); - - /** - * Add a relationship count / exists condition to the query with an "or". - * - * @param string $relation - * @return static - */ - public function orDoesntHave($relation); - - /** - * Add a relationship count / exists condition to the query with where clauses. - * - * @param string $relation - * @param \Closure|null $callback - * @param string $operator - * @param int $count - * @return static - */ - public function whereHas($relation, \Closure $callback = null, $operator = '>=', $count = 1); - - /** - * Add a relationship count / exists condition to the query with where clauses and an "or". - * - * @param string $relation - * @param \Closure|null $callback - * @param string $operator - * @param int $count - * @return static - */ - public function orWhereHas($relation, \Closure $callback = null, $operator = '>=', $count = 1); - - /** - * Add a polymorphic relationship count / exists condition to the query. - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param string $operator - * @param int $count - * @param string $boolean - * @param \Closure|null $callback - * @return static - */ - public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', \Closure $callback = null); - - /** - * Add a polymorphic relationship count / exists condition to the query with an "or". - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param string $operator - * @param int $count - * @return static - */ - public function orHasMorph($relation, $types, $operator = '>=', $count = 1); - - /** - * Add a polymorphic relationship count / exists condition to the query. - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param string $boolean - * @param \Closure|null $callback - * @return static - */ - public function doesntHaveMorph($relation, $types, $boolean = 'and', \Closure $callback = null); - - /** - * Add a polymorphic relationship count / exists condition to the query with an "or". - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @return static - */ - public function orDoesntHaveMorph($relation, $types); - - /** - * Add a polymorphic relationship count / exists condition to the query with where clauses. - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param \Closure|null $callback - * @param string $operator - * @param int $count - * @return static - */ - public function whereHasMorph($relation, $types, \Closure $callback = null, $operator = '>=', $count = 1); - - /** - * Add a polymorphic relationship count / exists condition to the query with where clauses and an "or". - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param \Closure|null $callback - * @param string $operator - * @param int $count - * @return static - */ - public function orWhereHasMorph($relation, $types, \Closure $callback = null, $operator = '>=', $count = 1); - - /** - * Add a polymorphic relationship count / exists condition to the query with where clauses. - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param \Closure|null $callback - * @return static - */ - public function whereDoesntHaveMorph($relation, $types, \Closure $callback = null); - - /** - * Add a polymorphic relationship count / exists condition to the query with where clauses and an "or". - * - * @template TRelatedModel of Model - * @template TChildModel of Model - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation - * @param string|array $types - * @param \Closure|null $callback - * @return static - */ - public function orWhereDoesntHaveMorph($relation, $types, \Closure $callback = null); - - /** - * Merge the where constraints from another query to the current query. - * - * @param \Illuminate\Database\Eloquent\Builder $from - * @return static - */ - public function mergeConstraintsFrom(\Illuminate\Database\Eloquent\Builder $from); - - /** - * Add a relationship count / exists condition to the query with where clauses and an "or". - * - * @param string $relation - * @param \Closure|null $callback - * @return static - */ - public function orWhereDoesntHave($relation, \Closure $callback = null); - - /** - * Add a relationship count / exists condition to the query with where clauses. - * - * @param string $relation - * @param \Closure|null $callback - * @return static - */ - public function whereDoesntHave($relation, \Closure $callback = null); - - /** - * Add a basic where clause to the query, and return the first result. - * - * @param \Closure|model-property|array|int, mixed>|\Illuminate\Database\Query\Expression $column - * @param mixed $operator - * @param mixed $value - * @param string $boolean - * @phpstan-return TModelClass|null - */ - public function firstWhere($column, $operator = null, $value = null, $boolean = 'and'); - - /** - * Execute the query as a "select" statement. - * - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function get($columns = ['*']); - - /** - * Get the hydrated models without eager loading. - * - * @param array|'*')>|model-property|'*' $columns - * @phpstan-return TModelClass[] - */ - public function getModels($columns = ['*']); - - /** - * Get a single column's value from the first result of a query. - * - * @param model-property|\Illuminate\Database\Query\Expression $column - * @return mixed - */ - public function value($column); - - /** - * Apply the callback's query changes if the given "value" is true. - * - * @param mixed $value - * @param callable($this, mixed): (void|Builder) $callback - * @param callable($this, mixed): (null|Builder)|null $default - * @return mixed|$this - */ - public function when($value, $callback, $default = null); - - /** - * Apply the callback's query changes if the given "value" is false. - * - * @param mixed $value - * @param callable($this, mixed): (void|Builder) $callback - * @param callable($this, mixed): (null|Builder)|null $default - * @return mixed|$this - */ - public function unless($value, $callback, $default = null); -} - -class Scope {} - -/** - * @method static \Illuminate\Database\Eloquent\Builder withTrashed(bool $withTrashed = true) - * @method static \Illuminate\Database\Eloquent\Builder onlyTrashed() - * @method static \Illuminate\Database\Eloquent\Builder withoutTrashed() - * @method static bool restore() - */ -trait SoftDeletes {} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/EloquentCollection.stub b/php-packages/phpstan/stubs/Illuminate/Database/EloquentCollection.stub deleted file mode 100644 index 02da6d6835..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/EloquentCollection.stub +++ /dev/null @@ -1,43 +0,0 @@ - - */ -class Collection extends \Illuminate\Support\Collection -{ - - /** @phpstan-use EnumeratesValues */ - use EnumeratesValues; - - /** - * @param mixed $key - * @param mixed $default - * @phpstan-return TValue|null - */ - public function find($key, $default = null) {} - - /** - * @template TReturn - * @param callable(TValue, int): TReturn $callable - * @return static|\Illuminate\Support\Collection - */ - public function map($callable) {} - - /** - * @param callable(TValue, int): mixed $callback - * @return \Illuminate\Support\Collection - */ - public function flatMap(callable $callback) {} - - /** - * @template TReturn - * @param callable(TValue ...$values): TReturn $callback - * @return static|\Illuminate\Support\Collection - */ - public function mapSpread(callable $callback) {} -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/Factory.stub b/php-packages/phpstan/stubs/Illuminate/Database/Factory.stub deleted file mode 100644 index dc6add1a0c..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/Factory.stub +++ /dev/null @@ -1,81 +0,0 @@ - - */ - protected $model; - - /** - * Get a new factory instance for the given attributes. - * - * @param callable|array, mixed> $attributes - * @return static - */ - public static function new($attributes = []) {} - - /** - * Create a single model and persist it to the database. - * - * @param array, mixed> $attributes - * @return TModel - */ - public function createOne($attributes = []) {} - - /** - * Create a collection of models and persist them to the database. - * - * @param iterable, mixed>> $records - * @return \Illuminate\Database\Eloquent\Collection - */ - public function createMany(iterable $records) {} - - /** - * Create a collection of models and persist them to the database. - * - * @param array, mixed> $attributes - * @param \Illuminate\Database\Eloquent\Model|null $parent - * @return \Illuminate\Database\Eloquent\Collection|TModel - */ - public function create($attributes = [], ?\Illuminate\Database\Eloquent\Model $parent = null) {} - - /** - * Make a single instance of the model. - * - * @param callable|array, mixed> $attributes - * @return TModel - */ - public function makeOne($attributes = []) {} - - /** - * Create a collection of models. - * - * @param array, mixed> $attributes - * @param \Illuminate\Database\Eloquent\Model|null $parent - * @return \Illuminate\Database\Eloquent\Collection|TModel - */ - public function make($attributes = [], ?\Illuminate\Database\Eloquent\Model $parent = null) {} - - /** - * Make an instance of the model with the given attributes. - * - * @param \Illuminate\Database\Eloquent\Model|null $parent - * @return TModel - */ - protected function makeInstance(?\Illuminate\Database\Eloquent\Model $parent) {} - - /** - * Define the model's default state. - * - * @return array, mixed> - */ - abstract public function definition(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/Gate.stub b/php-packages/phpstan/stubs/Illuminate/Database/Gate.stub deleted file mode 100644 index ed57dd6953..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/Gate.stub +++ /dev/null @@ -1,31 +0,0 @@ - - */ -class HasMany extends HasOneOrMany -{ - /** - * Get the results of the relationship. - * - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/HasManyThrough.stub b/php-packages/phpstan/stubs/Illuminate/Database/HasManyThrough.stub deleted file mode 100644 index e4537e0157..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/HasManyThrough.stub +++ /dev/null @@ -1,17 +0,0 @@ - - */ -class HasManyThrough extends Relation -{ - /** - * Get the results of the relationship. - * - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/HasOne.stub b/php-packages/phpstan/stubs/Illuminate/Database/HasOne.stub deleted file mode 100644 index 336dd2d6d3..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/HasOne.stub +++ /dev/null @@ -1,17 +0,0 @@ - - */ -class HasOne extends HasOneOrMany -{ - /** - * Get the results of the relationship. - * - * @phpstan-return ?TRelatedModel - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/HasOneOrMany.stub b/php-packages/phpstan/stubs/Illuminate/Database/HasOneOrMany.stub deleted file mode 100644 index 75c04a1f92..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/HasOneOrMany.stub +++ /dev/null @@ -1,86 +0,0 @@ - - */ -abstract class HasOneOrMany extends Relation -{ - /** - * Create a new has one or many relationship instance. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param TRelatedModel $parent - * @param non-empty-string $foreignKey - * @param non-empty-string $localKey - * @return void - */ - public function __construct(\Illuminate\Database\Eloquent\Builder $query, \Illuminate\Database\Eloquent\Model $parent, $foreignKey, $localKey); - - /** - * @param array, mixed> $attributes - * @phpstan-return TRelatedModel - */ - public function make(array $attributes = []); - - /** - * Find a model by its primary key or return new instance of the related model. - * - * @param mixed $id - * @param array $columns - * @return \Illuminate\Support\Collection|TRelatedModel - */ - public function findOrNew($id, $columns = ['*']); - - /** - * Get the first related model record matching the attributes or instantiate it. - * - * @param array, mixed> $attributes - * @param array $values - * @return TRelatedModel - */ - public function firstOrNew(array $attributes, array $values = []); - - /** - * Get the first related record matching the attributes or create it. - * - * @param array, mixed> $attributes - * @param array $values - * @return TRelatedModel - */ - public function firstOrCreate(array $attributes, array $values = []); - - /** - * Create or update a related record matching the attributes, and fill it with values. - * - * @param array, mixed> $attributes - * @param array $values - * @return TRelatedModel - */ - public function updateOrCreate(array $attributes, array $values = []); - - /** - * Attach a model instance to the parent model. - * - * @param \Illuminate\Database\Eloquent\Model $model - * @return TRelatedModel|false - */ - public function save(\Illuminate\Database\Eloquent\Model $model); - - /** - * @phpstan-param array, mixed> $attributes - * - * @phpstan-return TRelatedModel - */ - public function create(array $attributes = []); - - /** - * Create a Collection of new instances of the related model. - * - * @param iterable $records - * @return \Illuminate\Database\Eloquent\Collection - */ - public function createMany(iterable $records); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/HasOneThrough.stub b/php-packages/phpstan/stubs/Illuminate/Database/HasOneThrough.stub deleted file mode 100644 index 222878f9e6..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/HasOneThrough.stub +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class HasOneThrough extends HasManyThrough -{ - /** - * @param array, mixed> $attributes - * - * @phpstan-return TRelatedModel - */ - public function create(array $attributes = []); - - /** - * Get the results of the relationship. - * - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/Model.stub b/php-packages/phpstan/stubs/Illuminate/Database/Model.stub deleted file mode 100644 index a71b3a0275..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/Model.stub +++ /dev/null @@ -1,28 +0,0 @@ - - */ -abstract class Model implements \JsonSerializable, \ArrayAccess -{ - /** - * Update the model in the database. - * - * @param array, mixed> $attributes - * @param array $options - * @return bool - */ - public function update(array $attributes = [], array $options = []); - - /** - * Begin querying a model with eager loading. - * - * @param non-empty-string|array $relations - * @return \Illuminate\Database\Eloquent\Builder - */ - public static function with($relations); -} - -class ModelNotFoundException extends \RuntimeException {} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/MorphMany.stub b/php-packages/phpstan/stubs/Illuminate/Database/MorphMany.stub deleted file mode 100644 index 4543315c06..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/MorphMany.stub +++ /dev/null @@ -1,24 +0,0 @@ - - */ -class MorphMany extends MorphOneOrMany -{ - /** - * @param array, mixed> $attributes - * - * @phpstan-return TRelatedModel - */ - public function create(array $attributes = []); - - /** - * Get the results of the relationship. - * - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/MorphOne.stub b/php-packages/phpstan/stubs/Illuminate/Database/MorphOne.stub deleted file mode 100644 index bf5e437fa0..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/MorphOne.stub +++ /dev/null @@ -1,17 +0,0 @@ - - */ -class MorphOne extends MorphOneOrMany -{ - /** - * Get the results of the relationship. - * - * @phpstan-return ?TRelatedModel - */ - public function getResults(); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/MorphOneOrMany.stub b/php-packages/phpstan/stubs/Illuminate/Database/MorphOneOrMany.stub deleted file mode 100644 index c3b775b79f..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/MorphOneOrMany.stub +++ /dev/null @@ -1,17 +0,0 @@ - - */ -abstract class MorphOneOrMany extends HasOneOrMany -{ - /** - * @param array, mixed> $attributes - * - * @phpstan-return TRelatedModel - */ - public function create(array $attributes = []); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/MorphTo.stub b/php-packages/phpstan/stubs/Illuminate/Database/MorphTo.stub deleted file mode 100644 index 2904af2ce3..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/MorphTo.stub +++ /dev/null @@ -1,11 +0,0 @@ - - */ -class MorphTo extends BelongsTo -{} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/MorphToMany.stub b/php-packages/phpstan/stubs/Illuminate/Database/MorphToMany.stub deleted file mode 100644 index 65d0ec38c4..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/MorphToMany.stub +++ /dev/null @@ -1,11 +0,0 @@ - - */ -class MorphToMany extends BelongsToMany -{ -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/QueryBuilder.stub b/php-packages/phpstan/stubs/Illuminate/Database/QueryBuilder.stub deleted file mode 100644 index 5641034e41..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/QueryBuilder.stub +++ /dev/null @@ -1,1440 +0,0 @@ -|mixed $columns - * @return $this - */ - public function select($columns = ['*']) - {} - - /** - * Add a subselect expression to the query. - * - * @param \Closure|$this|non-empty-string $query - * @param non-empty-string $as - * @return $this - * - * @throws \InvalidArgumentException - */ - public function selectSub($query, $as) - {} - - /** - * Add a new "raw" select expression to the query. - * - * @param non-empty-string $expression - * @param array $bindings - * @return $this - */ - public function selectRaw($expression, array $bindings = []) - {} - - /** - * Makes "from" fetch from a subquery. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @param non-empty-string $as - * @return $this - * - * @throws \InvalidArgumentException - */ - public function fromSub($query, $as) - {} - - /** - * Add a raw from clause to the query. - * - * @param non-empty-string $expression - * @param mixed $bindings - * @return $this - */ - public function fromRaw($expression, $bindings = []) - {} - - /** - * Creates a subquery and parse it. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @return array - */ - protected function createSub($query) - {} - - /** - * Parse the subquery into SQL and bindings. - * - * @param mixed $query - * @return array - * - * @throws \InvalidArgumentException - */ - protected function parseSub($query) - {} - - /** - * Add a new select column to the query. - * - * @param array|mixed $column - * @return $this - */ - public function addSelect($column) - {} - - /** - * Force the query to only return distinct results. - * - * @return $this - */ - public function distinct() - {} - - /** - * Set the table which the query is targeting. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $table - * @param non-empty-string|null $as - * @return $this - */ - public function from($table, $as = null) - {} - - /** - * Add a join clause to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @param non-empty-string $type - * @param bool $where - * @return $this - */ - public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false) - {} - - /** - * Add a "join where" clause to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string $operator - * @param non-empty-string $second - * @param non-empty-string $type - * @return $this - */ - public function joinWhere($table, $first, $operator, $second, $type = 'inner') - {} - - /** - * Add a subquery join clause to the query. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @param non-empty-string $as - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @param non-empty-string $type - * @param bool $where - * @return $this - * - * @throws \InvalidArgumentException - */ - public function joinSub($query, $as, $first, $operator = null, $second = null, $type = 'inner', $where = false) - {} - - /** - * Add a left join to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function leftJoin($table, $first, $operator = null, $second = null) - {} - - /** - * Add a "join where" clause to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string $operator - * @param non-empty-string $second - * @return $this - */ - public function leftJoinWhere($table, $first, $operator, $second) - {} - - /** - * Add a subquery left join to the query. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @param non-empty-string $as - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function leftJoinSub($query, $as, $first, $operator = null, $second = null) - {} - - /** - * Add a right join to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function rightJoin($table, $first, $operator = null, $second = null) - {} - - /** - * Add a "right join where" clause to the query. - * - * @param non-empty-string $table - * @param \Closure|non-empty-string $first - * @param non-empty-string $operator - * @param non-empty-string $second - * @return $this - */ - public function rightJoinWhere($table, $first, $operator, $second) - {} - - /** - * Add a subquery right join to the query. - * - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @param non-empty-string $as - * @param \Closure|non-empty-string $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function rightJoinSub($query, $as, $first, $operator = null, $second = null) - {} - - /** - * Add a "cross join" clause to the query. - * - * @param non-empty-string $table - * @param \Closure|string|null $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function crossJoin($table, $first = null, $operator = null, $second = null) - {} - - /** - * Add a basic where clause to the query. - * - * @param \Closure|string|array $column - * @param mixed $operator - * @param mixed $value - * @param non-empty-string $boolean - * @return $this - */ - public function where($column, $operator = null, $value = null, $boolean = 'and') - {} - - /** - * Add an array of where clauses to the query. - * - * @param array $column - * @param non-empty-string $boolean - * @param non-empty-string $method - * @return $this - */ - protected function addArrayOfWheres($column, $boolean, $method = 'where') - {} - - /** - * Prepare the value and operator for a where clause. - * - * @param non-empty-string $value - * @param non-empty-string $operator - * @param bool $useDefault - * @return array - * - * @throws \InvalidArgumentException - */ - public function prepareValueAndOperator($value, $operator, $useDefault = false) - {} - - /** - * Determine if the given operator and value combination is legal. - * - * Prevents using Null values with invalid operators. - * - * @param non-empty-string $operator - * @param mixed $value - * @return bool - */ - protected function invalidOperatorAndValue($operator, $value) - {} - - /** - * Determine if the given operator is supported. - * - * @param non-empty-string $operator - * @return bool - */ - protected function invalidOperator($operator) - {} - - /** - * Add an "or where" clause to the query. - * - * @param \Closure|array $column - * @param mixed $operator - * @param mixed $value - * @return $this - */ - public function orWhere($column, $operator = null, $value = null) - {} - - /** - * Add a "where" clause comparing two columns to the query. - * - * @param array $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @param non-empty-string|null $boolean - * @return $this - */ - public function whereColumn($first, $operator = null, $second = null, $boolean = 'and') - {} - - /** - * Add an "or where" clause comparing two columns to the query. - * - * @param non-empty-string|array $first - * @param non-empty-string|null $operator - * @param non-empty-string|null $second - * @return $this - */ - public function orWhereColumn($first, $operator = null, $second = null) - {} - - /** - * Add a raw where clause to the query. - * - * @param non-empty-string $sql - * @param mixed $bindings - * @param non-empty-string $boolean - * @return $this - */ - public function whereRaw($sql, $bindings = [], $boolean = 'and') - {} - - /** - * Add a raw or where clause to the query. - * - * @param non-empty-string $sql - * @param mixed $bindings - * @return $this - */ - public function orWhereRaw($sql, $bindings = []) - {} - - /** - * Add a "where in" clause to the query. - * - * @param non-empty-string $column - * @param mixed $values - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereIn($column, $values, $boolean = 'and', $not = false) - {} - - /** - * Add an "or where in" clause to the query. - * - * @param non-empty-string $column - * @param mixed $values - * @return $this - */ - public function orWhereIn($column, $values) - {} - - /** - * Add a "where not in" clause to the query. - * - * @param non-empty-string $column - * @param mixed $values - * @param non-empty-string $boolean - * @return $this - */ - public function whereNotIn($column, $values, $boolean = 'and') - {} - - /** - * Add an "or where not in" clause to the query. - * - * @param non-empty-string $column - * @param mixed $values - * @return $this - */ - public function orWhereNotIn($column, $values) - {} - - /** - * Add a "where in raw" clause for integer values to the query. - * - * @param non-empty-string $column - * @param \Illuminate\Contracts\Support\Arrayable|array $values - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereIntegerInRaw($column, $values, $boolean = 'and', $not = false) - {} - - /** - * Add an "or where in raw" clause for integer values to the query. - * - * @param non-empty-string $column - * @param \Illuminate\Contracts\Support\Arrayable|array $values - * @return $this - */ - public function orWhereIntegerInRaw($column, $values) - {} - - /** - * Add a "where not in raw" clause for integer values to the query. - * - * @param non-empty-string $column - * @param \Illuminate\Contracts\Support\Arrayable|array $values - * @param non-empty-string $boolean - * @return $this - */ - public function whereIntegerNotInRaw($column, $values, $boolean = 'and') - {} - - /** - * Add an "or where not in raw" clause for integer values to the query. - * - * @param non-empty-string $column - * @param \Illuminate\Contracts\Support\Arrayable|array $values - * @return $this - */ - public function orWhereIntegerNotInRaw($column, $values) - {} - - /** - * Add a "where null" clause to the query. - * - * @param non-empty-string|array $columns - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereNull($columns, $boolean = 'and', $not = false) - {} - - /** - * Add an "or where null" clause to the query. - * - * @param non-empty-string $column - * @return $this - */ - public function orWhereNull($column) - {} - - /** - * Add a "where not null" clause to the query. - * - * @param non-empty-string|array $columns - * @param non-empty-string $boolean - * @return $this - */ - public function whereNotNull($columns, $boolean = 'and') - {} - - /** - * Add a where between statement to the query. - * - * @param non-empty-string $column - * @param array $values - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereBetween($column, array $values, $boolean = 'and', $not = false) - {} - - /** - * Add an or where between statement to the query. - * - * @param non-empty-string $column - * @param array $values - * @return $this - */ - public function orWhereBetween($column, array $values) - {} - - /** - * Add a where not between statement to the query. - * - * @param non-empty-string $column - * @param array $values - * @param non-empty-string $boolean - * @return $this - */ - public function whereNotBetween($column, array $values, $boolean = 'and') - {} - - /** - * Add an or where not between statement to the query. - * - * @param non-empty-string $column - * @param array $values - * @return $this - */ - public function orWhereNotBetween($column, array $values) - {} - - /** - * Add an "or where not null" clause to the query. - * - * @param non-empty-string $column - * @return $this - */ - public function orWhereNotNull($column) - {} - - /** - * Add a "where date" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereDate($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add an "or where date" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @return $this - */ - public function orWhereDate($column, $operator, $value = null) - {} - - /** - * Add a "where time" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereTime($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add an "or where time" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @return $this - */ - public function orWhereTime($column, $operator, $value = null) - {} - - /** - * Add a "where day" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereDay($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add an "or where day" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @return $this - */ - public function orWhereDay($column, $operator, $value = null) - {} - - /** - * Add a "where month" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereMonth($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add an "or where month" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|null $value - * @return $this - */ - public function orWhereMonth($column, $operator, $value = null) - {} - - /** - * Add a "where year" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|int|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereYear($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add an "or where year" statement to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \DateTimeInterface|string|int|null $value - * @return $this - */ - public function orWhereYear($column, $operator, $value = null) - {} - - /** - * Add a date based (year, month, day, time) statement to the query. - * - * @param non-empty-string $type - * @param non-empty-string $column - * @param non-empty-string $operator - * @param mixed $value - * @param non-empty-string $boolean - * @return $this - */ - protected function addDateBasedWhere($type, $column, $operator, $value, $boolean = 'and') - {} - - /** - * Add a nested where statement to the query. - * - * @param \Closure $callback - * @param non-empty-string $boolean - * @return $this - */ - public function whereNested(\Closure $callback, $boolean = 'and') - {} - - /** - * Create a new query instance for nested where condition. - * - * @return $this - */ - public function forNestedWhere() - {} - - /** - * Add another query builder as a nested where to the query builder. - * - * @param $this $query - * @param non-empty-string $boolean - * @return $this - */ - public function addNestedWhereQuery($query, $boolean = 'and') - {} - - /** - * Add a full sub-select to the query. - * - * @param non-empty-string $column - * @param non-empty-string $operator - * @param \Closure $callback - * @param non-empty-string $boolean - * @return $this - */ - protected function whereSub($column, $operator, \Closure $callback, $boolean) - {} - - /** - * Add an exists clause to the query. - * - * @param \Closure $callback - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereExists(\Closure $callback, $boolean = 'and', $not = false) - {} - - /** - * Add an or exists clause to the query. - * - * @param \Closure $callback - * @param bool $not - * @return $this - */ - public function orWhereExists(\Closure $callback, $not = false) - {} - - /** - * Add a where not exists clause to the query. - * - * @param \Closure $callback - * @param non-empty-string $boolean - * @return $this - */ - public function whereNotExists(\Closure $callback, $boolean = 'and') - {} - - /** - * Add a where not exists clause to the query. - * - * @param \Closure $callback - * @return $this - */ - public function orWhereNotExists(\Closure $callback) - {} - - /** - * Add an exists clause to the query. - * - * @param \Illuminate\Database\Query\Builder $query - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function addWhereExistsQuery(self $query, $boolean = 'and', $not = false) - {} - - /** - * Adds a where condition using row values. - * - * @param array $columns - * @param non-empty-string $operator - * @param array $values - * @param non-empty-string $boolean - * @return $this - * - * @throws \InvalidArgumentException - */ - public function whereRowValues($columns, $operator, $values, $boolean = 'and') - {} - - /** - * Adds a or where condition using row values. - * - * @param array $columns - * @param non-empty-string $operator - * @param array $values - * @return $this - */ - public function orWhereRowValues($columns, $operator, $values) - {} - - /** - * Add a "where JSON contains" clause to the query. - * - * @param non-empty-string $column - * @param mixed $value - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function whereJsonContains($column, $value, $boolean = 'and', $not = false) - {} - - /** - * Add a "or where JSON contains" clause to the query. - * - * @param non-empty-string $column - * @param mixed $value - * @return $this - */ - public function orWhereJsonContains($column, $value) - {} - - /** - * Add a "where JSON not contains" clause to the query. - * - * @param non-empty-string $column - * @param mixed $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereJsonDoesntContain($column, $value, $boolean = 'and') - {} - - /** - * Add a "or where JSON not contains" clause to the query. - * - * @param non-empty-string $column - * @param mixed $value - * @return $this - */ - public function orWhereJsonDoesntContain($column, $value) - {} - - /** - * Add a "where JSON length" clause to the query. - * - * @param non-empty-string $column - * @param mixed $operator - * @param mixed $value - * @param non-empty-string $boolean - * @return $this - */ - public function whereJsonLength($column, $operator, $value = null, $boolean = 'and') - {} - - /** - * Add a "or where JSON length" clause to the query. - * - * @param non-empty-string $column - * @param mixed $operator - * @param mixed $value - * @return $this - */ - public function orWhereJsonLength($column, $operator, $value = null) - {} - - /** - * Handles dynamic "where" clauses to the query. - * - * @param non-empty-string $method - * @param array $parameters - * @return $this - */ - public function dynamicWhere($method, $parameters) - {} - - /** - * Add a single dynamic where clause statement to the query. - * - * @param non-empty-string $segment - * @param non-empty-string $connector - * @param array $parameters - * @param int $index - * @return void - */ - protected function addDynamic($segment, $connector, $parameters, $index) - {} - - /** - * Add a "group by" clause to the query. - * - * @param array|non-empty-string ...$groups - * @return $this - */ - public function groupBy(...$groups) - {} - - /** - * Add a raw groupBy clause to the query. - * - * @param non-empty-string $sql - * @param array $bindings - * @return $this - */ - public function groupByRaw($sql, array $bindings = []) - {} - - /** - * Add a "having" clause to the query. - * - * @param non-empty-string $column - * @param non-empty-string|null $operator - * @param non-empty-string|null $value - * @param non-empty-string $boolean - * @return $this - */ - public function having($column, $operator = null, $value = null, $boolean = 'and') - {} - - /** - * Add a "or having" clause to the query. - * - * @param non-empty-string $column - * @param non-empty-string|null $operator - * @param non-empty-string|null $value - * @return $this - */ - public function orHaving($column, $operator = null, $value = null) - {} - - /** - * Add a "having between " clause to the query. - * - * @param non-empty-string $column - * @param array $values - * @param non-empty-string $boolean - * @param bool $not - * @return $this - */ - public function havingBetween($column, array $values, $boolean = 'and', $not = false) - {} - - /** - * Add a raw having clause to the query. - * - * @param non-empty-string $sql - * @param array $bindings - * @param non-empty-string $boolean - * @return $this - */ - public function havingRaw($sql, array $bindings = [], $boolean = 'and') - {} - - /** - * Add a raw or having clause to the query. - * - * @param non-empty-string $sql - * @param array $bindings - * @return $this - */ - public function orHavingRaw($sql, array $bindings = []) - {} - - /** - * Add an "order by" clause to the query. - * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|non-empty-string $column - * @param non-empty-string $direction - * @return $this - * - * @throws \InvalidArgumentException - */ - public function orderBy($column, $direction = 'asc') - {} - - /** - * Add a descending "order by" clause to the query. - * - * @param non-empty-string $column - * @return $this - */ - public function orderByDesc($column) - {} - - /** - * Add an "order by" clause for a timestamp to the query. - * - * @param non-empty-string|\Illuminate\Database\Query\Expression $column - * @return $this - */ - public function latest($column = 'created_at') - {} - - /** - * Add an "order by" clause for a timestamp to the query. - * - * @param non-empty-string|\Illuminate\Database\Query\Expression $column - * @return $this - */ - public function oldest($column = 'created_at') - {} - - /** - * Put the query's results in random order. - * - * @param non-empty-string $seed - * @return $this - */ - public function inRandomOrder($seed = '') - {} - - /** - * Add a raw "order by" clause to the query. - * - * @param non-empty-string $sql - * @param array $bindings - * @return $this - */ - public function orderByRaw($sql, $bindings = []) - {} - - /** - * Alias to set the "offset" value of the query. - * - * @param int $value - * @return $this - */ - public function skip($value) - {} - - /** - * Set the "offset" value of the query. - * - * @param int $value - * @return $this - */ - public function offset($value) - {} - - /** - * Alias to set the "limit" value of the query. - * - * @param int $value - * @return $this - */ - public function take($value) - {} - - /** - * Set the "limit" value of the query. - * - * @param int $value - * @return $this - */ - public function limit($value) - {} - - /** - * Set the limit and offset for a given page. - * - * @param int $page - * @param int $perPage - * @return $this - */ - public function forPage($page, $perPage = 15) - {} - - /** - * Constrain the query to the previous "page" of results before a given ID. - * - * @param int $perPage - * @param int|null $lastId - * @param non-empty-string $column - * @return $this - */ - public function forPageBeforeId($perPage = 15, $lastId = 0, $column = 'id') - {} - - /** - * Constrain the query to the next "page" of results after a given ID. - * - * @param int $perPage - * @param int|null $lastId - * @param non-empty-string $column - * @return $this - */ - public function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id') - {} - - /** - * Remove all existing orders and optionally add a new order. - * - * @param non-empty-string|null $column - * @param non-empty-string $direction - * @return $this - */ - public function reorder($column = null, $direction = 'asc') - {} - - /** - * Get an array with all orders with a given column removed. - * - * @param non-empty-string $column - * @return array - */ - protected function removeExistingOrdersFor($column) - {} - - /** - * Add a union statement to the query. - * - * @param \Illuminate\Database\Query\Builder|\Closure $query - * @param bool $all - * @return $this - */ - public function union($query, $all = false) - {} - - /** - * Add a union all statement to the query. - * - * @param \Illuminate\Database\Query\Builder|\Closure $query - * @return $this - */ - public function unionAll($query) - {} - - /** - * Lock the selected rows in the table. - * - * @param non-empty-string|bool $value - * @return $this - */ - public function lock($value = true) - {} - - /** - * Lock the selected rows in the table for updating. - * - * @return static - */ - public function lockForUpdate() - {} - - /** - * Share lock the selected rows in the table. - * - * @return $this - */ - public function sharedLock() - {} - - /** - * Execute a query for a single record by ID. - * - * @param int|non-empty-string $id - * @param array $columns - * @return mixed|static - */ - public function find($id, $columns = ['*']) - {} - - /** - * Throw an exception if the query doesn't have an orderBy clause. - * - * @return void - * - * @throws \RuntimeException - */ - protected function enforceOrderBy() - {} - - /** - * Get an array with the values of a given column. - * - * @param non-empty-string|\Illuminate\Database\Query\Expression $column - * @param non-empty-string|null $key - * @return \Illuminate\Support\Collection - */ - public function pluck($column, $key = null) - {} - - /** - * Concatenate values of a given column as a string. - * - * @param non-empty-string $column - * @param non-empty-string $glue - * @return string - */ - public function implode($column, $glue = '') - {} - - /** - * Determine if any rows exist for the current query. - * - * @return bool - */ - public function exists() - {} - - /** - * Determine if no rows exist for the current query. - * - * @return bool - */ - public function doesntExist() - {} - - /** - * Execute the given callback if no rows exist for the current query. - * - * @param \Closure $callback - * @return mixed - */ - public function existsOr(\Closure $callback) - {} - - /** - * Execute the given callback if rows exist for the current query. - * - * @param \Closure $callback - * @return mixed - */ - public function doesntExistOr(\Closure $callback) - {} - - /** - * Retrieve the "count" result of the query. - * - * @param non-empty-string $columns - * @return int - */ - public function count($columns = '*') - {} - - /** - * Retrieve the minimum value of a given column. - * - * @param non-empty-string $column - * @return mixed - */ - public function min($column) - {} - - /** - * Retrieve the maximum value of a given column. - * - * @param non-empty-string $column - * @return mixed - */ - public function max($column) - {} - - /** - * Retrieve the sum of the values of a given column. - * - * @param non-empty-string $column - * @return mixed - */ - public function sum($column) - {} - - /** - * Retrieve the average of the values of a given column. - * - * @param non-empty-string $column - * @return mixed - */ - public function avg($column) - {} - - /** - * Alias for the "avg" method. - * - * @param non-empty-string $column - * @return mixed - */ - public function average($column) - {} - - /** - * Execute an aggregate function on the database. - * - * @param non-empty-string $function - * @param array $columns - * @return mixed - */ - public function aggregate($function, $columns = ['*']) - {} - - /** - * Execute a numeric aggregate function on the database. - * - * @param non-empty-string $function - * @param array $columns - * @return float|int - */ - public function numericAggregate($function, $columns = ['*']) - {} - - /** - * Set the aggregate property without running the query. - * - * @param non-empty-string $function - * @param array $columns - * @return $this - */ - protected function setAggregate($function, $columns) - {} - - /** - * Execute the given callback while selecting the given columns. - * - * After running the callback, the columns are reset to the original value. - * - * @param array $columns - * @param callable $callback - * @return mixed - */ - protected function onceWithColumns($columns, $callback) - {} - - /** - * Insert a new record into the database. - * - * @param array $values - * @return bool - */ - public function insert(array $values) - {} - - /** - * Insert a new record into the database while ignoring errors. - * - * @param array $values - * @return int - */ - public function insertOrIgnore(array $values) - {} - - /** - * Insert a new record and get the value of the primary key. - * - * @param array $values - * @param non-empty-string|null $sequence - * @return int - */ - public function insertGetId(array $values, $sequence = null) - {} - - /** - * Insert new records into the table using a subquery. - * - * @param array $columns - * @param \Closure|\Illuminate\Database\Query\Builder|non-empty-string $query - * @return int - */ - public function insertUsing(array $columns, $query) - {} - - /** - * Update a record in the database. - * - * @param array $values - * @return int - */ - public function update(array $values) - {} - - /** - * Insert or update a record matching the attributes, and fill it with values. - * - * @param array $attributes - * @param array $values - * @return bool - */ - public function updateOrInsert(array $attributes, array $values = []) - {} - - /** - * Increment a column's value by a given amount. - * - * @param non-empty-string|\Illuminate\Database\Query\Expression $column - * @param float|int $amount - * @param array $extra - * @return int - * - * @throws \InvalidArgumentException - */ - public function increment($column, $amount = 1, array $extra = []) - {} - - /** - * Decrement a column's value by a given amount. - * - * @param non-empty-string|\Illuminate\Database\Query\Expression $column - * @param float|int $amount - * @param array $extra - * @return int - * - * @throws \InvalidArgumentException - */ - public function decrement($column, $amount = 1, array $extra = []) - {} - - /** - * Delete a record from the database. - * - * @param mixed $id - * @return int - */ - public function delete($id = null) - {} - - /** - * Run a truncate statement on the table. - * - * @return void - */ - public function truncate() - {} - - /** - * Get a new instance of the query builder. - * - * @return $this - */ - public function newQuery() - {} - - /** - * Get the current query value bindings in a flattened array. - * - * @return array - */ - public function getBindings() - {} - - /** - * Get the raw array of bindings. - * - * @return array - */ - public function getRawBindings() - {} - - /** - * Set the bindings on the query builder. - * - * @param array $bindings - * @param non-empty-string $type - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setBindings(array $bindings, $type = 'where') - {} - - /** - * Add a binding to the query. - * - * @param mixed $value - * @param non-empty-string $type - * @return $this - * - * @throws \InvalidArgumentException - */ - public function addBinding($value, $type = 'where') - {} - - /** - * Merge an array of bindings into our bindings. - * - * @param \Illuminate\Database\Query\Builder $query - * @return $this - */ - public function mergeBindings(self $query) - {} -} diff --git a/php-packages/phpstan/stubs/Illuminate/Database/Relation.stub b/php-packages/phpstan/stubs/Illuminate/Database/Relation.stub deleted file mode 100644 index dff9063081..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Database/Relation.stub +++ /dev/null @@ -1,24 +0,0 @@ - $columns - * @phpstan-return \Illuminate\Database\Eloquent\Collection - */ - public function get($columns = ['*']); - - - /** - * @param array, mixed> $attributes - * @phpstan-return TRelatedModel - */ - public function make(array $attributes = []); -} diff --git a/php-packages/phpstan/stubs/Illuminate/Enumerable.stub b/php-packages/phpstan/stubs/Illuminate/Enumerable.stub deleted file mode 100644 index 7fd2c1ea59..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Enumerable.stub +++ /dev/null @@ -1,58 +0,0 @@ - - */ -interface Enumerable extends \Countable, \IteratorAggregate, \JsonSerializable -{ - /** - * @param string|callable(TValue, TKey): bool $key - * @param mixed $operator - * @param mixed $value - * @return static - */ - public function partition($key, $operator = null, $value = null); - - /** - * @param string|callable(TValue, TKey): mixed $keyBy - * @return static - */ - public function keyBy($keyBy); - - /** - * @param callable(TValue, TKey): array $callback - * @return static - */ - public function mapWithKeys(callable $callback); - - /** - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToDictionary(callable $callback); - - /** - * @param string|callable(TValue, TKey): bool $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function every($key, $operator = null, $value = null); - - /** - * @param int $size - * @return static - */ - public function chunk($size); - - /** - * @param callable(static): void $callable - * @return static - */ - public function tap($callable); -} diff --git a/php-packages/phpstan/stubs/Illuminate/EnumeratesValues.stub b/php-packages/phpstan/stubs/Illuminate/EnumeratesValues.stub deleted file mode 100644 index 6cc58f849b..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/EnumeratesValues.stub +++ /dev/null @@ -1,36 +0,0 @@ - $average - * @property-read HigherOrderCollectionProxy<'avg', TValue> $avg - * @property-read HigherOrderCollectionProxy<'contains', TValue> $contains - * @property-read HigherOrderCollectionProxy<'each', TValue> $each - * @property-read HigherOrderCollectionProxy<'every', TValue> $every - * @property-read HigherOrderCollectionProxy<'filter', TValue> $filter - * @property-read HigherOrderCollectionProxy<'first', TValue> $first - * @property-read HigherOrderCollectionProxy<'flatMap', TValue> $flatMap - * @property-read HigherOrderCollectionProxy<'groupBy', TValue> $groupBy - * @property-read HigherOrderCollectionProxy<'keyBy', TValue> $keyBy - * @property-read HigherOrderCollectionProxy<'map', TValue> $map - * @property-read HigherOrderCollectionProxy<'max', TValue> $max - * @property-read HigherOrderCollectionProxy<'min', TValue> $min - * @property-read HigherOrderCollectionProxy<'partition', TValue> $partition - * @property-read HigherOrderCollectionProxy<'reject', TValue> $reject - * @property-read HigherOrderCollectionProxy<'some', TValue> $some - * @property-read HigherOrderCollectionProxy<'sortBy', TValue> $sortBy - * @property-read HigherOrderCollectionProxy<'sortByDesc', TValue> $sortByDesc - * @property-read HigherOrderCollectionProxy<'skipUntil', TValue> $skipUntil - * @property-read HigherOrderCollectionProxy<'skipWhile', TValue> $skipWhile - * @property-read HigherOrderCollectionProxy<'sum', TValue> $sum - * @property-read HigherOrderCollectionProxy<'takeUntil', TValue> $takeUntil - * @property-read HigherOrderCollectionProxy<'takeWhile', TValue> $takeWhile - * @property-read HigherOrderCollectionProxy<'unique', TValue> $unique - * @property-read HigherOrderCollectionProxy<'until', TValue> $until - */ -trait EnumeratesValues -{} diff --git a/php-packages/phpstan/stubs/Illuminate/Facades.stub b/php-packages/phpstan/stubs/Illuminate/Facades.stub deleted file mode 100644 index 30f2089af4..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Facades.stub +++ /dev/null @@ -1,30 +0,0 @@ - $data - * @param array $mergeData - * @return mixed - */ -function view($view = null, $data = [], $mergeData = []) -{ -} diff --git a/php-packages/phpstan/stubs/Illuminate/HigherOrderProxies.stub b/php-packages/phpstan/stubs/Illuminate/HigherOrderProxies.stub deleted file mode 100644 index b3cf0f30af..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/HigherOrderProxies.stub +++ /dev/null @@ -1,24 +0,0 @@ - $data - * @return $this - */ - public function markdown($view, array $data = []) - {} - - /** - * @param view-string $view - * @param array $data - * @return $this - */ - public function view($view, array $data = []) - {} -} diff --git a/php-packages/phpstan/stubs/Illuminate/Pagination.stub b/php-packages/phpstan/stubs/Illuminate/Pagination.stub deleted file mode 100644 index 8c57cd079d..0000000000 --- a/php-packages/phpstan/stubs/Illuminate/Pagination.stub +++ /dev/null @@ -1,23 +0,0 @@ - - * @implements \IteratorAggregate - */ -class Paginator extends AbstractPaginator implements \Illuminate\Contracts\Support\Arrayable, \ArrayAccess, \Countable, \IteratorAggregate, \Illuminate\Contracts\Support\Jsonable, \JsonSerializable, \Illuminate\Contracts\Pagination\Paginator -{} - -/** - * @implements \ArrayAccess - * @implements \IteratorAggregate - */ -class LengthAwarePaginator extends AbstractPaginator implements \Illuminate\Contracts\Support\Arrayable, \ArrayAccess, \Countable, \IteratorAggregate, \Illuminate\Contracts\Support\Jsonable, \JsonSerializable, \Illuminate\Contracts\Pagination\LengthAwarePaginator -{} diff --git a/php-packages/phpstan/stubs/Illuminate/Queue/ListenerOptions.stub b/php-packages/phpstan/stubs/Illuminate/Queue/ListenerOptions.stub new file mode 100644 index 0000000000..c77b7600dc --- /dev/null +++ b/php-packages/phpstan/stubs/Illuminate/Queue/ListenerOptions.stub @@ -0,0 +1,13 @@ + Date: Sat, 23 Jul 2022 19:21:54 +0100 Subject: [PATCH 03/16] chore: level 5 phpstan Signed-off-by: Sami Mazouz --- .editorconfig | 3 +++ framework/core/src/Api/Client.php | 1 - .../Controller/AbstractSerializeController.php | 2 +- .../src/Api/Serializer/AbstractSerializer.php | 2 +- .../Database/DatabaseMigrationRepository.php | 5 ++--- .../src/Database/DatabaseServiceProvider.php | 1 + framework/core/src/Database/Migrator.php | 16 +++++----------- .../src/Discussion/Access/DiscussionPolicy.php | 1 - framework/core/src/Discussion/Discussion.php | 8 ++++---- .../src/Discussion/DiscussionRepository.php | 2 +- .../Extension/Exception/ExtensionBootError.php | 2 +- framework/core/src/Foundation/Application.php | 2 +- .../core/src/Foundation/Console/InfoCommand.php | 6 +----- .../core/src/Install/Console/InstallCommand.php | 5 ++++- framework/core/src/Install/Installation.php | 2 +- framework/core/src/Install/ReversibleStep.php | 2 +- .../Install/Steps/EnableBundledExtensions.php | 6 +++--- .../core/src/Install/Steps/PublishAssets.php | 3 +-- .../core/src/Install/Steps/RunMigrations.php | 6 +++--- .../core/src/Install/Steps/StoreConfig.php | 3 +-- .../src/Notification/NotificationRepository.php | 6 ++++-- framework/core/src/Post/MergeableInterface.php | 2 +- .../core/src/Queue/QueueServiceProvider.php | 4 ++-- .../src/User/Command/RegisterUserHandler.php | 1 + framework/core/src/User/RegistrationToken.php | 4 +++- framework/core/src/User/User.php | 2 +- framework/core/src/User/UserRepository.php | 2 +- framework/core/src/User/UserServiceProvider.php | 1 - framework/core/src/helpers.php | 2 +- php-packages/phpstan/extension.neon | 1 + php-packages/phpstan/phpstan-baseline.neon | 6 +++++- .../Filesystem/FilesystemManager.stub | 17 +++++++++++++++++ .../Illuminate/Support/ServiceProvider.stub | 8 ++++++++ phpstan.neon | 4 +--- 34 files changed, 81 insertions(+), 57 deletions(-) create mode 100644 php-packages/phpstan/stubs/Illuminate/Filesystem/FilesystemManager.stub diff --git a/.editorconfig b/.editorconfig index d240f3e4fd..8abbe8cda4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,3 +20,6 @@ indent_size = 4 [tsconfig.json] indent_size = 2 + +[*.neon] +indent_style = tab diff --git a/framework/core/src/Api/Client.php b/framework/core/src/Api/Client.php index a65fd06db4..11e3d45bc7 100644 --- a/framework/core/src/Api/Client.php +++ b/framework/core/src/Api/Client.php @@ -11,7 +11,6 @@ use Flarum\Http\RequestUtil; use Flarum\User\User; -use Illuminate\Contracts\Container\Container; use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; use Laminas\Stratigility\MiddlewarePipeInterface; diff --git a/framework/core/src/Api/Controller/AbstractSerializeController.php b/framework/core/src/Api/Controller/AbstractSerializeController.php index ee9e907b1c..0c813eabfe 100644 --- a/framework/core/src/Api/Controller/AbstractSerializeController.php +++ b/framework/core/src/Api/Controller/AbstractSerializeController.php @@ -88,7 +88,7 @@ abstract class AbstractSerializeController implements RequestHandlerInterface protected static $beforeSerializationCallbacks = []; /** - * @var string[] + * @var string[][] */ protected static $loadRelations = []; diff --git a/framework/core/src/Api/Serializer/AbstractSerializer.php b/framework/core/src/Api/Serializer/AbstractSerializer.php index ce707f18ed..69efef3eb4 100644 --- a/framework/core/src/Api/Serializer/AbstractSerializer.php +++ b/framework/core/src/Api/Serializer/AbstractSerializer.php @@ -194,7 +194,7 @@ public function hasMany($model, $serializer, $relation = null) protected function buildRelationship($model, $serializer, $relation = null, $many = false) { if (is_null($relation)) { - list(, , $caller) = debug_backtrace(false, 3); + list(, , $caller) = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 3); $relation = $caller['function']; } diff --git a/framework/core/src/Database/DatabaseMigrationRepository.php b/framework/core/src/Database/DatabaseMigrationRepository.php index 4a880d0eff..7e6ba84301 100644 --- a/framework/core/src/Database/DatabaseMigrationRepository.php +++ b/framework/core/src/Database/DatabaseMigrationRepository.php @@ -10,7 +10,6 @@ namespace Flarum\Database; use Illuminate\Database\Connection; -use Illuminate\Database\ConnectionInterface; class DatabaseMigrationRepository implements MigrationRepositoryInterface { @@ -32,9 +31,9 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface * Create a new database migration repository instance. * * @param Connection $connection - * @param string $table + * @param string $table */ - public function __construct(ConnectionInterface $connection, $table) + public function __construct(Connection $connection, $table) { $this->connection = $connection; $this->table = $table; diff --git a/framework/core/src/Database/DatabaseServiceProvider.php b/framework/core/src/Database/DatabaseServiceProvider.php index ad66fcbd49..52c23da6f8 100644 --- a/framework/core/src/Database/DatabaseServiceProvider.php +++ b/framework/core/src/Database/DatabaseServiceProvider.php @@ -23,6 +23,7 @@ class DatabaseServiceProvider extends AbstractServiceProvider public function register() { $this->container->singleton(Manager::class, function (Container $container) { + /** @var \Illuminate\Container\Container $container */ $manager = new Manager($container); $config = $container['flarum']->config('database'); diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 34ed0355d3..5ee922eab0 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -12,7 +12,6 @@ use Exception; use Flarum\Extension\Extension; use Illuminate\Database\Connection; -use Illuminate\Database\ConnectionInterface; use Illuminate\Database\MySqlConnection; use Illuminate\Filesystem\Filesystem; use InvalidArgumentException; @@ -45,20 +44,16 @@ class Migrator protected $output; /** - * @var Connection|MySqlConnection + * @var Connection */ protected $connection; /** * Create a new migrator instance. - * - * @param MigrationRepositoryInterface $repository - * @param Connection $connection - * @param Filesystem $files */ public function __construct( MigrationRepositoryInterface $repository, - ConnectionInterface $connection, + Connection $connection, Filesystem $files ) { $this->files = $files; @@ -78,7 +73,7 @@ public function __construct( * Run the outstanding migrations at a given path. * * @param string $path - * @param Extension $extension + * @param Extension|null $extension * @return void */ public function run($path, Extension $extension = null) @@ -97,7 +92,7 @@ public function run($path, Extension $extension = null) * * @param string $path * @param array $migrations - * @param Extension $extension + * @param Extension|null $extension * @return void */ public function runMigrationList($path, $migrations, Extension $extension = null) @@ -124,8 +119,7 @@ public function runMigrationList($path, $migrations, Extension $extension = null * * @param string $path * @param string $file - * @param string $path - * @param Extension $extension + * @param Extension|null $extension * @return void */ protected function runUp($path, $file, Extension $extension = null) diff --git a/framework/core/src/Discussion/Access/DiscussionPolicy.php b/framework/core/src/Discussion/Access/DiscussionPolicy.php index 202d9a49ee..c0124257c3 100644 --- a/framework/core/src/Discussion/Access/DiscussionPolicy.php +++ b/framework/core/src/Discussion/Access/DiscussionPolicy.php @@ -13,7 +13,6 @@ use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\Access\AbstractPolicy; use Flarum\User\User; -use Illuminate\Contracts\Events\Dispatcher; class DiscussionPolicy extends AbstractPolicy { diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index cebefb13d3..f4c00d2f84 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -225,7 +225,6 @@ public function setLastPost(Post $post) */ public function refreshLastPost() { - /** @var Post $lastPost */ if ($lastPost = $this->comments()->latest()->first()) { $this->setLastPost($lastPost); } @@ -265,8 +264,9 @@ public function refreshParticipantCount() * DiscussionRenamedPost, and delete if the title has been reverted * completely.) * - * @param \Flarum\Post\MergeableInterface $post The post to save. - * @return Post The resulting post. It may or may not be the same post as + * @template T of \Flarum\Post\MergeableInterface + * @param T $post The post to save. + * @return T The resulting post. It may or may not be the same post as * was originally intended to be saved. It also may not exist, if the * merge logic resulted in deletion. */ @@ -302,7 +302,7 @@ public function posts() /** * Define the relationship with the discussion's publicly-visible comments. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function comments() { diff --git a/framework/core/src/Discussion/DiscussionRepository.php b/framework/core/src/Discussion/DiscussionRepository.php index 2619bc9fcd..7af6e62bb7 100644 --- a/framework/core/src/Discussion/DiscussionRepository.php +++ b/framework/core/src/Discussion/DiscussionRepository.php @@ -28,7 +28,7 @@ public function query() * Find a discussion by ID, optionally making sure it is visible to a * certain user, or throw an exception. * - * @param int $id + * @param int|string $id * @param User|null $user * @return \Flarum\Discussion\Discussion */ diff --git a/framework/core/src/Extension/Exception/ExtensionBootError.php b/framework/core/src/Extension/Exception/ExtensionBootError.php index 881b982309..e015bf34bd 100644 --- a/framework/core/src/Extension/Exception/ExtensionBootError.php +++ b/framework/core/src/Extension/Exception/ExtensionBootError.php @@ -25,6 +25,6 @@ public function __construct(Extension $extension, $extender, Throwable $previous $extenderClass = get_class($extender); - parent::__construct("Experienced an error while booting extension: {$extension->getTitle()}.\n\nError occurred while applying an extender of type: $extenderClass.", null, $previous); + parent::__construct("Experienced an error while booting extension: {$extension->getTitle()}.\n\nError occurred while applying an extender of type: $extenderClass.", 0, $previous); } } diff --git a/framework/core/src/Foundation/Application.php b/framework/core/src/Foundation/Application.php index a4b81a12aa..cf83b8f664 100644 --- a/framework/core/src/Foundation/Application.php +++ b/framework/core/src/Foundation/Application.php @@ -140,7 +140,7 @@ protected function registerBaseBindings() * Use container inside flarum instead. */ $this->container->instance('app', $this->container); - $this->container->alias('app', \Illuminate\Container\Container::class); + $this->container->alias('app', \Illuminate\Container\Container::class); $this->container->instance('container', $this->container); $this->container->alias('container', \Illuminate\Container\Container::class); diff --git a/framework/core/src/Foundation/Console/InfoCommand.php b/framework/core/src/Foundation/Console/InfoCommand.php index a8c8dea70f..f131f6bc40 100644 --- a/framework/core/src/Foundation/Console/InfoCommand.php +++ b/framework/core/src/Foundation/Console/InfoCommand.php @@ -16,7 +16,6 @@ use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Queue\Queue; use Illuminate\Database\Connection; -use Illuminate\Database\ConnectionInterface; use Illuminate\Support\Str; use PDO; use Symfony\Component\Console\Helper\Table; @@ -49,14 +48,11 @@ class InfoCommand extends AbstractCommand */ private $queue; - /** - * @param Connection $db - */ public function __construct( ExtensionManager $extensions, Config $config, SettingsRepositoryInterface $settings, - ConnectionInterface $db, + Connection $db, Queue $queue ) { $this->extensions = $extensions; diff --git a/framework/core/src/Install/Console/InstallCommand.php b/framework/core/src/Install/Console/InstallCommand.php index d6b464054f..e74d2cd0f9 100644 --- a/framework/core/src/Install/Console/InstallCommand.php +++ b/framework/core/src/Install/Console/InstallCommand.php @@ -13,6 +13,7 @@ use Flarum\Install\Installation; use Flarum\Install\Pipeline; use Flarum\Install\Step; +use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputOption; class InstallCommand extends AbstractCommand @@ -83,7 +84,9 @@ protected function init() if ($this->input->getOption('file')) { $this->dataSource = new FileDataProvider($this->input); } else { - $this->dataSource = new UserDataProvider($this->input, $this->output, $this->getHelperSet()->get('question')); + /** @var QuestionHelper $questionHelper */ + $questionHelper = $this->getHelperSet()->get('question'); + $this->dataSource = new UserDataProvider($this->input, $this->output, $questionHelper); } } diff --git a/framework/core/src/Install/Installation.php b/framework/core/src/Install/Installation.php index 243614da01..b83fba5fb8 100644 --- a/framework/core/src/Install/Installation.php +++ b/framework/core/src/Install/Installation.php @@ -36,7 +36,7 @@ class Installation // Could also be local variables in build(), but this way // access in closures is easier. :) - /** @var \Illuminate\Database\ConnectionInterface */ + /** @var \Illuminate\Database\Connection */ private $db; public function __construct(Paths $paths) diff --git a/framework/core/src/Install/ReversibleStep.php b/framework/core/src/Install/ReversibleStep.php index da239f2c2e..0189bbf3e1 100644 --- a/framework/core/src/Install/ReversibleStep.php +++ b/framework/core/src/Install/ReversibleStep.php @@ -9,7 +9,7 @@ namespace Flarum\Install; -interface ReversibleStep +interface ReversibleStep extends Step { public function revert(); } diff --git a/framework/core/src/Install/Steps/EnableBundledExtensions.php b/framework/core/src/Install/Steps/EnableBundledExtensions.php index 5abcdf14e8..c8826c3f42 100644 --- a/framework/core/src/Install/Steps/EnableBundledExtensions.php +++ b/framework/core/src/Install/Steps/EnableBundledExtensions.php @@ -14,7 +14,7 @@ use Flarum\Extension\Extension; use Flarum\Install\Step; use Flarum\Settings\DatabaseSettingsRepository; -use Illuminate\Database\ConnectionInterface; +use Illuminate\Database\Connection; use Illuminate\Filesystem\FilesystemAdapter; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -41,7 +41,7 @@ class EnableBundledExtensions implements Step ]; /** - * @var ConnectionInterface + * @var Connection */ private $database; @@ -65,7 +65,7 @@ class EnableBundledExtensions implements Step */ private $migrator; - public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null) + public function __construct(Connection $database, $vendorPath, $assetPath, $enabledExtensions = null) { $this->database = $database; $this->vendorPath = $vendorPath; diff --git a/framework/core/src/Install/Steps/PublishAssets.php b/framework/core/src/Install/Steps/PublishAssets.php index f601831c6b..4b321a1a09 100644 --- a/framework/core/src/Install/Steps/PublishAssets.php +++ b/framework/core/src/Install/Steps/PublishAssets.php @@ -10,10 +10,9 @@ namespace Flarum\Install\Steps; use Flarum\Install\ReversibleStep; -use Flarum\Install\Step; use Illuminate\Filesystem\Filesystem; -class PublishAssets implements Step, ReversibleStep +class PublishAssets implements ReversibleStep { /** * @var string diff --git a/framework/core/src/Install/Steps/RunMigrations.php b/framework/core/src/Install/Steps/RunMigrations.php index 32ee13b40f..189c944dbe 100644 --- a/framework/core/src/Install/Steps/RunMigrations.php +++ b/framework/core/src/Install/Steps/RunMigrations.php @@ -12,13 +12,13 @@ use Flarum\Database\DatabaseMigrationRepository; use Flarum\Database\Migrator; use Flarum\Install\Step; -use Illuminate\Database\ConnectionInterface; +use Illuminate\Database\Connection; use Illuminate\Filesystem\Filesystem; class RunMigrations implements Step { /** - * @var ConnectionInterface + * @var Connection */ private $database; @@ -27,7 +27,7 @@ class RunMigrations implements Step */ private $path; - public function __construct(ConnectionInterface $database, $path) + public function __construct(Connection $database, $path) { $this->database = $database; $this->path = $path; diff --git a/framework/core/src/Install/Steps/StoreConfig.php b/framework/core/src/Install/Steps/StoreConfig.php index 63fa75ad6f..e878e6013c 100644 --- a/framework/core/src/Install/Steps/StoreConfig.php +++ b/framework/core/src/Install/Steps/StoreConfig.php @@ -12,9 +12,8 @@ use Flarum\Install\BaseUrl; use Flarum\Install\DatabaseConfig; use Flarum\Install\ReversibleStep; -use Flarum\Install\Step; -class StoreConfig implements Step, ReversibleStep +class StoreConfig implements ReversibleStep { private $debugMode; diff --git a/framework/core/src/Notification/NotificationRepository.php b/framework/core/src/Notification/NotificationRepository.php index dcb7acbd87..867005aafc 100644 --- a/framework/core/src/Notification/NotificationRepository.php +++ b/framework/core/src/Notification/NotificationRepository.php @@ -24,7 +24,8 @@ class NotificationRepository */ public function findByUser(User $user, $limit = null, $offset = 0) { - $primaries = Notification::selectRaw('MAX(id) AS id') + $primaries = Notification::query() + ->selectRaw('MAX(id) AS id') ->selectRaw('SUM(read_at IS NULL) AS unread_count') ->where('user_id', $user->id) ->whereIn('type', $user->getAlertableNotificationTypes()) @@ -35,7 +36,8 @@ public function findByUser(User $user, $limit = null, $offset = 0) ->skip($offset) ->take($limit); - return Notification::select('notifications.*', 'p.unread_count') + return Notification::query() + ->select('notifications.*', 'p.unread_count') ->joinSub($primaries, 'p', 'notifications.id', '=', 'p.id') ->latest() ->get(); diff --git a/framework/core/src/Post/MergeableInterface.php b/framework/core/src/Post/MergeableInterface.php index 6472cc9930..71260c6da7 100644 --- a/framework/core/src/Post/MergeableInterface.php +++ b/framework/core/src/Post/MergeableInterface.php @@ -23,7 +23,7 @@ interface MergeableInterface * passed model. * * @param \Flarum\Post\Post|null $previous - * @return Post The model resulting after the merge. If the merge is + * @return static The model resulting after the merge. If the merge is * unsuccessful, this should be the current model instance. Otherwise, * it should be the model that was merged into. */ diff --git a/framework/core/src/Queue/QueueServiceProvider.php b/framework/core/src/Queue/QueueServiceProvider.php index fd3bd6c2b5..38d075661c 100644 --- a/framework/core/src/Queue/QueueServiceProvider.php +++ b/framework/core/src/Queue/QueueServiceProvider.php @@ -52,7 +52,7 @@ public function register() // Extensions can override this binding if they want to make Flarum use // a different queuing backend. - $this->container->singleton('flarum.queue.connection', function (Container $container) { + $this->container->singleton('flarum.queue.connection', function (\Illuminate\Container\Container $container) { $queue = new SyncQueue; $queue->setContainer($container); @@ -91,7 +91,7 @@ function () use ($config) { $this->container->singleton('cache', function (Container $container) { return new class($container) implements CacheFactory { /** - * @var Container $container + * @var Container */ private $container; diff --git a/framework/core/src/User/Command/RegisterUserHandler.php b/framework/core/src/User/Command/RegisterUserHandler.php index c8b0670106..bde2e44908 100644 --- a/framework/core/src/User/Command/RegisterUserHandler.php +++ b/framework/core/src/User/Command/RegisterUserHandler.php @@ -85,6 +85,7 @@ public function handle(RegisterUser $command) // If a valid authentication token was provided as an attribute, // then we won't require the user to choose a password. if (isset($data['attributes']['token'])) { + /** @var RegistrationToken $token */ $token = RegistrationToken::validOrFail($data['attributes']['token']); $password = $password ?: Str::random(20); diff --git a/framework/core/src/User/RegistrationToken.php b/framework/core/src/User/RegistrationToken.php index 05951be7c7..adf3ade9cc 100644 --- a/framework/core/src/User/RegistrationToken.php +++ b/framework/core/src/User/RegistrationToken.php @@ -21,6 +21,8 @@ * @property array $user_attributes * @property array $payload * @property \Carbon\Carbon $created_at + * + * @method static self validOrFail(string $token) */ class RegistrationToken extends AbstractModel { @@ -74,7 +76,7 @@ public static function generate(string $provider, string $identifier, array $att /** * Find the token with the given ID, and assert that it has not expired. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param \Illuminate\Database\Eloquent\Builder $query * @param string $token * * @throws InvalidConfirmationTokenException diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index 5af55a839c..00bac23a9f 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -296,7 +296,7 @@ public function markNotificationsAsRead() /** * Change the path of the user avatar. * - * @param string $path + * @param string|null $path * @return $this */ public function changeAvatarPath($path) diff --git a/framework/core/src/User/UserRepository.php b/framework/core/src/User/UserRepository.php index 1a898d7b82..46df8ecf66 100644 --- a/framework/core/src/User/UserRepository.php +++ b/framework/core/src/User/UserRepository.php @@ -27,7 +27,7 @@ public function query() * Find a user by ID, optionally making sure it is visible to a certain * user, or throw an exception. * - * @param int $id + * @param int|string $id * @param User|null $actor * @return User * diff --git a/framework/core/src/User/UserServiceProvider.php b/framework/core/src/User/UserServiceProvider.php index d796def1b7..7998f27afb 100644 --- a/framework/core/src/User/UserServiceProvider.php +++ b/framework/core/src/User/UserServiceProvider.php @@ -101,7 +101,6 @@ public function boot(Container $container, Dispatcher $events) /** * @var \Illuminate\Container\Container $container */ - User::setHasher($container->make('hash')); User::setPasswordCheckers($container->make('flarum.user.password_checkers')); User::setGate($container->makeWith(Access\Gate::class, ['policyClasses' => $container->make('flarum.policies')])); diff --git a/framework/core/src/helpers.php b/framework/core/src/helpers.php index 565e911e3a..b97f166161 100644 --- a/framework/core/src/helpers.php +++ b/framework/core/src/helpers.php @@ -16,7 +16,7 @@ * Resolve a service from the container. * * @template T - * @param class-string $name + * @param string|class-string $name * @param array $parameters * @return T|mixed */ diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 7478bc370e..27e583952f 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -9,3 +9,4 @@ parameters: - stubs/Illuminate/Queue/ListenerOptions.stub - stubs/Illuminate/Support/ServiceProvider.stub - stubs/Illuminate/Filesystem/Filesystem.stub + - stubs/Illuminate/Filesystem/FilesystemManager.stub diff --git a/php-packages/phpstan/phpstan-baseline.neon b/php-packages/phpstan/phpstan-baseline.neon index a883f5569a..b285603e63 100644 --- a/php-packages/phpstan/phpstan-baseline.neon +++ b/php-packages/phpstan/phpstan-baseline.neon @@ -1,4 +1,8 @@ parameters: ignoreErrors: -# Remove with larastan 2.0 +# Remove this group below with larastan 2.0 (i.e Flarum 2.0) - "#Relation '[A-z_-]+' is not found in [A-z\_]+ model.#" + - '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:union\(\) expects [A-z_<> .,|\\]+ given\.$#' + - '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:joinSub\(\) expects [A-z_<> .,|\\]+ given\.$#' +# We ignore this because resolve can either take a class name as the generic return type or just a binding name. + - "#Template type T of function resolve[()]{2} is not referenced in a parameter.#" diff --git a/php-packages/phpstan/stubs/Illuminate/Filesystem/FilesystemManager.stub b/php-packages/phpstan/stubs/Illuminate/Filesystem/FilesystemManager.stub new file mode 100644 index 0000000000..a149072f1b --- /dev/null +++ b/php-packages/phpstan/stubs/Illuminate/Filesystem/FilesystemManager.stub @@ -0,0 +1,17 @@ +app = $app; + } +} diff --git a/php-packages/phpstan/stubs/Illuminate/Support/ServiceProvider.stub b/php-packages/phpstan/stubs/Illuminate/Support/ServiceProvider.stub index 366c9d4932..ee3ec4143e 100644 --- a/php-packages/phpstan/stubs/Illuminate/Support/ServiceProvider.stub +++ b/php-packages/phpstan/stubs/Illuminate/Support/ServiceProvider.stub @@ -12,4 +12,12 @@ abstract class ServiceProvider * @var Container */ protected $app; + + /** + * Create a new service provider instance. + * + * @param Container $app + * @return void + */ + public function __construct($app); } diff --git a/phpstan.neon b/phpstan.neon index 7fec5052ae..5c5b81eb4e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,11 +2,9 @@ includes: - php-packages/phpstan/extension.neon parameters: - level: 4 + level: 5 paths: - framework/core/src - ignoreErrors: - - '#PHPDoc tag @var#' excludePaths: - *.blade.php checkMissingIterableValueType: false From 8fd251fe14289fd19ba1b3c140c77255a9f0aa5c Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 23 Jul 2022 21:09:24 +0100 Subject: [PATCH 04/16] chore: add phpstan workflow Signed-off-by: Sami Mazouz --- .github/workflows/REUSABLE_backend.yml | 36 ++++++++++++ .github/workflows/phpstan.yml | 12 ++++ composer.json | 7 ++- php-packages/phpstan/composer.json | 1 - php-packages/phpstan/extension.neon | 1 - php-packages/phpstan/larastan-extension.neon | 62 ++++++++++---------- 6 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/phpstan.yml diff --git a/.github/workflows/REUSABLE_backend.yml b/.github/workflows/REUSABLE_backend.yml index 3d1925fea1..c24cbed33f 100644 --- a/.github/workflows/REUSABLE_backend.yml +++ b/.github/workflows/REUSABLE_backend.yml @@ -9,6 +9,12 @@ on: default: true required: false + enable_phpstan: + description: "Enable PHPStan Static Analysis?" + type: boolean + default: false + required: false + backend_directory: description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo. type: string @@ -110,3 +116,33 @@ jobs: working-directory: ${{ inputs.backend_directory }} env: COMPOSER_PROCESS_TIMEOUT: 600 + + phpstan: + runs-on: ubuntu-latest + + strategy: + matrix: + php: ${{ fromJSON(inputs.php_versions) }} + + name: 'PHPStan PHP ${{ matrix.php }}' + + if: inputs.enable_phpstan + + steps: + - uses: actions/checkout@master + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: xdebug + extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip + tools: phpunit, composer:v2 + ini-values: ${{ inputs.php_ini_values }} + + - name: Install Composer dependencies + run: composer install + working-directory: ${{ inputs.backend_directory }} + + - name: Run PHPStan + run: composer analyse:phpstan diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000000..e0088cfd26 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,12 @@ +name: Framework PHP + +on: [workflow_dispatch, push, pull_request] + +jobs: + run: + uses: ./.github/workflows/REUSABLE_backend.yml + with: + enable_backend_testing: false + enable_phpstan: true + + backend_directory: . diff --git a/composer.json b/composer.json index 8262c55a08..dc3c8ada7e 100644 --- a/composer.json +++ b/composer.json @@ -140,7 +140,6 @@ "require-dev": { "mockery/mockery": "^1.4", "phpunit/phpunit": "^9.0", - "phpstan/phpstan-php-parser": "^1.0", "phpstan/phpstan": "^1.2", "nunomaduro/larastan": "^1.0" }, @@ -179,5 +178,11 @@ "extension.neon" ] } + }, + "scripts": { + "analyse:phpstan": "phpstan analyse" + }, + "scripts-descriptions": { + "analyse:phpstan": "Run static analysis" } } diff --git a/php-packages/phpstan/composer.json b/php-packages/phpstan/composer.json index ce23184452..a5bbee2200 100644 --- a/php-packages/phpstan/composer.json +++ b/php-packages/phpstan/composer.json @@ -4,7 +4,6 @@ "minimum-stability": "dev", "license": "MIT", "require": { - "phpstan/phpstan-php-parser": "^1.0", "phpstan/phpstan": "^1.2", "nunomaduro/larastan": "^1.0" }, diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 27e583952f..8f8b8e6dd4 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -1,5 +1,4 @@ includes: - - vendor/phpstan/phpstan-php-parser/extension.neon - larastan-extension.neon - phpstan-baseline.neon diff --git a/php-packages/phpstan/larastan-extension.neon b/php-packages/phpstan/larastan-extension.neon index 78661d126d..bf75e3c98d 100644 --- a/php-packages/phpstan/larastan-extension.neon +++ b/php-packages/phpstan/larastan-extension.neon @@ -1,36 +1,36 @@ parameters: stubFiles: - - vendor/nunomaduro/larastan/stubs/Enumerable.stub - - vendor/nunomaduro/larastan/stubs/EloquentBuilder.stub - - vendor/nunomaduro/larastan/stubs/Collection.stub - - vendor/nunomaduro/larastan/stubs/EloquentCollection.stub - - vendor/nunomaduro/larastan/stubs/Factory.stub - - vendor/nunomaduro/larastan/stubs/Model.stub - - vendor/nunomaduro/larastan/stubs/Gate.stub - - vendor/nunomaduro/larastan/stubs/Relation.stub - - vendor/nunomaduro/larastan/stubs/BelongsTo.stub - - vendor/nunomaduro/larastan/stubs/BelongsToMany.stub - - vendor/nunomaduro/larastan/stubs/HasOneOrMany.stub - - vendor/nunomaduro/larastan/stubs/HasMany.stub - - vendor/nunomaduro/larastan/stubs/HasOne.stub - - vendor/nunomaduro/larastan/stubs/HasOneThrough.stub - - vendor/nunomaduro/larastan/stubs/HasManyThrough.stub - - vendor/nunomaduro/larastan/stubs/Mailable.stub - - vendor/nunomaduro/larastan/stubs/MorphOne.stub - - vendor/nunomaduro/larastan/stubs/MorphOneOrMany.stub - - vendor/nunomaduro/larastan/stubs/MorphTo.stub - - vendor/nunomaduro/larastan/stubs/MorphToMany.stub - - vendor/nunomaduro/larastan/stubs/MorphMany.stub - - vendor/nunomaduro/larastan/stubs/Helpers.stub - - vendor/nunomaduro/larastan/stubs/HigherOrderProxies.stub - - vendor/nunomaduro/larastan/stubs/QueryBuilder.stub - - vendor/nunomaduro/larastan/stubs/Facades.stub - - vendor/nunomaduro/larastan/stubs/Pagination.stub - - vendor/nunomaduro/larastan/stubs/Contracts/Pagination.stub - - vendor/nunomaduro/larastan/stubs/Contracts/Support.stub - - vendor/nunomaduro/larastan/stubs/Redis/Connection.stub - - vendor/nunomaduro/larastan/stubs/Logger.stub - - vendor/nunomaduro/larastan/stubs/EnumeratesValues.stub + - ../../vendor/nunomaduro/larastan/stubs/Enumerable.stub + - ../../vendor/nunomaduro/larastan/stubs/EloquentBuilder.stub + - ../../vendor/nunomaduro/larastan/stubs/Collection.stub + - ../../vendor/nunomaduro/larastan/stubs/EloquentCollection.stub + - ../../vendor/nunomaduro/larastan/stubs/Factory.stub + - ../../vendor/nunomaduro/larastan/stubs/Model.stub + - ../../vendor/nunomaduro/larastan/stubs/Gate.stub + - ../../vendor/nunomaduro/larastan/stubs/Relation.stub + - ../../vendor/nunomaduro/larastan/stubs/BelongsTo.stub + - ../../vendor/nunomaduro/larastan/stubs/BelongsToMany.stub + - ../../vendor/nunomaduro/larastan/stubs/HasOneOrMany.stub + - ../../vendor/nunomaduro/larastan/stubs/HasMany.stub + - ../../vendor/nunomaduro/larastan/stubs/HasOne.stub + - ../../vendor/nunomaduro/larastan/stubs/HasOneThrough.stub + - ../../vendor/nunomaduro/larastan/stubs/HasManyThrough.stub + - ../../vendor/nunomaduro/larastan/stubs/Mailable.stub + - ../../vendor/nunomaduro/larastan/stubs/MorphOne.stub + - ../../vendor/nunomaduro/larastan/stubs/MorphOneOrMany.stub + - ../../vendor/nunomaduro/larastan/stubs/MorphTo.stub + - ../../vendor/nunomaduro/larastan/stubs/MorphToMany.stub + - ../../vendor/nunomaduro/larastan/stubs/MorphMany.stub + - ../../vendor/nunomaduro/larastan/stubs/Helpers.stub + - ../../vendor/nunomaduro/larastan/stubs/HigherOrderProxies.stub + - ../../vendor/nunomaduro/larastan/stubs/QueryBuilder.stub + - ../../vendor/nunomaduro/larastan/stubs/Facades.stub + - ../../vendor/nunomaduro/larastan/stubs/Pagination.stub + - ../../vendor/nunomaduro/larastan/stubs/Contracts/Pagination.stub + - ../../vendor/nunomaduro/larastan/stubs/Contracts/Support.stub + - ../../vendor/nunomaduro/larastan/stubs/Redis/Connection.stub + - ../../vendor/nunomaduro/larastan/stubs/Logger.stub + - ../../vendor/nunomaduro/larastan/stubs/EnumeratesValues.stub universalObjectCratesClasses: - Illuminate\Http\Request earlyTerminatingFunctionCalls: From 13c3ed777e109be8cbabba1abade92af669a5b2d Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 23 Jul 2022 21:21:51 +0100 Subject: [PATCH 05/16] fix: php7.4 ini_set value should be string Signed-off-by: Sami Mazouz --- framework/core/src/Frontend/Compiler/LessCompiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/core/src/Frontend/Compiler/LessCompiler.php b/framework/core/src/Frontend/Compiler/LessCompiler.php index 9e070205c8..3825215c73 100644 --- a/framework/core/src/Frontend/Compiler/LessCompiler.php +++ b/framework/core/src/Frontend/Compiler/LessCompiler.php @@ -88,7 +88,7 @@ protected function compile(array $sources): string return ''; } - ini_set('xdebug.max_nesting_level', 200); + ini_set('xdebug.max_nesting_level', '200'); $parser = new Less_Parser([ 'compress' => true, From 554bf71091859f8f707ff74ec3e8cedb2787c9f5 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 11:25:49 +0100 Subject: [PATCH 06/16] chore: change Filesystem Factory contract to return Cloud rather than hack every bit of the codebase with a phpdoc @var Signed-off-by: Sami Mazouz --- .../core/src/Api/Serializer/ForumSerializer.php | 3 +-- framework/core/src/Frontend/Assets.php | 10 +++++----- .../src/Frontend/Compiler/RevisionCompiler.php | 13 +++++-------- php-packages/phpstan/extension.neon | 4 ++++ .../Illuminate/Contracts/Filesystem/Cloud.stub | 7 +++++++ .../Illuminate/Contracts/Filesystem/Factory.stub | 14 ++++++++++++++ 6 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Cloud.stub create mode 100644 php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Factory.stub diff --git a/framework/core/src/Api/Serializer/ForumSerializer.php b/framework/core/src/Api/Serializer/ForumSerializer.php index c61f365010..a9b353ca9f 100644 --- a/framework/core/src/Api/Serializer/ForumSerializer.php +++ b/framework/core/src/Api/Serializer/ForumSerializer.php @@ -40,7 +40,7 @@ class ForumSerializer extends AbstractSerializer protected $url; /** - * @var Filesystem + * @var Cloud */ protected $assetsFilesystem; @@ -133,7 +133,6 @@ protected function getFaviconUrl() public function getAssetUrl($assetPath): string { - /** @var Cloud $assetsFilesystem */ $assetsFilesystem = $this->assetsFilesystem; return $assetsFilesystem->url($assetPath); diff --git a/framework/core/src/Frontend/Assets.php b/framework/core/src/Frontend/Assets.php index 95d91f2ea9..d2836abfe8 100644 --- a/framework/core/src/Frontend/Assets.php +++ b/framework/core/src/Frontend/Assets.php @@ -13,7 +13,7 @@ use Flarum\Frontend\Compiler\JsCompiler; use Flarum\Frontend\Compiler\LessCompiler; use Flarum\Frontend\Compiler\Source\SourceCollector; -use Illuminate\Contracts\Filesystem\Filesystem; +use Illuminate\Contracts\Filesystem\Cloud; /** * A factory class for creating frontend asset compilers. @@ -38,7 +38,7 @@ class Assets protected $name; /** - * @var Filesystem + * @var Cloud */ protected $assetsDir; @@ -67,7 +67,7 @@ class Assets */ protected $customFunctions = []; - public function __construct(string $name, Filesystem $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = []) + public function __construct(string $name, Cloud $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = []) { $this->name = $name; $this->assetsDir = $assetsDir; @@ -194,12 +194,12 @@ public function setName(string $name) $this->name = $name; } - public function getAssetsDir(): Filesystem + public function getAssetsDir(): Cloud { return $this->assetsDir; } - public function setAssetsDir(Filesystem $assetsDir) + public function setAssetsDir(Cloud $assetsDir) { $this->assetsDir = $assetsDir; } diff --git a/framework/core/src/Frontend/Compiler/RevisionCompiler.php b/framework/core/src/Frontend/Compiler/RevisionCompiler.php index c7b5229b43..adf2e93050 100644 --- a/framework/core/src/Frontend/Compiler/RevisionCompiler.php +++ b/framework/core/src/Frontend/Compiler/RevisionCompiler.php @@ -11,7 +11,7 @@ use Flarum\Frontend\Compiler\Source\SourceCollector; use Flarum\Frontend\Compiler\Source\SourceInterface; -use Illuminate\Contracts\Filesystem\Filesystem; +use Illuminate\Contracts\Filesystem\Cloud; /** * @internal @@ -21,7 +21,7 @@ class RevisionCompiler implements CompilerInterface const EMPTY_REVISION = 'empty'; /** - * @var Filesystem + * @var Cloud */ protected $assetsDir; @@ -41,11 +41,11 @@ class RevisionCompiler implements CompilerInterface protected $sourcesCallbacks = []; /** - * @param Filesystem $assetsDir + * @param Cloud $assetsDir * @param string $filename * @param VersionerInterface|null $versioner @deprecated nullable will be removed at v2.0 */ - public function __construct(Filesystem $assetsDir, string $filename, VersionerInterface $versioner = null) + public function __construct(Cloud $assetsDir, string $filename, VersionerInterface $versioner = null) { $this->assetsDir = $assetsDir; $this->filename = $filename; @@ -121,10 +121,7 @@ public function getUrl(): ?string return null; } - /** @var \Illuminate\Contracts\Filesystem\Cloud $assetDir */ - $assetDir = $this->assetsDir; - - $url = $assetDir->url($this->filename); + $url = $this->assetsDir->url($this->filename); // Append revision as GET param to signify that there's been // a change to the file and it should be refreshed. diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 8f8b8e6dd4..77dbed38bc 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -9,3 +9,7 @@ parameters: - stubs/Illuminate/Support/ServiceProvider.stub - stubs/Illuminate/Filesystem/Filesystem.stub - stubs/Illuminate/Filesystem/FilesystemManager.stub + + # We're changing the disk return type from Filesystem to Cloud, + # rather than hacking every bit of the codebase with a phpdoc @var. + - stubs/Illuminate/Contracts/Filesystem/Factory.stub diff --git a/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Cloud.stub b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Cloud.stub new file mode 100644 index 0000000000..37e286c27c --- /dev/null +++ b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Cloud.stub @@ -0,0 +1,7 @@ + Date: Sat, 13 Aug 2022 11:31:40 +0100 Subject: [PATCH 07/16] chore: import fully qualified class names Signed-off-by: Sami Mazouz --- framework/core/src/Extend/View.php | 3 ++- framework/core/src/Queue/QueueServiceProvider.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/core/src/Extend/View.php b/framework/core/src/Extend/View.php index 3d42fb4897..1c0d39c8e7 100644 --- a/framework/core/src/Extend/View.php +++ b/framework/core/src/Extend/View.php @@ -13,6 +13,7 @@ use Flarum\Foundation\Paths; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\View\Factory; +use Illuminate\View\Factory as FactoryImplementation; /** * Views are PHP files that use the Laravel Blade syntax for creation of server-side generated HTML. @@ -65,7 +66,7 @@ public function extendNamespace(string $namespace, $hints): self public function extend(Container $container, Extension $extension = null) { - $container->resolving(Factory::class, function (\Illuminate\View\Factory $view) { + $container->resolving(Factory::class, function (FactoryImplementation $view) { foreach ($this->namespaces as $namespace => $hints) { $view->addNamespace($namespace, $hints); } diff --git a/framework/core/src/Queue/QueueServiceProvider.php b/framework/core/src/Queue/QueueServiceProvider.php index 38d075661c..fbf3b37dbb 100644 --- a/framework/core/src/Queue/QueueServiceProvider.php +++ b/framework/core/src/Queue/QueueServiceProvider.php @@ -15,6 +15,7 @@ use Flarum\Foundation\ErrorHandling\Reporter; use Flarum\Foundation\Paths; use Illuminate\Contracts\Cache\Factory as CacheFactory; +use Illuminate\Container\Container as ContainerImplementation; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling; use Illuminate\Contracts\Events\Dispatcher; @@ -52,7 +53,7 @@ public function register() // Extensions can override this binding if they want to make Flarum use // a different queuing backend. - $this->container->singleton('flarum.queue.connection', function (\Illuminate\Container\Container $container) { + $this->container->singleton('flarum.queue.connection', function (ContainerImplementation $container) { $queue = new SyncQueue; $queue->setContainer($container); From e2ca7026477a03d7a17304c53105baab90d66156 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 11:48:35 +0100 Subject: [PATCH 08/16] fix: need to define stub dependencies Signed-off-by: Sami Mazouz --- framework/core/src/Database/DatabaseServiceProvider.php | 4 ++-- php-packages/phpstan/extension.neon | 2 ++ .../stubs/Illuminate/Contracts/Filesystem/Factory.stub | 2 +- .../stubs/Illuminate/Contracts/Filesystem/Filesystem.stub | 7 +++++++ 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Filesystem.stub diff --git a/framework/core/src/Database/DatabaseServiceProvider.php b/framework/core/src/Database/DatabaseServiceProvider.php index 52c23da6f8..a23295a0ac 100644 --- a/framework/core/src/Database/DatabaseServiceProvider.php +++ b/framework/core/src/Database/DatabaseServiceProvider.php @@ -10,6 +10,7 @@ namespace Flarum\Database; use Flarum\Foundation\AbstractServiceProvider; +use Illuminate\Container\Container as ContainerImplementation; use Illuminate\Contracts\Container\Container; use Illuminate\Database\Capsule\Manager; use Illuminate\Database\ConnectionInterface; @@ -22,8 +23,7 @@ class DatabaseServiceProvider extends AbstractServiceProvider */ public function register() { - $this->container->singleton(Manager::class, function (Container $container) { - /** @var \Illuminate\Container\Container $container */ + $this->container->singleton(Manager::class, function (ContainerImplementation $container) { $manager = new Manager($container); $config = $container['flarum']->config('database'); diff --git a/php-packages/phpstan/extension.neon b/php-packages/phpstan/extension.neon index 77dbed38bc..c8950dbaee 100644 --- a/php-packages/phpstan/extension.neon +++ b/php-packages/phpstan/extension.neon @@ -13,3 +13,5 @@ parameters: # We're changing the disk return type from Filesystem to Cloud, # rather than hacking every bit of the codebase with a phpdoc @var. - stubs/Illuminate/Contracts/Filesystem/Factory.stub + - stubs/Illuminate/Contracts/Filesystem/Cloud.stub + - stubs/Illuminate/Contracts/Filesystem/Filesystem.stub diff --git a/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Factory.stub b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Factory.stub index 57c60fd187..fe87edc09f 100644 --- a/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Factory.stub +++ b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Factory.stub @@ -8,7 +8,7 @@ interface Factory * Get a filesystem implementation. * * @param string|null $name - * @return \Illuminate\Contracts\Filesystem\Cloud + * @return Cloud */ public function disk($name = null); } diff --git a/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Filesystem.stub b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Filesystem.stub new file mode 100644 index 0000000000..ea14b17208 --- /dev/null +++ b/php-packages/phpstan/stubs/Illuminate/Contracts/Filesystem/Filesystem.stub @@ -0,0 +1,7 @@ + Date: Sat, 13 Aug 2022 12:21:17 +0100 Subject: [PATCH 09/16] chore: Extension `migrate` method *can* return int Signed-off-by: Sami Mazouz --- framework/core/src/Database/Migrator.php | 2 +- framework/core/src/Extension/ExtensionManager.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 5ee922eab0..82266baf02 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -140,7 +140,7 @@ protected function runUp($path, $file, Extension $extension = null) * Rolls all of the currently applied migrations back. * * @param string $path - * @param Extension $extension + * @param Extension|null $extension * @return int */ public function reset($path, Extension $extension = null) diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php index e368a65dc2..d4ecefed17 100644 --- a/framework/core/src/Extension/ExtensionManager.php +++ b/framework/core/src/Extension/ExtensionManager.php @@ -316,7 +316,7 @@ protected function getAssetsFilesystem(): Cloud * * @param Extension $extension * @param string $direction - * @return void + * @return int * * @internal */ @@ -326,7 +326,7 @@ public function migrate(Extension $extension, $direction = 'up') return $container->make(ConnectionInterface::class)->getSchemaBuilder(); }); - $extension->migrate($this->migrator, $direction); + return $extension->migrate($this->migrator, $direction); } /** From 0485dde0c0d81c36cfa33c9dc01b64b5c8d08dc4 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 15:13:53 +0100 Subject: [PATCH 10/16] chore: allow `static` for now for the sake of extensibility Signed-off-by: Sami Mazouz --- framework/core/src/Database/AbstractModel.php | 2 +- .../core/src/Foundation/ErrorHandling/HandledError.php | 2 +- framework/core/src/Notification/Notification.php | 6 +++--- framework/core/src/User/EmailToken.php | 4 ++-- php-packages/phpstan/phpstan-baseline.neon | 3 +++ 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/framework/core/src/Database/AbstractModel.php b/framework/core/src/Database/AbstractModel.php index e926bcf60d..f61c89c875 100644 --- a/framework/core/src/Database/AbstractModel.php +++ b/framework/core/src/Database/AbstractModel.php @@ -84,7 +84,7 @@ public static function boot() /** * {@inheritdoc} */ - final public function __construct(array $attributes = []) + public function __construct(array $attributes = []) { $this->attributes = []; diff --git a/framework/core/src/Foundation/ErrorHandling/HandledError.php b/framework/core/src/Foundation/ErrorHandling/HandledError.php index 8ef07a6d5c..026d1b13e6 100644 --- a/framework/core/src/Foundation/ErrorHandling/HandledError.php +++ b/framework/core/src/Foundation/ErrorHandling/HandledError.php @@ -28,7 +28,7 @@ class HandledError public static function unknown(Throwable $error) { - return new self($error, 'unknown', 500); + return new static($error, 'unknown', 500); } public function __construct(Throwable $error, $type, $statusCode) diff --git a/framework/core/src/Notification/Notification.php b/framework/core/src/Notification/Notification.php index 765a1ef25d..2c6e8821c3 100644 --- a/framework/core/src/Notification/Notification.php +++ b/framework/core/src/Notification/Notification.php @@ -209,7 +209,7 @@ public function scopeWhereSubjectModel(Builder $query, string $class) */ public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $blueprint) { - return $query->where(self::getBlueprintAttributes($blueprint)); + return $query->where(static::getBlueprintAttributes($blueprint)); } /** @@ -220,7 +220,7 @@ public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $bluep */ public static function notify(array $recipients, BlueprintInterface $blueprint) { - $attributes = self::getBlueprintAttributes($blueprint); + $attributes = static::getBlueprintAttributes($blueprint); $now = Carbon::now()->toDateTimeString(); static::insert( @@ -256,7 +256,7 @@ public static function setSubjectModel($type, $subjectModel) static::$subjectModels[$type] = $subjectModel; } - private static function getBlueprintAttributes(BlueprintInterface $blueprint): array + protected static function getBlueprintAttributes(BlueprintInterface $blueprint): array { return [ 'type' => $blueprint::getType(), diff --git a/framework/core/src/User/EmailToken.php b/framework/core/src/User/EmailToken.php index 77dd3a7523..39313cb09f 100644 --- a/framework/core/src/User/EmailToken.php +++ b/framework/core/src/User/EmailToken.php @@ -76,12 +76,12 @@ public function user() * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $id - * @return self + * @return static * @throws InvalidConfirmationTokenException */ public function scopeValidOrFail($query, $id) { - /** @var EmailToken|null $token */ + /** @var static|null $token */ $token = $query->find($id); if (! $token || $token->created_at->diffInDays() >= 1) { diff --git a/php-packages/phpstan/phpstan-baseline.neon b/php-packages/phpstan/phpstan-baseline.neon index b285603e63..62a115ae70 100644 --- a/php-packages/phpstan/phpstan-baseline.neon +++ b/php-packages/phpstan/phpstan-baseline.neon @@ -6,3 +6,6 @@ parameters: - '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:joinSub\(\) expects [A-z_<> .,|\\]+ given\.$#' # We ignore this because resolve can either take a class name as the generic return type or just a binding name. - "#Template type T of function resolve[()]{2} is not referenced in a parameter.#" +# We ignore new static errors because we want extensibility. +# @TODO: needs discussion. + - "#^Unsafe usage of new static[()]{2}.$#" From f234e67733009d198f41b8fa3878885e1a782e9a Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 16:00:46 +0100 Subject: [PATCH 11/16] chore: revert injection of `Connection` instead of `ConnectionInterface` ignore for now. Signed-off-by: Sami Mazouz --- .../src/Database/DatabaseMigrationRepository.php | 8 ++++---- framework/core/src/Database/Migrator.php | 6 +++--- framework/core/src/Discussion/Discussion.php | 3 +++ .../core/src/Foundation/Console/InfoCommand.php | 6 +++--- .../core/src/Frontend/Compiler/JsCompiler.php | 5 +---- framework/core/src/Install/Installation.php | 2 +- .../src/Install/Steps/EnableBundledExtensions.php | 6 +++--- framework/core/src/Install/Steps/RunMigrations.php | 6 +++--- framework/core/src/Post/Post.php | 6 +++--- framework/core/src/User/User.php | 1 - php-packages/phpstan/phpstan-baseline.neon | 14 ++++++++++---- 11 files changed, 34 insertions(+), 29 deletions(-) diff --git a/framework/core/src/Database/DatabaseMigrationRepository.php b/framework/core/src/Database/DatabaseMigrationRepository.php index 7e6ba84301..04f32e5d42 100644 --- a/framework/core/src/Database/DatabaseMigrationRepository.php +++ b/framework/core/src/Database/DatabaseMigrationRepository.php @@ -9,14 +9,14 @@ namespace Flarum\Database; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; class DatabaseMigrationRepository implements MigrationRepositoryInterface { /** * The name of the database connection to use. * - * @var Connection + * @var ConnectionInterface */ protected $connection; @@ -30,10 +30,10 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface /** * Create a new database migration repository instance. * - * @param Connection $connection + * @param ConnectionInterface $connection * @param string $table */ - public function __construct(Connection $connection, $table) + public function __construct(ConnectionInterface $connection, $table) { $this->connection = $connection; $this->table = $table; diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 82266baf02..1a3119360d 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -11,7 +11,7 @@ use Exception; use Flarum\Extension\Extension; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; use Illuminate\Database\MySqlConnection; use Illuminate\Filesystem\Filesystem; use InvalidArgumentException; @@ -44,7 +44,7 @@ class Migrator protected $output; /** - * @var Connection + * @var ConnectionInterface */ protected $connection; @@ -53,7 +53,7 @@ class Migrator */ public function __construct( MigrationRepositoryInterface $repository, - Connection $connection, + ConnectionInterface $connection, Filesystem $files ) { $this->files = $files; diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index f4c00d2f84..132648425b 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -395,6 +395,9 @@ public function readers() * If no user is passed (i.e. in the case of eager loading the 'state' * relation), then the static `$stateUser` property is used. * + * @param User|null $user + * @return HasOne + * * @see Discussion::setStateUser() */ public function state(User $user = null): HasOne diff --git a/framework/core/src/Foundation/Console/InfoCommand.php b/framework/core/src/Foundation/Console/InfoCommand.php index f131f6bc40..383710bd5a 100644 --- a/framework/core/src/Foundation/Console/InfoCommand.php +++ b/framework/core/src/Foundation/Console/InfoCommand.php @@ -15,7 +15,7 @@ use Flarum\Foundation\Config; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Queue\Queue; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; use Illuminate\Support\Str; use PDO; use Symfony\Component\Console\Helper\Table; @@ -39,7 +39,7 @@ class InfoCommand extends AbstractCommand protected $settings; /** - * @var Connection + * @var ConnectionInterface */ protected $db; @@ -52,7 +52,7 @@ public function __construct( ExtensionManager $extensions, Config $config, SettingsRepositoryInterface $settings, - Connection $db, + ConnectionInterface $db, Queue $queue ) { $this->extensions = $extensions; diff --git a/framework/core/src/Frontend/Compiler/JsCompiler.php b/framework/core/src/Frontend/Compiler/JsCompiler.php index ddb3b0bc88..c9c4510a77 100644 --- a/framework/core/src/Frontend/Compiler/JsCompiler.php +++ b/framework/core/src/Frontend/Compiler/JsCompiler.php @@ -49,13 +49,10 @@ protected function save(string $file, array $sources): bool $line += substr_count($content, "\n") + 1; } - /** @var \Illuminate\Contracts\Filesystem\Cloud $assetsDir */ - $assetsDir = $this->assetsDir; - // Add a comment to the end of our file to point to the sourcemap // we just constructed. We will then store the JS file and the map // in our asset directory. - $output[] = '//# sourceMappingURL='.$assetsDir->url($mapFile); + $output[] = '//# sourceMappingURL='.$this->assetsDir->url($mapFile); $this->assetsDir->put($file, implode("\n", $output)); $this->assetsDir->put($mapFile, json_encode($map, JSON_UNESCAPED_SLASHES)); diff --git a/framework/core/src/Install/Installation.php b/framework/core/src/Install/Installation.php index b83fba5fb8..243614da01 100644 --- a/framework/core/src/Install/Installation.php +++ b/framework/core/src/Install/Installation.php @@ -36,7 +36,7 @@ class Installation // Could also be local variables in build(), but this way // access in closures is easier. :) - /** @var \Illuminate\Database\Connection */ + /** @var \Illuminate\Database\ConnectionInterface */ private $db; public function __construct(Paths $paths) diff --git a/framework/core/src/Install/Steps/EnableBundledExtensions.php b/framework/core/src/Install/Steps/EnableBundledExtensions.php index c8826c3f42..5abcdf14e8 100644 --- a/framework/core/src/Install/Steps/EnableBundledExtensions.php +++ b/framework/core/src/Install/Steps/EnableBundledExtensions.php @@ -14,7 +14,7 @@ use Flarum\Extension\Extension; use Flarum\Install\Step; use Flarum\Settings\DatabaseSettingsRepository; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; use Illuminate\Filesystem\FilesystemAdapter; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -41,7 +41,7 @@ class EnableBundledExtensions implements Step ]; /** - * @var Connection + * @var ConnectionInterface */ private $database; @@ -65,7 +65,7 @@ class EnableBundledExtensions implements Step */ private $migrator; - public function __construct(Connection $database, $vendorPath, $assetPath, $enabledExtensions = null) + public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null) { $this->database = $database; $this->vendorPath = $vendorPath; diff --git a/framework/core/src/Install/Steps/RunMigrations.php b/framework/core/src/Install/Steps/RunMigrations.php index 189c944dbe..32ee13b40f 100644 --- a/framework/core/src/Install/Steps/RunMigrations.php +++ b/framework/core/src/Install/Steps/RunMigrations.php @@ -12,13 +12,13 @@ use Flarum\Database\DatabaseMigrationRepository; use Flarum\Database\Migrator; use Flarum\Install\Step; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; use Illuminate\Filesystem\Filesystem; class RunMigrations implements Step { /** - * @var Connection + * @var ConnectionInterface */ private $database; @@ -27,7 +27,7 @@ class RunMigrations implements Step */ private $path; - public function __construct(Connection $database, $path) + public function __construct(ConnectionInterface $database, $path) { $this->database = $database; $this->path = $path; diff --git a/framework/core/src/Post/Post.php b/framework/core/src/Post/Post.php index 9866bfe493..1b8423346c 100644 --- a/framework/core/src/Post/Post.php +++ b/framework/core/src/Post/Post.php @@ -16,7 +16,7 @@ use Flarum\Notification\Notification; use Flarum\Post\Event\Deleted; use Flarum\User\User; -use Illuminate\Database\Connection; +use Illuminate\Database\ConnectionInterface; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Expression; @@ -94,8 +94,8 @@ public static function boot() static::creating(function (self $post) { $post->type = $post::$type; - /** @var Connection $db */ - $db = static::getConnectionResolver(); + $db = static::getConnectionResolver()->connection(); + $post->number = new Expression('('. $db->table('posts', 'pn') ->whereRaw($db->getTablePrefix().'pn.discussion_id = '.intval($post->discussion_id)) diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index 00bac23a9f..17fab1e23d 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -317,7 +317,6 @@ public function changeAvatarPath($path) public function getAvatarUrlAttribute(string $value = null) { if ($value && strpos($value, '://') === false) { - /** @var \Illuminate\Contracts\Filesystem\Cloud $disk */ $disk = resolve(Factory::class)->disk('flarum-avatars'); return $disk->url($value); diff --git a/php-packages/phpstan/phpstan-baseline.neon b/php-packages/phpstan/phpstan-baseline.neon index 62a115ae70..6a0b138829 100644 --- a/php-packages/phpstan/phpstan-baseline.neon +++ b/php-packages/phpstan/phpstan-baseline.neon @@ -1,11 +1,17 @@ parameters: ignoreErrors: -# Remove this group below with larastan 2.0 (i.e Flarum 2.0) + # Remove this group below with larastan 2.0 (i.e Flarum 2.0) - "#Relation '[A-z_-]+' is not found in [A-z\_]+ model.#" - '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:union\(\) expects [A-z_<> .,|\\]+ given\.$#' - '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:joinSub\(\) expects [A-z_<> .,|\\]+ given\.$#' -# We ignore this because resolve can either take a class name as the generic return type or just a binding name. + + # We ignore this because resolve can either take a class name as the generic return type or just a binding name. - "#Template type T of function resolve[()]{2} is not referenced in a parameter.#" -# We ignore new static errors because we want extensibility. -# @TODO: needs discussion. + + # We ignore new static errors because we want extensibility. + # @TODO: needs discussion. - "#^Unsafe usage of new static[()]{2}.$#" + + # ConnectionInterface lacks methods that exist in the implementation, + # yet we don't want to inject the implementation. + - '#^Call to an undefined method Illuminate\\Database\\ConnectionInterface\:\:[A-z0-9_]+\(\)\.$#' From cce1580b8ed13aaf45b9cbec3d6eb920cb1ca8a6 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 13 Aug 2022 15:02:21 +0000 Subject: [PATCH 12/16] Apply fixes from StyleCI --- framework/core/src/Api/Serializer/ForumSerializer.php | 1 - framework/core/src/Post/Post.php | 1 - framework/core/src/Queue/QueueServiceProvider.php | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/core/src/Api/Serializer/ForumSerializer.php b/framework/core/src/Api/Serializer/ForumSerializer.php index b601a04403..6b23d61439 100644 --- a/framework/core/src/Api/Serializer/ForumSerializer.php +++ b/framework/core/src/Api/Serializer/ForumSerializer.php @@ -15,7 +15,6 @@ use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Filesystem\Cloud; use Illuminate\Contracts\Filesystem\Factory; -use Illuminate\Contracts\Filesystem\Filesystem; class ForumSerializer extends AbstractSerializer { diff --git a/framework/core/src/Post/Post.php b/framework/core/src/Post/Post.php index 1b8423346c..bdabe071e1 100644 --- a/framework/core/src/Post/Post.php +++ b/framework/core/src/Post/Post.php @@ -16,7 +16,6 @@ use Flarum\Notification\Notification; use Flarum\Post\Event\Deleted; use Flarum\User\User; -use Illuminate\Database\ConnectionInterface; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Expression; diff --git a/framework/core/src/Queue/QueueServiceProvider.php b/framework/core/src/Queue/QueueServiceProvider.php index bc2c3723c6..b813b62d7c 100644 --- a/framework/core/src/Queue/QueueServiceProvider.php +++ b/framework/core/src/Queue/QueueServiceProvider.php @@ -14,8 +14,8 @@ use Flarum\Foundation\ErrorHandling\Registry; use Flarum\Foundation\ErrorHandling\Reporter; use Flarum\Foundation\Paths; -use Illuminate\Contracts\Cache\Factory as CacheFactory; use Illuminate\Container\Container as ContainerImplementation; +use Illuminate\Contracts\Cache\Factory as CacheFactory; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling; use Illuminate\Contracts\Events\Dispatcher; From e2a4b012329b650a7cbaf190bdb22c87adfb0bda Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 16:13:49 +0100 Subject: [PATCH 13/16] chore: fix issues after main merge Signed-off-by: Sami Mazouz --- framework/core/src/Notification/Event/DeletedAll.php | 2 +- framework/core/src/Notification/Notification.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/core/src/Notification/Event/DeletedAll.php b/framework/core/src/Notification/Event/DeletedAll.php index 8d202eb7cb..84eb20fdcf 100644 --- a/framework/core/src/Notification/Event/DeletedAll.php +++ b/framework/core/src/Notification/Event/DeletedAll.php @@ -26,7 +26,7 @@ class DeletedAll public function __construct(User $user, DateTime $timestamp) { - $this->user = $user; + $this->actor = $user; $this->timestamp = $timestamp; } } diff --git a/framework/core/src/Notification/Notification.php b/framework/core/src/Notification/Notification.php index 11c3fab99b..91da2c6c8c 100644 --- a/framework/core/src/Notification/Notification.php +++ b/framework/core/src/Notification/Notification.php @@ -76,7 +76,7 @@ public function read() * When getting the data attribute, unserialize the JSON stored in the * database into a plain array. * - * @param string $value + * @param string|null $value * @return mixed */ public function getDataAttribute($value) From df08d7ee4f239203440ee7d3061373c23a378fe0 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Sat, 13 Aug 2022 20:29:34 +0100 Subject: [PATCH 14/16] chore: adapt workflow to recent changes Signed-off-by: Sami Mazouz --- .github/workflows/REUSABLE_backend.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/REUSABLE_backend.yml b/.github/workflows/REUSABLE_backend.yml index 505e05a924..c45928c09d 100644 --- a/.github/workflows/REUSABLE_backend.yml +++ b/.github/workflows/REUSABLE_backend.yml @@ -146,7 +146,9 @@ jobs: name: 'PHPStan PHP ${{ matrix.php }}' - if: inputs.enable_phpstan + if: >- + inputs.enable_phpstan && + ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request') steps: - uses: actions/checkout@master From 5c5ffd63a5ab50d43db46e30b11ab14681884b58 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Wed, 31 Aug 2022 15:56:54 +0100 Subject: [PATCH 15/16] fix: adapt after new changes from main branch Signed-off-by: Sami Mazouz --- framework/core/src/Admin/Content/AdminPayload.php | 5 ----- framework/core/src/Discussion/Discussion.php | 2 +- framework/core/src/Discussion/Utf8SlugDriver.php | 12 ++++++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/framework/core/src/Admin/Content/AdminPayload.php b/framework/core/src/Admin/Content/AdminPayload.php index e31f89fe76..ef570b0b7e 100644 --- a/framework/core/src/Admin/Content/AdminPayload.php +++ b/framework/core/src/Admin/Content/AdminPayload.php @@ -54,11 +54,6 @@ class AdminPayload */ protected $config; - /** - * @var Dispatcher - */ - protected $events; - /** * @param Container $container * @param SettingsRepositoryInterface $settings diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index bf26e15811..22e602aff2 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -225,8 +225,8 @@ public function setLastPost(Post $post) */ public function refreshLastPost() { - /** @var Post $lastPost */ if ($lastPost = $this->comments()->latest()->first()) { + /** @var Post $lastPost */ $this->setLastPost($lastPost); } diff --git a/framework/core/src/Discussion/Utf8SlugDriver.php b/framework/core/src/Discussion/Utf8SlugDriver.php index b84facbbe0..d0467df49b 100644 --- a/framework/core/src/Discussion/Utf8SlugDriver.php +++ b/framework/core/src/Discussion/Utf8SlugDriver.php @@ -13,6 +13,9 @@ use Flarum\Http\SlugDriverInterface; use Flarum\User\User; +/** + * @implements SlugDriverInterface + */ class Utf8SlugDriver implements SlugDriverInterface { /** @@ -25,6 +28,10 @@ public function __construct(DiscussionRepository $discussions) $this->discussions = $discussions; } + /** + * @param Discussion $instance + * @return string + */ public function toSlug(AbstractModel $instance): string { $slug = preg_replace('/[-\s]+/u', '-', $instance->title); @@ -34,6 +41,11 @@ public function toSlug(AbstractModel $instance): string return $instance->id.(trim($slug) ? '-'.$slug : ''); } + /** + * @param string $slug + * @param User $actor + * @return Discussion + */ public function fromSlug(string $slug, User $actor): AbstractModel { if (strpos($slug, '-')) { From bf4a9495deae0d7c2ffb49b8649bc23d9578df6a Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Wed, 7 Sep 2022 13:50:16 +0100 Subject: [PATCH 16/16] chore(review): review comments Signed-off-by: Sami Mazouz --- framework/core/src/Api/Serializer/ForumSerializer.php | 4 +--- framework/core/src/Discussion/DiscussionRepository.php | 2 +- framework/core/src/User/User.php | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/framework/core/src/Api/Serializer/ForumSerializer.php b/framework/core/src/Api/Serializer/ForumSerializer.php index 6b23d61439..44e89d26ab 100644 --- a/framework/core/src/Api/Serializer/ForumSerializer.php +++ b/framework/core/src/Api/Serializer/ForumSerializer.php @@ -133,8 +133,6 @@ protected function getFaviconUrl() public function getAssetUrl($assetPath): string { - $assetsFilesystem = $this->assetsFilesystem; - - return $assetsFilesystem->url($assetPath); + return $this->assetsFilesystem->url($assetPath); } } diff --git a/framework/core/src/Discussion/DiscussionRepository.php b/framework/core/src/Discussion/DiscussionRepository.php index 7af6e62bb7..87793f5b7a 100644 --- a/framework/core/src/Discussion/DiscussionRepository.php +++ b/framework/core/src/Discussion/DiscussionRepository.php @@ -59,7 +59,7 @@ public function getReadIds(User $user) */ public function getReadIdsQuery(User $user): Builder { - return Discussion::query() + return $this->query() ->leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id') ->where('discussion_user.user_id', $user->id) ->whereColumn('last_read_post_number', '>=', 'last_post_number') diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index 41e1c4f48d..4231328b6d 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -317,9 +317,7 @@ public function changeAvatarPath($path) public function getAvatarUrlAttribute(string $value = null) { if ($value && strpos($value, '://') === false) { - $disk = resolve(Factory::class)->disk('flarum-avatars'); - - return $disk->url($value); + return resolve(Factory::class)->disk('flarum-avatars')->url($value); } return $value;