Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
manytomany.php
1<?php
10
19
25class ManyToMany extends Relation
26{
29
31 protected $mediatorEntity;
32
35
38
41
44
47
49 protected $joinType = Join::TYPE_LEFT;
50
53
54 protected $cascadeDeletePolicy = CascadePolicy::NO_ACTION; // follow_orphans | no_action
55
62 public function __construct($name, $referenceEntity)
63 {
64 if ($referenceEntity instanceof Entity)
65 {
66 $this->refEntity = $referenceEntity;
67 $this->refEntityName = $referenceEntity->getFullName();
68 }
69 else
70 {
71 // this one could be without leading backslash and/or with Table-postfix
72 $this->refEntityName = Entity::normalizeName($referenceEntity);
73 }
74
75 parent::__construct($name);
76 }
77
78 public function getTypeMask()
79 {
81 }
82
91 {
92 if ($entity instanceof Entity)
93 {
94 $this->mediatorEntity = $entity;
95 $this->mediatorEntityName = $entity->getFullName();
96 }
97 else
98 {
99 // this one could be without leading backslash and/or with Table-postfix
100 $this->mediatorEntityName = Entity::normalizeName($entity);
101 }
102
103 return $this;
104 }
105
114 {
115 $this->mediatorTableName = $name;
116
117 return $this;
118 }
119
127 public function configureTableName($name)
128 {
129 return $this->configureMediatorTableName($name);
130 }
131
140 public function configureLocalPrimary($fieldName, $mediatorFieldName)
141 {
142 $this->localPrimaryNames[$fieldName] = $mediatorFieldName;
143
144 return $this;
145 }
146
155 {
156 $this->localReferenceName = $name;
157
158 return $this;
159 }
160
169 public function configureRemotePrimary($fieldName, $mediatorFieldName)
170 {
171 $this->remotePrimaryNames[$fieldName] = $mediatorFieldName;
172
173 return $this;
174 }
175
184 {
185 $this->remoteReferenceName = $name;
186
187 return $this;
188 }
189
195 public function getRemoteEntity()
196 {
197 return $this->getRefEntity();
198 }
199
205 public function getMediatorEntity()
206 {
207 if ($this->mediatorEntity === null)
208 {
209 if (!empty($this->mediatorEntityName) && Entity::has($this->mediatorEntityName))
210 {
211 $this->mediatorEntity = Entity::getInstance($this->mediatorEntityName);
212 }
213 else
214 {
215 // there is no described mediator entity
216 // check table_name first, entity can not exist without it
217 if (empty($this->mediatorTableName))
218 {
219 throw new ArgumentException(sprintf(
220 'Table Name for mediator entity of relation `%s` between %s and %s was not found',
221 $this->name, $this->getEntity()->getObjectClass(), $this->getRefEntity()->getObjectClass()
222 ));
223 }
224
225 // generate mediator entity runtime
226 if (empty($this->mediatorEntityName))
227 {
228 $localEntityName = $this->getEntity()->getName();
229 $remoteEntityName = $this->getRefEntity()->getName();
230 $fieldToClassName = StringHelper::snake2camel($this->name);
231
232 // each field has its own entity in case of ManyToMany definitions will be different
233 $this->mediatorEntityName = "MediatorFrom{$localEntityName}To{$remoteEntityName}Via{$fieldToClassName}Table";
234 }
235
236 // fields of mediator entity
237 $fields = [];
238
239 // local entity primary
240 $localReferenceConditions = Query::filter();
241
242 foreach ($this->getEntity()->getPrimaryArray() as $primaryName)
243 {
244 $mediatorPrimaryName = $this->localPrimaryNames[$primaryName] ?? $this->getLocalReferenceName().'_'.$primaryName;
245
246 $fieldType = get_class($this->getEntity()->getField($primaryName));
247
249 $mediatorPrimary = new $fieldType($mediatorPrimaryName);
250 $mediatorPrimary->configurePrimary(true);
251
252 $fields[] = $mediatorPrimary;
253
254 // save join condition for reference
255 $localReferenceConditions->whereColumn('this.'.$mediatorPrimaryName, 'ref.'.$primaryName);
256 }
257
258 // local reference
259 $localReference = (new Reference($this->getLocalReferenceName(), $this->getEntity(), $localReferenceConditions))
260 ->configureJoinType($this->joinType);
261 $fields[] = $localReference;
262
263 // remote entity primary
264 $remoteReferenceConditions = Query::filter();
265
266 foreach ($this->getRefEntity()->getPrimaryArray() as $primaryName)
267 {
268 $mediatorPrimaryName = $this->remotePrimaryNames[$primaryName] ?? $this->getRemoteReferenceName().'_'.$primaryName;
269
270 $fieldType = get_class($this->getRefEntity()->getField($primaryName));
271
273 $mediatorPrimary = new $fieldType($mediatorPrimaryName);
274 $mediatorPrimary->configurePrimary(true);
275
276 $fields[] = $mediatorPrimary;
277
278 // save join condition for reference
279 $remoteReferenceConditions->whereColumn('this.'.$mediatorPrimaryName, 'ref.'.$primaryName);
280 }
281
282 // remote reference
283 $remoteReference = (new Reference($this->getRemoteReferenceName(), $this->getRefEntity(), $remoteReferenceConditions))
284 ->configureJoinType($this->joinType);
285 $fields[] = $remoteReference;
286
287 // set table name
288 $parameters = ['table_name' => $this->mediatorTableName];
289
290 // finalize
291 $this->mediatorEntity = Entity::compileEntity($this->mediatorEntityName, $fields, $parameters);
292 }
293 }
294
296 }
297
301 public function getLocalReferenceName()
302 {
303 if (empty($this->localReferenceName))
304 {
305 $this->localReferenceName = strtoupper(StringHelper::camel2snake($this->getEntity()->getName()));
306 }
307
309 }
310
318 public function getLocalReference()
319 {
320 return $this->getMediatorEntity()->getField($this->getLocalReferenceName());
321 }
322
328 public function getRemoteReferenceName()
329 {
330 if (empty($this->remoteReferenceName))
331 {
332 $this->remoteReferenceName = strtoupper(StringHelper::camel2snake($this->getRefEntity()->getName()));
333 }
334
336 }
337
345 public function getRemoteReference()
346 {
347 return $this->getMediatorEntity()->getField($this->getRemoteReferenceName());
348 }
349}
static normalizeName($entityName)
Definition entity.php:876
static getInstance($entityName)
Definition entity.php:103
static has($entityName)
Definition entity.php:88
configureLocalPrimary($fieldName, $mediatorFieldName)
configureRemotePrimary($fieldName, $mediatorFieldName)