Permalink
Newer
Older
100644 254 lines (213 sloc) 7.44 KB
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;
13
14
use Symfony\Component\Form\Exception\FormException;
15
use Symfony\Component\Form\Exception\UnexpectedTypeException;
16
use Symfony\Component\Form\Exception\TypeDefinitionException;
17
use Symfony\Component\EventDispatcher\EventDispatcher;
18
use Symfony\Component\OptionsResolver\OptionsResolver;
19
20
/**
21
* A wrapper for a form type and its extensions.
22
*
23
* @author Bernhard Schussek <bschussek@gmail.com>
24
*/
25
class ResolvedFormType implements ResolvedFormTypeInterface
26
{
27
/**
28
* @var FormTypeInterface
29
*/
30
private $innerType;
31
32
/**
33
* @var array
34
*/
35
private $typeExtensions;
36
37
/**
38
* @var ResolvedFormTypeInterface
39
*/
40
private $parent;
41
42
/**
43
* @var OptionsResolver
44
*/
45
private $optionsResolver;
46
47
public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null)
48
{
49
if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) {
50
throw new FormException(sprintf(
51
'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".',
52
get_class($innerType),
53
$innerType->getName()
54
));
55
}
56
57
foreach ($typeExtensions as $extension) {
58
if (!$extension instanceof FormTypeExtensionInterface) {
59
throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface');
60
}
61
}
62
63
// BC
64
if ($innerType instanceof AbstractType) {
65
/* @var AbstractType $innerType */
66
$innerType->setExtensions($typeExtensions);
67
}
68
69
$this->innerType = $innerType;
70
$this->typeExtensions = $typeExtensions;
71
$this->parent = $parent;
72
}
73
74
/**
75
* {@inheritdoc}
76
*/
77
public function getName()
78
{
79
return $this->innerType->getName();
80
}
81
82
/**
83
* {@inheritdoc}
84
*/
85
public function getParent()
86
{
87
return $this->parent;
88
}
89
90
/**
91
* {@inheritdoc}
92
*/
93
public function getInnerType()
94
{
95
return $this->innerType;
96
}
97
98
/**
99
* {@inheritdoc}
100
*/
101
public function getTypeExtensions()
102
{
103
// BC
104
if ($this->innerType instanceof AbstractType) {
105
return $this->innerType->getExtensions();
106
}
107
108
return $this->typeExtensions;
109
}
110
111
/**
112
* {@inheritdoc}
113
*/
114
public function createBuilder(FormFactoryInterface $factory, $name, array $options = array(), FormBuilderInterface $parent = null)
115
{
116
$options = $this->getOptionsResolver()->resolve($options);
117
118
// Should be decoupled from the specific option at some point
119
$dataClass = isset($options['data_class']) ? $options['data_class'] : null;
120
121
$builder = new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options);
122
$builder->setType($this);
123
$builder->setParent($parent);
124
125
$this->buildForm($builder, $options);
126
127
return $builder;
128
}
129
130
/**
131
* {@inheritdoc}
132
*/
133
public function createView(FormInterface $form, FormView $parent = null)
134
{
135
$options = $form->getConfig()->getOptions();
136
138
139
$this->buildView($view, $form, $options);
140
141
foreach ($form as $name => $child) {
142
/* @var FormInterface $child */
143
$view->children[$name] = $child->createView($view);
144
}
145
146
$this->finishView($view, $form, $options);
147
148
return $view;
149
}
150
151
/**
152
* Configures a form builder for the type hierarchy.
153
*
154
* This method is protected in order to allow implementing classes
155
* to change or call it in re-implementations of {@link createBuilder()}.
156
*
157
* @param FormBuilderInterface $builder The builder to configure.
158
* @param array $options The options used for the configuration.
159
*/
160
public function buildForm(FormBuilderInterface $builder, array $options)
161
{
162
if (null !== $this->parent) {
163
$this->parent->buildForm($builder, $options);
164
}
165
166
$this->innerType->buildForm($builder, $options);
167
168
foreach ($this->typeExtensions as $extension) {
169
/* @var FormTypeExtensionInterface $extension */
170
$extension->buildForm($builder, $options);
171
}
172
}
173
174
/**
175
* Configures a form view for the type hierarchy.
176
*
177
* This method is protected in order to allow implementing classes
178
* to change or call it in re-implementations of {@link createView()}.
179
*
180
* It is called before the children of the view are built.
181
*
182
* @param FormView $view The form view to configure.
183
* @param FormInterface $form The form corresponding to the view.
184
* @param array $options The options used for the configuration.
185
*/
186
public function buildView(FormView $view, FormInterface $form, array $options)
187
{
188
if (null !== $this->parent) {
189
$this->parent->buildView($view, $form, $options);
190
}
191
192
$this->innerType->buildView($view, $form, $options);
193
194
foreach ($this->typeExtensions as $extension) {
195
/* @var FormTypeExtensionInterface $extension */
196
$extension->buildView($view, $form, $options);
197
}
198
}
199
200
/**
201
* Finishes a form view for the type hierarchy.
202
*
203
* This method is protected in order to allow implementing classes
204
* to change or call it in re-implementations of {@link createView()}.
205
*
206
* It is called after the children of the view have been built.
207
*
208
* @param FormView $view The form view to configure.
209
* @param FormInterface $form The form corresponding to the view.
210
* @param array $options The options used for the configuration.
211
*/
212
public function finishView(FormView $view, FormInterface $form, array $options)
213
{
214
if (null !== $this->parent) {
215
$this->parent->finishView($view, $form, $options);
216
}
217
218
$this->innerType->finishView($view, $form, $options);
219
220
foreach ($this->typeExtensions as $extension) {
221
/* @var FormTypeExtensionInterface $extension */
222
$extension->finishView($view, $form, $options);
223
}
224
}
225
226
/**
227
* Returns the configured options resolver used for this type.
228
*
229
* This method is protected in order to allow implementing classes
230
* to change or call it in re-implementations of {@link createBuilder()}.
231
*
232
* @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver.
233
*/
234
public function getOptionsResolver()
235
{
236
if (null === $this->optionsResolver) {
237
if (null !== $this->parent) {
238
$this->optionsResolver = clone $this->parent->getOptionsResolver();
239
} else {
240
$this->optionsResolver = new OptionsResolver();
241
}
242
243
$this->innerType->setDefaultOptions($this->optionsResolver);
244
245
foreach ($this->typeExtensions as $extension) {
246
/* @var FormTypeExtensionInterface $extension */
247
$extension->setDefaultOptions($this->optionsResolver);
248
}
249
}
250
251
return $this->optionsResolver;
252
}
253
}