8000 merged branch bschussek/issue3354 (PR #3789) · symfony/symfony@05842c5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 05842c5

Browse files
committed
merged branch bschussek/issue3354 (PR #3789)
Commits ------- 8329087 [Form] Moved calculation of ChoiceType options to closures 5adec19 [Form] Fixed typos cb87ccb [Form] Failing test for empty_data option BC break b733045 [Form] Fixed option support in Form component Discussion ---------- [Form] Fixed option support in Form component Bug fix: yes Feature addition: no Backwards compatibility break: yes Symfony2 tests pass: yes Fixes the following tickets: #3354, #3512, #3685, #3694 Todo: - ![Travis Build Status](https://secure.travis-ci.org/bschussek/symfony.png?branch=issue3354) This PR also introduces a new helper `DefaultOptions` for solving option graphs. It accepts default options to be defined on various layers of your class hierarchy. These options can then be merged with the options passed by the user. This is called *resolving*. The important feature of this utility is that it lets you define *lazy options*. Lazy options are specified using closures that are evaluated when resolving and thus have access to the resolved values of other (potentially lazy) options. The class detects cyclic option dependencies and fails with an exception in this case. For more information, check the inline documentation of the `DefaultOptions` class and the UPGRADE file. @fabpot: Might this be worth a separate component? (in total the utility consists of five classes with two associated tests) --------------------------------------------------------------------------- by beberlei at 2012-04-05T08:54:10Z "The important feature of this utility is that it lets you define lazy options. Lazy options are specified using closures" What about options that are closures? are those differentiated? --------------------------------------------------------------------------- by bschussek at 2012-04-05T08:57:35Z @beberlei Yes. Closures for lazy options receive a Symfony\Component\Form\Options instance as first argument. All other closures are interpreted as normal values. --------------------------------------------------------------------------- by stof at 2012-04-05T11:09:49Z I'm wondering if these classes should go in the Config component. My issue with it is that it would add a required dependency to the Config component and that the Config component mixes many different things in it already (the loader part, the resource part, the definition part...) --------------------------------------------------------------------------- by sstok at 2012-04-06T13:36:36Z Sharing the Options class would be great, and its more then one class so why not give it its own Component folder? Filesystem is just one class, and that has its own folder. Great job on the class bschussek :clap: --------------------------------------------------------------------------- by bschussek at 2012-04-10T12:32:34Z @fabpot Any input? --------------------------------------------------------------------------- by bschussek at 2012-04-10T13:54:13Z @fabpot Apart from the decision about the final location of DefaultOptions et al., could you merge this soon? This would make my work a bit easier since this one is a blocker. --------------------------------------------------------------------------- by fabpot at 2012-04-10T18:08:18Z @bschussek: Can you rebase on master? I will merge afterwards. Thanks.
2 parents d167fd4 + 8329087 commit 05842c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1313
-245
lines changed

CHANGELOG-2.1.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
256256
* forms now don't create an empty object anymore if they are completely
257257
empty and not required. The empty value for such forms is null.
258258
* added constant Guess::VERY_HIGH_CONFIDENCE
259-
* FormType::getDefaultOptions() now sees default options defined by parent types
260259
* [BC BREAK] FormType::getParent() does not see default options anymore
261260
* [BC BREAK] The methods `add`, `remove`, `setParent`, `bind` and `setData`
262261
in class Form now throw an exception if the form is already bound
@@ -266,6 +265,8 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
266265
"single_text" unless "with_seconds" is set to true
267266
* checkboxes of in an expanded multiple-choice field don't include the choice
268267
in their name anymore. Their names terminate with "[]" now.
268+
* [BC BREAK] FormType::getDefaultOptions() and FormType::getAllowedOptionValues()
269+
don't receive an options array anymore.
269270

270271
### HttpFoundation
271272

UPGRADE-2.1.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
```
327327
328328
* The options passed to the `getParent()` method of form types no longer
329-
contain default options.
329+
contain default options. They only contain the options passed by the user.
330330
331331
You should check if options exist before attempting to read their value.
332332
@@ -347,6 +347,42 @@
347347
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'text' : 'choice';
348348
}
349349
```
350+
351+
* The methods `getDefaultOptions()` and `getAllowedOptionValues()` of form
352+
types no longer receive an option array.
353+
354+
You can specify options that depend on other options using closures instead.
355+
356+
Before:
357+
358+
```
359+
public function getDefaultOptions(array $options)
360+
{
361+
$defaultOptions = array();
362+
363+
if ($options['multiple']) {
364+
$defaultOptions['empty_data'] = array();
365+
}
366+
367+
return $defaultOptions;
368+
}
369+
```
370+
371+
After:
372+
373+
```
374+
public function getDefaultOptions()
375+
{
376+
return array(
377+
'empty_data' => function (Options $options, $previousValue) {
378+
return $options['multiple'] ? array() : $previousValue;
379+
}
380+
);
381+
}
382+
```
383+
384+
The second argument `$previousValue` does not have to be specified if not
385+
needed.
350386
351387
* The `add()`, `remove()`, `setParent()`, `bind()` and `setData()` methods in
352388
the Form class now throw an exception if the form is already bound.

src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener;
2020
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
2121
use Symfony\Component\Form\AbstractType;
22+
use Symfony\Component\Form\Options;
2223

2324
abstract class DoctrineType extends AbstractType
2425
{
@@ -42,37 +43,44 @@ public function buildForm(FormBuilder $builder, array $options)
4243
}
4344
}
4445

45-
public function getDefaultOptions(array $options)
46+
public function getDefaultOptions()
4647
{
47-
$defaultOptions = array(
48-
'em' => null,
49-
'class' => null,
50-
'property' => null,
51-
'query_builder' => null,
52-
'loader' => null,
53-
'group_by' => null,
54-
);
48+
$registry = $this->registry;
49+
$type = $this;
5550

56-
$options = array_replace($defaultOptions, $options);
51+
$loader = function (Options $options) use ($type, $registry) {
52+
if (null !== $options['query_builder']) {
53+
$manager = $registry->getManager($options['em']);
5754

58-
if (!isset($options['choice_list'])) {
59-
$manager = $this->registry->getManager($options['em']);
60-
61-
if (isset($options['query_builder'])) {
62-
$options['loader'] = $this->getLoader($manager, $options);
55+
return $type->getLoader($manager, $options['query_builder'], $options['class']);
6356
}
6457

65-
$defaultOptions['choice_list'] = new EntityChoiceList(
58+
return null;
59+
};
60+
61+
$choiceList = function (Options $options) use ($registry) {
62+
$manager = $registry->getManager($options['em']);
63+
64+
return new EntityChoiceList(
6665
$manager,
6766
$options['class'],
6867
$options['property'],
6968
$options['loader'],
7069
$options['choices'],
7170
$options['group_by']
7271
);
73-
}
72+
};
7473

75-
return $defaultOptions;
74+
return array(
75+
'em' => null,
76+
'class' => null,
77+
'property' => null,
78+
'query_builder' => null,
79+
'loader' => $loader,
80+
'choices' => null,
81+
'choice_list' => $choiceList,
82+
'group_by' => null,
83+
);
7684
}
7785

7886
/**
@@ -82,7 +90,7 @@ public function getDefaultOptions(array $options)
8290
* @param array $options
8391
* @return EntityLoaderInterface
8492
*/
85-
abstract protected function getLoader(ObjectManager $manager, array $options);
93+
abstract public function getLoader(ObjectManager $manager, $queryBuilder, $class);
8694

8795
public function getParent(array $options)
8896
{

src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class EntityType extends DoctrineType
2323
* @param array $options
2424
* @return ORMQueryBuilderLoader
2525
*/
26-
protected function getLoader(ObjectManager $manager, array $options)
26+
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
2727
{
2828
return new ORMQueryBuilderLoader(
29-
$options['query_builder'],
29+
$queryBuilder,
3030
$manager,
31-
$options['class']
31+
$class
3232
);
3333
}
3434

src/Symfony/Bridge/Propel1/Form/Type/ModelType.php

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bridge\Propel1\Form\ChoiceList\ModelChoiceList;
1515
use Symfony\Bridge\Propel1\Form\DataTransformer\CollectionToArrayTransformer;
1616
use Symfony\Component\Form\AbstractType;
17+
use Symfony\Component\Form\Options;
1718
use Symfony\Component\Form\FormBuilder;
1819

1920
/**
@@ -30,33 +31,30 @@ public function buildForm(FormBuilder $builder, array $options)
3031
}
3132
}
3233

33-
public function getDefaultOptions(array $options)
34+
public function getDefaultOptions()
3435
{
35-
$defaultOptions = array(
36+
$choiceList = function (Options $options) {
37+
return new ModelChoiceList(
38+
$options['class'],
39+
$options['property'],
40+
$options['choices'],
41+
$options['query'],
42+
$options['group_by']
43+
);
44+
};
45+
46+
return array(
3647
'template' => 'choice',
3748
'multiple' => false,
3849
'expanded' => false,
3950
'class' => null,
4051
'property' => null,
4152
'query' => null,
4253
'choices' => null,
54+
'choice_list' => $choiceList,
4355
'group_by' => null,
4456
'by_reference' => false,
4557
);
46-
47-
$options = array_replace($defaultOptions, $options);
48-
49-
if (!isset($options['choice_list'])) {
50-
$defaultOptions['choice_list'] = new ModelChoiceList(
51-
$options['class'],
52-
$options['property'],
53-
$options['choices'],
54-
$options['query'],
55-
$options['group_by']
56-
);
57-
}
58-
59-
return $defaultOptions;
6058
}
6159

6260
public function getParent(array $options)

src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginFormType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public function buildForm(FormBuilder $builder, array $options)
7676
/**
7777
* @see Symfony\Component\Form\AbstractType::getDefaultOptions()
7878
*/
79-
public function getDefaultOptions(array $options)
79+
public function getDefaultOptions()
8080
{
8181
/* Note: the form's intention must correspond to that for the form login
8282
* listener in order for the CSRF token to validate successfully.

src/Symfony/Component/Form/AbstractType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public function createBuilder($name, FormFactoryInterface $factory, array $optio
9696
*
9797
* @return array The default options
9898
*/
99-
public function getDefaultOptions(array $options)
99+
public function getDefaultOptions()
100100
{
101101
return array();
102102
}
@@ -108,7 +108,7 @@ public function getDefaultOptions(array $options)
108108
*
109109
* @return array The allowed option values
110110
*/
111-
public function getAllowedOptionValues(array $options)
111+
public function getAllowedOptionValues()
112112
{
113113
return array();
114114
}

src/Symfony/Component/Form/AbstractTypeExtension.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function buildViewBottomUp(FormView $view, FormInterface $form)
6565
*
6666
* @return array
6767
*/
68-
public function getDefaultOptions(array $options)
68+
public function getDefaultOptions()
6969
{
7070
return array();
7171
}
@@ -77,7 +77,7 @@ public function getDefaultOptions(array $options)
7777
*
7878
* @return array The allowed option values
7979
*/
80-
public function getAllowedOptionValues(array $options)
80+
public function getAllowedOptionValues()
8181
{
8282
return array();
8383
}

0 commit comments

Comments
 (0)
0