[Form] Fixed issues mentioned in the PR comments
This commit is contained in:
parent
7a4ba521c4
commit
ea5ff77121
@ -42,7 +42,7 @@ class CallbackTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param mixed $data The value in the original representation
|
||||
*
|
||||
* @return mixed The value in the transformed representation
|
||||
* @return mixed The value in the transformed representation
|
||||
*
|
||||
* @throws UnexpectedTypeException when the argument is not a string
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
@ -58,7 +58,7 @@ class CallbackTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param mixed $data The value in the transformed representation
|
||||
*
|
||||
* @return mixed The value in the original representation
|
||||
* @return mixed The value in the original representation
|
||||
*
|
||||
* @throws UnexpectedTypeException when the argument is not of the expected type
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
|
@ -41,7 +41,7 @@ interface DataTransformerInterface
|
||||
*
|
||||
* @param mixed $value The value in the original representation
|
||||
*
|
||||
* @return mixed The value in the transformed representation
|
||||
* @return mixed The value in the transformed representation
|
||||
*
|
||||
* @throws UnexpectedTypeException when the argument is not a string
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
@ -68,7 +68,7 @@ interface DataTransformerInterface
|
||||
*
|
||||
* @param mixed $value The value in the transformed representation
|
||||
*
|
||||
* @return mixed The value in the original representation
|
||||
* @return mixed The value in the original representation
|
||||
*
|
||||
* @throws UnexpectedTypeException when the argument is not of the expected type
|
||||
* @throws TransformationFailedException when the transformation fails
|
||||
|
@ -43,7 +43,7 @@ class BooleanToStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param Boolean $value Boolean value.
|
||||
*
|
||||
* @return string String value.
|
||||
* @return string String value.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a Boolean
|
||||
*/
|
||||
@ -65,7 +65,7 @@ class BooleanToStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param string $value String value.
|
||||
*
|
||||
* @return Boolean Boolean value.
|
||||
* @return Boolean Boolean value.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a string
|
||||
*/
|
||||
|
@ -46,7 +46,7 @@ class DataTransformerChain implements DataTransformerInterface
|
||||
*
|
||||
* @param mixed $value The original value
|
||||
*
|
||||
* @return mixed The transformed value
|
||||
* @return mixed The transformed value
|
||||
*
|
||||
* @throws Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @throws Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
@ -71,7 +71,7 @@ class DataTransformerChain implements DataTransformerInterface
|
||||
*
|
||||
* @param mixed $value The transformed value
|
||||
*
|
||||
* @return mixed The reverse-transformed value
|
||||
* @return mixed The reverse-transformed value
|
||||
*
|
||||
* @throws Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @throws Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
|
@ -53,7 +53,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
||||
*
|
||||
* @param DateTime $dateTime Normalized date.
|
||||
*
|
||||
* @return array Localized date.
|
||||
* @return array Localized date.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not an instance of \DateTime
|
||||
* @throws TransformationFailedException if the output timezone is not supported
|
||||
@ -108,7 +108,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
||||
*
|
||||
* @param array $value Localized date
|
||||
*
|
||||
* @return DateTime Normalized date
|
||||
* @return DateTime Normalized date
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not an array
|
||||
* @throws TransformationFailedException if the value could not bet transformed
|
||||
|
@ -48,7 +48,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
|
||||
*
|
||||
* @param DateTime $value A DateTime object
|
||||
*
|
||||
* @return string A value as produced by PHP's date() function
|
||||
* @return string A value as produced by PHP's date() function
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a \DateTime instance
|
||||
* @throws TransformationFailedException if the output timezone is not supported
|
||||
|
@ -27,7 +27,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
|
||||
*
|
||||
* @param DateTime $value A DateTime object
|
||||
*
|
||||
* @return integer A timestamp
|
||||
* @return integer A timestamp
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not an instance of \DateTime
|
||||
* @throws TransformationFailedException if the output timezone is not supported
|
||||
|
@ -48,7 +48,7 @@ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransform
|
||||
*
|
||||
* @param number $value Normalized number
|
||||
*
|
||||
* @return string Localized money string.
|
||||
* @return string Localized money string.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not numeric
|
||||
* @throws TransformationFailedException if the value can not be transformed
|
||||
|
@ -66,7 +66,7 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param number $value Normalized value
|
||||
*
|
||||
* @return number Percentage value
|
||||
* @return number Percentage value
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not numeric
|
||||
* @throws TransformationFailedException if the value could not be transformed
|
||||
@ -101,7 +101,7 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param number $value Percentage value.
|
||||
*
|
||||
* @return number Normalized value.
|
||||
* @return number Normalized value.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a string
|
||||
* @throws TransformationFailedException if the value could not be transformed
|
||||
|
@ -26,7 +26,7 @@ class ValueToStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param mixed $value Mixed value.
|
||||
*
|
||||
* @return string String value.
|
||||
* @return string String value.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a string or number
|
||||
*/
|
||||
@ -48,7 +48,7 @@ class ValueToStringTransformer implements DataTransformerInterface
|
||||
*
|
||||
* @param string $value String value.
|
||||
*
|
||||
* @return string String value.
|
||||
* @return string String value.
|
||||
*
|
||||
* @throws UnexpectedTypeException if the given value is not a string
|
||||
*/
|
||||
|
@ -89,7 +89,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
*
|
||||
* @param Constraint $constraint The constraint to guess for
|
||||
*
|
||||
* @return TypeGuess The guessed field class and options
|
||||
* @return TypeGuess The guessed field class and options
|
||||
*/
|
||||
public function guessTypeForConstraint(Constraint $constraint)
|
||||
{
|
||||
@ -178,7 +178,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
*
|
||||
* @param Constraint $constraint The constraint to guess for
|
||||
*
|
||||
* @return Guess The guess whether the field is required
|
||||
* @return Guess The guess whether the field is required
|
||||
*/
|
||||
public function guessRequiredForConstraint(Constraint $constraint)
|
||||
{
|
||||
@ -194,7 +194,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
*
|
||||
* @param Constraint $constraint The constraint to guess for
|
||||
*
|
||||
* @return Guess The guess for the maximum length
|
||||
* @return Guess The guess for the maximum length
|
||||
*/
|
||||
public function guessMaxLengthForConstraint(Constraint $constraint)
|
||||
{
|
||||
@ -282,7 +282,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
* @param mixed $default The default value assumed if no other value
|
||||
* can be guessed.
|
||||
*
|
||||
* @return Guess The guessed value with the highest confidence
|
||||
* @return Guess The guessed value with the highest confidence
|
||||
*/
|
||||
protected function guess($class, $property, \Closure $closure, $defaultValue = null)
|
||||
{
|
||||
|
@ -89,11 +89,11 @@ class ViolationMapper
|
||||
}
|
||||
}
|
||||
|
||||
$template = $violation->getMessageTemplate();
|
||||
$parameters = $violation->getMessageParameters();
|
||||
$pluralization = $violation->getMessagePluralization();
|
||||
|
||||
$this->scope->addError(new FormError($template, $parameters, $pluralization));
|
||||
$this->scope->addError(new FormError(
|
||||
$violation->getMessageTemplate(),
|
||||
$violation->getMessageParameters(),
|
||||
$violation->getMessagePluralization()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,9 +177,9 @@ class ViolationMapper
|
||||
* Reconstructs a property path from a violation path and a form tree.
|
||||
*
|
||||
* @param ViolationPath $violationPath The violation path.
|
||||
* @param FormInterface $origin The root form of the tree.
|
||||
* @param FormInterface $origin The root form of the tree.
|
||||
*
|
||||
* @return RelativePath The reconstructed path.
|
||||
* @return RelativePath The reconstructed path.
|
||||
*/
|
||||
private function reconstructPath(ViolationPath $violationPath, FormInterface $origin)
|
||||
{
|
||||
@ -220,10 +220,10 @@ class ViolationMapper
|
||||
// Property path of a mapped form is null
|
||||
// Should not happen, bail out
|
||||
break;
|
||||
} else {
|
||||
$propertyPathBuilder->replace($i, 1, $propertyPath);
|
||||
$i += $propertyPath->getLength();
|
||||
}
|
||||
|
||||
$propertyPathBuilder->replace($i, 1, $propertyPath);
|
||||
$i += $propertyPath->getLength();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $string = '';
|
||||
private $pathAsString = '';
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
@ -59,32 +59,28 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
public function __construct($violationPath)
|
||||
{
|
||||
$path = new PropertyPath($violationPath);
|
||||
$pathElements = $path->getElements();
|
||||
$pathPositions = $path->getPositions();
|
||||
$elements = array();
|
||||
$positions = array();
|
||||
$isIndex = array();
|
||||
$mapsForm = array();
|
||||
$elements = $path->getElements();
|
||||
$positions = $path->getPositions();
|
||||
$data = false;
|
||||
|
||||
for ($i = 0, $l = count($pathElements); $i < $l; ++$i) {
|
||||
for ($i = 0, $l = count($elements); $i < $l; ++$i) {
|
||||
if (!$data) {
|
||||
// The element "data" has not yet been passed
|
||||
if ('children' === $pathElements[$i] && $path->isProperty($i)) {
|
||||
if ('children' === $elements[$i] && $path->isProperty($i)) {
|
||||
// Skip element "children"
|
||||
++$i;
|
||||
|
||||
// Next element must exist and must be an index
|
||||
// Otherwise not a valid path
|
||||
// Otherwise consider this the end of the path
|
||||
if ($i >= $l || !$path->isIndex($i)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
$elements[] = $pathElements[$i];
|
||||
$positions[] = $pathPositions[$i];
|
||||
$isIndex[] = true;
|
||||
$mapsForm[] = true;
|
||||
} elseif ('data' === $pathElements[$i] && $path->isProperty($i)) {
|
||||
$this->elements[] = $elements[$i];
|
||||
$this->positions[] = $positions[$i];
|
||||
$this->isIndex[] = true;
|
||||
$this->mapsForm[] = true;
|
||||
} elseif ('data' === $elements[$i] && $path->isProperty($i)) {
|
||||
// Skip element "data"
|
||||
++$i;
|
||||
|
||||
@ -93,32 +89,28 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
break;
|
||||
}
|
||||
|
||||
$elements[] = $pathElements[$i];
|
||||
$positions[] = $pathPositions[$i];
|
||||
$isIndex[] = $path->isIndex($i);
|
||||
$mapsForm[] = false;
|
||||
$this->elements[] = $elements[$i];
|
||||
$this->positions[] = $positions[$i];
|
||||
$this->isIndex[] = $path->isIndex($i);
|
||||
$this->mapsForm[] = false;
|
||||
$data = true;
|
||||
} else {
|
||||
// Neither "children" nor "data" property found
|
||||
// Be nice and consider this the end of the path
|
||||
// Consider this the end of the path
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Already after the "data" element
|
||||
// Pick everything as is
|
||||
$elements[] = $pathElements[$i];
|
||||
$positions[] = $pathPositions[$i];
|
||||
$isIndex[] = $path->isIndex($i);
|
||||
$mapsForm[] = false;
|
||||
$this->elements[] = $elements[$i];
|
||||
$this->positions[] = $positions[$i];
|
||||
$this->isIndex[] = $path->isIndex($i);
|
||||
$this->mapsForm[] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->elements = $elements;
|
||||
$this->positions = $positions;
|
||||
$this->isIndex = $isIndex;
|
||||
$this->mapsForm = $mapsForm;
|
||||
$this->length = count($elements);
|
||||
$this->string = $violationPath;
|
||||
$this->length = count($this->elements);
|
||||
$this->pathAsString = $violationPath;
|
||||
|
||||
$this->resizeString();
|
||||
}
|
||||
@ -128,7 +120,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->string;
|
||||
return $this->pathAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,7 +207,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*
|
||||
* @param integer $index The element index.
|
||||
*
|
||||
* @return Boolean Whether the element maps to a form.
|
||||
* @return Boolean Whether the element maps to a form.
|
||||
*/
|
||||
public function mapsForm($index)
|
||||
{
|
||||
@ -241,7 +233,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
$lastIndex = $this->length - 1;
|
||||
|
||||
if ($lastIndex < 0) {
|
||||
$this->string = '';
|
||||
$this->pathAsString = '';
|
||||
} else {
|
||||
// +1 for the dot/opening bracket
|
||||
$length = $this->positions[$lastIndex] + strlen($this->elements[$lastIndex]) + 1;
|
||||
@ -251,7 +243,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface
|
||||
++$length;
|
||||
}
|
||||
|
||||
$this->string = substr($this->string, 0, $length);
|
||||
$this->pathAsString = substr($this->pathAsString, 0, $length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,8 +127,8 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
*/
|
||||
public function __construct(FormConfigInterface $config)
|
||||
{
|
||||
if (!$config instanceof ImmutableFormConfig) {
|
||||
$config = new ImmutableFormConfig($config);
|
||||
if (!$config instanceof UnmodifiableFormConfig) {
|
||||
$config = new UnmodifiableFormConfig($config);
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
@ -146,7 +146,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns the configuration of the form.
|
||||
*
|
||||
* @return ImmutableFormConfig The form's immutable configuration.
|
||||
* @return UnmodifiableFormConfig The form's immutable configuration.
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
@ -156,7 +156,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns the name by which the form is identified in forms.
|
||||
*
|
||||
* @return string The name of the form.
|
||||
* @return string The name of the form.
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
@ -265,7 +265,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns the root of the form tree.
|
||||
*
|
||||
* @return FormInterface The root of the tree
|
||||
* @return FormInterface The root of the tree
|
||||
*/
|
||||
public function getRoot()
|
||||
{
|
||||
@ -287,7 +287,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
*
|
||||
* @param string $name The name of the attribute.
|
||||
*
|
||||
* @return Boolean Whether the attribute exists.
|
||||
* @return Boolean Whether the attribute exists.
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
@ -299,7 +299,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
*
|
||||
* @param string $name The name of the attribute
|
||||
*
|
||||
* @return mixed The attribute value.
|
||||
* @return mixed The attribute value.
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
@ -338,20 +338,32 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
|
||||
// Validate if client data matches data class (unless empty)
|
||||
if (!empty($clientData)) {
|
||||
// TESTME
|
||||
$dataClass = $this->config->getDataClass();
|
||||
|
||||
if (null === $dataClass && is_object($clientData)) {
|
||||
// TODO clarify error message: should not be transformed to object if data class is null
|
||||
// possible solutions: set data class or change client transformers
|
||||
throw new UnexpectedTypeException($clientData, 'scalar or array');
|
||||
$expectedType = 'scalar';
|
||||
|
||||
if (count($this->children) > 0 && $this->config->getDataMapper()) {
|
||||
$expectedType = 'array';
|
||||
}
|
||||
|
||||
throw new FormException(
|
||||
'The form\'s client data is expected to of type ' . $expectedType . ', ' .
|
||||
'but is an instance of class ' . get_class($clientData) . '. You ' .
|
||||
'can avoid this error by setting the "data_class" option to ' .
|
||||
'"' . get_class($clientData) . '" or by adding a client transformer ' .
|
||||
'that transforms ' . get_class($clientData) . ' to ' . $expectedType . '.'
|
||||
);
|
||||
}
|
||||
|
||||
// TESTME
|
||||
if (null !== $dataClass && !$clientData instanceof $dataClass) {
|
||||
// TODO clarify error message: should be transformed to object if data class is set
|
||||
// possible solutions: change data class or client transformers
|
||||
throw new UnexpectedTypeException($clientData, $dataClass);
|
||||
throw new FormException(
|
||||
'The form\'s client data is expected to be an instance of class ' .
|
||||
$dataClass . ', but has the type ' . gettype($clientData) . '. You ' .
|
||||
'can avoid this error by setting the "data_class" option to ' .
|
||||
'null or by adding a client transformer that transforms ' .
|
||||
gettype($clientData) . ' to ' . $dataClass . '.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,7 +594,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns the normalized data of the form.
|
||||
*
|
||||
* @return mixed When the form is not bound, the default data is returned.
|
||||
* @return mixed When the form is not bound, the default data is returned.
|
||||
* When the form is bound, the normalized bound data is
|
||||
* returned if the form is valid, null otherwise.
|
||||
*/
|
||||
@ -687,7 +699,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns whether or not there are errors.
|
||||
*
|
||||
* @return Boolean true if form is bound and not valid
|
||||
* @return Boolean true if form is bound and not valid
|
||||
*/
|
||||
public function hasErrors()
|
||||
{
|
||||
@ -700,7 +712,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns all errors.
|
||||
*
|
||||
* @return array An array of FormError instances that occurred during binding
|
||||
* @return array An array of FormError instances that occurred during binding
|
||||
*/
|
||||
public function getErrors()
|
||||
{
|
||||
@ -858,7 +870,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
*
|
||||
* @param string $name The offset of the value to get
|
||||
*
|
||||
* @return FormInterface A form instance
|
||||
* @return FormInterface A form instance
|
||||
*/
|
||||
public function offsetGet($name)
|
||||
{
|
||||
|
@ -176,9 +176,7 @@ class FormBuilder extends FormConfig
|
||||
*/
|
||||
public function remove($name)
|
||||
{
|
||||
if (isset($this->unresolvedChildren[$name])) {
|
||||
unset($this->unresolvedChildren[$name]);
|
||||
}
|
||||
unset($this->unresolvedChildren[$name]);
|
||||
|
||||
if (isset($this->children[$name])) {
|
||||
if ($this->children[$name] instanceof self) {
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
class FormConfig implements FormConfigInterface
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
private $dispatcher;
|
||||
|
||||
@ -64,7 +64,7 @@ class FormConfig implements FormConfigInterface
|
||||
private $dataMapper;
|
||||
|
||||
/**
|
||||
* @var FormValidatorInterface
|
||||
* @var array
|
||||
*/
|
||||
private $validators = array();
|
||||
|
||||
@ -374,7 +374,7 @@ class FormConfig implements FormConfigInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function hasAttribute($name)
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]);
|
||||
}
|
||||
@ -382,7 +382,7 @@ class FormConfig implements FormConfigInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getAttribute($name)
|
||||
public function getAttribute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ interface FormConfigInterface
|
||||
/**
|
||||
* Returns the data that should be returned when the form is empty.
|
||||
*
|
||||
* @return mixed|\Closure The data returned if the form is empty.
|
||||
* @return mixed The data returned if the form is empty.
|
||||
*/
|
||||
function getEmptyData();
|
||||
|
||||
@ -124,7 +124,7 @@ interface FormConfigInterface
|
||||
*
|
||||
* @param string $name The attribute name.
|
||||
*
|
||||
* @return Boolean Whether the attribute exists.
|
||||
* @return Boolean Whether the attribute exists.
|
||||
*/
|
||||
function hasAttribute($name);
|
||||
|
||||
@ -133,7 +133,7 @@ interface FormConfigInterface
|
||||
*
|
||||
* @param string $name The attribute name.
|
||||
*
|
||||
* @return mixed The attribute value.
|
||||
* @return mixed The attribute value.
|
||||
*/
|
||||
function getAttribute($name);
|
||||
|
||||
|
@ -21,7 +21,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Sets the parent form.
|
||||
*
|
||||
* @param FormInterface $parent The parent form
|
||||
* @param FormInterface $parent The parent form
|
||||
*
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function setParent(FormInterface $parent = null);
|
||||
|
||||
@ -42,7 +44,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Adds a child to the form.
|
||||
*
|
||||
* @param FormInterface $child The FormInterface to add as a child
|
||||
* @param FormInterface $child The FormInterface to add as a child
|
||||
*
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function add(FormInterface $child);
|
||||
|
||||
@ -67,7 +71,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Removes a child from the form.
|
||||
*
|
||||
* @param string $name The name of the child to remove
|
||||
* @param string $name The name of the child to remove
|
||||
*
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function remove($name);
|
||||
|
||||
@ -95,9 +101,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Updates the field with default data.
|
||||
*
|
||||
* @param array $appData The data formatted as expected for the underlying object
|
||||
* @param array $appData The data formatted as expected for the underlying object
|
||||
*
|
||||
* @return Form The current form
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function setData($appData);
|
||||
|
||||
@ -111,7 +117,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Returns the normalized data of the field.
|
||||
*
|
||||
* @return mixed When the field is not bound, the default data is returned.
|
||||
* @return mixed When the field is not bound, the default data is returned.
|
||||
* When the field is bound, the normalized bound data is
|
||||
* returned if the field is valid, null otherwise.
|
||||
*/
|
||||
@ -148,7 +154,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Returns the name by which the form is identified in forms.
|
||||
*
|
||||
* @return string The name of the form.
|
||||
* @return string The name of the form.
|
||||
*/
|
||||
function getName();
|
||||
|
||||
@ -162,7 +168,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Adds an error to this form.
|
||||
*
|
||||
* @param FormError $error
|
||||
* @param FormError $error
|
||||
*
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function addError(FormError $error);
|
||||
|
||||
@ -214,7 +222,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Writes data into the form.
|
||||
*
|
||||
* @param mixed $data The data
|
||||
* @param mixed $data The data
|
||||
*
|
||||
* @return FormInterface The form instance
|
||||
*/
|
||||
function bind($data);
|
||||
|
||||
@ -235,7 +245,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
/**
|
||||
* Returns the root of the form tree.
|
||||
*
|
||||
* @return FormInterface The root of the tree
|
||||
* @return FormInterface The root of the tree
|
||||
*/
|
||||
function getRoot();
|
||||
|
||||
|
@ -97,7 +97,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface
|
||||
* @param \Closure $closure The closure to execute. Accepts a guesser
|
||||
* as argument and should return a Guess instance
|
||||
*
|
||||
* @return Guess The guess with the highest confidence
|
||||
* @return Guess The guess with the highest confidence
|
||||
*/
|
||||
private function guess(\Closure $closure)
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ interface FormTypeGuesserInterface
|
||||
* @param string $class The fully qualified class name
|
||||
* @param string $property The name of the property to guess for
|
||||
*
|
||||
* @return Guess A guess for the field's required setting
|
||||
* @return Guess A guess for the field's required setting
|
||||
*/
|
||||
function guessRequired($class, $property);
|
||||
|
||||
@ -39,7 +39,7 @@ interface FormTypeGuesserInterface
|
||||
* @param string $class The fully qualified class name
|
||||
* @param string $property The name of the property to guess for
|
||||
*
|
||||
* @return Guess A guess for the field's maximum length
|
||||
* @return Guess A guess for the field's maximum length
|
||||
*/
|
||||
function guessMaxLength($class, $property);
|
||||
|
||||
@ -49,7 +49,7 @@ interface FormTypeGuesserInterface
|
||||
* @param string $class The fully qualified class name
|
||||
* @param string $property The name of the property to guess for
|
||||
*
|
||||
* @return Guess A guess for the field's minimum length
|
||||
* @return Guess A guess for the field's minimum length
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
|
||||
*/
|
||||
@ -67,7 +67,7 @@ interface FormTypeGuesserInterface
|
||||
* @param string $class The fully qualified class name
|
||||
* @param string $property The name of the property to guess for
|
||||
*
|
||||
* @return Guess A guess for the field's required pattern
|
||||
* @return Guess A guess for the field's required pattern
|
||||
*/
|
||||
function guessPattern($class, $property);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ abstract class Guess
|
||||
*
|
||||
* @param array $guesses A list of guesses
|
||||
*
|
||||
* @return Guess The guess with the highest confidence
|
||||
* @return Guess The guess with the highest confidence
|
||||
*/
|
||||
static public function getBestGuess(array $guesses)
|
||||
{
|
||||
@ -103,8 +103,8 @@ abstract class Guess
|
||||
/**
|
||||
* Returns the confidence that the guessed value is correct
|
||||
*
|
||||
* @return integer One of the constants VERY_HIGH_CONFIDENCE,
|
||||
* HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE
|
||||
* @return integer One of the constants VERY_HIGH_CONFIDENCE,
|
||||
* HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE
|
||||
*/
|
||||
public function getConfidence()
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ class FormConfigTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @dataProvider getHtml4Ids
|
||||
*/
|
||||
public function testSetNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted)
|
||||
public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted)
|
||||
{
|
||||
$dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
|
||||
|
@ -1234,6 +1234,36 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testClientDataMustNotBeObjectIfDataClassIsNull()
|
||||
{
|
||||
$config = new FormConfig('name', null, $this->dispatcher);
|
||||
$config->appendClientTransformer(new FixedDataTransformer(array(
|
||||
'' => '',
|
||||
'foo' => new \stdClass(),
|
||||
)));
|
||||
$form = new Form($config);
|
||||
|
||||
$form->setData('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testClientDataMustBeObjectIfDataClassIsSet()
|
||||
{
|
||||
$config = new FormConfig('name', 'stdClass', $this->dispatcher);
|
||||
$config->appendClientTransformer(new FixedDataTransformer(array(
|
||||
'' => '',
|
||||
'foo' => array('bar' => 'baz'),
|
||||
)));
|
||||
$form = new Form($config);
|
||||
|
||||
$form->setData('foo');
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null)
|
||||
{
|
||||
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory);
|
||||
|
@ -93,40 +93,22 @@ class PropertyPathBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testReplaceByIndex()
|
||||
{
|
||||
$this->builder->replaceByIndex(1, 1, 'new1');
|
||||
$this->builder->replaceByIndex(1, 'new1');
|
||||
|
||||
$path = new PropertyPath('old1[new1].old3[old4][old5].old6');
|
||||
|
||||
$this->assertEquals($path, $this->builder->getPropertyPath());
|
||||
}
|
||||
|
||||
public function testReplaceByIndexWithLength()
|
||||
{
|
||||
$this->builder->replaceByIndex(0, 2, 'new1');
|
||||
|
||||
$path = new PropertyPath('[new1].old3[old4][old5].old6');
|
||||
|
||||
$this->assertEquals($path, $this->builder->getPropertyPath());
|
||||
}
|
||||
|
||||
public function testReplaceByProperty()
|
||||
{
|
||||
$this->builder->replaceByProperty(1, 1, 'new1');
|
||||
$this->builder->replaceByProperty(1, 'new1');
|
||||
|
||||
$path = new PropertyPath('old1.new1.old3[old4][old5].old6');
|
||||
|
||||
$this->assertEquals($path, $this->builder->getPropertyPath());
|
||||
}
|
||||
|
||||
public function testReplaceByPropertyWithLength()
|
||||
{
|
||||
$this->builder->replaceByProperty(0, 2, 'new1');
|
||||
|
||||
$path = new PropertyPath('new1.old3[old4][old5].old6');
|
||||
|
||||
$this->assertEquals($path, $this->builder->getPropertyPath());
|
||||
}
|
||||
|
||||
public function testReplace()
|
||||
{
|
||||
$this->builder->replace(1, 1, new PropertyPath('new1[new2].new3'));
|
||||
|
@ -464,6 +464,11 @@ class PropertyPathTest extends \PHPUnit_Framework_TestCase
|
||||
new PropertyPath(false);
|
||||
}
|
||||
|
||||
public function testValidPropertyPath_zero()
|
||||
{
|
||||
new PropertyPath('0');
|
||||
}
|
||||
|
||||
public function testGetParent_dot()
|
||||
{
|
||||
$propertyPath = new PropertyPath('grandpa.parent.child');
|
||||
|
@ -13,13 +13,14 @@ namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\EventDispatcher\UnmodifiableEventDispatcher;
|
||||
|
||||
/**
|
||||
* An immutable form configuration.
|
||||
* A read-only form configuration.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ImmutableFormConfig implements FormConfigInterface
|
||||
class UnmodifiableFormConfig implements FormConfigInterface
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
@ -102,13 +103,18 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
private $dataClass;
|
||||
|
||||
/**
|
||||
* Creates an immutable copy of a given configuration.
|
||||
* Creates an unmodifiable copy of a given configuration.
|
||||
*
|
||||
* @param FormConfigInterface $config The configuration to copy.
|
||||
*/
|
||||
public function __construct(FormConfigInterface $config)
|
||||
{
|
||||
$this->dispatcher = $config->getEventDispatcher();
|
||||
$dispatcher = $config->getEventDispatcher();
|
||||
if (!$dispatcher instanceof UnmodifiableEventDispatcher) {
|
||||
$dispatcher = new UnmodifiableEventDispatcher($dispatcher);
|
||||
}
|
||||
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->name = $config->getName();
|
||||
$this->propertyPath = $config->getPropertyPath();
|
||||
$this->mapped = $config->getMapped();
|
||||
@ -243,7 +249,7 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function hasAttribute($name)
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]);
|
||||
}
|
||||
@ -251,7 +257,7 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getAttribute($name)
|
||||
public function getAttribute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
|
||||
}
|
@ -60,7 +60,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
* String representation of the path
|
||||
* @var string
|
||||
*/
|
||||
private $string;
|
||||
private $pathAsString;
|
||||
|
||||
/**
|
||||
* Positions where the individual elements start in the string representation
|
||||
@ -85,20 +85,20 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
$this->singulars = $propertyPath->singulars;
|
||||
$this->length = $propertyPath->length;
|
||||
$this->isIndex = $propertyPath->isIndex;
|
||||
$this->string = $propertyPath->string;
|
||||
$this->pathAsString = $propertyPath->pathAsString;
|
||||
$this->positions = $propertyPath->positions;
|
||||
|
||||
return;
|
||||
}
|
||||
if (!is_string($propertyPath)) {
|
||||
throw new UnexpectedTypeException($propertyPath, 'string');
|
||||
throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\Form\Util\PropertyPath');
|
||||
}
|
||||
|
||||
if (empty($propertyPath)) {
|
||||
if ('' === $propertyPath) {
|
||||
throw new InvalidPropertyPathException('The property path should not be empty.');
|
||||
}
|
||||
|
||||
$this->string = (string) $propertyPath;
|
||||
$this->pathAsString = $propertyPath;
|
||||
$position = 0;
|
||||
$remaining = $propertyPath;
|
||||
|
||||
@ -149,7 +149,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->string;
|
||||
return $this->pathAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,7 +180,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
$parent = clone $this;
|
||||
|
||||
--$parent->length;
|
||||
$parent->string = substr($parent->string, 0, $parent->positions[$parent->length]);
|
||||
$parent->pathAsString = substr($parent->pathAsString, 0, $parent->positions[$parent->length]);
|
||||
array_pop($parent->elements);
|
||||
array_pop($parent->singulars);
|
||||
array_pop($parent->isIndex);
|
||||
@ -253,7 +253,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*
|
||||
* @param object|array $objectOrArray The object or array to traverse
|
||||
*
|
||||
* @return mixed The value at the end of the property path
|
||||
* @return mixed The value at the end of the property path
|
||||
*
|
||||
* @throws InvalidPropertyException If the property/getter does not exist
|
||||
* @throws PropertyAccessDeniedException If the property/getter exists but is not public
|
||||
@ -345,7 +345,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
* @param string $property The property to read.
|
||||
* @param integer $isIndex Whether to interpret the property as index.
|
||||
*
|
||||
* @return mixed The value of the read property
|
||||
* @return mixed The value of the read property
|
||||
*
|
||||
* @throws InvalidPropertyException If the property does not exist.
|
||||
* @throws PropertyAccessDeniedException If the property cannot be accessed due to
|
||||
@ -564,7 +564,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*
|
||||
* @param string $string Some string.
|
||||
*
|
||||
* @return string The camelized version of the string.
|
||||
* @return string The camelized version of the string.
|
||||
*/
|
||||
protected function camelize($string)
|
||||
{
|
||||
@ -578,7 +578,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
* @param string $methodName The method name.
|
||||
* @param integer $parameters The number of parameters.
|
||||
*
|
||||
* @return Boolean Whether the method is public and has $parameters
|
||||
* @return Boolean Whether the method is public and has $parameters
|
||||
* required parameters.
|
||||
*/
|
||||
private function isAccessible(ReflectionClass $class, $methodName, $parameters)
|
||||
|
@ -46,6 +46,7 @@ class PropertyPathBuilder
|
||||
* @param integer $offset The offset where the appended piece
|
||||
* starts in $path.
|
||||
* @param integer $length The length of the appended piece.
|
||||
* If 0, the full path is appended.
|
||||
*/
|
||||
public function append(PropertyPathInterface $path, $offset = 0, $length = 0)
|
||||
{
|
||||
@ -103,6 +104,7 @@ class PropertyPathBuilder
|
||||
* @param integer $pathOffset The offset where the inserted piece
|
||||
* starts in $path.
|
||||
* @param integer $pathLength The length of the inserted piece.
|
||||
* If 0, the full path is inserted.
|
||||
*/
|
||||
public function replace($offset, $length, PropertyPathInterface $path, $pathOffset = 0, $pathLength = 0)
|
||||
{
|
||||
@ -122,13 +124,10 @@ class PropertyPathBuilder
|
||||
* Replaces a sub-path by a single index element.
|
||||
*
|
||||
* @param integer $offset The offset at which to replace.
|
||||
* @param integer $length The length of the piece to replace.
|
||||
* @param string $name The inserted index name.
|
||||
*/
|
||||
public function replaceByIndex($offset, $length, $name)
|
||||
public function replaceByIndex($offset, $name)
|
||||
{
|
||||
$this->resize($offset, $length, 1);
|
||||
|
||||
$this->elements[$offset] = $name;
|
||||
$this->isIndex[$offset] = true;
|
||||
}
|
||||
@ -137,26 +136,66 @@ class PropertyPathBuilder
|
||||
* Replaces a sub-path by a single property element.
|
||||
*
|
||||
* @param integer $offset The offset at which to replace.
|
||||
* @param integer $length The length of the piece to replace.
|
||||
* @param string $name The inserted property name.
|
||||
*/
|
||||
public function replaceByProperty($offset, $length, $name)
|
||||
public function replaceByProperty($offset, $name)
|
||||
{
|
||||
$this->resize($offset, $length, 1);
|
||||
|
||||
$this->elements[$offset] = $name;
|
||||
$this->isIndex[$offset] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the current path.
|
||||
*
|
||||
* @return integer The path length.
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
return count($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current property path.
|
||||
*
|
||||
* @return PropertyPathInterface The constructed property path.
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
$pathAsString = $this->__toString();
|
||||
|
||||
return '' !== $pathAsString ? new PropertyPath($pathAsString) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current property path as string.
|
||||
*
|
||||
* @return string The property path as string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$string = '';
|
||||
|
||||
foreach ($this->elements as $offset => $element) {
|
||||
if ($this->isIndex[$offset]) {
|
||||
$element = '[' . $element . ']';
|
||||
} elseif ('' !== $string) {
|
||||
$string .= '.';
|
||||
}
|
||||
|
||||
$string .= $element;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the path so that a chunk of length $cutLength is
|
||||
* removed at $offset and another chunk of length $insertionLength
|
||||
* is inserted.
|
||||
* can be inserted.
|
||||
*
|
||||
* @param integer $offset The offset where a chunk should be removed.
|
||||
* @param $cutLength
|
||||
* @param $insertionLength
|
||||
* @return mixed
|
||||
* @param integer $offset The offset where the removed chunk starts.
|
||||
* @param integer $cutLength The length of the removed chunk.
|
||||
* @param integer $insertionLength The length of the inserted chunk.
|
||||
*/
|
||||
private function resize($offset, $cutLength, $insertionLength)
|
||||
{
|
||||
@ -210,36 +249,4 @@ class PropertyPathBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the current path.
|
||||
*
|
||||
* @return integer The path length.
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
return count($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current property path.
|
||||
*
|
||||
* @return PropertyPathInterface The constructed property path.
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
$string = null;
|
||||
|
||||
foreach ($this->elements as $offset => $element) {
|
||||
if ($this->isIndex[$offset]) {
|
||||
$element = '[' . $element . ']';
|
||||
} elseif (null !== $string) {
|
||||
$string .= '.';
|
||||
}
|
||||
|
||||
$string .= $element;
|
||||
}
|
||||
|
||||
return null !== $string ? new PropertyPath($string) : null;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ interface PropertyPathInterface extends \Traversable
|
||||
*
|
||||
* @param integer $index The index key
|
||||
*
|
||||
* @return string A property or index name
|
||||
* @return string A property or index name
|
||||
*/
|
||||
function getElement($index);
|
||||
|
||||
@ -71,7 +71,7 @@ interface PropertyPathInterface extends \Traversable
|
||||
*
|
||||
* @param integer $index The index in the property path
|
||||
*
|
||||
* @return Boolean Whether the element at this index is a property
|
||||
* @return Boolean Whether the element at this index is a property
|
||||
*/
|
||||
function isProperty($index);
|
||||
|
||||
@ -80,7 +80,7 @@ interface PropertyPathInterface extends \Traversable
|
||||
*
|
||||
* @param integer $index The index in the property path
|
||||
*
|
||||
* @return Boolean Whether the element at this index is an array index
|
||||
* @return Boolean Whether the element at this index is an array index
|
||||
*/
|
||||
function isIndex($index);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ interface PropertyPathIteratorInterface extends \Iterator, \SeekableIterator
|
||||
|
||||
/**
|
||||
* Returns whether the current element in the property path is a property
|
||||
* names.
|
||||
* name.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
|
Reference in New Issue
Block a user