Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
BaseEntity.php
1<?php
2
3namespace Bitrix\Catalog\v2;
4
12
21abstract class BaseEntity
22{
25
27 private $fieldStorage;
29 private $parentCollection;
30
31 // ToDo do we need $repository for every base entity?
32 public function __construct(RepositoryContract $repository = null)
33 {
34 $this->entityRepository = $repository;
35 }
36
37 protected function getFieldStorage(): FieldStorage
38 {
39 if ($this->fieldStorage === null)
40 {
41 $this->fieldStorage = $this->createFieldStorage();
42 }
43
44 return $this->fieldStorage;
45 }
46
47 protected function createFieldStorage(): FieldStorage
48 {
49 $fieldMap = $this->getFieldsMap();
50
51 if ($fieldMap === null)
52 {
53 $typeCaster = new NullTypeCaster();
54 }
55 else
56 {
57 $typeCaster = new MapTypeCaster($fieldMap);
58 }
59
60 return new FieldStorage($typeCaster);
61 }
62
63 public function initFields(array $fields): self
64 {
65 if (!empty($fields))
66 {
67 $this->getFieldStorage()->initFields($fields);
68 }
69
70 return $this;
71 }
72
73 public function setParentCollection(?BaseCollection $collection): self
74 {
75 $this->parentCollection = $collection;
76
77 return $this;
78 }
79
81 {
82 return $this->parentCollection;
83 }
84
85 public function getParent(): ?self
86 {
87 $collection = $this->getParentCollection();
88
89 if ($collection)
90 {
91 return $collection->getParent();
92 }
93
94 return null;
95 }
96
97 public function getHash(): string
98 {
99 return spl_object_hash($this);
100 }
101
102 public function setField(string $name, $value): self
103 {
104 return $this->setFieldNoDemand($name, $value);
105 }
106
107 public function setFieldNoDemand(string $name, $value): self
108 {
109 $this->getFieldStorage()->setField($name, $value);
110
111 return $this;
112 }
113
114 public function hasField(string $name): bool
115 {
116 return $this->getFieldStorage()->hasField($name);
117 }
118
119 public function getField(string $name)
120 {
121 return $this->getFieldStorage()->getField($name);
122 }
123
124 // ToDo make map to execute set{$name} instead of setField($name) to check each field limitations? e.g. price with setFields is string instead of float
125 public function setFields(array $fields): self
126 {
127 foreach ($fields as $name => $value)
128 {
129 $this->setField($name, $value);
130 }
131
132 return $this;
133 }
134
135 public function getFields(): array
136 {
137 return $this->getFieldStorage()->toArray();
138 }
139
140 public function getChangedFields(): array
141 {
142 return array_intersect_key($this->getFields(), $this->getFieldStorage()->getChangedFields());
143 }
144
145 public function hasChangedFields(): bool
146 {
147 return $this->getFieldStorage()->hasChangedFields();
148 }
149
150 public function isChanged(): bool
151 {
152 if ($this->hasChangedFields())
153 {
154 return true;
155 }
156
157 foreach ($this->getChildCollections() as $childCollection)
158 {
159 if ($childCollection->isChanged())
160 {
161 return true;
162 }
163 }
164
165 return false;
166 }
167
168 public function isNew(): bool
169 {
170 return $this->getId() === null;
171 }
172
173 public function getId(): ?int
174 {
175 return (int)$this->getField('ID') ?: null;
176 }
177
178 public function setId(int $id): self
179 {
180 return $this->setField('ID', $id);
181 }
182
183 public function remove(): self
184 {
185 $collection = $this->getParentCollection();
186
187 if ($collection)
188 {
189 $collection->remove($this);
190 }
191
192 return $this;
193 }
194
195 public function save(): Result
196 {
197 if ($parent = $this->getParent())
198 {
199 return $parent->save();
200 }
201
202 $connection = Application::getConnection();
203 try
204 {
205 $connection->startTransaction();
206 $result = $this->saveInternal();
207 if ($result->isSuccess())
208 {
209 $connection->commitTransaction();
210 }
211 else
212 {
213 $connection->rollbackTransaction();
214 }
215 }
216 catch (SqlException $exception)
217 {
218 $result = new Result();
219 $connection->rollbackTransaction();
220 $result->addError(new Error($exception->getMessage()));
221 }
222
223 return $result;
224 }
225
226 protected function getFieldsMap(): ?array
227 {
228 return null;
229 }
230
237 public function saveInternal(): Result
238 {
239 $result = new Result();
240
241 if ($this->hasChangedFields())
242 {
243 $res = $this->saveInternalEntity();
244
245 if (!$res->isSuccess())
246 {
247 $result->addErrors($res->getErrors());
248 }
249 }
250
251 if ($result->isSuccess())
252 {
253 foreach ($this->getChildCollections() as $childCollection)
254 {
255 $res = $childCollection->saveInternal();
256
257 if (!$res->isSuccess())
258 {
259 $result->addErrors($res->getErrors());
260 }
261 }
262 }
263
264 return $result;
265 }
266
267 protected function saveInternalEntity(): Result
268 {
269 $result = $this->entityRepository->save($this);
270
271 if ($result->isSuccess())
272 {
273 $this->clearChangedFields();
274 }
275
276 return $result;
277 }
278
282 public function deleteInternal(): Result
283 {
284 $result = $this->entityRepository->delete($this);
285
286 if ($result->isSuccess())
287 {
288 foreach ($this->getChildCollections(true) as $childCollection)
289 {
290 $res = $childCollection->deleteInternal();
291
292 if (!$res->isSuccess())
293 {
294 $result->addErrors($res->getErrors());
295 }
296 }
297 }
298
299 return $result;
300 }
301
306 final protected function getChildCollections(bool $initCollections = false): \Generator
307 {
308 $collectionPostfix = 'Collection';
309 $collectionPostfixLength = mb_strlen($collectionPostfix);
310 $parentCollection = "parent{$collectionPostfix}";
311
312 foreach ((new \ReflectionObject($this))->getProperties() as $property)
313 {
314 $propertyName = $property->getName();
315
316 if (
317 $propertyName !== $parentCollection
318 && mb_substr($propertyName, -$collectionPostfixLength) === $collectionPostfix
319 )
320 {
321 $property->setAccessible(true);
322 $value = $property->getValue($this);
323
324 if ($value === null && $initCollections)
325 {
326 $propertyGetter = "get{$propertyName}";
327
328 if (is_callable([$this, $propertyGetter]))
329 {
330 $value = $this->$propertyGetter();
331 }
332 }
333
334 if ($value instanceof BaseCollection)
335 {
336 yield $value;
337 }
338 }
339 }
340 }
341
346 public function clearChangedFields(): self
347 {
348 $this->getFieldStorage()->clearChanged();
349
350 return $this;
351 }
352}
__construct(RepositoryContract $repository=null)
getChildCollections(bool $initCollections=false)
setFieldNoDemand(string $name, $value)
setField(string $name, $value)
setParentCollection(?BaseCollection $collection)
static getConnection($name="")
addErrors(array $errors)
Definition result.php:98