/
githubmirror
/
symfony
Обзор
Документация
Войти
/
githubmirror
/
symfony
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
8.2
src/Symfony/Component/JsonStreamer/Mapping/Write/AttributePropertyMetadataLoader.php
126 строк
5 KB
Mathias Arlaud
[JsonStreamer] Handle value objects
06 мар 2026, 17:50
06 мар 2026, 17:50
8cf1714
Код
Авторство
О чём код?
<?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\JsonStreamer\Mapping\Write; use Psr\Container\ContainerInterface; use Symfony\Component\JsonStreamer\Attribute\StreamedName; use Symfony\Component\JsonStreamer\Attribute\ValueTransformer; use Symfony\Component\JsonStreamer\Exception\InvalidArgumentException; use Symfony\Component\JsonStreamer\Exception\RuntimeException; use Symfony\Component\JsonStreamer\Mapping\PropertyMetadataLoaderInterface; use Symfony\Component\JsonStreamer\Transformer\PropertyValueTransformerInterface; use Symfony\Component\JsonStreamer\Transformer\ValueObjectTransformerInterface; use Symfony\Component\TypeInfo\TypeResolver\TypeResolverInterface; /** * Enhances properties stream writing metadata based on properties' attributes. * * @author Mathias Arlaud <mathias.arlaud@gmail.com> * * @internal */ final class AttributePropertyMetadataLoader implements PropertyMetadataLoaderInterface { public function __construct( private PropertyMetadataLoaderInterface $decorated, private ContainerInterface $transformers, private TypeResolverInterface $typeResolver, ) { } public function load(string $className, array $options = [], array $context = []): array { $initialResult = $this->decorated->load($className, $options, $context); $result = []; foreach ($initialResult as $initialStreamedName => $initialMetadata) { if (!$initialName = $initialMetadata->getName()) { continue; } try { $propertyReflection = new \ReflectionProperty($className, $initialName); } catch (\ReflectionException $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } $attributesMetadata = $this->getPropertyAttributesMetadata($propertyReflection); $streamedName = $attributesMetadata['name'] ?? $initialStreamedName; if (null === $valueTransformer = $attributesMetadata['nativeToStreamValueTransformer'] ?? null) { $result[$streamedName] = $initialMetadata; continue; } if (\is_string($valueTransformer)) { $valueTransformerService = $this->getAndValidatePropertyValueTransformerService($valueTransformer); $result[$streamedName] = $initialMetadata ->withType($valueTransformerService::getStreamValueType()) ->withAdditionalValueTransformer($valueTransformer); continue; } try { $valueTransformerReflection = new \ReflectionFunction($valueTransformer); } catch (\ReflectionException $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } $result[$streamedName] = $initialMetadata ->withType($this->typeResolver->resolve($valueTransformerReflection)) ->withAdditionalValueTransformer($valueTransformer); } return $result; } /** * @return array{name?: string, nativeToStreamValueTransformer?: string|\Closure} */ private function getPropertyAttributesMetadata(\ReflectionProperty $reflectionProperty): array { $metadata = []; $reflectionAttribute = $reflectionProperty->getAttributes(StreamedName::class, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null; if (null !== $reflectionAttribute) { $metadata['name'] = $reflectionAttribute->newInstance()->getName(); } $reflectionAttribute = $reflectionProperty->getAttributes(ValueTransformer::class, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null; if (null !== $reflectionAttribute) { $metadata['nativeToStreamValueTransformer'] = $reflectionAttribute->newInstance()->getNativeToStream(); } return $metadata; } private function getAndValidatePropertyValueTransformerService(string $id): PropertyValueTransformerInterface { if (!$this->transformers->has($id)) { throw new InvalidArgumentException(\sprintf('You have requested a non-existent property value transformer service "%s". Did you implement "%s"?', $id, PropertyValueTransformerInterface::class)); } $transformer = $this->transformers->get($id); if ($transformer instanceof ValueObjectTransformerInterface) { throw new InvalidArgumentException(\sprintf('"%s" is a "%s" and must not be specified as a property value transformer.', $id, ValueObjectTransformerInterface::class)); } if (!$transformer instanceof PropertyValueTransformerInterface) { throw new InvalidArgumentException(\sprintf('The "%s" property value transformer service does not implement "%s".', $id, PropertyValueTransformerInterface::class)); } return $transformer; } }