Skip to content

Commit bd7e719

Browse files
author
matheo
committed
use LiveComponentMetadataFactory logic to generate LivePropMetadata
1 parent bac591e commit bd7e719

File tree

2 files changed

+47
-36
lines changed

2 files changed

+47
-36
lines changed

src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ function (ChildDefinition $definition, AsLiveComponent $attribute) {
9898
->setArguments([
9999
tagged_iterator(LiveComponentBundle::HYDRATION_EXTENSION_TAG),
100100
new Reference('property_accessor'),
101+
new Reference('property_info'),
101102
new Reference('serializer'),
102103
'%kernel.secret%',
103104
])

src/LiveComponent/src/LiveComponentHydrator.php

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
1717
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
1818
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
19-
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
19+
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
2020
use Symfony\Component\PropertyInfo\Type;
2121
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
2222
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
@@ -47,6 +47,7 @@ final class LiveComponentHydrator
4747
public function __construct(
4848
private iterable $hydrationExtensions,
4949
private PropertyAccessorInterface $propertyAccessor,
50+
private PropertyTypeExtractorInterface $propertyTypeExtractor,
5051
private NormalizerInterface|DenormalizerInterface $normalizer,
5152
private string $secret
5253
) {
@@ -343,22 +344,15 @@ private function dehydrateValue(mixed $value, LivePropMetadata $propMetadata, ob
343344
}
344345

345346
if (\is_array($value)) {
346-
if ($propMetadata->collectionValueType() && Type::BUILTIN_TYPE_OBJECT === $propMetadata->collectionValueType()->getBuiltinType()) {
347-
$collectionClass = $propMetadata->collectionValueType()->getClassName();
348-
foreach ($value as $key => $objectItem) {
349-
if (!$objectItem instanceof $collectionClass) {
350-
throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array. We determined the array is full of %s objects, but at least on key had a different value of %s', $propMetadata->getName(), $component::class, $collectionClass, get_debug_type($objectItem)));
351-
}
352-
353-
$value[$key] = $this->dehydrateObjectValue($objectItem, $collectionClass, $propMetadata->getFormat(), $component::class, sprintf('%s.%s', $propMetadata->getName(), $key));
347+
foreach ($value as $key => $objectItem) {
348+
$type = \gettype($objectItem);
349+
if ('object' === $type) {
350+
$type = $objectItem::class;
354351
}
355-
}
356352

357-
if (!$this->isValueValidDehydratedValue($value)) {
358-
$badKeys = $this->getNonScalarKeys($value, $propMetadata->getName());
359-
$badKeysText = implode(', ', array_map(fn ($key) => sprintf('%s: %s', $key, $badKeys[$key]), array_keys($badKeys)));
353+
$propMetadata = new LivePropMetadata($key, new LiveProp(true), $type, false, true, null);
360354

361-
throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array, but it contains one or more keys that are not scalars: %s', $propMetadata->getName(), $component::class, $badKeysText));
355+
$value[$key] = $this->dehydrateValue($objectItem, $propMetadata, $component);
362356
}
363357

364358
return $value;
@@ -394,19 +388,11 @@ private function dehydrateObjectValue(object $value, string $classType, ?string
394388
}
395389
}
396390

397-
$reflexionExtractor = new ReflectionExtractor();
398-
$properties = $reflexionExtractor->getProperties($classType);
399391
$propertiesValues = [];
400-
foreach ($properties as $property) {
401-
if ($reflexionExtractor->isReadable($classType, $property)) {
402-
$propertyValue = $this->propertyAccessor->getValue($value, $property);
403-
$type = $reflexionExtractor->getTypes($classType, $property)[0]->getBuiltinType();
404-
if ($type === 'object') {
405-
$type = $reflexionExtractor->getTypes($classType, $property)[0]->getClassName();
406-
}
407-
$propMetadata = new LivePropMetadata($property, new LiveProp(true), $type, false, true, null);
408-
$propertiesValues[$property] = $this->dehydrateValue($propertyValue, $propMetadata, $component);
409-
}
392+
foreach ((new \ReflectionClass($classType))->getProperties() as $property) {
393+
$propertyValue = $this->propertyAccessor->getValue($value, $property->getName());
394+
$propMetadata = $this->generateLivePropMetadata($classType, $property->getName());
395+
$propertiesValues[$property->getName()] = $this->dehydrateValue($propertyValue, $propMetadata, $component);
410396
}
411397

412398
return $propertiesValues;
@@ -484,17 +470,10 @@ private function hydrateObjectValue(mixed $value, string $className, bool $allow
484470
}
485471
}
486472

487-
if (is_array($value)) {
488-
$object = new $className;
489-
$extractor = new ReflectionExtractor();
473+
if (\is_array($value)) {
474+
$object = new $className();
490475
foreach ($value as $property => $propertyValue) {
491-
$type = $extractor->getTypes($className, $property)[0]->getBuiltinType();
492-
$buildIn = true;
493-
if ($type === 'object') {
494-
$type = $extractor->getTypes($className, $property)[0]->getClassName();
495-
$buildIn = false;
496-
}
497-
$propMetadata = new LivePropMetadata($property, new LiveProp(true), $type, $buildIn, true, null);
476+
$propMetadata = $this->generateLivePropMetadata($className, $property);
498477
$this->propertyAccessor->setValue($object, $property, $this->hydrateValue($propertyValue, $propMetadata, $component));
499478
}
500479

@@ -593,4 +572,35 @@ private function recursiveKeySort(array &$data): void
593572
}
594573
ksort($data);
595574
}
575+
576+
private function generateLivePropMetadata(string $className, string $propertyName): LivePropMetadata
577+
{
578+
$reflexionClass = new \ReflectionClass($className);
579+
$property = $reflexionClass->getProperty($propertyName);
580+
581+
$collectionValueType = null;
582+
$infoTypes = $this->propertyTypeExtractor->getTypes($className, $propertyName) ?? [];
583+
foreach ($infoTypes as $infoType) {
584+
if ($infoType->isCollection()) {
585+
foreach ($infoType->getCollectionValueTypes() as $valueType) {
586+
$collectionValueType = $valueType;
587+
break;
588+
}
589+
}
590+
}
591+
592+
$type = $property->getType();
593+
if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) {
594+
throw new \LogicException(sprintf('Union or intersection types are not supported for LiveProps. You may want to change the type of property %s in %s.', $property->getName(), $property->getDeclaringClass()->getName()));
595+
}
596+
597+
return new LivePropMetadata(
598+
$property->getName(),
599+
new LiveProp(true),
600+
$type ? $type->getName() : null,
601+
$type ? $type->isBuiltin() : false,
602+
$type ? $type->allowsNull() : true,
603+
$collectionValueType,
604+
);
605+
}
596606
}

0 commit comments

Comments
 (0)