Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Form] ObjectChoiceList now compares choices by their value, if a value path is given #10572

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ CHANGELOG
* [BC BREAK] added two optional parameters to FormInterface::getErrors() and
changed the method to return a Symfony\Component\Form\FormErrorIterator
instance instead of an array
* ObjectChoiceList now compares choices by their value, if a value path is
given

2.4.0
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ class ChoiceList implements ChoiceListInterface
*
* @var array
*/
private $choices = array();
protected $choices = array();

/**
* The choice values with the indices of the matching choices as keys.
*
* @var array
*/
private $values = array();
protected $values = array();

/**
* The preferred view objects as hierarchy containing also the choice groups
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,80 @@ protected function initialize($choices, array $labels, array $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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,119 @@ public function testInitArrayThrowsExceptionIfToStringNotFound()
);
}

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
*/
Expand Down