Spaces:
No application file
No application file
| namespace Mautic\FormBundle\Helper; | |
| use Mautic\CoreBundle\Helper\AbstractFormFieldHelper; | |
| use Mautic\CoreBundle\Helper\InputHelper; | |
| use Mautic\CoreBundle\Translation\Translator; | |
| use Mautic\FormBundle\Entity\Field; | |
| use Symfony\Component\Validator\Constraints\Blank; | |
| use Symfony\Component\Validator\Constraints\Email; | |
| use Symfony\Component\Validator\Constraints\EqualTo; | |
| use Symfony\Component\Validator\Constraints\NotBlank; | |
| use Symfony\Component\Validator\Constraints\Url; | |
| use Symfony\Component\Validator\ConstraintViolation; | |
| use Symfony\Component\Validator\ConstraintViolationList; | |
| use Symfony\Component\Validator\Validation; | |
| use Symfony\Component\Validator\Validator\ValidatorInterface; | |
| class FormFieldHelper extends AbstractFormFieldHelper | |
| { | |
| private ?ValidatorInterface $validator; | |
| private array $types = [ | |
| 'captcha' => [ | |
| 'constraints' => [ | |
| NotBlank::class => ['message' => 'mautic.form.submission.captcha.invalid'], | |
| EqualTo::class => ['message' => 'mautic.form.submission.captcha.invalid'], | |
| Blank::class => ['message' => 'mautic.form.submission.captcha.invalid'], | |
| ], | |
| ], | |
| 'checkboxgrp' => [], | |
| 'country' => [], | |
| 'date' => [], | |
| 'datetime' => [], | |
| 'email' => [ | |
| 'filter' => 'email', | |
| 'constraints' => [ | |
| Email::class => ['message' => 'mautic.form.submission.email.invalid'], | |
| ], | |
| ], | |
| 'freetext' => [], | |
| 'freehtml' => [], | |
| 'hidden' => [], | |
| 'number' => [ | |
| 'filter' => 'float', | |
| ], | |
| 'pagebreak' => [], | |
| 'password' => [], | |
| 'radiogrp' => [], | |
| 'select' => [], | |
| 'tel' => [], | |
| 'text' => [], | |
| 'textarea' => [], | |
| 'url' => [ | |
| 'filter' => 'url', | |
| 'constraints' => [ | |
| Url::class => ['message' => 'mautic.form.submission.url.invalid'], | |
| ], | |
| ], | |
| 'file' => [], | |
| ]; | |
| public function __construct(Translator $translator, ValidatorInterface $validator = null) | |
| { | |
| $this->translator = $translator; | |
| if (null === $validator) { | |
| $validator = $validator = Validation::createValidator(); | |
| } | |
| $this->validator = $validator; | |
| parent::__construct(); | |
| } | |
| /** | |
| * Set the translation key prefix. | |
| */ | |
| public function setTranslationKeyPrefix(): void | |
| { | |
| $this->translationKeyPrefix = 'mautic.form.field.type.'; | |
| } | |
| /** | |
| * @param array $customFields | |
| * | |
| * @deprecated to be removed in 3.0; use getChoiceList($customFields = []) instead | |
| * | |
| * @return array | |
| */ | |
| public function getList($customFields = []) | |
| { | |
| return $this->getChoiceList($customFields); | |
| } | |
| /** | |
| * @return array | |
| */ | |
| public function getTypes() | |
| { | |
| return $this->types; | |
| } | |
| /** | |
| * Get fields input filter. | |
| * | |
| * @return string | |
| */ | |
| public function getFieldFilter($type) | |
| { | |
| if (array_key_exists($type, $this->types)) { | |
| return $this->types[$type]['filter'] ?? 'clean'; | |
| } | |
| return 'alphanum'; | |
| } | |
| /** | |
| * @param Field $f | |
| */ | |
| public function validateFieldValue($type, $value, $f = null): array | |
| { | |
| $errors = []; | |
| if (isset($this->types[$type]['constraints'])) { | |
| foreach ($this->types[$type]['constraints'] as $constraint => $opts) { | |
| // don't check empty values unless the constraint is NotBlank | |
| if (NotBlank::class === $constraint && empty($value)) { | |
| continue; | |
| } | |
| if ('captcha' == $type) { | |
| $captcha = $f->getProperties()['captcha']; | |
| if (empty($captcha) && Blank::class !== $constraint) { | |
| // Used as a honeypot | |
| $captcha = ''; | |
| } elseif (Blank::class === $constraint) { | |
| continue; | |
| } | |
| if (EqualTo::class == $constraint) { | |
| $opts['value'] = $captcha; | |
| } | |
| } | |
| /** @var ConstraintViolationList $violations */ | |
| $violations = $this->validator->validate($value, new $constraint($opts)); | |
| if (count($violations)) { | |
| /** @var ConstraintViolation $v */ | |
| foreach ($violations as $v) { | |
| $transParameters = $v->getParameters(); | |
| if (null !== $f) { | |
| $transParameters['%label%'] = '"'.$f->getLabel().'"'; | |
| } | |
| $errors[] = $this->translator->trans($v->getMessage(), $transParameters, 'validators'); | |
| } | |
| } | |
| } | |
| } | |
| return $errors; | |
| } | |
| /** | |
| * Search and replace the HTML of the form field with the value. | |
| */ | |
| public function populateField($field, $value, $formName, &$formHtml): void | |
| { | |
| $alias = $field->getAlias(); | |
| switch ($field->getType()) { | |
| case 'text': | |
| case 'number': | |
| case 'email': | |
| case 'hidden': | |
| case 'tel': | |
| case 'url': | |
| case 'date': | |
| case 'datetime': | |
| if ('tel' === $field->getType()) { | |
| $sanitizedValue = InputHelper::clean($value); | |
| } else { | |
| $sanitizedValue = $this->sanitizeValue($value); | |
| } | |
| if (preg_match('/<input(.*?)value="(.*?)"(.*?)id="mauticform_input_'.$formName.'_'.$alias.'"(.*?)\/?>/i', $formHtml, $match)) { | |
| $replace = '<input'.$match[1].'id="mauticform_input_'.$formName.'_'.$alias.'"'.$match[3].'value="'.$sanitizedValue.'"' | |
| .$match[4].'/>'; | |
| $formHtml = str_replace($match[0], $replace, $formHtml); | |
| } | |
| break; | |
| case 'textarea': | |
| if (preg_match('/<textarea(.*?)id="mauticform_input_'.$formName.'_'.$alias.'"(.*?)>(.*?)<\/textarea>/i', $formHtml, $match)) { | |
| $replace = '<textarea'.$match[1].'id="mauticform_input_'.$formName.'_'.$alias.'"'.$match[2].'>'.$this->sanitizeValue($value).'</textarea>'; | |
| $formHtml = str_replace($match[0], $replace, $formHtml); | |
| } | |
| break; | |
| case 'checkboxgrp': | |
| $separator = urlencode('|'); | |
| if (is_string($value) && strrpos($value, $separator) > 0) { | |
| $value = explode($separator, $value); | |
| } elseif (!is_array($value)) { | |
| $value = [$value]; | |
| } | |
| foreach ($value as $val) { | |
| $val = $this->sanitizeValue($val); | |
| if (preg_match( | |
| '/<input(.*?)id="mauticform_checkboxgrp_checkbox_'.$alias.'(.*?)"(.*?)value="'.$val.'"(.*?)\/?>/i', | |
| $formHtml, | |
| $match | |
| )) { | |
| $replace = '<input'.$match[1].'id="mauticform_checkboxgrp_checkbox_'.$alias.$match[2].'"'.$match[3].'value="'.$val.'"' | |
| .$match[4].' checked />'; | |
| $formHtml = str_replace($match[0], $replace, $formHtml); | |
| } | |
| } | |
| break; | |
| case 'radiogrp': | |
| $value = $this->sanitizeValue($value); | |
| if (preg_match('/<input(.*?)id="mauticform_radiogrp_radio_'.$alias.'(.*?)"(.*?)value="'.$value.'"(.*?)\/?>/i', $formHtml, $match)) { | |
| $replace = '<input'.$match[1].'id="mauticform_radiogrp_radio_'.$alias.$match[2].'"'.$match[3].'value="'.$value.'"'.$match[4] | |
| .' checked />'; | |
| $formHtml = str_replace($match[0], $replace, $formHtml); | |
| } | |
| break; | |
| case 'select': | |
| case 'country': | |
| $regex = '/<select\s*id="mauticform_input_'.$formName.'_'.$alias.'"(.*?)<\/select>/is'; | |
| if (preg_match($regex, $formHtml, $match)) { | |
| $origText = $match[0]; | |
| $replace = str_replace( | |
| '<option value="'.$this->sanitizeValue($value).'">', | |
| '<option value="'.$this->sanitizeValue($value).'" selected="selected">', | |
| $origText | |
| ); | |
| $formHtml = str_replace($origText, $replace, $formHtml); | |
| } | |
| break; | |
| } | |
| } | |
| /** | |
| * @param string $value | |
| * | |
| * @return string | |
| */ | |
| public function sanitizeValue($value) | |
| { | |
| $valueType = gettype($value); | |
| $value = str_replace(['"', '>', '<'], ['"', '>', '<'], strip_tags(rawurldecode($value))); | |
| // for boolean expect 0 or 1 | |
| if ('boolean' === $valueType) { | |
| return (int) $value; | |
| } | |
| return $value; | |
| } | |
| } | |