From dca8ba87ff5a5aff0c50a379aef0d2553da78b2f Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Thu, 11 Aug 2022 19:04:28 +0200 Subject: [PATCH] chore: better PHP types (#4886) --- AbstractCollectionNormalizer.php | 19 +---- AbstractConstraintViolationListNormalizer.php | 5 +- AbstractItemNormalizer.php | 79 ++++++------------- Filter/FilterInterface.php | 2 +- Filter/PropertyFilter.php | 2 +- InputOutputMetadataTrait.php | 9 +-- Mapping/Factory/ClassMetadataFactory.php | 2 +- 7 files changed, 36 insertions(+), 82 deletions(-) diff --git a/AbstractCollectionNormalizer.php b/AbstractCollectionNormalizer.php index be79a19..62aa50a 100644 --- a/AbstractCollectionNormalizer.php +++ b/AbstractCollectionNormalizer.php @@ -52,9 +52,6 @@ public function supportsNormalization(mixed $data, string $format = null, array return static::FORMAT === $format && is_iterable($data); } - /** - * {@inheritdoc} - */ public function hasCacheableSupportsMethod(): bool { return true; @@ -84,10 +81,8 @@ public function normalize(mixed $object, string $format = null, array $context = /** * Normalizes a raw collection (not API resources). - * - * @param string|null $format */ - protected function normalizeRawCollection($object, $format = null, array $context = []): array + protected function normalizeRawCollection(iterable $object, string $format = null, array $context = []): array { $data = []; foreach ($object as $index => $obj) { @@ -99,10 +94,8 @@ protected function normalizeRawCollection($object, $format = null, array $contex /** * Gets the pagination configuration. - * - * @param iterable $object */ - protected function getPaginationConfig($object, array $context = []): array + protected function getPaginationConfig(iterable $object, array $context = []): array { $currentPage = $lastPage = $itemsPerPage = $pageTotalItems = $totalItems = null; $paginated = $paginator = false; @@ -127,15 +120,11 @@ protected function getPaginationConfig($object, array $context = []): array /** * Gets the pagination data. - * - * @param iterable $object */ - abstract protected function getPaginationData($object, array $context = []): array; + abstract protected function getPaginationData(iterable $object, array $context = []): array; /** * Gets items data. - * - * @param iterable $object */ - abstract protected function getItemsData($object, string $format = null, array $context = []): array; + abstract protected function getItemsData(iterable $object, string $format = null, array $context = []): array; } diff --git a/AbstractConstraintViolationListNormalizer.php b/AbstractConstraintViolationListNormalizer.php index 132f231..d20b2c7 100644 --- a/AbstractConstraintViolationListNormalizer.php +++ b/AbstractConstraintViolationListNormalizer.php @@ -28,7 +28,7 @@ */ abstract class AbstractConstraintViolationListNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface { - public const FORMAT = null; // Must be overrode + public const FORMAT = null; // Must be overridden private readonly ?array $serializePayloadFields; @@ -45,9 +45,6 @@ public function supportsNormalization(mixed $data, string $format = null, array return static::FORMAT === $format && $data instanceof ConstraintViolationListInterface; } - /** - * {@inheritdoc} - */ public function hasCacheableSupportsMethod(): bool { return true; diff --git a/AbstractItemNormalizer.php b/AbstractItemNormalizer.php index 7ca3487..a8b95f7 100644 --- a/AbstractItemNormalizer.php +++ b/AbstractItemNormalizer.php @@ -17,7 +17,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\InvalidValueException; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -54,7 +53,7 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer use InputOutputMetadataTrait; protected PropertyAccessorInterface $propertyAccessor; - protected $localCache = []; + protected array $localCache = []; public function __construct(protected PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, protected PropertyMetadataFactoryInterface $propertyMetadataFactory, protected IriConverterInterface $iriConverter, protected ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, protected ?ResourceAccessCheckerInterface $resourceAccessChecker = null) { @@ -100,14 +99,12 @@ public function hasCacheableSupportsMethod(): bool public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { $resourceClass = $this->getObjectClass($object); - if ($outputClass = $this->getOutputClass($resourceClass, $context)) { + if ($outputClass = $this->getOutputClass($context)) { if (!$this->serializer instanceof NormalizerInterface) { throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); } - unset($context['output']); - unset($context['operation']); - unset($context['operation_name']); + unset($context['output'], $context['operation'], $context['operation_name']); $context['resource_class'] = $outputClass; $context['api_sub_level'] = true; $context[self::ALLOW_EXTRA_ATTRIBUTES] = false; @@ -167,14 +164,12 @@ public function denormalize(mixed $data, string $class, string $format = null, a { $resourceClass = $class; - if ($inputClass = $this->getInputClass($class, $context)) { + if ($inputClass = $this->getInputClass($context)) { if (!$this->serializer instanceof DenormalizerInterface) { throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); } - unset($context['input']); - unset($context['operation']); - unset($context['operation_name']); + unset($context['input'], $context['operation'], $context['operation_name']); $context['resource_class'] = $inputClass; try { @@ -240,7 +235,7 @@ public function denormalize(mixed $data, string $class, string $format = null, a * * @internal */ - protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null): object + protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null): object { if (null !== $object = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) { unset($context[static::OBJECT_TO_POPULATE]); @@ -294,7 +289,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref return new $class(); } - protected function getClassDiscriminatorResolvedClass(array &$data, string $class): string + protected function getClassDiscriminatorResolvedClass(array $data, string $class): string { if (null === $this->classDiscriminatorResolver || (null === $mapping = $this->classDiscriminatorResolver->getMappingForClass($class))) { return $class; @@ -312,10 +307,7 @@ protected function getClassDiscriminatorResolvedClass(array &$data, string $clas return $mappedClass; } - /** - * {@inheritdoc} - */ - protected function createConstructorArgument($parameterData, string $key, \ReflectionParameter $constructorParameter, array &$context, string $format = null) + protected function createConstructorArgument($parameterData, string $key, \ReflectionParameter $constructorParameter, array &$context, string $format = null): mixed { return $this->createAttributeValue($constructorParameter->name, $parameterData, $format, $context); } @@ -377,10 +369,8 @@ protected function isAllowedAttribute(object|string $classOrObject, string $attr /** * Check if access to the attribute is granted. - * - * @param object $object */ - protected function canAccessAttribute($object, string $attribute, array $context = []): bool + protected function canAccessAttribute(?object $object, string $attribute, array $context = []): bool { if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { return true; @@ -400,11 +390,8 @@ protected function canAccessAttribute($object, string $attribute, array $context /** * Check if access to the attribute is granted. - * - * @param object $object - * @param object|null $previousObject */ - protected function canAccessAttributePostDenormalize($object, $previousObject, string $attribute, array $context = []): bool + protected function canAccessAttributePostDenormalize(?object $object, ?object $previousObject, string $attribute, array $context = []): bool { $options = $this->getFactoryOptions($context); $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); @@ -422,7 +409,7 @@ protected function canAccessAttributePostDenormalize($object, $previousObject, s /** * {@inheritdoc} */ - protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []): void + protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []): void { $this->setValue($object, $attribute, $this->createAttributeValue($attribute, $value, $format, $context)); } @@ -432,7 +419,7 @@ protected function setAttributeValue($object, $attribute, $value, $format = null * * @throws InvalidArgumentException */ - protected function validateType(string $attribute, Type $type, $value, string $format = null): void + protected function validateType(string $attribute, Type $type, mixed $value, string $format = null): void { $builtinType = $type->getBuiltinType(); if (Type::BUILTIN_TYPE_FLOAT === $builtinType && null !== $format && str_contains($format, 'json')) { @@ -451,14 +438,14 @@ protected function validateType(string $attribute, Type $type, $value, string $f * * @throws InvalidArgumentException */ - protected function denormalizeCollection(string $attribute, ApiProperty $propertyMetadata, Type $type, string $className, $value, ?string $format, array $context): array + protected function denormalizeCollection(string $attribute, ApiProperty $propertyMetadata, Type $type, string $className, mixed $value, ?string $format, array $context): array { if (!\is_array($value)) { throw new InvalidArgumentException(sprintf('The type of the "%s" attribute must be "array", "%s" given.', $attribute, \gettype($value))); } $collectionKeyType = $type->getCollectionKeyTypes()[0] ?? null; - $collectionKeyBuiltinType = null === $collectionKeyType ? null : $collectionKeyType->getBuiltinType(); + $collectionKeyBuiltinType = $collectionKeyType?->getBuiltinType(); $values = []; foreach ($value as $index => $obj) { @@ -477,11 +464,8 @@ protected function denormalizeCollection(string $attribute, ApiProperty $propert * * @throws LogicException * @throws UnexpectedValueException - * @throws ItemNotFoundException - * - * @return object|null */ - protected function denormalizeRelation(string $attributeName, ApiProperty $propertyMetadata, string $className, $value, ?string $format, array $context) + protected function denormalizeRelation(string $attributeName, ApiProperty $propertyMetadata, string $className, mixed $value, ?string $format, array $context): ?object { if (\is_string($value)) { try { @@ -500,16 +484,12 @@ protected function denormalizeRelation(string $attributeName, ApiProperty $prope throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', DenormalizerInterface::class)); } - try { - $item = $this->serializer->denormalize($value, $className, $format, $context); - if (!\is_object($item) && null !== $item) { - throw new \UnexpectedValueException('Expected item to be an object or null.'); - } - - return $item; - } catch (InvalidValueException $e) { - throw $e; + $item = $this->serializer->denormalize($value, $className, $format, $context); + if (!\is_object($item) && null !== $item) { + throw new \UnexpectedValueException('Expected item to be an object or null.'); } + + return $item; } if (!\is_array($value)) { @@ -547,18 +527,13 @@ protected function getFactoryOptions(array $context): array * {@inheritdoc} * * @throws UnexpectedValueException - * @throws LogicException */ - protected function getAttributeValue($object, $attribute, $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed { $context['api_attribute'] = $attribute; $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); - try { - $attributeValue = $this->propertyAccessor->getValue($object, $attribute); - } catch (NoSuchPropertyException $e) { - throw $e; - } + $attributeValue = $this->propertyAccessor->getValue($object, $attribute); if ($context['api_denormalize'] ?? false) { return $attributeValue; @@ -652,10 +627,8 @@ protected function normalizeCollectionOfRelations(ApiProperty $propertyMetadata, * * @throws LogicException * @throws UnexpectedValueException - * - * @return string|array|\ArrayObject|null IRI or normalized object data */ - protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $relatedObject, string $resourceClass, ?string $format, array $context) + protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $relatedObject, string $resourceClass, ?string $format, array $context): \ArrayObject|array|string|null { if (null === $relatedObject || !empty($context['attributes']) || $propertyMetadata->isReadableLink()) { if (!$this->serializer instanceof NormalizerInterface) { @@ -685,7 +658,7 @@ protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $rel return $iri; } - private function createAttributeValue($attribute, $value, $format = null, array $context = []) + private function createAttributeValue(string $attribute, mixed $value, string $format = null, array $context = []): mixed { $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; @@ -810,10 +783,8 @@ private function createAttributeValue($attribute, $value, $format = null, array /** * Sets a value of the object using the PropertyAccess component. - * - * @param object $object */ - private function setValue($object, string $attributeName, $value): void + private function setValue(object $object, string $attributeName, mixed $value): void { try { $this->propertyAccessor->setValue($object, $attributeName, $value); diff --git a/Filter/FilterInterface.php b/Filter/FilterInterface.php index 31b7c57..7093ad2 100644 --- a/Filter/FilterInterface.php +++ b/Filter/FilterInterface.php @@ -26,5 +26,5 @@ interface FilterInterface extends BaseFilterInterface /** * Apply a filter to the serializer context. */ - public function apply(Request $request, bool $normalization, array $attributes, array &$context); + public function apply(Request $request, bool $normalization, array $attributes, array &$context): void; } diff --git a/Filter/PropertyFilter.php b/Filter/PropertyFilter.php index 783cb0e..4030f85 100644 --- a/Filter/PropertyFilter.php +++ b/Filter/PropertyFilter.php @@ -157,7 +157,7 @@ private function denormalizeProperties(array $properties): array return $result; } - private function denormalizePropertyName($property) + private function denormalizePropertyName($property): string { return null !== $this->nameConverter ? $this->nameConverter->denormalize($property) : $property; } diff --git a/InputOutputMetadataTrait.php b/InputOutputMetadataTrait.php index c17c0e3..03b604f 100644 --- a/InputOutputMetadataTrait.php +++ b/InputOutputMetadataTrait.php @@ -17,12 +17,9 @@ trait InputOutputMetadataTrait { - /** - * @var ResourceMetadataCollectionFactoryInterface|null - */ - protected $resourceMetadataCollectionFactory; + protected ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null; - protected function getInputClass(string $class, array $context = []): ?string + protected function getInputClass(array $context = []): ?string { if (!$this->resourceMetadataCollectionFactory) { return $context['input']['class'] ?? null; @@ -35,7 +32,7 @@ protected function getInputClass(string $class, array $context = []): ?string return null; } - protected function getOutputClass(string $class, array $context = []): ?string + protected function getOutputClass(array $context = []): ?string { if (!$this->resourceMetadataCollectionFactory) { return $context['output']['class'] ?? null; diff --git a/Mapping/Factory/ClassMetadataFactory.php b/Mapping/Factory/ClassMetadataFactory.php index d3651bc..c8fe61e 100644 --- a/Mapping/Factory/ClassMetadataFactory.php +++ b/Mapping/Factory/ClassMetadataFactory.php @@ -36,7 +36,7 @@ public function getMetadataFor($value): ClassMetadataInterface /** * {@inheritdoc} */ - public function hasMetadataFor($value): bool + public function hasMetadataFor(mixed $value): bool { return $this->decorated->hasMetadataFor(\is_object($value) ? $this->getObjectClass($value) : $this->getRealClassName($value)); }