Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit93dac3e

Browse files
committed
[Form] Added a "choice_filter" option to ChoiceType
1 parent269c4a2 commit93dac3e

18 files changed

+552
-35
lines changed

‎UPGRADE-5.1.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Form
2323
is deprecated. The method will be added to the interface in 6.0.
2424
* Implementing the`FormConfigBuilderInterface` without implementing the`setIsEmptyCallback()` method
2525
is deprecated. The method will be added to the interface in 6.0.
26+
* Not defining a third`callable|null $filter` argument to`ChoiceListFactoryInterface::createListFromChoices` and`ChoiceListFactoryInterface::createListFromLoader` methods is deprecated.
27+
The argument will de defined in 6.0.
2628

2729
FrameworkBundle
2830
---------------

‎UPGRADE-6.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Form
2121

2222
* Added the`getIsEmptyCallback()` method to the`FormConfigInterface`.
2323
* Added the`setIsEmptyCallback()` method to the`FormConfigBuilderInterface`.
24+
* Added a third`callable|null $filter` argument to`ChoiceListFactoryInterface::createListFromChoices` and`ChoiceListFactoryInterface::createListFromLoader` methods.
2425

2526
FrameworkBundle
2627
---------------

‎src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
5.1.0
55
-----
66

7+
* Added a`choice_filter` option to`ChoiceType`
78
* Added a`ChoiceList` facade to leverage explicit choice list caching based on options
89
* Added an`AbstractChoiceLoader` to simplify implementations and handle global optimizations
910
* The`view_timezone` option defaults to the`model_timezone` if no`reference_date` is configured.

‎src/Symfony/Component/Form/ChoiceList/ChoiceList.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceAttr;
1515
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFieldName;
16+
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFilter;
1617
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLabel;
1718
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLoader;
1819
useSymfony\Component\Form\ChoiceList\Factory\Cache\ChoiceValue;
@@ -66,6 +67,16 @@ public static function value($formType, $value, $vary = null): ChoiceValue
6667
returnnewChoiceValue($formType,$value,$vary);
6768
}
6869

70+
/**
71+
* @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list
72+
* @param callable $filter Any pseudo callable to filter a choice list
73+
* @param mixed|null $vary Dynamic data used to compute a unique hash when caching the callback
74+
*/
75+
publicstaticfunctionfilter(FormTypeInterface$formType,$filter,$vary =null):ChoiceFilter
76+
{
77+
returnnewChoiceFilter($formType,$filter,$vary);
78+
}
79+
6980
/**
7081
* Decorates a "choice_label" option to make it cacheable.
7182
*
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
namespaceSymfony\Component\Form\ChoiceList\Factory\Cache;
13+
14+
useSymfony\Component\Form\FormTypeInterface;
15+
16+
/**
17+
* A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface}
18+
* which configures a "choice_filter" option.
19+
*
20+
* @internal
21+
*
22+
* @author Jules Pietri <jules@heahprod.com>
23+
*/
24+
finalclass ChoiceFilterextends AbstractStaticOption
25+
{
26+
}

‎src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,34 @@ public function getDecoratedFactory()
8181
/**
8282
* {@inheritdoc}
8383
*/
84-
publicfunctioncreateListFromChoices(iterable$choices,$value =null)
84+
publicfunctioncreateListFromChoices(iterable$choices,$value =null,$filter =null)
8585
{
8686
if ($choicesinstanceof \Traversable) {
8787
$choices =iterator_to_array($choices);
8888
}
8989

90-
// Only cache per value when needed. The value is not validated on purpose.
90+
$cache =true;
91+
// Only cache per value and filter when needed. The value is not validated on purpose.
9192
// The decorated factory may decide which values to accept and which not.
9293
if ($valueinstanceofCache\ChoiceValue) {
9394
$value =$value->getOption();
9495
}elseif ($value) {
95-
return$this->decoratedFactory->createListFromChoices($choices,$value);
96+
$cache =false;
97+
}
98+
if ($filterinstanceofCache\ChoiceFilter) {
99+
$filter =$filter->getOption();
100+
}elseif ($filter) {
101+
$cache =false;
102+
}
103+
104+
if (!$cache) {
105+
return$this->decoratedFactory->createListFromChoices($choices,$value,$filter);
96106
}
97107

98-
$hash =self::generateHash([$choices,$value],'fromChoices');
108+
$hash =self::generateHash([$choices,$value,$filter],'fromChoices');
99109

100110
if (!isset($this->lists[$hash])) {
101-
$this->lists[$hash] =$this->decoratedFactory->createListFromChoices($choices,$value);
111+
$this->lists[$hash] =$this->decoratedFactory->createListFromChoices($choices,$value,$filter);
102112
}
103113

104114
return$this->lists[$hash];
@@ -107,7 +117,7 @@ public function createListFromChoices(iterable $choices, $value = null)
107117
/**
108118
* {@inheritdoc}
109119
*/
110-
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,$value =null)
120+
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,$value =null,$filter =null)
111121
{
112122
$cache =true;
113123

@@ -123,14 +133,20 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
123133
$cache =false;
124134
}
125135

136+
if ($filterinstanceofCache\ChoiceFilter) {
137+
$filter =$filter->getOption();
138+
}elseif ($filter) {
139+
$cache =false;
140+
}
141+
126142
if (!$cache) {
127-
return$this->decoratedFactory->createListFromLoader($loader,$value);
143+
return$this->decoratedFactory->createListFromLoader($loader,$value,$filter);
128144
}
129145

130-
$hash =self::generateHash([$loader,$value],'fromLoader');
146+
$hash =self::generateHash([$loader,$value,$filter],'fromLoader');
131147

132148
if (!isset($this->lists[$hash])) {
133-
$this->lists[$hash] =$this->decoratedFactory->createListFromLoader($loader,$value);
149+
$this->lists[$hash] =$this->decoratedFactory->createListFromLoader($loader,$value,$filter);
134150
}
135151

136152
return$this->lists[$hash];

‎src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ interface ChoiceListFactoryInterface
3131
* The callable receives the choice as only argument.
3232
* Null may be passed when the choice list contains the empty value.
3333
*
34+
* @param callable|null $filter The callable filtering the choices
35+
* (will be added in Symfony 6.0)
36+
*
3437
* @return ChoiceListInterface The choice list
3538
*/
36-
publicfunctioncreateListFromChoices(iterable$choices,callable$value =null);
39+
publicfunctioncreateListFromChoices(iterable$choices,callable$value =null/*, $filter = null*/);
3740

3841
/**
3942
* Creates a choice list that is loaded with the given loader.
@@ -42,9 +45,12 @@ public function createListFromChoices(iterable $choices, callable $value = null)
4245
* The callable receives the choice as only argument.
4346
* Null may be passed when the choice list contains the empty value.
4447
*
48+
* @param callable|null $filter The callable filtering the choices
49+
* (will be added in Symfony 6.0)
50+
*
4551
* @return ChoiceListInterface The choice list
4652
*/
47-
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,callable$value =null);
53+
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,callable$value =null/*, $filter = null*/);
4854

4955
/**
5056
* Creates a view for the given choice list.

‎src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
useSymfony\Component\Form\ChoiceList\ChoiceListInterface;
1616
useSymfony\Component\Form\ChoiceList\LazyChoiceList;
1717
useSymfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
18+
useSymfony\Component\Form\ChoiceList\Loader\FilterChoiceLoaderDecorator;
1819
useSymfony\Component\Form\ChoiceList\View\ChoiceGroupView;
1920
useSymfony\Component\Form\ChoiceList\View\ChoiceListView;
2021
useSymfony\Component\Form\ChoiceList\View\ChoiceView;
@@ -29,16 +30,44 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
2930
/**
3031
* {@inheritdoc}
3132
*/
32-
publicfunctioncreateListFromChoices(iterable$choices,callable$value =null)
33+
publicfunctioncreateListFromChoices(iterable$choices,callable$value =null,callable$filter =null)
3334
{
35+
if ($filter) {
36+
if ($choicesinstanceof \Traversable) {
37+
$choices =iterator_to_array($choices);
38+
}
39+
40+
foreach ($choicesas$group =>$choiceOrGroup) {
41+
if (!\is_array($choiceOrGroup)) {
42+
$choices =array_filter($choices,$filter);
43+
44+
break;
45+
}
46+
47+
// choices are structured, filter by group
48+
if ($filtered =array_filter($choiceOrGroup,$filter)) {
49+
$choices[$group] =$filtered;
50+
51+
continue;
52+
}
53+
54+
// also filter empty groups
55+
unset($choices[$group]);
56+
}
57+
}
58+
3459
returnnewArrayChoiceList($choices,$value);
3560
}
3661

3762
/**
3863
* {@inheritdoc}
3964
*/
40-
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,callable$value =null)
65+
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,callable$value =null,callable$filter =null)
4166
{
67+
if ($filter) {
68+
$loader =newFilterChoiceLoaderDecorator($loader,$filter);
69+
}
70+
4271
returnnewLazyChoiceList($loader,$value);
4372
}
4473

‎src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ public function getDecoratedFactory()
5959
/**
6060
* {@inheritdoc}
6161
*
62-
* @param callable|string|PropertyPath|null $value The callable or path for
63-
* generating the choice values
62+
* @param callable|string|PropertyPath|null $value The callable or path for
63+
* generating the choice values
64+
* @param callable|string|PropertyPath|null $filter The callable or path for
65+
* filtering the choices
6466
*
6567
* @return ChoiceListInterface The choice list
6668
*/
67-
publicfunctioncreateListFromChoices(iterable$choices,$value =null)
69+
publicfunctioncreateListFromChoices(iterable$choices,$value =null,$filter =null)
6870
{
6971
if (\is_string($value)) {
7072
$value =newPropertyPath($value);
@@ -81,18 +83,33 @@ public function createListFromChoices(iterable $choices, $value = null)
8183
};
8284
}
8385

84-
return$this->decoratedFactory->createListFromChoices($choices,$value);
86+
if (\is_string($filter)) {
87+
$filter =newPropertyPath($filter);
88+
}
89+
90+
if ($filterinstanceof PropertyPath) {
91+
$accessor =$this->propertyAccessor;
92+
$filter =staticfunction ($choice)use ($accessor,$filter) {
93+
if (\is_object($choice) ||\is_array($choice)) {
94+
return (bool)$accessor->getValue($choice,$filter);
95+
}
96+
};
97+
}
98+
99+
return$this->decoratedFactory->createListFromChoices($choices,$value,$filter);
85100
}
86101

87102
/**
88103
* {@inheritdoc}
89104
*
90-
* @param callable|string|PropertyPath|null $value The callable or path for
91-
* generating the choice values
105+
* @param callable|string|PropertyPath|null $value The callable or path for
106+
* generating the choice values
107+
* @param callable|string|PropertyPath|null $filter The callable or path for
108+
* filtering the choices
92109
*
93110
* @return ChoiceListInterface The choice list
94111
*/
95-
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,$value =null)
112+
publicfunctioncreateListFromLoader(ChoiceLoaderInterface$loader,$value =null,$filter =null)
96113
{
97114
if (\is_string($value)) {
98115
$value =newPropertyPath($value);
@@ -109,7 +126,20 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
109126
};
110127
}
111128

112-
return$this->decoratedFactory->createListFromLoader($loader,$value);
129+
if (\is_string($filter)) {
130+
$filter =newPropertyPath($filter);
131+
}
132+
133+
if ($filterinstanceof PropertyPath) {
134+
$accessor =$this->propertyAccessor;
135+
$filter =staticfunction ($choice)use ($accessor,$filter) {
136+
if (\is_object($choice) ||\is_array($choice)) {
137+
return (bool)$accessor->getValue($choice,$filter);
138+
}
139+
};
140+
}
141+
142+
return$this->decoratedFactory->createListFromLoader($loader,$value,$filter);
113143
}
114144

115145
/**
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
namespaceSymfony\Component\Form\ChoiceList\Loader;
13+
14+
/**
15+
* A decorator to filter choices only when they are loaded or partially loaded.
16+
*
17+
* @author Jules Pietri <jules@heahprod.com>
18+
*/
19+
class FilterChoiceLoaderDecoratorextends AbstractChoiceLoader
20+
{
21+
private$decoratedLoader;
22+
private$filter;
23+
24+
publicfunction__construct(ChoiceLoaderInterface$loader,callable$filter)
25+
{
26+
$this->decoratedLoader =$loader;
27+
$this->filter =$filter;
28+
}
29+
30+
protectedfunctionloadChoices():iterable
31+
{
32+
$list =$this->decoratedLoader->loadChoiceList();
33+
34+
if (array_values($list->getValues()) ===array_values($structuredValues =$list->getStructuredValues())) {
35+
returnarray_filter(array_combine($list->getOriginalKeys(),$list->getChoices()),$this->filter);
36+
}
37+
38+
foreach ($structuredValuesas$group =>$values) {
39+
if ($filtered =array_filter($list->getChoicesForValues($values),$this->filter)) {
40+
$choices[$group] =$filtered;
41+
}
42+
// filter empty groups
43+
}
44+
45+
return$choices ?? [];
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
publicfunctionloadChoicesForValues(array$values,callable$value =null):array
52+
{
53+
returnarray_filter($this->decoratedLoader->loadChoicesForValues($values,$value),$this->filter);
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
publicfunctionloadValuesForChoices(array$choices,callable$value =null):array
60+
{
61+
return$this->decoratedLoader->loadValuesForChoices(array_filter($choices,$this->filter),$value);
62+
}
63+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp