8000 [Form] add `CallbackChoiceLoader` · symfony/symfony@3de5c7e · GitHub
[go: up one dir, main page]

Skip to content

Commit 3de5c7e

Browse files
committed
[Form] add CallbackChoiceLoader
1 parent 0b67fa3 commit 3de5c7e

File tree

4 files changed

+255
-0
lines changed

4 files changed

+255
-0
lines changed

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* deprecated the "choices_as_values" option of ChoiceType
88
* deprecated support for data objects that implements both `Traversable` and
99
`ArrayAccess` in `ResizeFormListener::preSubmit` method
10+
* added `CallbackChoiceLoader`
1011

1112
3.0.0
1213
-----
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\ChoiceList\Loader;
13+
14+
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
15+
16+
/**
17+
* Loads a {@link ArrayChoiceList} interface from any callable.
18+
*
19+
* @author Jules Pietri <jules@heahprod.com>
20+
*/
21+
class CallbackChoiceLoader implements ChoiceLoaderInterface
22+
{
23+
/**
24+
* The callable used to load the array of choices.
25+
*
26+
* @var callable
27+
*/
28+
private $callback;
29+
30+
/**
31+
* The loaded choice list.
32+
*
33+
* @var ArrayChoiceList
34+
*/
35+
private $choiceList;
36+
37+
public function __construct(callable $callback)
38+
{
39+
$this->callback = $callback;
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function loadChoiceList($value = null)
46+
{
47+
if (null !== $this->choiceList) {
48+
return $this->choiceList;
49+
}
50+
51+
return $this->choiceList = new ArrayChoiceList(call_user_func($this->callback), $value);
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function loadChoicesForValues(array $values, $value = null)
58+
{
59+
// Optimize
60+
if (empty($values)) {
61+
return array();
62+
}
63+
64+
return $this->loadChoiceList($value)->getChoicesForValues($values);
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function loadValuesForChoices(array $choices, $value = null)
71+
{
72+
// Optimize
73+
if (empty($choices)) {
74+
return array();
75+
}
76+
77+
return $this->loadChoiceList($value)->getValuesForChoices($choices);
78+
}
79+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests\ChoiceList\Loader;
13+
14+
use Symfony\Component\Form\ChoiceList\LazyChoiceList;
15+
16+
/**
17+
* @author Jules Pietri <jules@heahprod.com>
18+
*/
19+
abstract class AbstractChoiceLoaderTest extends \PHPUnit_Framework_TestCase
20+
{
21+
/**
22+
* @var \Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface
23+
*/
24+
private $loader;
25+
26+
/**
27+
* @var null|callable
28+
*/
29+
private $value;
30+
31+
/**
32+
* @var array||Traversable
33+
*/
34+
private $choices;
35+
36+
/**
37+
* @var string[]
38+
*/
39+
private $choiceValues;
40+
41+
/**
42+
* @var \Symfony\Component\Form\ChoiceList\LazyChoiceList
43+
*/
44+
private $lazyChoiceList;
45+
46+
protected function setUp()
47+
{
48+
parent::setUp();
49+
50+
$this->loader = $this->createChoiceLoader();
51+
$this->value = $this->getValue();
52+
$this->choices = $this->getChoices();
53+
$this->choiceValues = $this->getChoiceValues();
54+
$this->lazyChoiceList = new LazyChoiceList($this->loader, $this->value);
55+
}
56+
57+
public function testLoadChoiceList()
58+
{
59+
$this->assertInstanceOf('\Symfony\Component\Form\ChoiceList\ChoiceListInterface', $this->loader->loadChoiceList($this->value));
60+
}
61+
62+
public function testLoadChoiceListOnlyOnce()
63+
{
64+
$loadedChoiceList = $this->loader->loadChoiceList($this->value);
65+
66+
$this->assertSame($loadedChoiceList, $this->loader->loadChoiceList($this->value));
67+
}
68+
69+
public function testLoadChoicesForValuesLoadsChoiceListOnFirstCall()
70+
{
71+
$this->assertSame(
72+
$this->loader->loadChoicesForValues($this->choiceValues, $this->value),
73+
$this->lazyChoiceList->getChoicesForValues($this->choiceValues),
74+
'Choice list should not be reloaded.'
75+
);
76+
}
77+
78+
public function testLoadValuesForChoicesLoadsChoiceListOnFirstCall()
79+
{
80+
$this->assertSame(
81+
$this->loader->loadValuesForChoices($this->choices, $this->value),
82+
$this->lazyChoiceList->getValuesForChoices($this->choices),
83+
'Choice list should not be reloaded.'
84+
);
85+
}
86+
87+
protected function tearDown()
88+
{
89+
parent::tearDown();
90+
91+
$this->loader = null;
92+
$this->value = null;
93+
$this->choices = array();
94+
$this->choiceValues = array();
95+
$this->lazyChoiceList = null;
96+
}
97+
98+
/**
99+
* @return \Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface
100+
*/
101+
abstract protected function createChoiceLoader();
102+
103+
/**
104+
* @return null|callable
105+
*/
106+
abstract protected function getValue();
107+
108+
/**
109+
* @return array|\Traversable
110+
*/
111+
abstract protected function getChoices();
112+
113+
/**
114+
* @return string[]
115+
*/
116+
abstract protected function getChoiceValues();
117+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests\ChoiceList\Loader;
13+
14+
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
15+
16+
/**
17+
* @author Jules Pietri <jules@heahprod.com>
18+
*/
19+
class CallbackChoiceLoaderTest extends AbstractChoiceLoaderTest
20+
{
21+
/**
22+
* @return \Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface
23+
*/
24+
protected function createChoiceLoader()
25+
{
26+
return new CallbackChoiceLoader(function() {
27+
return $this->getChoices();
28+
});
29+
}
30+
31+
/**
32+
* @return null|callable
33+
*/
34+
protected function getValue() {
35+
return function ($choice) {
36+
return isset($choice->value) ? $choice->value : null;
37+
};
38+
}
39+
40+
/**
41+
* @return array|\Traversable
42+
*/
43+
protected function getChoices()
44+
{
45+
return array(
46+
(object) array('value' => 'choice_one'),
47+
(object) array('value' => 'choice_two'),
48+
);
49+
}
50+
51+
/**
52+
* @return string[]
53+
*/
54+
protected function getChoiceValues()
55+
{
56+
return array('choice_one', 'choice_two');
57+
}
58+
}

0 commit comments

Comments
 (0)
0