/**
  * @param FormInterface      $form
  * @param AttributeInterface $attribute
  * @param FamilyInterface    $family
  * @param DataInterface|null $data
  * @param array              $options
  *
  * @throws \Exception
  */
 protected function addAttribute(FormInterface $form, AttributeInterface $attribute, FamilyInterface $family, DataInterface $data = null, array $options = [])
 {
     if ($attribute->getOption('hidden')) {
         return;
     }
     if ($attribute->isMultiple() && $attribute->isCollection()) {
         $this->addMultipleAttribute($form, $attribute, $family, $data, $options);
     } else {
         $this->addSingleAttribute($form, $attribute, $family, $data, $options);
     }
 }
 /**
  * @param FamilyInterface    $parentFamily
  * @param AttributeInterface $attribute
  * @return string
  */
 protected function getTargetClass(FamilyInterface $parentFamily, AttributeInterface $attribute)
 {
     /** @var \Doctrine\ORM\Mapping\ClassMetadata $classMetadata */
     $classMetadata = $this->manager->getClassMetadata($parentFamily->getValueClass());
     try {
         $mapping = $classMetadata->getAssociationMapping($attribute->getType()->getDatabaseType());
     } catch (MappingException $e) {
         return null;
     }
     if (empty($mapping['targetEntity'])) {
         return null;
     }
     $type = $mapping['targetEntity'];
     if ($attribute->isMultiple()) {
         $type .= '[]';
     }
     return '\\' . $type;
 }
 /**
  * @param AttributeInterface|null $attribute
  * @param array|null              $context
  *
  * @throws UnexpectedValueException
  * @throws AccessException
  * @throws InvalidArgumentException
  * @throws UnexpectedTypeException
  *
  * @return Collection|ValueInterface[]
  */
 protected function createDefaultValues(AttributeInterface $attribute = null, array $context = null)
 {
     $default = $attribute->getDefault();
     if (!$attribute->isMultiple()) {
         $default = [$default];
     }
     return $this->setInternalValuesData($attribute, $default, $context);
 }
 /**
  * @param ExecutionContextInterface $context
  * @param AttributeInterface        $attribute
  * @param DataInterface             $data
  *
  * @throws Exception
  */
 protected function validateRules(ExecutionContextInterface $context, AttributeInterface $attribute, DataInterface $data)
 {
     if ($attribute->isMultiple()) {
         $valueData = $data->getValuesData($attribute);
     } else {
         $valueData = $data->getValueData($attribute);
     }
     $loader = new BaseLoader();
     foreach ($attribute->getValidationRules() as $validationRule) {
         foreach ($validationRule as $item => $options) {
             $constraint = $loader->newConstraint($item, $options);
             $violations = $context->getValidator()->validate($valueData, $constraint, $context->getGroup());
             /** @var ConstraintViolationInterface $violation */
             foreach ($violations as $violation) {
                 /** @noinspection DisconnectedForeachInstructionInspection */
                 $path = $attribute->getCode();
                 if ($attribute->getType()->isEmbedded()) {
                     if (!$attribute->isMultiple()) {
                         $path .= '.';
                     }
                     $path .= $violation->getPropertyPath();
                 }
                 if ($violation->getMessage()) {
                     $context->buildViolation($violation->getMessage())->atPath($path)->setInvalidValue($valueData)->addViolation();
                 } else {
                     $this->buildAttributeViolation($context, $attribute, strtolower($item), $valueData, $path);
                 }
             }
         }
     }
 }