/
CollectionField.php
119 lines (97 loc) · 3.08 KB
/
CollectionField.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php
namespace Symfony\Component\Form;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
use Symfony\Component\Form\FieldInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
*/
class CollectionField extends FieldGroup
{
/**
* The prototype for the inner fields
* @var FieldInterface
*/
protected $prototype;
/**
* Remembers which fields were removed upon binding
* @var array
*/
protected $removedFields = array();
/**
* Repeats the given field twice to verify the user's input
*
* @param FieldInterface $innerField
*/
public function __construct(FieldInterface $innerField, array $options = array())
{
$this->prototype = $innerField;
parent::__construct($innerField->getKey(), $options);
}
protected function configure()
{
$this->addOption('modifiable', false);
if ($this->getOption('modifiable')) {
$field = $this->newField('$$key$$', null);
// TESTME
$field->setRequired(false);
$this->add($field);
}
parent::configure();
}
public function setData($collection)
{
if (!is_array($collection) && !$collection instanceof \Traversable) {
throw new UnexpectedTypeException('The data passed to the CollectionField must be an array or a Traversable');
}
foreach ($this as $name => $field) {
if (!$this->getOption('modifiable') || $name != '$$key$$') {
$this->remove($name);
}
}
foreach ($collection as $name => $value) {
$this->add($this->newField($name, $name));
}
parent::setData($collection);
}
public function bind($taintedData)
{
$this->removedFields = array();
if (null === $taintedData) {
$taintedData = array();
}
foreach ($this as $name => $field) {
if (!isset($taintedData[$name]) && $this->getOption('modifiable') && $name != '$$key$$') {
$this->remove($name);
$this->removedFields[] = $name;
}
}
foreach ($taintedData as $name => $value) {
if (!isset($this[$name]) && $this->getOption('modifiable')) {
$this->add($this->newField($name, $name));
}
}
parent::bind($taintedData);
}
protected function updateObject(&$objectOrArray)
{
parent::updateObject($objectOrArray);
foreach ($this->removedFields as $name) {
unset($objectOrArray[$name]);
}
}
protected function newField($key, $propertyPath)
{
$field = clone $this->prototype;
$field->setKey($key);
$field->setPropertyPath(null === $propertyPath ? null : '['.$propertyPath.']');
return $field;
}
}