Skip to content

Commit

Permalink
Merge pull request #33 from sunrise-php/release/v3.6.0
Browse files Browse the repository at this point in the history
v3.6.0
  • Loading branch information
fenric authored Nov 21, 2023
2 parents e716354 + 28e93e6 commit 25077e5
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 24 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ composer require sunrise/hydrator
* * [Timestamp](#timestamp)
* * [Timezone](#timezone)
* * [Enumeration](#enumeration)
* * [UUID](#uid)
* * [UUID](#uuid)
* * [Relationship](#relationship)
* * [Custom type](#support-for-custom-types)
* [Ignored property](#ignored-property)
Expand Down Expand Up @@ -293,6 +293,16 @@ In general, remember that regardless of whether arrays or collections are used,
public readonly array $value;
```

Sometimes, there is a need to map a typed list to a collection. It's a relatively simple task; just use the example below:

```php
use Sunrise\Hydrator\Type;

$data = [...];

$collection = $hydrator->castValue($data, Type::fromName(SomeDtoCollection::class));
```

This property has no any additional behavior and only accepts arrays.

### Timestamp
Expand Down
7 changes: 7 additions & 0 deletions src/AnnotationReader/BuiltinAnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Generator;
use LogicException;
use ReflectionAttribute;
use ReflectionParameter;
use ReflectionProperty;
use Sunrise\Hydrator\AnnotationReaderInterface;

use function sprintf;
Expand Down Expand Up @@ -56,6 +58,11 @@ public function getAnnotations(string $name, $holder): Generator
return;
} // @codeCoverageIgnoreEnd

if (! $holder instanceof ReflectionProperty &&
! $holder instanceof ReflectionParameter) {
return;
}

$attributes = $holder->getAttributes($name, ReflectionAttribute::IS_INSTANCEOF);
foreach ($attributes as $attribute) {
yield $attribute->newInstance();
Expand Down
4 changes: 1 addition & 3 deletions src/AnnotationReaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
namespace Sunrise\Hydrator;

use Generator;
use ReflectionParameter;
use ReflectionProperty;

/**
* @since 3.1.0
Expand All @@ -27,7 +25,7 @@ interface AnnotationReaderInterface
* Gets annotations by the given name from the given holder
*
* @param class-string<T> $name
* @param ReflectionParameter|ReflectionProperty $holder
* @param mixed $holder
*
* @return Generator<mixed, T>
*
Expand Down
15 changes: 12 additions & 3 deletions src/Exception/InvalidObjectException.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,20 @@ final public static function uninstantiableObject(string $className): self
*/
final public static function unsupportedType(Type $type): self
{
/** @var mixed $holder */
$holder = $type->getHolder();

return $holder instanceof ReflectionProperty ?
self::unsupportedPropertyType($type, $holder) :
self::unsupportedParameterType($type, $holder);
if ($holder instanceof ReflectionProperty) {
return self::unsupportedPropertyType($type, $holder);
}
if ($holder instanceof ReflectionParameter) {
return self::unsupportedParameterType($type, $holder);
}

return new self(sprintf(
'The type {%s} is not supported.',
$type->getName(),
));
}

/**
Expand Down
49 changes: 32 additions & 17 deletions src/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class Type
/**
* The type holder
*
* @var ReflectionParameter|ReflectionProperty
* @var mixed
*/
private $holder;

Expand All @@ -48,7 +48,7 @@ final class Type
/**
* Constructor of the class
*
* @param ReflectionParameter|ReflectionProperty $holder
* @param mixed $holder
* @param string $name
* @param bool $allowsNull
*/
Expand All @@ -60,26 +60,18 @@ public function __construct($holder, string $name, bool $allowsNull)
}

/**
* Creates a new type from the given property
* Creates a new type from the given name
*
* @param ReflectionProperty $property
* @param string $name
* @param bool $allowsNull
*
* @return self
*
* @since 3.4.0
* @since 3.6.0
*/
public static function fromProperty(ReflectionProperty $property): self
public static function fromName(string $name, bool $allowsNull = false): self
{
$type = $property->getType();
if ($type === null) {
return new Type($property, BuiltinType::MIXED, true);
}

if ($type instanceof ReflectionNamedType) {
return new Type($property, $type->getName(), $type->allowsNull());
}

return new Type($property, (string) $type, $type->allowsNull());
return new Type(null, $name, $allowsNull);
}

/**
Expand All @@ -105,10 +97,33 @@ public static function fromParameter(ReflectionParameter $parameter): self
return new Type($parameter, (string) $type, $type->allowsNull());
}

/**
* Creates a new type from the given property
*
* @param ReflectionProperty $property
*
* @return self
*
* @since 3.4.0
*/
public static function fromProperty(ReflectionProperty $property): self
{
$type = $property->getType();
if ($type === null) {
return new Type($property, BuiltinType::MIXED, true);
}

if ($type instanceof ReflectionNamedType) {
return new Type($property, $type->getName(), $type->allowsNull());
}

return new Type($property, (string) $type, $type->allowsNull());
}

/**
* Gets the type holder
*
* @return ReflectionParameter|ReflectionProperty
* @return mixed
*/
public function getHolder()
{
Expand Down
12 changes: 12 additions & 0 deletions tests/HydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Sunrise\Hydrator\Exception\InvalidObjectException;
use Sunrise\Hydrator\Hydrator;
use Sunrise\Hydrator\HydratorInterface;
use Sunrise\Hydrator\Tests\Stub\BooleanCollection;
use Sunrise\Hydrator\Type;
use Sunrise\Hydrator\TypeConverter\TimestampTypeConverter;

Expand Down Expand Up @@ -2602,6 +2603,17 @@ public function testSymfonyViolations(): void
$this->assertSame('value', $violations->get(0)->getPropertyPath());
}

/**
* @dataProvider strictBooleanProvider
* @dataProvider nonStrictBooleanProvider
*/
public function testSourcelessType($element, bool $expected): void
{
$type = Type::fromName(BuiltinType::BOOL);

$this->assertSame($expected, $this->createHydrator()->castValue($element, $type));
}

public function strictNullProvider(): Generator
{
yield [null, null];
Expand Down

0 comments on commit 25077e5

Please sign in to comment.