1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* TEntityContainer.php |
4
|
|
|
* |
5
|
|
|
* @copyright More in license.md |
6
|
|
|
* @license https://www.ipublikuj.eu |
7
|
|
|
* @author Adam Kadlec <[email protected]> |
8
|
|
|
* @package iPublikuj:Forms! |
9
|
|
|
* @subpackage Forms |
10
|
|
|
* @since 1.0.0 |
11
|
|
|
* |
12
|
|
|
* @date 10.01.16 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
declare(strict_types = 1); |
16
|
|
|
|
17
|
|
|
namespace IPub\Forms\Forms; |
18
|
|
|
|
19
|
|
|
use Doctrine\ORM; |
20
|
|
|
|
21
|
|
|
use Nette\Application; |
22
|
|
|
use Nette\ComponentModel; |
23
|
|
|
use Nette\Forms; |
24
|
|
|
|
25
|
|
|
use IPub\Forms\Exceptions; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Form trait for entity binding |
29
|
|
|
* |
30
|
|
|
* @package iPublikuj:Forms! |
31
|
|
|
* @subpackage Forms |
32
|
|
|
* |
33
|
|
|
* @author Adam Kadlec <[email protected]> |
34
|
|
|
* |
35
|
|
|
* @method Application\UI\Form getForm($need = TRUE) |
36
|
|
|
* @method setValues($values, $erase = FALSE) |
37
|
|
|
*/ |
38
|
|
|
trait TEntityContainer |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* @var mixed |
42
|
|
|
*/ |
43
|
|
|
private $entity; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param array|\Traversable $values |
47
|
|
|
* @param bool $erase |
48
|
|
|
* |
49
|
|
|
* @return void |
50
|
|
|
* |
51
|
|
|
* @throws Exceptions\InvalidArgumentException |
52
|
|
|
*/ |
53
|
|
|
public function setDefaults($values, $erase = FALSE) : void |
54
|
|
|
{ |
55
|
|
|
$form = $this->getForm(FALSE); |
56
|
|
|
|
57
|
|
|
if (!$form || !$form->isAnchored() || !$form->isSubmitted()) { |
58
|
|
|
if ($this->isEntity($values)) { |
59
|
|
|
$this->bindEntity($this, $values, $erase); |
|
|
|
|
60
|
|
|
|
61
|
|
|
} else { |
62
|
|
|
$this->setValues($values, $erase); |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @param mixed $entity |
69
|
|
|
* |
70
|
|
|
* @return void |
71
|
|
|
*/ |
72
|
|
|
public function setEntity($entity) : void |
73
|
|
|
{ |
74
|
|
|
$this->entity = $entity; |
75
|
|
|
|
76
|
|
|
if (method_exists($entity, 'getId')) { |
77
|
|
|
$this->setId((string) $entity->getId()); |
|
|
|
|
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @return mixed |
83
|
|
|
*/ |
84
|
|
|
public function getEntity() |
85
|
|
|
{ |
86
|
|
|
return $this->entity; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @param ComponentModel\Component $formElement |
91
|
|
|
* @param object $entity |
92
|
|
|
* @param bool $erase |
93
|
|
|
* |
94
|
|
|
* @return void |
95
|
|
|
* |
96
|
|
|
* @throws Exceptions\InvalidArgumentException |
97
|
|
|
*/ |
98
|
|
|
private function bindEntity($formElement, $entity, bool $erase) : void |
99
|
|
|
{ |
100
|
|
|
$classMetadata = $this->getMetadata($entity); |
101
|
|
|
|
102
|
|
|
foreach (self::iterate($formElement) as $name => $component) { |
|
|
|
|
103
|
|
|
if ($component instanceof Forms\IControl) { |
104
|
|
|
if (($classMetadata->hasField($name) || $classMetadata->hasAssociation($name)) && $value = $classMetadata->getFieldValue($entity, $name)) { |
105
|
|
View Code Duplication |
if (is_object($value) && $this->isEntity($value)) { |
|
|
|
|
106
|
|
|
$UoW = $this->entityManager->getUnitOfWork(); |
|
|
|
|
107
|
|
|
$value = $UoW->getSingleIdentifierValue($value); |
108
|
|
|
|
109
|
|
|
$component->setValue($value); |
110
|
|
|
|
111
|
|
|
} else { |
112
|
|
|
$component->setValue($value); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
} else { |
116
|
|
|
$methodName = 'get' . ucfirst($name); |
117
|
|
|
|
118
|
|
|
if (method_exists($entity, $methodName) && $value = call_user_func([$entity, $methodName])) { |
119
|
|
View Code Duplication |
if (is_object($value) && $this->isEntity($value)) { |
|
|
|
|
120
|
|
|
$UoW = $this->entityManager->getUnitOfWork(); |
|
|
|
|
121
|
|
|
$value = $UoW->getSingleIdentifierValue($value); |
122
|
|
|
|
123
|
|
|
$component->setValue($value); |
124
|
|
|
|
125
|
|
|
} else { |
126
|
|
|
$component->setValue($value); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
} else { |
130
|
|
|
if ($erase) { |
131
|
|
|
$component->setValue(NULL); |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
} elseif ($component instanceof Forms\Container) { |
137
|
|
|
if (($classMetadata->hasField($name) || $classMetadata->hasAssociation($name)) && $value = $classMetadata->getFieldValue($entity, $name)) { |
138
|
|
View Code Duplication |
if (is_object($value) && $this->isEntity($value)) { |
|
|
|
|
139
|
|
|
$this->bindEntity($component, $value, $erase); |
140
|
|
|
|
141
|
|
|
} else { |
142
|
|
|
$component->setValues($value, $erase); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
} else { |
146
|
|
|
$methodName = 'get' . ucfirst($name); |
147
|
|
|
|
148
|
|
|
if (method_exists($entity, $methodName) && $value = call_user_func([$entity, $methodName])) { |
149
|
|
View Code Duplication |
if (is_object($value) && $this->isEntity($value)) { |
|
|
|
|
150
|
|
|
$this->bindEntity($component, $value, $erase); |
151
|
|
|
|
152
|
|
|
} else { |
153
|
|
|
$component->setValues($value, $erase); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
} else { |
157
|
|
|
if ($erase) { |
158
|
|
|
$component->setValues([], $erase); |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @param object $entity |
168
|
|
|
* |
169
|
|
|
* @return ORM\Mapping\ClassMetadata |
170
|
|
|
* |
171
|
|
|
* @throws Exceptions\InvalidArgumentException |
172
|
|
|
*/ |
173
|
|
|
private function getMetadata($entity) : ORM\Mapping\ClassMetadata |
174
|
|
|
{ |
175
|
|
|
if (!$this->isEntity($entity)) { |
176
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Expected object, "%s" given.', gettype($entity))); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
return $this->entityManager->getClassMetadata(get_class($entity)); |
|
|
|
|
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* @param mixed $entity |
184
|
|
|
* |
185
|
|
|
* @return bool |
186
|
|
|
*/ |
187
|
|
|
private function isEntity($entity) : bool |
188
|
|
|
{ |
189
|
|
|
return is_object($entity) && $this->entityManager->getMetadataFactory()->hasMetadataFor(get_class($entity)); |
|
|
|
|
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* @param Forms\IControl|Forms\Container $formElement |
194
|
|
|
* |
195
|
|
|
* @return array|\ArrayIterator |
196
|
|
|
* |
197
|
|
|
* @throws Exceptions\InvalidArgumentException |
198
|
|
|
*/ |
199
|
|
|
private static function iterate($formElement) |
200
|
|
|
{ |
201
|
|
|
if ($formElement instanceof Forms\Container) { |
202
|
|
|
return $formElement->getComponents(); |
203
|
|
|
|
204
|
|
|
} elseif ($formElement instanceof Forms\IControl) { |
205
|
|
|
return [$formElement]; |
206
|
|
|
|
207
|
|
|
} else { |
208
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Expected Nette\Forms\Container or Nette\Forms\IControl, but "%s" given', get_class($formElement))); |
209
|
|
|
} |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.