Completed
Push — master ( fc4fc8...fd2b1b )
by Thomas
02:20
created

Relations::fetch()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 4
cts 4
cp 1
rs 9.0777
c 0
b 0
f 0
cc 6
nc 6
nop 2
crap 6
1
<?php
2
3
namespace ORM\Entity;
4
5
use ORM\Entity;
6
use ORM\EntityFetcher;
7
use ORM\EntityManager as EM;
8
use ORM\Exception;
9
use ORM\Exception\IncompletePrimaryKey;
10
use ORM\Exception\InvalidConfiguration;
11
use ORM\Exception\InvalidRelation;
12
use ORM\Exception\NoEntityManager;
13
use ORM\Exception\UndefinedRelation;
14
use ORM\Relation;
15
16
trait Relations
17
{
18
    /** Relation definitions
19
     * @var array */
20
    protected static $relations = [];
21
22
    /** The entity manager from which this entity got created
23
     * @var EM */
24
    protected $entityManager;
25
26
    /** Related objects for getRelated
27
     * @var array */
28
    protected $relatedObjects = [];
29
30
    /**
31
     * Get the definition for $relation
32
     *
33
     * It normalize the short definition form and create a Relation object from it.
34
     *
35
     * @param string $relation
36
     * @return Relation
37
     * @throws InvalidConfiguration
38
     * @throws UndefinedRelation
39
     */
40 83
    public static function getRelation($relation)
41
    {
42 83
        if (!isset(static::$relations[$relation])) {
43 3
            throw new UndefinedRelation('Relation ' . $relation . ' is not defined');
44
        }
45
46 82
        $relDef = &static::$relations[$relation];
47
48 82
        if (!$relDef instanceof Relation) {
49 14
            $relDef = Relation::createRelation($relation, $relDef);
50
        }
51
52 81
        return $relDef;
53
    }
54
55
    /**
56
     * Get related objects
57
     *
58
     * The difference between getRelated and fetch is that getRelated stores the fetched entities. To refresh set
59
     * $refresh to true.
60
     *
61
     * @param string $relation
62
     * @param bool   $refresh
63
     * @return mixed
64
     * @throws Exception\NoConnection
65
     * @throws Exception\NoEntity
66
     * @throws IncompletePrimaryKey
67
     * @throws InvalidConfiguration
68
     * @throws NoEntityManager
69
     * @throws UndefinedRelation
70
     */
71 11
    public function getRelated($relation, $refresh = false)
72
    {
73 11
        if ($refresh || !isset($this->relatedObjects[$relation])) {
74 9
            $this->relatedObjects[$relation] = $this->fetch($relation, true);
75
        }
76
77 11
        return $this->relatedObjects[$relation];
78
    }
79
80
    /**
81
     * Set $relation to $entity
82
     *
83
     * This method is only for the owner of a relation.
84
     *
85
     * @param string $relation
86
     * @param Entity $entity
87
     * @throws IncompletePrimaryKey
88
     * @throws InvalidRelation
89
     */
90 7
    public function setRelated($relation, Entity $entity = null)
91
    {
92 7
        $this::getRelation($relation)->setRelated($this, $entity);
93
94 4
        $this->relatedObjects[$relation] = $entity;
95 4
    }
96
97
    /**
98
     * Add relations for $relation to $entities
99
     *
100
     * This method is only for many-to-many relations.
101
     *
102
     * This method does not take care about already existing relations and will fail hard.
103
     *
104
     * @param string   $relation
105
     * @param Entity[] $entities
106
     * @throws NoEntityManager
107
     */
108 8
    public function addRelated($relation, array $entities)
109
    {
110
        // @codeCoverageIgnoreStart
111
        if (func_num_args() === 3 && func_get_arg(2) instanceof EM) {
112
            trigger_error(
113
                'Passing EntityManager to addRelated is deprecated. Use ->setEntityManager() to overwrite',
114
                E_USER_DEPRECATED
115
            );
116
        }
117
        // @codeCoverageIgnoreEnd
118
119 8
        $this::getRelation($relation)->addRelated($this, $entities, $this->entityManager);
120 4
    }
121
122
    /**
123
     * Delete relations for $relation to $entities
124
     *
125
     * This method is only for many-to-many relations.
126
     *
127
     * @param string   $relation
128
     * @param Entity[] $entities
129
     * @throws NoEntityManager
130
     */
131 8
    public function deleteRelated($relation, $entities)
132
    {
133
        // @codeCoverageIgnoreStart
134
        if (func_num_args() === 3 && func_get_arg(2) instanceof EM) {
135
            trigger_error(
136
                'Passing EntityManager to deleteRelated is deprecated. Use ->setEntityManager() to overwrite',
137
                E_USER_DEPRECATED
138
            );
139
        }
140
        // @codeCoverageIgnoreEnd
141
142 8
        $this::getRelation($relation)->deleteRelated($this, $entities, $this->entityManager);
143 4
    }
144
145
    /**
146
     * Fetches related objects
147
     *
148
     * For relations with cardinality many it returns an EntityFetcher. Otherwise it returns the entity.
149
     *
150
     * It will throw an error for non owner when the key is incomplete.
151
     *
152
     * @param string $relation The relation to fetch
153
     * @param bool   $getAll
154
     * @return Entity|Entity[]|EntityFetcher
155
     * @throws NoEntityManager
156
     */
157 20
    public function fetch($relation, $getAll = false)
158
    {
159
        // @codeCoverageIgnoreStart
160
        if ($getAll instanceof EM || func_num_args() === 3 && $getAll === null) {
161
            $getAll = func_num_args() === 3 ? func_get_arg(2) : false;
162
            trigger_error(
163
                'Passing EntityManager to fetch is deprecated. Use ->setEntityManager() to overwrite',
164
                E_USER_DEPRECATED
165
            );
166
        }
167
        // @codeCoverageIgnoreEnd
168
169 20
        $relation = $this::getRelation($relation);
170
171 20
        return $getAll ? $relation->fetchAll($this, $this->entityManager) :
172 20
            $relation->fetch($this, $this->entityManager);
173
    }
174
}
175