Skip to content

Commit

Permalink
chore: better PHP types (#4886)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain authored Aug 11, 2022
1 parent a188888 commit dca8ba8
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 82 deletions.
19 changes: 4 additions & 15 deletions AbstractCollectionNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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;
}
5 changes: 1 addition & 4 deletions AbstractConstraintViolationListNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down
79 changes: 25 additions & 54 deletions AbstractItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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));
}
Expand All @@ -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')) {
Expand All @@ -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) {
Expand All @@ -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 {
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Filter/FilterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion Filter/PropertyFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
9 changes: 3 additions & 6 deletions InputOutputMetadataTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Mapping/Factory/ClassMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down

0 comments on commit dca8ba8

Please sign in to comment.