diff --git a/src/Support/DataType.php b/src/Support/DataType.php index ea485f21a..95a0b72e9 100644 --- a/src/Support/DataType.php +++ b/src/Support/DataType.php @@ -58,6 +58,98 @@ public function acceptsValue(mixed $value): bool default => $type, }; + return $this->acceptsType($type); + } + + public function acceptsType(string $type): bool + { + if ($this->isMixed) { + return true; + } + + if (array_key_exists($type, $this->acceptedTypes)) { + return true; + } + + if (in_array($type, ['string', 'int', 'bool', 'float', 'array'])) { + return false; + } + + foreach ([$type, ...$this->resolveBaseTypes($type)] as $givenType) { + if (array_key_exists($givenType, $this->acceptedTypes)) { + return true; + } + } + + return false; + } + + public function findAcceptedTypeForBaseType(string $class): ?string + { + foreach ($this->acceptedTypes as $acceptedType => $acceptedBaseTypes) { + if ($class === $acceptedType) { + return $acceptedType; + } + + if (in_array($class, $acceptedBaseTypes)) { + return $acceptedType; + } + } + + return null; + } + + protected function resolveBaseTypes(string $type): array + { + if (! class_exists($type)) { + return []; + } + + return array_unique([ + ...array_values(class_parents($type)), + ...array_values(class_implements($type)), + ]); + } + + protected function resolveDataCollectableClass( + ReflectionProperty|ReflectionParameter $reflection, + ): ?string { + $attributes = $reflection->getAttributes(DataCollectionOf::class); + + if (! empty($attributes)) { + $attributeArgumentKey = array_key_first($attributes[0]->getArguments()); + + return $attributes[0]->getArguments()[$attributeArgumentKey]; + } + + if ($reflection instanceof ReflectionParameter) { + return null; + } + + $class = (new DataCollectionAnnotationReader())->getClass($reflection); + + if ($class === null) { + throw CannotFindDataClass::wrongDataCollectionAnnotation( + $reflection->class, + $reflection->name + ); + } + + return $class; + } + + protected function resolveDataCollectableType( + ReflectionNamedType $reflection, + ): ?DataCollectableType { + $className = $reflection->getName(); + + return match (true) { + is_a($className, DataCollection::class, true) => DataCollectableType::Default, + is_a($className, PaginatedDataCollection::class, true) => DataCollectableType::Paginated, + is_a($className, CursorPaginatedDataCollection::class, true) => DataCollectableType::CursorPaginated, + default => null, + }; + return $this->type->acceptsType($type); } }