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

Appearance settings

Commit 3968607

Browse filesBrowse files
committed
merged branch bschussek/property-path (PR #6595)
This PR was merged into the master branch. Commits ------- 6b1652e [PropertyAccess] Property path, small refactoring, read/writeProperty to read/write Property/Index. 1bae7b2 [PropertyAccess] Extracted PropertyAccess component out of Form Discussion ---------- [PropertyAccess] Extracted PropertyAccess component out of Form Bug fix: no Feature addition: no Backwards compatibility break: yes Symfony2 tests pass: yes Fixes the following tickets: - Todo: - License of the code: MIT Documentation PR: - TODO: adapt DoctrineBundle/PropelBundle to pass the "property_accessor" service to EntityType/ModelType Usage: ```php $accessor = PropertyAccess::getPropertyAccessor(); // equivalent to $object->getFoo()->setBar('value') $accessor->setValue($object, 'foo.bar', 'value'); // equivalent to $object->getFoo()->getBar() $accessor->getValue($object, 'foo.bar'); // equivalent to $object->getFoo()['bar'] $accessor->getValue($object, 'foo[bar]'); // equivalent to $array['foo']->setBar('value') $accessor->setValue($array, '[foo].bar', 'value'); // equivalent to $array['foo']['bar'] $accessor->getValue($array, '[foo][bar]'); ``` Later on, once we have generation and caching of class-specific accessors, configuration will be something like this (consistent with the Form and Validator component): ```php $accessor = PropertyAccess::getPropertyAccessorBuilder() ->setCacheDirectory(__DIR__ . '/cache') ->setCacheLifeTime(86400) ->enableMagicGetSet() ->enableMagicCall() ->getPropertyAccessor(); ``` or ```php $accessor = PropertyAccess::getPropertyAccessorBuilder() ->setCache($cache) ->getPropertyAccessor(); ``` etc. --------------------------------------------------------------------------- by Burgov at 2013-01-07T08:48:15Z +1. I use this feature outside of the Form context a lot --------------------------------------------------------------------------- by stof at 2013-01-07T08:49:34Z The classes in the Form component should be kept for BC (and deprecated) for people using the feature --------------------------------------------------------------------------- by michelsalib at 2013-01-07T10:02:19Z YES YES YES :+1:. Sorry for my enthusiasm, but I already copy pasted the PropertyPath class to some of my libraries to avoid linking to the whole Form component. I thus will be glad to officially use this component into my libraries via composer. --------------------------------------------------------------------------- by norzechowicz at 2013-01-07T10:17:39Z Same as @michelsalib to avoid linking full Form component I was using copied parts of code. Can't wait to use this component in my lib. 👍 --------------------------------------------------------------------------- by bschussek at 2013-01-07T10:43:41Z I split away `getValue()` and `setValue()` from `PropertyPath` into a new class `ReflectionGraph`. The component is also named ReflectionGraph now. --------------------------------------------------------------------------- by michelsalib at 2013-01-07T10:47:10Z I am not found of the name. What do you intend to do in the component more than what PropertyPath does ? --------------------------------------------------------------------------- by bschussek at 2013-01-07T10:58:59Z @michelsalib A `PropertyPath` is simply a string like `foo.bar[baz]`. `getValue()` and `setValue()` interpret this path. There may be different interpretations for the same path, so these methods were split into a new class. I chose the name `ReflectionGraph` because the functionality is very similar to `ReflectionProperty`. ```php $reflProperty = new ReflectionProperty('Vendor/Class', 'property'); $reflProperty->setValue($object, 'foo'); $reflGraph = new ReflectionGraph(); $reflGraph->setValue($object, 'property.path', 'foo'); ``` --------------------------------------------------------------------------- by michelsalib at 2013-01-07T11:00:42Z What about naming it `Reflection`, maybe sometime we will want to add more reflection tools for classes, interfaces... ? --------------------------------------------------------------------------- by bschussek at 2013-01-07T11:02:32Z @michelsalib I doubt that we will do that. PHP's implementation is sufficient. --------------------------------------------------------------------------- by vicb at 2013-01-07T11:03:57Z > Backwards compatibility break: no Really ? --------------------------------------------------------------------------- by michelsalib at 2013-01-07T11:05:07Z Well, that is just a suggestion. If I am the only one to oppose, I won't complain. --------------------------------------------------------------------------- by bschussek at 2013-01-07T11:09:08Z > Really ? @vicb Would you please refrain from such meanginless comments in the future? I'm getting a bit tired of them. If you think that BC is broken somewhere, tell me where so that I can fix it. --------------------------------------------------------------------------- by stof at 2013-01-07T11:09:43Z @vicb There is no BC break as he kept deprecated classes for BC --------------------------------------------------------------------------- by norzechowicz at 2013-01-07T11:13:12Z @bschussek what do you think about some kind of factory for Reflection? This will prevent creating new Reflection objects each time you want to access properties values. --------------------------------------------------------------------------- by vicb at 2013-01-07T11:18:47Z @bschussek my point is that my comment is no more meaningless than closing #6453 because it will break BC.We could also keep BC by extending the classes in the new ns but in both cases BC will ultimately be broken (when the legacy classes are removed) --------------------------------------------------------------------------- by vicb at 2013-01-07T12:23:45Z @bschussek @stof I think that modifying the constructor signatures of `EntityChoiceList`, `FormType` are BC breaks (this is not an exhaustive list) --------------------------------------------------------------------------- by bschussek at 2013-01-07T12:35:13Z @vicb You are right. I added corresponding entries to the CHANGELOG and adapted the above description. --------------------------------------------------------------------------- by vicb at 2013-01-08T13:39:13Z @bschussek looking at this PR, I was wondering if an alternate syntax would make sense: ```php <?php $reflGraph = new ReflectionGraph($object); // equivalent to $object->getFoo()->setBar('value') $reflGraph['foo.bar'] = 'value'; // equivalent to $object->getFoo()->getBar() $reflGraph['foo.bar']; ``` _Sorry for the off topic_ --------------------------------------------------------------------------- by vicb at 2013-01-08T13:49:46Z The advantage of using such a `ReflectionGraph` factory is that it might be easier to return specialized reflection graphs, ie optimized instances (that would be cached). --------------------------------------------------------------------------- by Toflar at 2013-01-08T14:49:54Z I was also puzzled by the fact that there will be many `ReflectionGraph` instances although they don't have to. I'm with @vicb and I'd also vote for using the constructor to set the subject you're working on. Otherwise you'll repeat yourself over and over again by passing the subject - say `$object` - to `getValue()` or `setValue()`. If however you don't like the constructor thing then why do we have to have an instance of `ReflectionGraph` rather than just go for static methods and use `ReflectionGraph::getValue()` and `ReflectionGraph::setValue()`? In my opinion there are a few methods that could be static anyway (especially some private ones) :) But probably I misunderstood something as I'm just about to discover the SF components and don't have any experience working with them (so basically I just read the PR because of @bschussek's tweet :D) Couldn't come up with any intuitive name for the component though :( Generally when we talk about "getting" and "setting" values we call those things "mutators"...so `GraphMutator` might be more intuitive than the word `Reflection` :) --------------------------------------------------------------------------- by Taluu at 2013-01-08T14:57:42Z I like the last proposition made by @vicb (implementing `ArrayAccess` on `ReflectionGraph` - or whatever name will be chosen (`PathMutator` for example :D), and also specify which object should be worked on in the constructor rather than in each method). Would this also be used in the `Validator` component ? --------------------------------------------------------------------------- by stof at 2013-01-08T15:16:12Z @Toflar A static ``ReflectionGraph::getValue()`` means you have a coupling to the implementation (as with any static call). The current implementation allows you to replace it with your own implementation as long as you implement the interface as it follows the DI pattern (as done in other places in Symfony). @vicb The issue with ``$reflGraph = new ReflectionGraph($object);`` is that you cannot inject the ReflectionGraph anymore, as you need a new one each time. This would mean adding a ``ReflectionGraphFactory`` to be injected (and which could then be replaced by a factory using code generation). Using the constructor directly would not allow using a replacement based on code generation later. So the resulting code would more likely be ```php $reflGraph = new ReflectionGraph(); $mutator = $reflGraph->getMutator($object); // equivalent to $object->getFoo()->setBar('value') $mutator['foo.bar'] = 'value'; // equivalent to $object->getFoo()->getBar() $mutator['foo.bar']; ``` Btw, writing this, I find the naming Mutator suggested by @Taluu good when it concerns the setter, but quite weird when getting the value. --------------------------------------------------------------------------- by Taluu at 2013-01-08T15:21:00Z I was not the one to suggest though, it was @everzet. But then something like `PathAccessor`, as it is both a mutator and a getter ? I also like @stof suggestion, still in the idea of avoiding to have to put the object as an argument and also allowing to use an `ArrayAccess` interface.. --------------------------------------------------------------------------- by vicb at 2013-01-08T15:21:54Z @stof your remark makes sense. What about `Accessor`, the benefit being that it might well be the name of a coming PHP feature: https://wiki.php.net/rfc/propertygetsetsyntax-v1.2 --------------------------------------------------------------------------- by everzet at 2013-01-08T15:27:02Z ```php $manager = new PropertyManager(new PropertyPath()); $num = $manager->getValue($object, 'foo.num'); $manager->setValue($object, 'foo.num', $num + 1); $objectManager = new ObjectPropertyManager($object[, $manager]); $num = $objectManager->getValue('foo.num'); $objectManager->setValue('foo.num', $num + 1); $objectManager['foo.num'] += 1; ``` --------------------------------------------------------------------------- by bschussek at 2013-01-08T15:28:01Z It might be me, but I don't like `ArrayAccess` to be misused for features like that. If I access a key in an array access structure, I expect it to be something like a collection, an associative array or a key value store. This class is neither. Putting that aside, an accessor for a specific object might make sense, but I'm not sure about that yet. ```php $reflObject->setValue('foo.bar', 'value'); $reflObject->getValue('foo.bar'); ``` --------------------------------------------------------------------------- by stof at 2013-01-08T15:28:52Z @vicb I would vote for PathAccessor then, as we are not doing simple accessor but accessors through a path in an object graph. In my snippet above, we would then have a ReflectionGraph instance and a PathAccessor instance (``$mutator``). Btw, I would also keep the methods ``setValue`` and ``getValue``. I find it more clear. --------------------------------------------------------------------------- by bschussek at 2013-01-08T15:32:07Z @stof But then we're rather left with the question of ReflectionGraph **vs.** PathAccessor. I don't think that the tiny interface difference (one global, one object-based) justifies the big naming difference. --------------------------------------------------------------------------- by vicb at 2013-01-08T15:33:24Z > This class is neither. It might be `$pa['foo.bar[baz]'] = $pa['foo.bar']['baz'];` I don't know if it would help though. --------------------------------------------------------------------------- by stof at 2013-01-08T15:35:51Z @bschussek In my suggestion, ``ReflectionGraph`` is a factory for the PathAccessor objects. It is not accessing anymore itself (which would probably continue to cause issues to implement it with code generation). But the naming could indeed be changed to something else.
2 parents 357d747 + 6b1652e commit 3968607
Copy full SHA for 3968607

File tree

Expand file treeCollapse file tree

73 files changed

+2743
-1887
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

73 files changed

+2743
-1887
lines changed

‎UPGRADE-2.2.md

Copy file name to clipboardExpand all lines: UPGRADE-2.2.md
+128Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,141 @@
8484
{{ error.message }}
8585
```
8686

87+
* FormType, ModelType and PropertyPathMapper now have constructors. If you
88+
extended these classes, you should call the parent constructor now.
89+
Note that you are not recommended to extend FormType nor ModelType. You should
90+
extend AbstractType instead and use the Form component's own inheritance
91+
mechanism (`AbstractType::getParent()`).
92+
93+
Before:
94+
95+
```
96+
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
97+
98+
class CustomMapper extends PropertyPathMapper
99+
{
100+
public function __construct()
101+
{
102+
// ...
103+
}
104+
105+
// ...
106+
}
107+
```
108+
109+
After:
110+
111+
```
112+
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
113+
114+
class CustomMapper extends PropertyPathMapper
115+
{
116+
public function __construct()
117+
{
118+
parent::__construct();
119+
120+
// ...
121+
}
122+
123+
// ...
124+
}
125+
```
126+
87127
#### Deprecations
88128

89129
* The methods `getParent()`, `setParent()` and `hasParent()` in
90130
`FormBuilderInterface` were deprecated and will be removed in Symfony 2.3.
91131
You should not rely on these methods in your form type because the parent
92132
of a form can change after building it.
93133

134+
* The class PropertyPath and related classes were deprecated and moved to a
135+
dedicated component PropertyAccess. If you used any of these classes or
136+
interfaces, you should adapt the namespaces now. During the move,
137+
InvalidPropertyException was renamed to NoSuchPropertyException.
138+
139+
Before:
140+
141+
```
142+
use Symfony\Component\Form\Util\PropertyPath;
143+
use Symfony\Component\Form\Util\PropertyPathBuilder;
144+
use Symfony\Component\Form\Util\PropertyPathInterface;
145+
use Symfony\Component\Form\Util\PropertyPathIterator;
146+
use Symfony\Component\Form\Util\PropertyPathIteratorInterface;
147+
use Symfony\Component\Form\Exception\InvalidPropertyException;
148+
use Symfony\Component\Form\Exception\InvalidPropertyPathException;
149+
use Symfony\Component\Form\Exception\PropertyAccessDeniedException;
150+
```
151+
152+
After:
153+
154+
```
155+
use Symfony\Component\PropertyAccess\PropertyPath;
156+
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
157+
use Symfony\Component\PropertyAccess\PropertyPathInterface;
158+
use Symfony\Component\PropertyAccess\PropertyPathIterator;
159+
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
160+
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
161+
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
162+
use Symfony\Component\PropertyAccess\Exception\PropertyAccessDeniedException;
163+
```
164+
165+
Also, `FormUtil::singularify()` was split away into a class StringUtil
166+
in the new component.
167+
168+
Before:
169+
170+
```
171+
use Symfony\Component\Form\Util\FormUtil;
172+
173+
$singular = FormUtil::singularify($plural);
174+
```
175+
176+
After:
177+
178+
```
179+
use Symfony\Component\PropertyAccess\StringUtil;
180+
181+
$singular = StringUtil::singularify($plural);
182+
```
183+
184+
The methods `getValue()` and `setValue()` were moved to a new class
185+
PropertyAccessor.
186+
187+
Before:
188+
189+
```
190+
use Symfony\Component\Form\Util\PropertyPath;
191+
192+
$propertyPath = new PropertyPath('some.path');
193+
194+
$value = $propertyPath->getValue($object);
195+
$propertyPath->setValue($object, 'new value');
196+
```
197+
198+
After (alternative 1):
199+
200+
```
201+
use Symfony\Component\PropertyAccess\PropertyAccess;
202+
203+
$accessor = PropertyAccess::getPropertyAccessor();
204+
205+
$value = $propertyAccessor->getValue($object, 'some.path');
206+
$accessor->setValue($object, 'some.path', 'new value');
207+
```
208+
209+
After (alternative 2):
210+
211+
```
212+
use Symfony\Component\PropertyAccess\PropertyAccess;
213+
use Symfony\Component\PropertyAccess\PropertyPath;
214+
215+
$accessor = PropertyAccess::getPropertyAccessor();
216+
$propertyPath = new PropertyPath('some.path');
217+
218+
$value = $propertyAccessor->getValue($object, $propertyPath);
219+
$accessor->setValue($object, $propertyPath, 'new value');
220+
```
221+
94222
### Routing
95223

96224
* RouteCollection does not behave like a tree structure anymore but as a flat

‎src/Symfony/Bridge/Doctrine/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
2.2.0
5+
-----
6+
7+
* added an optional PropertyAccessorInterface parameter to DoctrineType,
8+
EntityType and EntityChoiceList
9+
410
2.1.0
511
-----
612

‎src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php
+13-11Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Form\Exception\StringCastException;
1616
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
1717
use Doctrine\Common\Persistence\ObjectManager;
18+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
1819

1920
/**
2021
* A choice list presenting a list of Doctrine entities as choices
@@ -86,17 +87,18 @@ class EntityChoiceList extends ObjectChoiceList
8687
/**
8788
* Creates a new entity choice list.
8889
*
89-
* @param ObjectManager $manager An EntityManager instance
90-
* @param string $class The class name
91-
* @param string $labelPath The property path used for the label
92-
* @param EntityLoaderInterface $entityLoader An optional query builder
93-
* @param array $entities An array of choices
94-
* @param array $preferredEntities An array of preferred choices
95-
* @param string $groupPath A property path pointing to the property used
96-
* to group the choices. Only allowed if
97-
* the choices are given as flat array.
90+
* @param ObjectManager $manager An EntityManager instance
91+
* @param string $class The class name
92+
* @param string $labelPath The property path used for the label
93+
* @param EntityLoaderInterface $entityLoader An optional query builder
94+
* @param array $entities An array of choices
95+
* @param array $preferredEntities An array of preferred choices
96+
* @param string $groupPath A property path pointing to the property used
97+
* to group the choices. Only allowed if
98+
* the choices are given as flat array.
99+
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
98100
*/
99-
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null)
101+
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null)
100102
{
101103
$this->em = $manager;
102104
$this->entityLoader = $entityLoader;
@@ -122,7 +124,7 @@ public function __construct(ObjectManager $manager, $class, $labelPath = null, E
122124
$entities = array();
123125
}
124126

125-
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath);
127+
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor);
126128
}
127129

128130
/**

‎src/Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Doctrine\Common\Persistence\ManagerRegistry;
1515
use Symfony\Component\Form\AbstractExtension;
16+
use Symfony\Component\PropertyAccess\PropertyAccess;
1617

1718
class DoctrineOrmExtension extends AbstractExtension
1819
{
@@ -26,7 +27,7 @@ public function __construct(ManagerRegistry $registry)
2627
protected function loadTypes()
2728
{
2829
return array(
29-
new Type\EntityType($this->registry),
30+
new Type\EntityType($this->registry, PropertyAccess::getPropertyAccessor()),
3031
);
3132
}
3233

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

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php
+13-3Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Symfony\Component\Form\AbstractType;
2323
use Symfony\Component\OptionsResolver\Options;
2424
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
25+
use Symfony\Component\PropertyAccess\PropertyAccess;
26+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
2527

2628
abstract class DoctrineType extends AbstractType
2729
{
@@ -35,9 +37,15 @@ abstract class DoctrineType extends AbstractType
3537
*/
3638
private $choiceListCache = array();
3739

38-
public function __construct(ManagerRegistry $registry)
40+
/**
41+
* @var PropertyAccessorInterface
42+
*/
43+
private $propertyAccessor;
44+
45+
public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null)
3946
{
4047
$this->registry = $registry;
48+
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
4149
}
4250

4351
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -54,6 +62,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
5462
{
5563
$choiceListCache =& $this->choiceListCache;
5664
$registry = $this->registry;
65+
$propertyAccessor = $this->propertyAccessor;
5766
$type = $this;
5867

5968
$loader = function (Options $options) use ($type) {
@@ -64,7 +73,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
6473
return null;
6574
};
6675

67-
$choiceList = function (Options $options) use (&$choiceListCache, &$time) {
76+
$choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) {
6877
// Support for closures
6978
$propertyHash = is_object($options['property'])
7079
? spl_object_hash($options['property'])
@@ -118,7 +127,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
118127
$options['loader'],
119128
$options['choices'],
120129
$options['preferred_choices'],
121-
$options['group_by']
130+
$options['group_by'],
131+
$propertyAccessor
122132
);
123133
}
124134

‎src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ protected function tearDown()
9090
parent::tearDown();
9191

9292
$this->em = null;
93+
$this->emRegistry = null;
9394
}
9495

9596
protected function getExtensions()

‎src/Symfony/Bridge/Propel1/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Propel1/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ CHANGELOG
55
-----
66

77
* added a collection type for the I18n behavior
8+
* added an optional PropertyAccessorInterface parameter to ModelType and
9+
ModelChoiceList
10+
* [BC BREAK] ModelType now has a constructor
811

912
2.1.0
1013
-----

‎src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php
+12-10Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Form\Exception\FormException;
1919
use Symfony\Component\Form\Exception\StringCastException;
2020
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
21+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
2122

2223
/**
2324
* Widely inspired by the EntityChoiceList.
@@ -69,16 +70,17 @@ class ModelChoiceList extends ObjectChoiceList
6970
*
7071
* @see Symfony\Bridge\Propel1\Form\Type\ModelType How to use the preferred choices.
7172
*
72-
* @param string $class The FQCN of the model class to be loaded.
73-
* @param string $labelPath A property path pointing to the property used for the choice labels.
74-
* @param array $choices An optional array to use, rather than fetching the models.
75-
* @param ModelCriteria $queryObject The query to use retrieving model data from database.
76-
* @param string $groupPath A property path pointing to the property used to group the choices.
77-
* @param array|ModelCriteria $preferred The preferred items of this choice.
78-
* Either an array if $choices is given,
79-
* or a ModelCriteria to be merged with the $queryObject.
73+
* @param string $class The FQCN of the model class to be loaded.
74+
* @param string $labelPath A property path pointing to the property used for the choice labels.
75+
* @param array $choices An optional array to use, rather than fetching the models.
76+
* @param ModelCriteria $queryObject The query to use retrieving model data from database.
77+
* @param string $groupPath A property path pointing to the property used to group the choices.
78+
* @param array|ModelCriteria $preferred The preferred items of this choice.
79+
* Either an array if $choices is given,
80+
* or a ModelCriteria to be merged with the $queryObject.
81+
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
8082
*/
81-
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array())
83+
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array(), PropertyAccessorInterface $propertyAccessor = null)
8284
{
8385
$this->class = $class;
8486

@@ -104,7 +106,7 @@ public function __construct($class, $labelPath = null, $choices = null, $queryOb
104106
$this->identifierAsIndex = true;
105107
}
106108

107-
parent::__construct($choices, $labelPath, $preferred, $groupPath);
109+
parent::__construct($choices, $labelPath, $preferred, $groupPath, null, $propertyAccessor);
108110
}
109111

110112
/**

‎src/Symfony/Bridge/Propel1/Form/PropelExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Propel1/Form/PropelExtension.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Propel1\Form;
1313

1414
use Symfony\Component\Form\AbstractExtension;
15+
use Symfony\Component\PropertyAccess\PropertyAccess;
1516

1617
/**
1718
* Represents the Propel form extension, which loads the Propel functionality.
@@ -23,7 +24,7 @@ class PropelExtension extends AbstractExtension
2324
protected function loadTypes()
2425
{
2526
return array(
26-
new Type\ModelType(),
27+
new Type\ModelType(PropertyAccess::getPropertyAccessor()),
2728
new Type\TranslationCollectionType(),
2829
new Type\TranslationType()
2930
);

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

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Propel1/Form/Type/ModelType.php
+17-2Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
use Symfony\Component\Form\FormBuilderInterface;
1818
use Symfony\Component\OptionsResolver\Options;
1919
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
20+
use Symfony\Component\PropertyAccess\PropertyAccess;
21+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
2022

2123
/**
2224
* ModelType class.
@@ -48,6 +50,16 @@
4850
*/
4951
class ModelType extends AbstractType
5052
{
53+
/**
54+
* @var PropertyAccessorInterface
55+
*/
56+
private $propertyAccessor;
57+
58+
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
59+
{
60+
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
61+
}
62+
5163
public function buildForm(FormBuilderInterface $builder, array $options)
5264
{
5365
if ($options['multiple']) {
@@ -57,14 +69,17 @@ public function buildForm(FormBuilderInterface $builder, array $options)
5769

5870
public function setDefaultOptions(OptionsResolverInterface $resolver)
5971
{
60-
$choiceList = function (Options $options) {
72+
$propertyAccessor = $this->propertyAccessor;
73+
74+
$choiceList = function (Options $options) use ($propertyAccessor) {
6175
return new ModelChoiceList(
6276
$options['class'],
6377
$options['property'],
6478
$options['choices'],
6579
$options['query'],
6680
$options['group_by'],
67-
$options['preferred_choices']
81+
$options['preferred_choices'],
82+
$propertyAccessor
6883
);
6984
};
7085

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.