Completed
Push — master ( a8cb34...ce5009 )
by Anton
03:37
created

RelationDefinition::isLateBinded()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral, Core Components
4
 *
5
 * @author Wolfy-J
6
 */
7
8
namespace Spiral\ORM\Schemas\Definitions;
9
10
use Spiral\ORM\Exceptions\ORMException;
11
use Spiral\ORM\Exceptions\SchemaException;
12
use Spiral\ORM\RecordEntity;
13
14
/**
15
 * Defines relation in schema.
16
 */
17
final class RelationDefinition
18
{
19
    /**
20
     * Relation name.
21
     *
22
     * @var string
23
     */
24
    private $name;
25
26
    /**
27
     * @var string
28
     */
29
    private $type;
30
31
    /**
32
     * @var string
33
     */
34
    private $target;
35
36
    /**
37
     * @var array
38
     */
39
    private $options = [];
40
41
    /**
42
     * Name or definition or inversion.
43
     *
44
     * @var string|array
45
     */
46
    private $inverse = null;
47
48
    /**
49
     * Defines where relation comes from.
50
     *
51
     * @var RelationContext
52
     */
53
    private $sourceContext;
54
55
    /**
56
     * Defines where relation points to (if any).
57
     *
58
     * @var RelationContext|null
59
     */
60
    private $targetContext;
61
62
    /**
63
     * @param string       $name
64
     * @param string       $type
65
     * @param string       $target
66
     * @param array        $options
67
     * @param string|array $inverse Name or definition of relation to inversed to.
68
     */
69
    public function __construct(
70
        string $name,
71
        string $type,
72
        string $target,
73
        array $options,
74
        $inverse = null
75
    ) {
76
        $this->name = $name;
77
        $this->type = $type;
78
        $this->target = $target;
79
        $this->options = $options;
80
        $this->inverse = $inverse;
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    public function getName(): string
87
    {
88
        return $this->name;
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function getType(): string
95
    {
96
        return $this->type;
97
    }
98
99
    /**
100
     * Target class name, see more information about target context via targetContext() method.
101
     *
102
     * @return string
103
     */
104
    public function getTarget(): string
105
    {
106
        return $this->target;
107
    }
108
109
    /**
110
     * Indicates that relation must be late binded. In relations like that targetContext() can
111
     * return null.
112
     *
113
     * @return bool
114
     */
115
    public function isLateBinded(): bool
116
    {
117
        return !empty($this->options[RecordEntity::LATE_BINDING]);
118
    }
119
120
    /**
121
     * @return array
122
     */
123
    public function getOptions(): array
124
    {
125
        return $this->options;
126
    }
127
128
    /**
129
     * Source context (where relation comes from).
130
     *
131
     * @return RelationContext
132
     */
133
    public function sourceContext(): RelationContext
134
    {
135
        if (empty($this->sourceContext)) {
136
            throw new SchemaException("Source context not set");
137
        }
138
139
        return $this->sourceContext;
140
    }
141
142
    /**
143
     * Target context if any.
144
     *
145
     * @return null|RelationContext
146
     */
147
    public function targetContext()
148
    {
149
        return $this->targetContext;
150
    }
151
152
    /**
153
     * Set relation contexts.
154
     *
155
     * @param RelationContext      $source
156
     * @param RelationContext|null $target
157
     *
158
     * @return RelationDefinition
159
     */
160
    public function withContext(RelationContext $source, RelationContext $target = null): self
161
    {
162
        $definition = clone $this;
163
        $definition->sourceContext = $source;
164
        $definition->targetContext = $target;
165
166
        return $definition;
167
    }
168
169
    /**
170
     * Create version of definition with different set of options.
171
     *
172
     * @param array $options
173
     *
174
     * @return RelationDefinition
175
     */
176
    public function withOptions(array $options): self
177
    {
178
        $definition = clone $this;
179
        $definition->options = $options;
180
181
        return $definition;
182
    }
183
184
    /**
185
     * Checks if inversion if required.
186
     *
187
     * @return bool
188
     */
189
    public function needInversion(): bool
190
    {
191
        return !empty($this->inverse);
192
    }
193
194
    /**
195
     * Name of relation to be inversed to.
196
     *
197
     * @return string|array
198
     */
199
    public function getInverse()
200
    {
201
        if (!$this->needInversion()) {
202
            throw new ORMException("Unable to get inversed name, not inversable");
203
        }
204
205
        return $this->inverse;
206
    }
207
}