From ab9cdcf8c3afaf344e98299341896c3b49b34ce8 Mon Sep 17 00:00:00 2001 From: Jan Skrasek Date: Mon, 8 Mar 2021 23:11:17 +0100 Subject: [PATCH] update phpstan: fix generics & add more safety checks --- composer.json | 2 +- src/Bridges/NetteDI/OrmExtension.php | 5 +++-- src/Entity/Reflection/PropertyMetadata.php | 7 ++++--- src/Mapper/Dbal/Conventions/Conventions.php | 3 ++- src/Model/IModel.php | 5 +++-- src/Model/Model.php | 3 ++- src/Repository/Repository.php | 4 +++- 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index e7a92cd8..c60b5621 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "marc-mabe/php-enum": "~3.0", "mockery/mockery": "~1.2", "phpstan/extension-installer": "1.1.0", - "phpstan/phpstan": "0.12.71", + "phpstan/phpstan": "0.12.81", "phpstan/phpstan-deprecation-rules": "0.12.6", "phpstan/phpstan-nette": "0.12.14", "phpstan/phpstan-mockery": "0.12.12", diff --git a/src/Bridges/NetteDI/OrmExtension.php b/src/Bridges/NetteDI/OrmExtension.php index 84600c2d..b67c9da3 100644 --- a/src/Bridges/NetteDI/OrmExtension.php +++ b/src/Bridges/NetteDI/OrmExtension.php @@ -13,6 +13,7 @@ use Nextras\Orm\Mapper\Dbal\DbalMapperCoordinator; use Nextras\Orm\Model\MetadataStorage; use Nextras\Orm\Model\Model; +use function is_subclass_of; use function method_exists; @@ -40,10 +41,10 @@ public function loadConfiguration() $this->modelClass = $config['model']; $repositoryFinderClass = $config['repositoryFinder']; - $this->repositoryFinder = new $repositoryFinderClass($this->modelClass, $this->builder, $this); - if (!$this->repositoryFinder instanceof IRepositoryFinder) { + if (!is_subclass_of($repositoryFinderClass, IRepositoryFinder::class)) { throw new InvalidStateException('Repository finder does not implement Nextras\Orm\Bridges\NetteDI\IRepositoryFinder interface.'); } + $this->repositoryFinder = new $repositoryFinderClass($this->modelClass, $this->builder, $this); $repositories = $this->repositoryFinder->loadConfiguration(); diff --git a/src/Entity/Reflection/PropertyMetadata.php b/src/Entity/Reflection/PropertyMetadata.php index fe6b8d4c..0e982d33 100644 --- a/src/Entity/Reflection/PropertyMetadata.php +++ b/src/Entity/Reflection/PropertyMetadata.php @@ -16,6 +16,7 @@ use Nette\SmartObject; use Nextras\Orm\Entity\IProperty; use Nextras\Orm\Exception\InvalidStateException; +use function is_subclass_of; class PropertyMetadata @@ -69,10 +70,10 @@ class PropertyMetadata public function getWrapperPrototype(): IProperty { if ($this->wrapperPrototype === null) { - if ($this->wrapper === null) { - throw new InvalidStateException(); - } $class = $this->wrapper; + if ($class === null || !is_subclass_of($class, IProperty::class)) { + throw new InvalidStateException('Wrapper class has to implement ' . IProperty::class . ' interface.'); + } $this->wrapperPrototype = new $class($this); } return $this->wrapperPrototype; diff --git a/src/Mapper/Dbal/Conventions/Conventions.php b/src/Mapper/Dbal/Conventions/Conventions.php index ca3cc3d2..f04bb2dc 100644 --- a/src/Mapper/Dbal/Conventions/Conventions.php +++ b/src/Mapper/Dbal/Conventions/Conventions.php @@ -368,7 +368,8 @@ protected function getDefaultMappings(): array /** @phpstan-var list}> $toProcess */ $toProcess = [[$this->entityMetadata, []]]; - while (([$metadata, $tokens] = array_shift($toProcess)) !== null) { + while (($entry = array_shift($toProcess)) !== null) { + [$metadata, $tokens] = $entry; foreach ($metadata->getProperties() as $property) { if ($property->wrapper !== EmbeddableContainer::class) { continue; diff --git a/src/Model/IModel.php b/src/Model/IModel.php index 8468065c..cb12991a 100644 --- a/src/Model/IModel.php +++ b/src/Model/IModel.php @@ -32,7 +32,8 @@ public function hasRepository(string $className): bool; /** * Returns repository by repository class. - * @template T of IRepository + * @template E of IEntity + * @template T of IRepository * @phpstan-param class-string $className * @phpstan-return T */ @@ -42,7 +43,7 @@ public function getRepository(string $className): IRepository; /** * Returns repository associated for entity type. * @param IEntity|string $entity - * @phpstan-template E of IEntity + * @template E of IEntity * @phpstan-param E|class-string $entity * @phpstan-return IRepository */ diff --git a/src/Model/Model.php b/src/Model/Model.php index 55fe4ea4..50797add 100644 --- a/src/Model/Model.php +++ b/src/Model/Model.php @@ -116,7 +116,8 @@ public function hasRepository(string $className): bool /** * Returns repository by repository class. - * @template T of IRepository + * @template E of IEntity + * @template T of IRepository * @phpstan-param class-string $className * @phpstan-return T */ diff --git a/src/Repository/Repository.php b/src/Repository/Repository.php index 0c4343c0..6efacdc8 100644 --- a/src/Repository/Repository.php +++ b/src/Repository/Repository.php @@ -338,7 +338,9 @@ protected function createCollectionFunction(string $name) } if (isset($knownFunctions[$name])) { - return new $name(); + /** @var IQueryBuilderFunction|IArrayFunction $function */ + $function = new $name(); + return $function; } else { throw new NotImplementedException('Override ' . get_class($this) . '::createCollectionFunction() to return an instance of ' . $name . ' collection function.'); }