8000 [Form] ensure that already loaded lists are always reused by xabbuh · Pull Request #46101 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Form] ensure that already loaded lists are always reused #46101

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

Closed
wants to merge 1 commit into from
Closed
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
33 changes: 31 additions & 2 deletions src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class LazyChoiceList implements ChoiceListInterface
*/
private $value;

/**
* @var ChoiceListInterface|null
*/
private $loadedList;

/**
* Creates a lazily-loaded list using the given loader.
*
Expand All @@ -58,22 +63,34 @@ public function __construct(ChoiceLoaderInterface $loader, callable $value = nul
*/
public function getChoices()
{
return $this->loader->loadChoiceList($this->value)->getChoices();
if (null === $this->loadedList) {
$this->loadedList = $this->loader->loadChoiceList($this->value);
}

return $this->loadedList->getChoices();
}

/**
* {@inheritdoc}
*/
public function getValues()
{
return $this->loader->loadChoiceList($this->value)->getValues();
if (null === $this->loadedList) {
$this->loadedList = $this->loader->loadChoiceList($this->value);
}

return $this->loadedList->getValues();
}

/**
* {@inheritdoc}
*/
public function getStructuredValues()
{
if (null !== $this->loadedList) {
return $this->loadedList->getStructuredValues();
}

return $this->loader->loadChoiceList($this->value)->getStructuredValues();
}

Expand All @@ -82,6 +99,10 @@ public function getStructuredValues()
*/
public function getOriginalKeys()
{
if (null !== $this->loadedList) {
return $this->loadedList->getOriginalKeys();
}

return $this->loader->loadChoiceList($this->value)->getOriginalKeys();
}

Expand All @@ -90,6 +111,10 @@ public function getOriginalKeys()
*/
public function getChoicesForValues(array $values)
{
if (null !== $this->loadedList) {
return $this->loadedList->getChoicesForValues($values);
}

return $this->loader->loadChoicesForValues($values, $this->value);
}

Expand All @@ -98,6 +123,10 @@ public function getChoicesForValues(array $values)
*/
public function getValuesForChoices(array $choices)
{
if (null !== $this->loadedList) {
return $this->loadedList->getValuesForChoices($choices);
}

return $this->loader->loadValuesForChoices($choices, $this->value);
}
}
< 8000 /tr>
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Form\Tests\ChoiceList;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\ChoiceList\LazyChoiceList;
use Symfony\Component\Form\Tests\Fixtures\ArrayChoiceLoader;

Expand All @@ -23,82 +24,67 @@ class LazyChoiceListTest extends TestCase
public function testGetChoiceLoadersLoadsLoadedListOnFirstCall()
{
$choices = ['RESULT'];
$calls = 0;
$list = new LazyChoiceList(new ArrayChoiceLoader($choices), function ($choice) use ($choices, &$calls) {
++$calls;

$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader($choices), function ($choice) use ($choices) {
return array_search($choice, $choices);
});

$this->assertSame(['RESULT'], $list->getChoices());
$this->assertSame(['RESULT'], $list->getChoices());
$this->assertSame(1, $calls);
$this->assertSame(1, $choiceLoader->loadChoiceListCalls);
}

public function testGetValuesLoadsLoadedListOnFirstCall()
{
$calls = 0;
$list = new LazyChoiceList(new ArrayChoiceLoader(['RESULT']), function ($choice) use (&$calls) {
++$calls;

$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader(['RESULT']), function ($choice) {
return $choice;
});

$this->assertSame(['RESULT'], $list->getValues());
$this->assertSame(['RESULT'], $list->getValues());
$this->assertSame(1, $calls);
$this->assertSame(1, $choiceLoader->loadChoiceListCalls);
}

public function testGetStructuredValuesLoadsLoadedListOnFirstCall()
{
$calls = 0;
$list = new LazyChoiceList(new ArrayChoiceLoader(['RESULT']), function ($choice) use (&$calls) {
++$calls;

$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader(['RESULT']), function ($choice) {
return $choice;
});

$this->assertSame(['RESULT'], $list->getStructuredValues());
$this->assertSame(['RESULT'], $list->getStructuredValues());
$this->assertSame(1, $calls);
$this->assertSame(2, $choiceLoader->loadChoiceListCalls);
}

public function testGetOriginalKeysLoadsLoadedListOnFirstCall()
{
$calls = 0;
$choices = [
'a' => 'foo',
'b' => 'bar',
'c' => 'baz',
];
$list = new LazyChoiceList(new ArrayChoiceLoader($choices), function ($choice) use (&$calls) {
++$calls;

$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader($choices), function ($choice) {
return $choice;
});

$this->assertSame(['foo' => 'a', 'bar' => 'b', 'baz' => 'c'], $list->getOriginalKeys());
$this->assertSame(['foo' => 'a', 'bar' => 'b', 'baz' => 'c'], $list->getOriginalKeys());
$this->assertSame(3, $calls);
$this->assertSame(2, $choiceLoader->loadChoiceListCalls);
}

public function testGetChoicesForValuesForwardsCallIfListNotLoaded()
{
$calls = 0;
$choices = [
'a' => 'foo',
'b' => 'bar',
'c' => 'baz',
];
$list = new LazyChoiceList(new ArrayChoiceLoader($choices), function ($choice) use ($choices, &$calls) {
++$calls;

$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader($choices), function ($choice) use ($choices) {
return array_search($choice, $choices);
});

$this->assertSame(['foo', 'bar'], $list->getChoicesForValues(['a', 'b']));
$this->assertSame(['foo', 'bar'], $list->getChoicesForValues(['a', 'b']));
$this->assertSame(3, $calls);
$this->assertSame(2, $choiceLoader->loadChoiceListCalls);
}

public function testGetChoicesForValuesUsesLoadedList()
Expand All @@ -108,7 +94,7 @@ public function testGetChoicesForValuesUsesLoadedList()
'b' => 'bar',
'c' => 'baz',
];
$list = new LazyChoiceList(new ArrayChoiceLoader($choices), function ($choice) use ($choices) {
$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader($choices), function ($choice) use ($choices) {
return array_search($choice, $choices);
});

Expand All @@ -117,6 +103,7 @@ public function testGetChoicesForValuesUsesLoadedList()

$this->assertSame(['foo', 'bar'], $list->getChoicesForValues(['a', 'b']));
$this->assertSame(['foo', 'bar'], $list->getChoicesForValues(['a', 'b']));
$this->assertSame(1, $choiceLoader->loadChoiceListCalls);
}

public function testGetValuesForChoicesUsesLoadedList()
Expand All @@ -126,7 +113,7 @@ public function testGetValuesForChoicesUsesLoadedList()
'b' => 'bar',
'c' => 'baz',
];
$list = new LazyChoiceList(new ArrayChoiceLoader($choices), function ($choice) use ($choices) {
$list = new LazyChoiceList($choiceLoader = new UsageTrackingChoiceLoader($choices), function ($choice) use ($choices) {
return array_search($choice, $choices);
});

Expand All @@ -135,5 +122,18 @@ public function testGetValuesForChoicesUsesLoadedList()

$this->assertSame(['a', 'b'], $list->getValuesForChoices(['foo', 'bar']));
$this->assertSame(['a', 'b'], $list->getValuesForChoices(['foo', 'bar']));
$this->assertSame(1, $choiceLoader->loadChoiceListCalls);
}
}

class UsageTrackingChoiceLoader extends ArrayChoiceLoader
{
public $loadChoiceListCalls = 0;

public function loadChoiceList($value = null): ChoiceListInterface
{
++$this->loadChoiceListCalls;

return parent::loadChoiceList($value);
}
}
0