<?php
namespace MailPoetVendor\Symfony\Component\Validator\Mapping\Loader;
if (!defined('ABSPATH')) exit;
use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use MailPoetVendor\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use MailPoetVendor\Symfony\Component\PropertyInfo\Type as PropertyInfoType;
use MailPoetVendor\Symfony\Component\Validator\Constraints\All;
use MailPoetVendor\Symfony\Component\Validator\Constraints\NotBlank;
use MailPoetVendor\Symfony\Component\Validator\Constraints\NotNull;
use MailPoetVendor\Symfony\Component\Validator\Constraints\Type;
use MailPoetVendor\Symfony\Component\Validator\Mapping\AutoMappingStrategy;
use MailPoetVendor\Symfony\Component\Validator\Mapping\ClassMetadata;
final class PropertyInfoLoader implements LoaderInterface
{
 use AutoMappingTrait;
 private $listExtractor;
 private $typeExtractor;
 private $accessExtractor;
 private $classValidatorRegexp;
 public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, PropertyAccessExtractorInterface $accessExtractor, ?string $classValidatorRegexp = null)
 {
 $this->listExtractor = $listExtractor;
 $this->typeExtractor = $typeExtractor;
 $this->accessExtractor = $accessExtractor;
 $this->classValidatorRegexp = $classValidatorRegexp;
 }
 public function loadClassMetadata(ClassMetadata $metadata) : bool
 {
 $className = $metadata->getClassName();
 if (!($properties = $this->listExtractor->getProperties($className))) {
 return \false;
 }
 $loaded = \false;
 $enabledForClass = $this->isAutoMappingEnabledForClass($metadata, $this->classValidatorRegexp);
 foreach ($properties as $property) {
 if (\false === $this->accessExtractor->isWritable($className, $property)) {
 continue;
 }
 if (!\property_exists($className, $property)) {
 continue;
 }
 $types = $this->typeExtractor->getTypes($className, $property);
 if (null === $types) {
 continue;
 }
 $enabledForProperty = $enabledForClass;
 $hasTypeConstraint = \false;
 $hasNotNullConstraint = \false;
 $hasNotBlankConstraint = \false;
 $allConstraint = null;
 foreach ($metadata->getPropertyMetadata($property) as $propertyMetadata) {
 // Enabling or disabling auto-mapping explicitly always takes precedence
 if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) {
 continue 2;
 }
 if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) {
 $enabledForProperty = \true;
 }
 foreach ($propertyMetadata->getConstraints() as $constraint) {
 if ($constraint instanceof Type) {
 $hasTypeConstraint = \true;
 } elseif ($constraint instanceof NotNull) {
 $hasNotNullConstraint = \true;
 } elseif ($constraint instanceof NotBlank) {
 $hasNotBlankConstraint = \true;
 } elseif ($constraint instanceof All) {
 $allConstraint = $constraint;
 }
 }
 }
 if (!$enabledForProperty) {
 continue;
 }
 $loaded = \true;
 $builtinTypes = [];
 $nullable = \false;
 $scalar = \true;
 foreach ($types as $type) {
 $builtinTypes[] = $type->getBuiltinType();
 if ($scalar && !\in_array($type->getBuiltinType(), [PropertyInfoType::BUILTIN_TYPE_INT, PropertyInfoType::BUILTIN_TYPE_FLOAT, PropertyInfoType::BUILTIN_TYPE_STRING, PropertyInfoType::BUILTIN_TYPE_BOOL], \true)) {
 $scalar = \false;
 }
 if (!$nullable && $type->isNullable()) {
 $nullable = \true;
 }
 }
 if (!$hasTypeConstraint) {
 if (1 === \count($builtinTypes)) {
 if ($types[0]->isCollection() && \count($collectionValueType = $types[0]->getCollectionValueTypes()) > 0) {
 [$collectionValueType] = $collectionValueType;
 $this->handleAllConstraint($property, $allConstraint, $collectionValueType, $metadata);
 }
 $metadata->addPropertyConstraint($property, $this->getTypeConstraint($builtinTypes[0], $types[0]));
 } elseif ($scalar) {
 $metadata->addPropertyConstraint($property, new Type(['type' => 'scalar']));
 }
 }
 if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) {
 $metadata->addPropertyConstraint($property, new NotNull());
 }
 }
 return $loaded;
 }
 private function getTypeConstraint(string $builtinType, PropertyInfoType $type) : Type
 {
 if (PropertyInfoType::BUILTIN_TYPE_OBJECT === $builtinType && null !== ($className = $type->getClassName())) {
 return new Type(['type' => $className]);
 }
 return new Type(['type' => $builtinType]);
 }
 private function handleAllConstraint(string $property, ?All $allConstraint, PropertyInfoType $propertyInfoType, ClassMetadata $metadata)
 {
 $containsTypeConstraint = \false;
 $containsNotNullConstraint = \false;
 if (null !== $allConstraint) {
 foreach ($allConstraint->constraints as $constraint) {
 if ($constraint instanceof Type) {
 $containsTypeConstraint = \true;
 } elseif ($constraint instanceof NotNull) {
 $containsNotNullConstraint = \true;
 }
 }
 }
 $constraints = [];
 if (!$containsNotNullConstraint && !$propertyInfoType->isNullable()) {
 $constraints[] = new NotNull();
 }
 if (!$containsTypeConstraint) {
 $constraints[] = $this->getTypeConstraint($propertyInfoType->getBuiltinType(), $propertyInfoType);
 }
 if (null === $allConstraint) {
 $metadata->addPropertyConstraint($property, new All(['constraints' => $constraints]));
 } else {
 $allConstraint->constraints = \array_merge($allConstraint->constraints, $constraints);
 }
 }
}
