152 lines
9.4 KiB
YAML
152 lines
9.4 KiB
YAML
|
name: ViolationMapper
|
||
|
class_comment: '# * @author Bernhard Schussek <bschussek@gmail.com>'
|
||
|
dependencies:
|
||
|
- name: FileUploadError
|
||
|
type: class
|
||
|
source: Symfony\Component\Form\FileUploadError
|
||
|
- name: FormError
|
||
|
type: class
|
||
|
source: Symfony\Component\Form\FormError
|
||
|
- name: FormInterface
|
||
|
type: class
|
||
|
source: Symfony\Component\Form\FormInterface
|
||
|
- name: FormRendererInterface
|
||
|
type: class
|
||
|
source: Symfony\Component\Form\FormRendererInterface
|
||
|
- name: InheritDataAwareIterator
|
||
|
type: class
|
||
|
source: Symfony\Component\Form\Util\InheritDataAwareIterator
|
||
|
- name: PropertyPathBuilder
|
||
|
type: class
|
||
|
source: Symfony\Component\PropertyAccess\PropertyPathBuilder
|
||
|
- name: PropertyPathIterator
|
||
|
type: class
|
||
|
source: Symfony\Component\PropertyAccess\PropertyPathIterator
|
||
|
- name: PropertyPathIteratorInterface
|
||
|
type: class
|
||
|
source: Symfony\Component\PropertyAccess\PropertyPathIteratorInterface
|
||
|
- name: File
|
||
|
type: class
|
||
|
source: Symfony\Component\Validator\Constraints\File
|
||
|
- name: ConstraintViolation
|
||
|
type: class
|
||
|
source: Symfony\Component\Validator\ConstraintViolation
|
||
|
- name: TranslatorInterface
|
||
|
type: class
|
||
|
source: Symfony\Contracts\Translation\TranslatorInterface
|
||
|
properties: []
|
||
|
methods:
|
||
|
- name: matchChild
|
||
|
visibility: private
|
||
|
parameters:
|
||
|
- name: form
|
||
|
- name: it
|
||
|
comment: "# * @author Bernhard Schussek <bschussek@gmail.com>\n# */\n# class ViolationMapper\
|
||
|
\ implements ViolationMapperInterface\n# {\n# private bool $allowNonSynchronized\
|
||
|
\ = false;\n# \n# public function __construct(\n# private ?FormRendererInterface\
|
||
|
\ $formRenderer = null,\n# private ?TranslatorInterface $translator = null,\n\
|
||
|
# ) {\n# }\n# \n# public function mapViolation(ConstraintViolation $violation,\
|
||
|
\ FormInterface $form, bool $allowNonSynchronized = false): void\n# {\n# $this->allowNonSynchronized\
|
||
|
\ = $allowNonSynchronized;\n# \n# // The scope is the currently found most specific\
|
||
|
\ form that\n# // an error should be mapped to. After setting the scope, the\n\
|
||
|
# // mapper will try to continue to find more specific matches in\n# // the children\
|
||
|
\ of scope. If it cannot, the error will be\n# // mapped to this scope.\n# $scope\
|
||
|
\ = null;\n# \n# $violationPath = null;\n# $relativePath = null;\n# $match = false;\n\
|
||
|
# \n# // Don't create a ViolationPath instance for empty property paths\n# if\
|
||
|
\ ('' !== $violation->getPropertyPath()) {\n# $violationPath = new ViolationPath($violation->getPropertyPath());\n\
|
||
|
# $relativePath = $this->reconstructPath($violationPath, $form);\n# }\n# \n# //\
|
||
|
\ This case happens if the violation path is empty and thus\n# // the violation\
|
||
|
\ should be mapped to the root form\n# if (null === $violationPath) {\n# $scope\
|
||
|
\ = $form;\n# }\n# \n# // In general, mapping happens from the root form to the\
|
||
|
\ leaf forms\n# // First, the rules of the root form are applied to determine\n\
|
||
|
# // the subsequent descendant. The rules of this descendant are then\n# // applied\
|
||
|
\ to find the next and so on, until we have found the\n# // most specific form\
|
||
|
\ that matches the violation.\n# \n# // If any of the forms found in this process\
|
||
|
\ is not synchronized,\n# // mapping is aborted. Non-synchronized forms could\
|
||
|
\ not reverse\n# // transform the value entered by the user, thus any further\
|
||
|
\ violations\n# // caused by the (invalid) reverse transformed value should be\n\
|
||
|
# // ignored.\n# \n# if (null !== $relativePath) {\n# // Set the scope to the\
|
||
|
\ root of the relative path\n# // This root will usually be $form. If the path\
|
||
|
\ contains\n# // an unmapped form though, the last unmapped form found\n# // will\
|
||
|
\ be the root of the path.\n# $scope = $relativePath->getRoot();\n# $it = new\
|
||
|
\ PropertyPathIterator($relativePath);\n# \n# while ($this->acceptsErrors($scope)\
|
||
|
\ && null !== ($child = $this->matchChild($scope, $it))) {\n# $scope = $child;\n\
|
||
|
# $it->next();\n# $match = true;\n# }\n# }\n# \n# // This case happens if an error\
|
||
|
\ happened in the data under a\n# // form inheriting its parent data that does\
|
||
|
\ not match any of the\n# // children of that form.\n# if (null !== $violationPath\
|
||
|
\ && !$match) {\n# // If we could not map the error to anything more specific\n\
|
||
|
# // than the root element, map it to the innermost directly\n# // mapped form\
|
||
|
\ of the violation path\n# // e.g. \"children[foo].children[bar].data.baz\"\n\
|
||
|
# // Here the innermost directly mapped child is \"bar\"\n# \n# $scope = $form;\n\
|
||
|
# $it = new ViolationPathIterator($violationPath);\n# \n# // Note: acceptsErrors()\
|
||
|
\ will always return true for forms inheriting\n# // their parent data, because\
|
||
|
\ these forms can never be non-synchronized\n# // (they don't do any data transformation\
|
||
|
\ on their own)\n# while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm())\
|
||
|
\ {\n# if (!$scope->has($it->current())) {\n# // Break if we find a reference\
|
||
|
\ to a non-existing child\n# break;\n# }\n# \n# $scope = $scope->get($it->current());\n\
|
||
|
# $it->next();\n# }\n# }\n# \n# // Follow dot rules until we have the final target\n\
|
||
|
# $mapping = $scope->getConfig()->getOption('error_mapping');\n# \n# while ($this->acceptsErrors($scope)\
|
||
|
\ && isset($mapping['.'])) {\n# $dotRule = new MappingRule($scope, '.', $mapping['.']);\n\
|
||
|
# $scope = $dotRule->getTarget();\n# $mapping = $scope->getConfig()->getOption('error_mapping');\n\
|
||
|
# }\n# \n# // Only add the error if the form is synchronized\n# if ($this->acceptsErrors($scope))\
|
||
|
\ {\n# if ($violation->getConstraint() instanceof File && (string) \\UPLOAD_ERR_INI_SIZE\
|
||
|
\ === $violation->getCode()) {\n# $errorsTarget = $scope;\n# \n# while (null !==\
|
||
|
\ $errorsTarget->getParent() && $errorsTarget->getConfig()->getErrorBubbling())\
|
||
|
\ {\n# $errorsTarget = $errorsTarget->getParent();\n# }\n# \n# $errors = $errorsTarget->getErrors();\n\
|
||
|
# $errorsTarget->clearErrors();\n# \n# foreach ($errors as $error) {\n# if (!$error\
|
||
|
\ instanceof FileUploadError) {\n# $errorsTarget->addError($error);\n# }\n# }\n\
|
||
|
# }\n# \n# $message = $violation->getMessage();\n# $messageTemplate = $violation->getMessageTemplate();\n\
|
||
|
# \n# if (str_contains($message, '{{ label }}') || str_contains($messageTemplate,\
|
||
|
\ '{{ label }}')) {\n# $form = $scope;\n# \n# do {\n# $labelFormat = $form->getConfig()->getOption('label_format');\n\
|
||
|
# } while (null === $labelFormat && null !== $form = $form->getParent());\n# \n\
|
||
|
# if (null !== $labelFormat) {\n# $label = str_replace(\n# [\n# '%name%',\n# '%id%',\n\
|
||
|
# ],\n# [\n# $scope->getName(),\n# (string) $scope->getPropertyPath(),\n# ],\n\
|
||
|
# $labelFormat\n# );\n# } else {\n# $label = $scope->getConfig()->getOption('label');\n\
|
||
|
# }\n# \n# if (false !== $label) {\n# if (null === $label && null !== $this->formRenderer)\
|
||
|
\ {\n# $label = $this->formRenderer->humanize($scope->getName());\n# } else {\n\
|
||
|
# $label ??= $scope->getName();\n# }\n# \n# if (null !== $this->translator) {\n\
|
||
|
# $form = $scope;\n# $translationParameters[] = $form->getConfig()->getOption('label_translation_parameters',\
|
||
|
\ []);\n# \n# do {\n# $translationDomain = $form->getConfig()->getOption('translation_domain');\n\
|
||
|
# array_unshift(\n# $translationParameters,\n# $form->getConfig()->getOption('label_translation_parameters',\
|
||
|
\ [])\n# );\n# } while (null === $translationDomain && null !== $form = $form->getParent());\n\
|
||
|
# \n# $translationParameters = array_merge([], ...$translationParameters);\n#\
|
||
|
\ \n# $label = $this->translator->trans(\n# $label,\n# $translationParameters,\n\
|
||
|
# $translationDomain\n# );\n# }\n# \n# $message = str_replace('{{ label }}', $label,\
|
||
|
\ $message);\n# $messageTemplate = str_replace('{{ label }}', $label, $messageTemplate);\n\
|
||
|
# }\n# }\n# \n# $scope->addError(new FormError(\n# $message,\n# $messageTemplate,\n\
|
||
|
# $violation->getParameters(),\n# $violation->getPlural(),\n# $violation\n# ));\n\
|
||
|
# }\n# }\n# \n# /**\n# * Tries to match the beginning of the property path at\
|
||
|
\ the\n# * current position against the children of the scope.\n# *\n# * If a\
|
||
|
\ matching child is found, it is returned. Otherwise\n# * null is returned."
|
||
|
- name: reconstructPath
|
||
|
visibility: private
|
||
|
parameters:
|
||
|
- name: violationPath
|
||
|
- name: origin
|
||
|
comment: "# @var FormInterface $child */\n# foreach ($children as $i => $child)\
|
||
|
\ {\n# $childPath = (string) $child->getPropertyPath();\n# if ($childPath ===\
|
||
|
\ $chunk) {\n# $target = $child;\n# $foundAtIndex = $it->key();\n# } elseif (str_starts_with($childPath,\
|
||
|
\ $chunk)) {\n# continue;\n# }\n# \n# unset($children[$i]);\n# }\n# \n# $it->next();\n\
|
||
|
# }\n# \n# if (null !== $foundAtIndex) {\n# $it->seek($foundAtIndex);\n# }\n#\
|
||
|
\ \n# return $target;\n# }\n# \n# /**\n# * Reconstructs a property path from a\
|
||
|
\ violation path and a form tree."
|
||
|
- name: acceptsErrors
|
||
|
visibility: private
|
||
|
parameters:
|
||
|
- name: form
|
||
|
comment: null
|
||
|
traits:
|
||
|
- Symfony\Component\Form\FileUploadError
|
||
|
- Symfony\Component\Form\FormError
|
||
|
- Symfony\Component\Form\FormInterface
|
||
|
- Symfony\Component\Form\FormRendererInterface
|
||
|
- Symfony\Component\Form\Util\InheritDataAwareIterator
|
||
|
- Symfony\Component\PropertyAccess\PropertyPathBuilder
|
||
|
- Symfony\Component\PropertyAccess\PropertyPathIterator
|
||
|
- Symfony\Component\PropertyAccess\PropertyPathIteratorInterface
|
||
|
- Symfony\Component\Validator\Constraints\File
|
||
|
- Symfony\Component\Validator\ConstraintViolation
|
||
|
- Symfony\Contracts\Translation\TranslatorInterface
|
||
|
interfaces:
|
||
|
- ViolationMapperInterface
|