Relation::createRelation()   C
last analyzed

Complexity

Conditions 12
Paths 256

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 16
cts 16
cp 1
rs 5.4333
c 0
b 0
f 0
cc 12
nc 256
nop 2
crap 12

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace ORM;
4
5
use ORM\Exception\IncompletePrimaryKey;
6
use ORM\Exception\InvalidConfiguration;
7
use ORM\Exception\InvalidRelation;
8
use ORM\Relation\ManyToMany;
9
use ORM\Relation\OneToMany;
10
use ORM\Relation\OneToOne;
11
use ORM\Relation\Owner;
12
13
/**
14
 * Base Relation
15
 *
16
 * @package ORM
17
 * @author  Thomas Flori <[email protected]>
18
 */
19
abstract class Relation
20
{
21
    const OPT_CLASS        = 'class';
22
    const OPT_REFERENCE    = 'reference';
23
    const OPT_CARDINALITY  = 'cardinality';
24
    const OPT_OPPONENT     = 'opponent';
25
    const OPT_TABLE        = 'table';
26
    const CARDINALITY_ONE  = 'one';
27
    const CARDINALITY_MANY = 'many';
28
29
    /** The name of the relation for error messages
30
     * @var string */
31
    protected $name;
32
33
    /** The class that is related
34
     * @var string */
35
    protected $class;
36
37
    /** The name of the relation in the related class
38
     * @var string */
39
    protected $opponent;
40
41
    /** Reference definition as key value pairs
42
     * @var array */
43
    protected $reference;
44
45
    /**
46
     * Factory for relation definition object
47
     *
48
     * @param string $name
49
     * @param array $relDef
50
     * @return Relation
51
     */
52 14
    public static function createRelation($name, $relDef)
53
    {
54 14
        if (isset($relDef[0])) {
55 11
            $relDef = self::convertShort($name, $relDef);
56
        }
57
58 13
        $class       = isset($relDef[self::OPT_CLASS]) ? $relDef[self::OPT_CLASS] : null;
59 13
        $reference   = isset($relDef[self::OPT_REFERENCE]) ? $relDef[self::OPT_REFERENCE] : null;
60 13
        $table       = isset($relDef[self::OPT_TABLE]) ? $relDef[self::OPT_TABLE] : null;
61 13
        $opponent    = isset($relDef[self::OPT_OPPONENT]) ? $relDef[self::OPT_OPPONENT] : null;
62 13
        $cardinality = isset($relDef[self::OPT_CARDINALITY]) ?
63 13
            $relDef[self::OPT_CARDINALITY] : null;
64
65 13
        if ($reference && !isset($table)) {
66 4
            return new Owner($name, $class, $reference);
67 9
        } elseif ($table) {
68 2
            return new ManyToMany($name, $class, $reference, $opponent, $table);
69 7
        } elseif (!$cardinality || $cardinality === self::CARDINALITY_MANY) {
70 4
            return new OneToMany($name, $class, $opponent);
71
        } else {
72 4
            return new OneToOne($name, $class, $opponent);
73
        }
74
    }
75
76
    /**
77
     * Converts short form to assoc form
78
     *
79
     * @param string $name
80
     * @param array $relDef
81
     * @return array
82
     * @throws InvalidConfiguration
83
     */
84 11
    protected static function convertShort($name, $relDef)
85
    {
86
        // convert the short form
87 11
        $length = count($relDef);
88
89 11
        if ($length === 2 && gettype($relDef[1]) === 'array') {
90
            // owner of one-to-many or one-to-one
91
            return [
92 2
                self::OPT_CARDINALITY => self::CARDINALITY_ONE,
93 2
                self::OPT_CLASS       => $relDef[0],
94 2
                self::OPT_REFERENCE   => $relDef[1],
95
            ];
96 9
        } elseif ($length === 3 && $relDef[0] === self::CARDINALITY_ONE) {
97
            // non-owner of one-to-one
98
            return [
99 4
                self::OPT_CARDINALITY => self::CARDINALITY_ONE,
100 4
                self::OPT_CLASS       => $relDef[1],
101 4
                self::OPT_OPPONENT    => $relDef[2],
102
            ];
103 6
        } elseif ($length === 2) {
104
            // non-owner of one-to-many
105
            return [
106 3
                self::OPT_CARDINALITY => self::CARDINALITY_MANY,
107 3
                self::OPT_CLASS       => $relDef[0],
108 3
                self::OPT_OPPONENT    => $relDef[1],
109
            ];
110 3
        } elseif ($length === 4 && gettype($relDef[1]) === 'array') {
111
            // many-to-many
112
            return [
113 2
                self::OPT_CARDINALITY => self::CARDINALITY_MANY,
114 2
                self::OPT_CLASS       => $relDef[0],
115 2
                self::OPT_REFERENCE   => $relDef[1],
116 2
                self::OPT_OPPONENT    => $relDef[2],
117 2
                self::OPT_TABLE       => $relDef[3],
118
            ];
119
        } else {
120 1
            throw new InvalidConfiguration('Invalid short form for relation ' . $name);
121
        }
122
    }
123
124
    /**
125
     * @return string
126
     */
127 8
    public function getClass()
128
    {
129 8
        return $this->class;
130
    }
131
132
    /**
133
     * @return array
134
     */
135 36
    public function getReference()
136
    {
137 36
        return $this->reference;
138
    }
139
140
    /**
141
     * @return Relation
142
     */
143 35
    public function getOpponent()
144
    {
145
        // @todo seems we need a test for it
146
//        if (!$this->opponent) {
147
//            return null;
148
//        }
149
150 35
        return call_user_func([ $this->class, 'getRelation' ], $this->opponent);
151
    }
152
153
    /**
154
     * Fetch the relation
155
     *
156
     * Runs fetch on the EntityManager and returns its result.
157
     *
158
     * @param Entity        $self
159
     * @param EntityManager $entityManager
160
     * @return mixed
161
     */
162
    abstract public function fetch(Entity $self, EntityManager $entityManager);
163
164
    /**
165
     * Fetch all from the relation
166
     *
167
     * Runs fetch and returns EntityFetcher::all() if a Fetcher is returned.
168
     *
169
     * @param Entity        $self
170
     * @param EntityManager $entityManager
171
     * @return Entity[]|Entity
172
     */
173 3
    public function fetchAll(Entity $self, EntityManager $entityManager)
174
    {
175 3
        $fetcher = $this->fetch($self, $entityManager);
176
177 3
        if ($fetcher instanceof EntityFetcher) {
178 1
            return $fetcher->all();
179
        }
180
181 2
        return $fetcher;
182
    }
183
184
    /**
185
     * Get the foreign key for the given reference
186
     *
187
     * @param Entity $self
188
     * @param array $reference
189
     * @return array
190
     * @throws IncompletePrimaryKey
191
     */
192 12
    protected function getForeignKey(Entity $self, $reference)
193
    {
194 12
        $foreignKey = [];
195
196 12
        foreach ($reference as $attribute => $fkAttribute) {
197 12
            $value = $self->__get($attribute);
198
199 12
            if ($value === null) {
200 2
                throw new IncompletePrimaryKey('Key incomplete for join');
201
            }
202
203 10
            $foreignKey[$fkAttribute] = $value;
204
        }
205
206 10
        return $foreignKey;
207
    }
208
209
    /**
210
     * Set the relation to $entity
211
     *
212
     * @param Entity $self
213
     * @param Entity|null $entity
214
     * @throws InvalidRelation
215
     */
216 1
    public function setRelated(Entity $self, Entity $entity = null)
217
    {
218 1
        throw new InvalidRelation('This is not the owner of the relation');
219
    }
220
221
    /**
222
     * Add $entities to association table
223
     *
224
     * @param Entity $self
225
     * @param Entity[] $entities
226
     * @param EntityManager $entityManager
227
     * @throws InvalidRelation
228
     */
229 1
    public function addRelated(Entity $self, array $entities, EntityManager $entityManager)
230
    {
231 1
        throw new InvalidRelation('This is not a many-to-many relation');
232
    }
233
234
    /**
235
     * Delete $entities from association table
236
     *
237
     * @param Entity $self
238
     * @param Entity[] $entities
239
     * @param EntityManager $entityManager
240
     * @throws InvalidRelation
241
     */
242 1
    public function deleteRelated(Entity $self, array $entities, EntityManager $entityManager)
243
    {
244 1
        throw new InvalidRelation('This is not a many-to-many relation');
245
    }
246
247
    /**
248
     * Join this relation in $fetcher
249
     *
250
     * @param EntityFetcher $fetcher
251
     * @param string        $join
252
     * @param string        $alias
253
     * @return mixed
254
     */
255
    abstract public function addJoin(EntityFetcher $fetcher, $join, $alias);
256
}
257