[Form] ObjectChoiceList now compares choices by their value, if a value path is given
This commit is contained in:
parent
3cd1c9cd5b
commit
ce0efb189f
@ -11,6 +11,8 @@ CHANGELOG
|
|||||||
* [BC BREAK] added two optional parameters to FormInterface::getErrors() and
|
* [BC BREAK] added two optional parameters to FormInterface::getErrors() and
|
||||||
changed the method to return a Symfony\Component\Form\FormErrorIterator
|
changed the method to return a Symfony\Component\Form\FormErrorIterator
|
||||||
instance instead of an array
|
instance instead of an array
|
||||||
|
* ObjectChoiceList now compares choices by their value, if a value path is
|
||||||
|
given
|
||||||
|
|
||||||
2.4.0
|
2.4.0
|
||||||
-----
|
-----
|
||||||
|
@ -41,14 +41,14 @@ class ChoiceList implements ChoiceListInterface
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $choices = array();
|
protected $choices = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The choice values with the indices of the matching choices as keys.
|
* The choice values with the indices of the matching choices as keys.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $values = array();
|
protected $values = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The preferred view objects as hierarchy containing also the choice groups
|
* The preferred view objects as hierarchy containing also the choice groups
|
||||||
|
@ -148,6 +148,80 @@ class ObjectChoiceList extends ChoiceList
|
|||||||
parent::initialize($choices, $labels, $preferredChoices);
|
parent::initialize($choices, $labels, $preferredChoices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getValuesForChoices(array $choices)
|
||||||
|
{
|
||||||
|
if (!$this->valuePath) {
|
||||||
|
return parent::getValuesForChoices($choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the value path to compare the choices
|
||||||
|
$choices = $this->fixChoices($choices);
|
||||||
|
$values = array();
|
||||||
|
|
||||||
|
foreach ($choices as $i => $givenChoice) {
|
||||||
|
// Ignore non-readable choices
|
||||||
|
if (!is_object($givenChoice) && !is_array($givenChoice)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$givenValue = (string) $this->propertyAccessor->getValue($givenChoice, $this->valuePath);
|
||||||
|
|
||||||
|
foreach ($this->values as $value) {
|
||||||
|
if ($value === $givenValue) {
|
||||||
|
$values[$i] = $value;
|
||||||
|
unset($choices[$i]);
|
||||||
|
|
||||||
|
if (0 === count($choices)) {
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated Deprecated since version 2.4, to be removed in 3.0.
|
||||||
|
*/
|
||||||
|
public function getIndicesForChoices(array $choices)
|
||||||
|
{
|
||||||
|
if (!$this->valuePath) {
|
||||||
|
return parent::getIndicesForChoices($choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the value path to compare the choices
|
||||||
|
$choices = $this->fixChoices($choices);
|
||||||
|
$indices = array();
|
||||||
|
|
||||||
|
foreach ($choices as $i => $givenChoice) {
|
||||||
|
// Ignore non-readable choices
|
||||||
|
if (!is_object($givenChoice) && !is_array($givenChoice)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$givenValue = (string) $this->propertyAccessor->getValue($givenChoice, $this->valuePath);
|
||||||
|
|
||||||
|
foreach ($this->values as $j => $value) {
|
||||||
|
if ($value === $givenValue) {
|
||||||
|
$indices[$i] = $j;
|
||||||
|
unset($choices[$i]);
|
||||||
|
|
||||||
|
if (0 === count($choices)) {
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $indices;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new unique value for this choice.
|
* Creates a new unique value for this choice.
|
||||||
*
|
*
|
||||||
|
@ -185,6 +185,119 @@ class ObjectChoiceListTest extends AbstractChoiceListTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetIndicesForChoicesWithValuePath()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compare by value, not by identity
|
||||||
|
$choices = array(clone $this->obj1, clone $this->obj2);
|
||||||
|
$this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetIndicesForChoicesWithValuePathPreservesKeys()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(5 => clone $this->obj1, 8 => clone $this->obj2);
|
||||||
|
$this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetIndicesForChoicesWithValuePathPreservesOrder()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(clone $this->obj2, clone $this->obj1);
|
||||||
|
$this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(clone $this->obj1, clone $this->obj2, 'foobar');
|
||||||
|
$this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetValuesForChoicesWithValuePath()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(clone $this->obj1, clone $this->obj2);
|
||||||
|
$this->assertSame(array('A', 'B'), $this->list->getValuesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetValuesForChoicesWithValuePathPreservesKeys()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(5 => clone $this->obj1, 8 => clone $this->obj2);
|
||||||
|
$this->assertSame(array(5 => 'A', 8 => 'B'), $this->list->getValuesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetValuesForChoicesWithValuePathPreservesOrder()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(clone $this->obj2, clone $this->obj1);
|
||||||
|
$this->assertSame(array('B', 'A'), $this->list->getValuesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetValuesForChoicesWithValuePathIgnoresNonExistingChoices()
|
||||||
|
{
|
||||||
|
$this->list = new ObjectChoiceList(
|
||||||
|
array($this->obj1, $this->obj2, $this->obj3, $this->obj4),
|
||||||
|
'name',
|
||||||
|
array(),
|
||||||
|
null,
|
||||||
|
'name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$choices = array(clone $this->obj1, clone $this->obj2, 'foobar');
|
||||||
|
$this->assertSame(array('A', 'B'), $this->list->getValuesForChoices($choices));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
|
* @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user