| <?php |
| |
| namespace OpenObjects\Bundle\CoreBundle\Service; |
| |
| use OpenObjects\Bundle\StyleGuideBundle\Form\FieldType\FieldsetComponentType; |
| use Symfony\Component\Form\Form; |
| use Symfony\Component\Form\FormError; |
| use Symfony\Component\PropertyAccess\PropertyAccess; |
| use Symfony\Component\PropertyAccess\PropertyPath; |
| use Symfony\Component\Validator\ConstraintViolation; |
| |
| |
| |
| |
| |
| class FormErrorsSerializer |
| { |
| |
| |
| |
| private $breakErrorLoop = false; |
| |
| |
| |
| |
| private $originalFormErrors = []; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function serializeFormErrors(Form $form, $flatArray = false, $addFormName = false, $glueKeys = '_') |
| { |
| $errors = []; |
| $errors['global'] = []; |
| $errors['fields'] = []; |
| |
| foreach ($form->getErrors() as $error) { |
| $errors['global'][] = $error->getMessage(); |
| } |
| |
| $errors['fields'] = $this->serialize($form); |
| |
| if ($flatArray) { |
| $errors['fields'] = $this->arrayFlatten( |
| $errors['fields'], |
| $glueKeys, |
| (($addFormName) ? $form->getName() : '') |
| ); |
| } |
| |
| return $errors; |
| } |
| |
| |
| |
| |
| |
| |
| |
| private function serialize(Form $form) : array |
| { |
| $localErrors = []; |
| |
| if ($form->getErrors()->count() > 0) { |
| foreach ($form->getErrors() as $error) { |
| $localErrors = $this->buildErrorArray($error); |
| } |
| } else { |
| foreach ($form->getIterator() as $key => $child) { |
| foreach ($child->getErrors() as $error) { |
| if (!empty($this->serialize($child))) { |
| $localErrors[$key] = $this->buildErrorArray($error); |
| } |
| } |
| |
| if (count($child->getIterator()) > 0 && ($child instanceof Form)) { |
| if (!empty($this->serialize($child))) { |
| $localErrors[$key] = $this->serialize($child); |
| } |
| } |
| } |
| } |
| |
| return $localErrors; |
| } |
| |
| |
| |
| |
| |
| public function unserialize(Form &$form, array $errors) |
| { |
| foreach ($errors as $field => $error) { |
| if ($this->breakErrorLoop) { |
| break; |
| } |
| |
| if (count($errors) > 0 && !isset($error['message'])) { |
| if ($this->isFieldset($form, $field) && !empty($error)) { |
| $form->get($field)->addError( |
| new FormError( |
| ucfirst(str_replace('_', ' ', $field)) . ' is invalid.' |
| ) |
| ); |
| } |
| |
| $this->unserialize($form, $error); |
| } else { |
| $this->searchForm($form, $field, $error); |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| private function isFieldset(Form $form, $field) : bool |
| { |
| if ($form->has($field)) { |
| return $form->get($field) |
| ->getConfig() |
| ->getType() |
| ->getInnerType() instanceof FieldsetComponentType; |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| private function searchForm(Form &$form, string $needle, array $error) |
| { |
| $searchKey = $form->getName(); |
| |
| |
| if (!$form->getParent()) { |
| $searchKey = $needle; |
| } |
| |
| if ($form->has($needle) && $this->keyExists($this->originalFormErrors['fields'], $searchKey)) { |
| $addError = true; |
| |
| foreach ($form->get($needle)->getErrors() as $item) { |
| if ($item->getMessage() == $error['message']) { |
| $addError = false; |
| } |
| } |
| |
| if ($addError) { |
| $formError = $this->createNewFormError($form, $error, $needle); |
| $form->get($needle)->addError($formError); |
| } |
| } else { |
| $originalFormErrors = $this->originalFormErrors; |
| |
| foreach ($form->getIterator() as $key => $child) { |
| if (isset($this->originalFormErrors['fields'][$key])) { |
| $originalFormErrors = $this->originalFormErrors['fields'][$key]; |
| } |
| |
| if (!$child instanceof Form) { |
| continue; |
| } |
| |
| $childIterator = $child->getIterator(); |
| |
| $numItems = $childIterator->count(); |
| $counter = 0; |
| |
| foreach ($childIterator as $name => $field) { |
| if ($this->isTimestamp($name)) { |
| foreach ($originalFormErrors as $fieldName => $fieldValue) { |
| |
| $epochName = str_replace('.', '', ($fieldName/1000)); |
| |
| if ($name == $epochName) { |
| if ($child->get($name)->getErrors()->count() === 0) { |
| $formError = $this->createNewFormError($field, $error, $needle); |
| if ($child->get($name)->has($needle)) { |
| $child->get($name)->get($needle)->addError($formError); |
| } |
| } |
| } |
| } |
| |
| if (++$counter === $numItems) { |
| $this->breakErrorLoop = true; |
| break 2; |
| } |
| } |
| } |
| |
| if ($form->get($key)->has($needle) && isset($originalFormErrors[$key])) { |
| $formError = $this->createNewFormError($child, $error, $needle); |
| $form->get($key)->get($needle)->addError($formError); |
| |
| |
| unset($this->originalFormErrors['fields'][$key][$needle]); |
| |
| break; |
| } |
| |
| if (count($child->getIterator()) > 0 && ($child instanceof Form)) { |
| $this->searchForm($child, $needle, $error); |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| private function isTimestamp($timestamp) : bool |
| { |
| $check = (is_int($timestamp) OR is_float($timestamp)) |
| ? $timestamp |
| : (string) (int) $timestamp; |
| return ($check === $timestamp) |
| && ( (int) $timestamp <= PHP_INT_MAX) |
| && ( (int) $timestamp >= ~PHP_INT_MAX) |
| && $check != 0; |
| } |
| |
| |
| |
| |
| |
| |
| private function buildErrorArray(FormError $errorIn) : array |
| { |
| $errorOut = []; |
| |
| $errorOut['message'] = $errorIn->getMessage(); |
| $errorOut['messageTemplate'] = $errorIn->getMessageTemplate(); |
| $errorOut['messagePluralization'] = $errorIn->getMessagePluralization(); |
| $errorOut['messageParameters'] = $errorIn->getMessageParameters(); |
| |
| if ($errorCause = $errorIn->getCause()) { |
| $errorOut['cause']['message'] = $errorCause->getMessage(); |
| $errorOut['cause']['messageTemplate'] = $errorCause->getMessageTemplate(); |
| $errorOut['cause']['parameters'] = $errorCause->getParameters(); |
| $errorOut['cause']['plural'] = $errorCause->getPlural(); |
| $errorOut['cause']['propertyPath'] = $errorCause->getPropertyPath(); |
| $errorOut['cause']['invalidValue'] = $errorCause->getInvalidValue(); |
| $errorOut['cause']['constraint'] = serialize($errorCause->getConstraint()); |
| $errorOut['cause']['code'] = $errorCause->getCode(); |
| $errorOut['cause']['cause'] = $errorCause->getCause(); |
| } |
| |
| return $errorOut; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| private function createNewFormError(Form $form, $error, $field) : FormError |
| { |
| if (isset($error['cause']['cause'])) { |
| $error['cause']['propertyPath'] = |
| $error['cause']['cause']['propertyPath'] ?? 'children[' . $field . '].data'; |
| $error['cause']['invalidValue'] = $error['cause']['cause']['invalidValue'] ?? null; |
| $error['cause']['plural'] = $error['cause']['cause']['plural'] ?? null; |
| $error['cause']['code'] = $error['cause']['cause']['code'] ?? null; |
| $error['cause']['constraint'] = $error['cause']['cause']['constraint'] ?? null; |
| } |
| |
| $constraint = null; |
| |
| if (isset($error['cause']['constraint'])) { |
| $constraint = unserialize($error['cause']['constraint']); |
| } |
| |
| return new FormError( |
| $error['message'], |
| $error['messageTemplate'] ?? null, |
| $error['messageParameters'] ?? [], |
| $error['messagePluralization'] ?? null, |
| new ConstraintViolation( |
| $error['cause']['message'], |
| $error['cause']['messageTemplate'], |
| $error['cause']['parameters'], |
| $form, |
| $error['cause']['propertyPath'] ?? $field . '.data', |
| $error['cause']['invalidValue'] ?? '', |
| $error['cause']['plural'] ?? null, |
| $error['cause']['code'] ?? null, |
| $constraint, |
| $error['cause']['cause'] ?? null |
| ) |
| ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| private function arrayFlatten(array $array, string $separator = '_', string $flattenedKey = '') : array |
| { |
| $flattenedArray = []; |
| |
| foreach ($array as $key => $value) { |
| if (is_array($value)) { |
| $flattenedArray = array_merge( |
| $flattenedArray, |
| $this->arrayFlatten( |
| $value, |
| $separator, |
| ( |
| strlen($flattenedKey) > 0 ? $flattenedKey . $separator : "" |
| ) . $key |
| ) |
| ); |
| } else { |
| $flattenedArray[(strlen($flattenedKey) > 0 ? $flattenedKey . $separator : "") . $key] = $value; |
| } |
| } |
| |
| return $flattenedArray; |
| } |
| |
| |
| |
| |
| |
| |
| |
| protected function keyExists($array, $keySearch) |
| { |
| foreach ($array as $key => $item) { |
| if ( |
| $key == $keySearch || |
| (is_array($item) && $this->keyExists($item, $keySearch)) |
| ) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| |
| |
| public function setOriginalFormErrors(array $errors) : FormErrorsSerializer |
| { |
| $this->originalFormErrors = $errors; |
| |
| return $this; |
| } |
| |
| |
| |
| |
| public function getOriginalFormErrors() : array |
| { |
| return $this->originalFormErrors; |
| } |
| } |