From 1c5958c9b60480fd89c73ecb1466661736b3c176 Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Mon, 1 Apr 2024 19:16:42 +0200 Subject: [PATCH] fix(sca): fix type system with legacy FactoryCollection --- phpstan-baseline.neon | 33 ++++++++++++++-- src/Factory.php | 12 +++--- src/FactoryCollection.php | 2 +- src/ModelFactory.php | 19 ++++++++- src/Persistence/ProxyRepositoryDecorator.php | 2 +- src/Persistence/RepositoryDecorator.php | 2 +- utils/phpstan/tests/FoundryRuleTest.php | 41 ++++++++++++++++++++ utils/rector/composer.json | 2 +- 8 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 utils/phpstan/tests/FoundryRuleTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 81436056..4ede1fe7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -16,7 +16,12 @@ parameters: path: src/Configuration.php - - message: "#^Method Zenstruck\\\\Foundry\\\\Factory\\:\\:createAndUproxify\\(\\) should return TObject of object but returns object\\.$#" + message: "#^Method Zenstruck\\\\Foundry\\\\Factory\\:\\:__call\\(\\) should return array\\\\> but returns array\\\\|Zenstruck\\\\Foundry\\\\Proxy\\\\>\\>\\.$#" + count: 1 + path: src/Factory.php + + - + message: "#^Method Zenstruck\\\\Foundry\\\\Factory\\:\\:createAndUnproxify\\(\\) should return TObject of object but returns object\\.$#" count: 1 path: src/Factory.php @@ -26,7 +31,7 @@ parameters: path: src/Factory.php - - message: "#^Method Zenstruck\\\\Foundry\\\\FactoryCollection\\:\\:create\\(\\) should return array\\ but returns array\\, \\(TObject of object\\)\\|Zenstruck\\\\Foundry\\\\Persistence\\\\Proxy\\\\>\\.$#" + message: "#^Method Zenstruck\\\\Foundry\\\\FactoryCollection\\:\\:create\\(\\) should return array\\\\> but returns array\\, \\(TObject of object\\)\\|Zenstruck\\\\Foundry\\\\Persistence\\\\Proxy\\\\>\\.$#" count: 1 path: src/FactoryCollection.php @@ -56,12 +61,12 @@ parameters: path: src/Instantiator.php - - message: "#^Method Zenstruck\\\\Foundry\\\\ObjectFactory\\:\\:__callStatic\\(\\) should return array\\ but returns array\\\\>\\.$#" + message: "#^Method Zenstruck\\\\Foundry\\\\ObjectFactory\\:\\:__callStatic\\(\\) should return array\\ but returns array\\\\|Zenstruck\\\\Foundry\\\\Proxy\\\\>\\>\\.$#" count: 1 path: src/ObjectFactory.php - - message: "#^Method Zenstruck\\\\Foundry\\\\ObjectFactory\\:\\:createSequence\\(\\) should return array\\ but returns array\\\\>\\.$#" + message: "#^Method Zenstruck\\\\Foundry\\\\ObjectFactory\\:\\:createSequence\\(\\) should return array\\ but returns array\\\\|Zenstruck\\\\Foundry\\\\Proxy\\\\>\\>\\.$#" count: 1 path: src/ObjectFactory.php @@ -75,6 +80,16 @@ parameters: count: 1 path: src/ObjectFactory.php + - + message: "#^Method Zenstruck\\\\Foundry\\\\Persistence\\\\PersistentProxyObjectFactory\\:\\:__callStatic\\(\\) should return array\\\\> but returns array\\\\>\\>\\.$#" + count: 1 + path: src/Persistence/PersistentProxyObjectFactory.php + + - + message: "#^Method Zenstruck\\\\Foundry\\\\Persistence\\\\PersistentProxyObjectFactory\\:\\:createSequence\\(\\) should return array\\\\> but returns array\\\\>\\>\\.$#" + count: 1 + path: src/Persistence/PersistentProxyObjectFactory.php + - message: "#^Should not use function \"debug_backtrace\", please change the code\\.$#" count: 1 @@ -149,3 +164,13 @@ parameters: message: "#^Parameter \\#1 \\$configuration of static method Zenstruck\\\\Foundry\\\\Factory\\\\:\\:boot\\(\\) expects Zenstruck\\\\Foundry\\\\Configuration, object\\|null given\\.$#" count: 1 path: src/ZenstruckFoundryBundle.php + + - + message: "#^Function Zenstruck\\\\Foundry\\\\create_many\\(\\) should return array\\\\> but returns array\\\\>\\>\\.$#" + count: 1 + path: src/functions.php + + - + message: "#^Function Zenstruck\\\\Foundry\\\\instantiate_many\\(\\) should return array\\\\> but returns array\\\\>\\>\\.$#" + count: 1 + path: src/functions.php diff --git a/src/Factory.php b/src/Factory.php index be480df9..a9fd7a86 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -383,7 +383,7 @@ final public static function delayFlush(callable $callback): mixed * * @return TObject */ - public function createAndUproxify(): object + public function createAndUnproxify(): object { $object = $this->create( noProxy: !$this->shouldUseProxy(), @@ -469,7 +469,7 @@ private function normalizeAttribute(mixed $value, string $name): mixed } if (!self::configuration()->hasManagerRegistry()) { - return $value->createAndUproxify(); + return $value->createAndUnproxify(); } try { @@ -477,17 +477,17 @@ private function normalizeAttribute(mixed $value, string $name): mixed if (!$objectManager instanceof EntityManagerInterface || $objectManager->getClassMetadata($value->class)->isEmbeddedClass) { // we may deal with ODM document or ORM\Embedded - return $value->createAndUproxify(); + return $value->createAndUnproxify(); } } catch (\Throwable) { // not persisted object - return $value->createAndUproxify(); + return $value->createAndUnproxify(); } $relationshipMetadata = self::getRelationshipMetadata($objectManager, $this->class, $name); if (!$relationshipMetadata) { - return $value->createAndUproxify(); + return $value->createAndUnproxify(); } if ($relationshipMetadata['isOwningSide']) { @@ -506,7 +506,7 @@ private function normalizeAttribute(mixed $value, string $name): mixed $value = $value->withCascadePersist(); } - return $value->createAndUproxify(); + return $value->createAndUnproxify(); } private static function normalizeObject(object $object): object diff --git a/src/FactoryCollection.php b/src/FactoryCollection.php index 3a5fd624..a9d49aee 100644 --- a/src/FactoryCollection.php +++ b/src/FactoryCollection.php @@ -75,7 +75,7 @@ public static function sequence(Factory $factory, iterable $sequence): self } /** - * @return list + * @return ($noProxy is true ? list : list>) */ public function create( array|callable $attributes = [], diff --git a/src/ModelFactory.php b/src/ModelFactory.php index 62592088..fa1a7571 100644 --- a/src/ModelFactory.php +++ b/src/ModelFactory.php @@ -21,11 +21,26 @@ * * @method static Proxy[]|TModel[] createMany(int $number, array|callable $attributes = []) * - * @phpstan-method FactoryCollection> sequence(iterable>|callable(): iterable> $sequence) - * @phpstan-method FactoryCollection> many(int $min, int|null $max = null) + * @phpstan-method Proxy create(array|callable $attributes = []) + * @phpstan-method static Proxy createOne(array $attributes = []) + * @phpstan-method static Proxy find(object|array|mixed $criteria) + * @phpstan-method static Proxy findOrCreate(array $attributes) + * @phpstan-method static Proxy first(string $sortedField = 'id') + * @phpstan-method static Proxy last(string $sortedField = 'id') + * @phpstan-method static Proxy random(array $attributes = []) + * @phpstan-method static Proxy randomOrCreate(array $attributes = []) * + * @phpstan-method FactoryCollection sequence(iterable>|callable(): iterable> $sequence) + * @phpstan-method FactoryCollection many(int $min, int|null $max = null) + * + * @phpstan-method static list> all() * @phpstan-method static list> createSequence(iterable>|callable(): iterable> $sequence) * @phpstan-method static list> createMany(int $number, array|callable $attributes = []) + * @phpstan-method static list> createMany(int $number, array|callable $attributes = []) + * @phpstan-method static list> createSequence(array|callable $sequence) + * @phpstan-method static list> findBy(array $attributes) + * @phpstan-method static list> randomRange(int $min, int $max, array $attributes = []) + * @phpstan-method static list> randomSet(int $number, array $attributes = []) * * @author Kevin Bond * diff --git a/src/Persistence/ProxyRepositoryDecorator.php b/src/Persistence/ProxyRepositoryDecorator.php index 1a071461..1b738acf 100644 --- a/src/Persistence/ProxyRepositoryDecorator.php +++ b/src/Persistence/ProxyRepositoryDecorator.php @@ -301,7 +301,7 @@ public function find($criteria) } if ($attributeValue instanceof Factory) { - $attributeValue = $attributeValue->withoutPersisting()->createAndUproxify(); + $attributeValue = $attributeValue->withoutPersisting()->createAndUnproxify(); } elseif ($attributeValue instanceof Proxy) { $attributeValue = $attributeValue->_real(); } diff --git a/src/Persistence/RepositoryDecorator.php b/src/Persistence/RepositoryDecorator.php index e1c6e120..387fb108 100644 --- a/src/Persistence/RepositoryDecorator.php +++ b/src/Persistence/RepositoryDecorator.php @@ -217,7 +217,7 @@ public function find($criteria) } if ($attributeValue instanceof Factory) { - $attributeValue = $attributeValue->withoutPersisting()->createAndUproxify(); + $attributeValue = $attributeValue->withoutPersisting()->createAndUnproxify(); } elseif ($attributeValue instanceof Proxy) { $attributeValue = $attributeValue->_real(); } diff --git a/utils/phpstan/tests/FoundryRuleTest.php b/utils/phpstan/tests/FoundryRuleTest.php new file mode 100644 index 00000000..4b4cc9f2 --- /dev/null +++ b/utils/phpstan/tests/FoundryRuleTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Zenstruck\Foundry\Tests\PhpStan; + +use PHPStan\Testing\TypeInferenceTestCase; + +final class FoundryRuleTest extends TypeInferenceTestCase +{ + /** + * @return iterable + */ + public function typesProvider(): iterable + { + yield from $this->gatherAssertTypes(__DIR__.'/test-types.php'); + } + + /** + * @test + * @dataProvider typesProvider + */ + public function it_can_resolve_tests(string $assertType, string $file, mixed ...$args): void + { + $this->assertFileAsserts($assertType, $file, ...$args); + } + + public static function getAdditionalConfigFiles(): array + { + return [__DIR__.'/../../phpstan-foundry.neon']; + } +} diff --git a/utils/rector/composer.json b/utils/rector/composer.json index 57d34742..2a970b6d 100644 --- a/utils/rector/composer.json +++ b/utils/rector/composer.json @@ -20,7 +20,7 @@ "rector/rector": "^1.0", "phpunit/phpunit": "^10.5", "phpstan/phpstan-doctrine": "^1.3", - "zenstruck/foundry": "dev-1.x-bc", + "zenstruck/foundry": "1.x-dev", "symfony/var-dumper": "^7.0", "doctrine/orm": "^2.17", "symfony/framework-bundle": "^7.0",