|
1
|
|
|
<?php /** @noinspection PhpParamsInspection */ |
|
2
|
|
|
|
|
3
|
|
|
namespace ORM\Entity; |
|
4
|
|
|
|
|
5
|
|
|
use ORM\Entity; |
|
6
|
|
|
use ORM\EntityFetcher; |
|
7
|
|
|
use ORM\EntityManager as EM; |
|
8
|
|
|
use ORM\Exception\UndefinedRelation; |
|
9
|
|
|
use ORM\Relation; |
|
10
|
|
|
|
|
11
|
|
|
trait Relations |
|
12
|
|
|
{ |
|
13
|
|
|
/** Relation definitions |
|
14
|
|
|
* @var array */ |
|
15
|
|
|
protected static $relations = []; |
|
16
|
|
|
|
|
17
|
|
|
/** The entity manager from which this entity got created |
|
18
|
|
|
* @var EM */ |
|
19
|
|
|
protected $entityManager; |
|
20
|
|
|
|
|
21
|
|
|
/** Related objects for getRelated |
|
22
|
|
|
* @var array */ |
|
23
|
|
|
protected $relatedObjects = []; |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* Get the definition for $relation |
|
27
|
|
|
* |
|
28
|
|
|
* It normalize the short definition form and create a Relation object from it. |
|
29
|
|
|
* |
|
30
|
|
|
* @param string $relation |
|
31
|
|
|
* @return Relation |
|
32
|
|
|
* @throws UndefinedRelation |
|
33
|
|
|
*/ |
|
34
|
|
|
public static function getRelation($relation) |
|
35
|
|
|
{ |
|
36
|
|
|
if (!isset(static::$relations[$relation])) { |
|
37
|
|
|
throw new UndefinedRelation('Relation ' . $relation . ' is not defined'); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
83 |
|
$relDef = &static::$relations[$relation]; |
|
41
|
|
|
|
|
42
|
83 |
|
if (!$relDef instanceof Relation) { |
|
43
|
3 |
|
$relDef = Relation::createRelation($relation, $relDef); |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
82 |
|
return $relDef; |
|
47
|
|
|
} |
|
48
|
82 |
|
|
|
49
|
14 |
|
/** |
|
50
|
|
|
* Get related objects |
|
51
|
|
|
* |
|
52
|
81 |
|
* The difference between getRelated and fetch is that getRelated stores the fetched entities. To refresh set |
|
53
|
|
|
* $refresh to true. |
|
54
|
|
|
* |
|
55
|
|
|
* @param string $relation |
|
56
|
|
|
* @param bool $refresh |
|
57
|
|
|
* @return mixed |
|
58
|
|
|
*/ |
|
59
|
|
|
public function getRelated($relation, $refresh = false) |
|
60
|
|
|
{ |
|
61
|
|
|
if ($refresh || !isset($this->relatedObjects[$relation])) { |
|
62
|
|
|
$this->relatedObjects[$relation] = $this->fetch($relation, true); |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
return $this->relatedObjects[$relation]; |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* Set $relation to $entity |
|
70
|
|
|
* |
|
71
|
11 |
|
* This method is only for the owner of a relation. |
|
72
|
|
|
* |
|
73
|
11 |
|
* @param string $relation |
|
74
|
9 |
|
* @param Entity $entity |
|
75
|
|
|
*/ |
|
76
|
|
|
public function setRelated($relation, Entity $entity = null) |
|
77
|
11 |
|
{ |
|
78
|
|
|
$this::getRelation($relation)->setRelated($this, $entity); |
|
79
|
|
|
|
|
80
|
|
|
$this->relatedObjects[$relation] = $entity; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* Add relations for $relation to $entities |
|
85
|
|
|
* |
|
86
|
|
|
* This method is only for many-to-many relations. |
|
87
|
|
|
* |
|
88
|
|
|
* This method does not take care about already existing relations and will fail hard. |
|
89
|
|
|
* |
|
90
|
7 |
|
* @param string $relation |
|
91
|
|
|
* @param Entity[] $entities |
|
92
|
7 |
|
*/ |
|
93
|
|
View Code Duplication |
public function addRelated($relation, array $entities) |
|
|
|
|
|
|
94
|
4 |
|
{ |
|
95
|
4 |
|
// @codeCoverageIgnoreStart |
|
96
|
|
|
if (func_num_args() === 3 && func_get_arg(2) instanceof EM) { |
|
97
|
|
|
trigger_error( |
|
98
|
|
|
'Passing EntityManager to addRelated is deprecated. Use ->setEntityManager() to overwrite', |
|
99
|
|
|
E_USER_DEPRECATED |
|
100
|
|
|
); |
|
101
|
|
|
} |
|
102
|
|
|
// @codeCoverageIgnoreEnd |
|
103
|
|
|
|
|
104
|
|
|
$this::getRelation($relation)->addRelated($this, $entities, $this->entityManager); |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
/** |
|
108
|
8 |
|
* Delete relations for $relation to $entities |
|
109
|
|
|
* |
|
110
|
|
|
* This method is only for many-to-many relations. |
|
111
|
|
|
* |
|
112
|
|
|
* @param string $relation |
|
113
|
|
|
* @param Entity[] $entities |
|
114
|
|
|
*/ |
|
115
|
|
View Code Duplication |
public function deleteRelated($relation, $entities) |
|
|
|
|
|
|
116
|
|
|
{ |
|
117
|
|
|
// @codeCoverageIgnoreStart |
|
118
|
|
|
if (func_num_args() === 3 && func_get_arg(2) instanceof EM) { |
|
119
|
8 |
|
trigger_error( |
|
120
|
4 |
|
'Passing EntityManager to deleteRelated is deprecated. Use ->setEntityManager() to overwrite', |
|
121
|
|
|
E_USER_DEPRECATED |
|
122
|
|
|
); |
|
123
|
|
|
} |
|
124
|
|
|
// @codeCoverageIgnoreEnd |
|
125
|
|
|
|
|
126
|
|
|
$this::getRelation($relation)->deleteRelated($this, $entities, $this->entityManager); |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* Fetches related objects |
|
131
|
8 |
|
* |
|
132
|
|
|
* For relations with cardinality many it returns an EntityFetcher. Otherwise it returns the entity. |
|
133
|
|
|
* |
|
134
|
|
|
* It will throw an error for non owner when the key is incomplete. |
|
135
|
|
|
* |
|
136
|
|
|
* @param string $relation The relation to fetch |
|
137
|
|
|
* @param bool $getAll |
|
138
|
|
|
* @return Entity|Entity[]|EntityFetcher |
|
139
|
|
|
*/ |
|
140
|
|
|
public function fetch($relation, $getAll = false) |
|
141
|
|
|
{ |
|
142
|
8 |
|
// @codeCoverageIgnoreStart |
|
143
|
4 |
|
if ($getAll instanceof EM || func_num_args() === 3 && $getAll === null) { |
|
144
|
|
|
$getAll = func_num_args() === 3 ? func_get_arg(2) : false; |
|
145
|
|
|
trigger_error( |
|
146
|
|
|
'Passing EntityManager to fetch is deprecated. Use ->setEntityManager() to overwrite', |
|
147
|
|
|
E_USER_DEPRECATED |
|
148
|
|
|
); |
|
149
|
|
|
} |
|
150
|
|
|
// @codeCoverageIgnoreEnd |
|
151
|
|
|
|
|
152
|
|
|
$relation = $this::getRelation($relation); |
|
153
|
|
|
|
|
154
|
|
|
return $getAll ? $relation->fetchAll($this, $this->entityManager) : |
|
155
|
|
|
$relation->fetch($this, $this->entityManager); |
|
156
|
|
|
} |
|
157
|
|
|
} |
|
158
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.