schema
3 years ago
AbstractLoader.php
4 years ago
AnnotationLoader.php
1 year ago
AutoMappingTrait.php
1 year ago
FileLoader.php
4 years ago
FilesLoader.php
4 years ago
LoaderChain.php
4 years ago
LoaderInterface.php
4 years ago
PropertyInfoLoader.php
1 year ago
StaticMethodLoader.php
4 years ago
XmlFileLoader.php
4 years ago
XmlFilesLoader.php
4 years ago
YamlFileLoader.php
4 years ago
YamlFilesLoader.php
4 years ago
index.php
3 years ago
PropertyInfoLoader.php
139 lines
| 1 | <?php |
| 2 | namespace MailPoetVendor\Symfony\Component\Validator\Mapping\Loader; |
| 3 | if (!defined('ABSPATH')) exit; |
| 4 | use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; |
| 5 | use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyListExtractorInterface; |
| 6 | use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; |
| 7 | use MailPoetVendor\Symfony\Component\PropertyInfo\Type as PropertyInfoType; |
| 8 | use MailPoetVendor\Symfony\Component\Validator\Constraints\All; |
| 9 | use MailPoetVendor\Symfony\Component\Validator\Constraints\NotBlank; |
| 10 | use MailPoetVendor\Symfony\Component\Validator\Constraints\NotNull; |
| 11 | use MailPoetVendor\Symfony\Component\Validator\Constraints\Type; |
| 12 | use MailPoetVendor\Symfony\Component\Validator\Mapping\AutoMappingStrategy; |
| 13 | use MailPoetVendor\Symfony\Component\Validator\Mapping\ClassMetadata; |
| 14 | final class PropertyInfoLoader implements LoaderInterface |
| 15 | { |
| 16 | use AutoMappingTrait; |
| 17 | private $listExtractor; |
| 18 | private $typeExtractor; |
| 19 | private $accessExtractor; |
| 20 | private $classValidatorRegexp; |
| 21 | public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, PropertyAccessExtractorInterface $accessExtractor, ?string $classValidatorRegexp = null) |
| 22 | { |
| 23 | $this->listExtractor = $listExtractor; |
| 24 | $this->typeExtractor = $typeExtractor; |
| 25 | $this->accessExtractor = $accessExtractor; |
| 26 | $this->classValidatorRegexp = $classValidatorRegexp; |
| 27 | } |
| 28 | public function loadClassMetadata(ClassMetadata $metadata) : bool |
| 29 | { |
| 30 | $className = $metadata->getClassName(); |
| 31 | if (!($properties = $this->listExtractor->getProperties($className))) { |
| 32 | return \false; |
| 33 | } |
| 34 | $loaded = \false; |
| 35 | $enabledForClass = $this->isAutoMappingEnabledForClass($metadata, $this->classValidatorRegexp); |
| 36 | foreach ($properties as $property) { |
| 37 | if (\false === $this->accessExtractor->isWritable($className, $property)) { |
| 38 | continue; |
| 39 | } |
| 40 | if (!\property_exists($className, $property)) { |
| 41 | continue; |
| 42 | } |
| 43 | $types = $this->typeExtractor->getTypes($className, $property); |
| 44 | if (null === $types) { |
| 45 | continue; |
| 46 | } |
| 47 | $enabledForProperty = $enabledForClass; |
| 48 | $hasTypeConstraint = \false; |
| 49 | $hasNotNullConstraint = \false; |
| 50 | $hasNotBlankConstraint = \false; |
| 51 | $allConstraint = null; |
| 52 | foreach ($metadata->getPropertyMetadata($property) as $propertyMetadata) { |
| 53 | // Enabling or disabling auto-mapping explicitly always takes precedence |
| 54 | if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) { |
| 55 | continue 2; |
| 56 | } |
| 57 | if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) { |
| 58 | $enabledForProperty = \true; |
| 59 | } |
| 60 | foreach ($propertyMetadata->getConstraints() as $constraint) { |
| 61 | if ($constraint instanceof Type) { |
| 62 | $hasTypeConstraint = \true; |
| 63 | } elseif ($constraint instanceof NotNull) { |
| 64 | $hasNotNullConstraint = \true; |
| 65 | } elseif ($constraint instanceof NotBlank) { |
| 66 | $hasNotBlankConstraint = \true; |
| 67 | } elseif ($constraint instanceof All) { |
| 68 | $allConstraint = $constraint; |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | if (!$enabledForProperty) { |
| 73 | continue; |
| 74 | } |
| 75 | $loaded = \true; |
| 76 | $builtinTypes = []; |
| 77 | $nullable = \false; |
| 78 | $scalar = \true; |
| 79 | foreach ($types as $type) { |
| 80 | $builtinTypes[] = $type->getBuiltinType(); |
| 81 | if ($scalar && !\in_array($type->getBuiltinType(), [PropertyInfoType::BUILTIN_TYPE_INT, PropertyInfoType::BUILTIN_TYPE_FLOAT, PropertyInfoType::BUILTIN_TYPE_STRING, PropertyInfoType::BUILTIN_TYPE_BOOL], \true)) { |
| 82 | $scalar = \false; |
| 83 | } |
| 84 | if (!$nullable && $type->isNullable()) { |
| 85 | $nullable = \true; |
| 86 | } |
| 87 | } |
| 88 | if (!$hasTypeConstraint) { |
| 89 | if (1 === \count($builtinTypes)) { |
| 90 | if ($types[0]->isCollection() && \count($collectionValueType = $types[0]->getCollectionValueTypes()) > 0) { |
| 91 | [$collectionValueType] = $collectionValueType; |
| 92 | $this->handleAllConstraint($property, $allConstraint, $collectionValueType, $metadata); |
| 93 | } |
| 94 | $metadata->addPropertyConstraint($property, $this->getTypeConstraint($builtinTypes[0], $types[0])); |
| 95 | } elseif ($scalar) { |
| 96 | $metadata->addPropertyConstraint($property, new Type(['type' => 'scalar'])); |
| 97 | } |
| 98 | } |
| 99 | if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) { |
| 100 | $metadata->addPropertyConstraint($property, new NotNull()); |
| 101 | } |
| 102 | } |
| 103 | return $loaded; |
| 104 | } |
| 105 | private function getTypeConstraint(string $builtinType, PropertyInfoType $type) : Type |
| 106 | { |
| 107 | if (PropertyInfoType::BUILTIN_TYPE_OBJECT === $builtinType && null !== ($className = $type->getClassName())) { |
| 108 | return new Type(['type' => $className]); |
| 109 | } |
| 110 | return new Type(['type' => $builtinType]); |
| 111 | } |
| 112 | private function handleAllConstraint(string $property, ?All $allConstraint, PropertyInfoType $propertyInfoType, ClassMetadata $metadata) |
| 113 | { |
| 114 | $containsTypeConstraint = \false; |
| 115 | $containsNotNullConstraint = \false; |
| 116 | if (null !== $allConstraint) { |
| 117 | foreach ($allConstraint->constraints as $constraint) { |
| 118 | if ($constraint instanceof Type) { |
| 119 | $containsTypeConstraint = \true; |
| 120 | } elseif ($constraint instanceof NotNull) { |
| 121 | $containsNotNullConstraint = \true; |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | $constraints = []; |
| 126 | if (!$containsNotNullConstraint && !$propertyInfoType->isNullable()) { |
| 127 | $constraints[] = new NotNull(); |
| 128 | } |
| 129 | if (!$containsTypeConstraint) { |
| 130 | $constraints[] = $this->getTypeConstraint($propertyInfoType->getBuiltinType(), $propertyInfoType); |
| 131 | } |
| 132 | if (null === $allConstraint) { |
| 133 | $metadata->addPropertyConstraint($property, new All(['constraints' => $constraints])); |
| 134 | } else { |
| 135 | $allConstraint->constraints = \array_merge($allConstraint->constraints, $constraints); |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 |