Skip to content

Commit

Permalink
feat: Added createTypeReflectionBasedOnReflectionType method the factory
Browse files Browse the repository at this point in the history
  • Loading branch information
patrykbaszak committed Aug 7, 2024
1 parent 6a9e910 commit d7a0f72
Show file tree
Hide file tree
Showing 9 changed files with 356 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public static function recreate(
return new static($collectionType, $keyType, $valueType);
}

public function allowsNull(): bool
{
return false;
}

public function normalize(): array
{
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public static function recreate(
return new static($types);
}

public function allowsNull(): bool
{
return false;
}

public function normalize(): array
{
return [
Expand Down
15 changes: 10 additions & 5 deletions src/Reflection/Domain/Entities/Type/NamedTypeReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

final class NamedTypeReflection extends TypeReflection
{
public const IS_BUILT_IN = 0;
public const IS_CLASS = 1;
public const IS_INTERFACE = 2;
public const IS_ABSTRACT = 4;
public const IS_ENUM = 8;
public const IS_BUILT_IN = 1;
public const IS_CLASS = 2;
public const IS_INTERFACE = 4;
public const IS_ABSTRACT = 8;
public const IS_ENUM = 16;

private function __construct(
/** @var string|class-string */
Expand Down Expand Up @@ -94,6 +94,11 @@ public function isEnum(): bool
return ($this->flags & self::IS_ENUM) == self::IS_ENUM;
}

public function allowsNull(): bool
{
return 'null' === $this->name || 'mixed' === $this->name;
}

public function normalize(): array
{
return [
Expand Down
1 change: 1 addition & 0 deletions src/Reflection/Domain/Entities/Type/TypeReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@

abstract class TypeReflection implements Normalizable
{
abstract public function allowsNull(): bool;
}
11 changes: 11 additions & 0 deletions src/Reflection/Domain/Entities/Type/UnionTypeReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ public static function recreate(
return new static($types);
}

public function allowsNull(): bool
{
foreach ($this->types as $type) {
if ($type->allowsNull()) {
return true;
}
}

return false;
}

public function normalize(): array
{
return [
Expand Down
95 changes: 90 additions & 5 deletions src/Reflection/Domain/Factories/TypeReflectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

namespace PBaszak\UltraMapper\Reflection\Domain\Factories;

use PBaszak\UltraMapper\Reflection\Domain\Entities\Type\CollectionTypeReflection;
use PBaszak\UltraMapper\Reflection\Domain\Entities\Type\IntersectionTypeReflection;
use PBaszak\UltraMapper\Reflection\Domain\Entities\Type\NamedTypeReflection;
use PBaszak\UltraMapper\Reflection\Domain\Entities\Type\TypeReflection;
use PBaszak\UltraMapper\Reflection\Domain\Entities\Type\UnionTypeReflection;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
Expand Down Expand Up @@ -45,16 +48,98 @@ public function create(?\ReflectionType $ref, ?PhpDocumentorReflectionType $docC
// intersection
// named

return NamedTypeReflection::create('mixed', NamedTypeReflection::IS_BUILT_IN);
return $this->createTypeReflectionBasedOnReflectionType($ref);
}

private function createNamedTypeReflection(?\ReflectionType $ref, ?PhpDocumentorReflectionType $docCommentRef): NamedTypeReflection
private function createTypeReflectionBasedOnReflectionType(?\ReflectionType $ref): TypeReflection
{
if ($ref && !$ref instanceof \ReflectionNamedType) {
// todo
if ($ref instanceof \ReflectionNamedType) {
$name = $ref->getName();
$flags = 0;
$isCollection = in_array($name, ['array', 'iterable']);

if ($ref->isBuiltin()) {
$flags |= NamedTypeReflection::IS_BUILT_IN;
}

if (class_exists($name, false) && !enum_exists($name, false)) {
$flags |= NamedTypeReflection::IS_CLASS;
$class = (new \ReflectionClass($name));

if ($class->isAbstract()) {
$flags |= NamedTypeReflection::IS_ABSTRACT;
}

if ($class->implementsInterface(\Traversable::class) || $class->implementsInterface(\ArrayAccess::class)) {
$isCollection = true;
}
}

if (interface_exists($name, false)) {
$flags |= NamedTypeReflection::IS_INTERFACE;
$interface = (new \ReflectionClass($name));

if ($interface->implementsInterface(\Traversable::class) || $interface->implementsInterface(\ArrayAccess::class)) {
$isCollection = true;
}
}

if (enum_exists($name, false)) {
$flags |= NamedTypeReflection::IS_ENUM;
}

$output = $isCollection
? CollectionTypeReflection::create(
NamedTypeReflection::create($name, $flags),
\SplObjectStorage::class === $name || (@$class && $class->isSubclassOf(\SplObjectStorage::class))
? NamedTypeReflection::create('object', NamedTypeReflection::IS_BUILT_IN)
: UnionTypeReflection::create([
NamedTypeReflection::create('int', NamedTypeReflection::IS_BUILT_IN),
NamedTypeReflection::create('string', NamedTypeReflection::IS_BUILT_IN),
]),
NamedTypeReflection::create('mixed', NamedTypeReflection::IS_BUILT_IN),
)
: NamedTypeReflection::create($name, $flags);

if ($ref->allowsNull()) {
if (!in_array($name, ['null', 'mixed'])) {
return UnionTypeReflection::create([
NamedTypeReflection::create('null', NamedTypeReflection::IS_BUILT_IN),
$output,
]);
}

if ('null' === $name) {
return NamedTypeReflection::create('null', NamedTypeReflection::IS_BUILT_IN);
}

if ('mixed' === $name) {
return NamedTypeReflection::create('mixed', NamedTypeReflection::IS_BUILT_IN);
}
}

return $output;
}

throw new \LogicException('Not implemented');
if ($ref instanceof \ReflectionUnionType) {
$types = array_map(
fn (\ReflectionType $type) => $this->createTypeReflectionBasedOnReflectionType($type),
$ref->getTypes()
);

return UnionTypeReflection::create($types);
}

if ($ref instanceof \ReflectionIntersectionType) {
$types = array_map(
fn (\ReflectionType $type) => $this->createTypeReflectionBasedOnReflectionType($type),
$ref->getTypes()
);

return IntersectionTypeReflection::create($types);
}

return NamedTypeReflection::create('mixed', NamedTypeReflection::IS_BUILT_IN);
}

private function getDocBlockReflectionTypeFromVarTag(\ReflectionProperty $ref): ?PhpDocumentorReflectionType
Expand Down
12 changes: 12 additions & 0 deletions tests/Support/Assets/Enums/TestEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace PBaszak\UltraMapper\Tests\Support\Assets\Enums;

enum TestEnum
{
case A;
case B;
case C;
}
Loading

0 comments on commit d7a0f72

Please sign in to comment.