Completed
Branch feature/pre-split (c871cb)
by Anton
03:37
created

AbstractRelation::isLeading()   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
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Entities\Relations;
8
9
use Spiral\ORM\Exceptions\RelationException;
10
use Spiral\ORM\ORMInterface;
11
use Spiral\ORM\Record;
12
use Spiral\ORM\RecordInterface;
13
use Spiral\ORM\RelationInterface;
14
15
abstract class AbstractRelation implements RelationInterface
16
{
17
    /**
18
     * Indicates that relation commands must be executed prior to parent command.
19
     */
20
    const LEADING_RELATION = false;
21
22
    /**
23
     * Indication that relation have been loaded.
24
     *
25
     * @var bool
26
     */
27
    protected $loaded;
28
29
    /**
30
     * Parent record. Only read operations!
31
     *
32
     * @invisible
33
     * @var RecordInterface
34
     */
35
    protected $parent;
36
37
    /**
38
     * Class name relation points to.
39
     *
40
     * @var string
41
     */
42
    protected $class;
43
44
    /**
45
     * Relation schema, defined when ORM being compiled. Check relation config to find out what
46
     * schema producer been used for this relation accessor.
47
     *
48
     * @var array
49
     */
50
    protected $schema;
51
52
    /**
53
     * Related data.
54
     *
55
     * @invisible
56
     * @var array|null
57
     */
58
    protected $data = null;
59
60
    /**
61
     * Provides ability for lazy-loading model initialization and inner selects.
62
     *
63
     * @invisible
64
     * @var ORMInterface
65
     */
66
    protected $orm;
67
68
    /**
69
     * @param string       $class Owner model class name.
70
     * @param array        $schema
71
     * @param ORMInterface $orm
72
     */
73
    public function __construct(string $class, array $schema, ORMInterface $orm)
74
    {
75
        $this->class = $class;
76
        $this->schema = $schema;
77
        $this->orm = $orm;
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function isLeading(): bool
84
    {
85
        return static::LEADING_RELATION;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function withContext(
92
        RecordInterface $parent,
93
        bool $loaded = false,
94
        array $data = null
95
    ): RelationInterface {
96
        $relation = clone $this;
97
        $relation->parent = $parent;
98
        $relation->loaded = $loaded;
99
        $relation->data = is_null($data) ? [] : $data;
100
101
        return $relation;
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107
    public function getClass(): string
108
    {
109
        return $this->class;
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115
    public function isLoaded(): bool
116
    {
117
        return $this->loaded;
118
    }
119
120
    /**
121
     * Get value from record based on schema key.
122
     *
123
     * @param RecordInterface $record
124
     * @param string          $key
125
     *
126
     * @return mixed
127
     */
128
    protected function value(RecordInterface $record, string $key)
129
    {
130
        return $record->getField($this->key($key));
131
    }
132
133
    /**
134
     * Schema value.
135
     *
136
     * @param int $key
137
     *
138
     * @return mixed
139
     */
140
    protected function key(int $key)
141
    {
142
        return $this->schema[$key];
143
    }
144
145
    /**
146
     * Get primary key column
147
     *
148
     * @param RecordInterface $record
149
     *
150
     * @return string
151
     */
152
    protected function primaryColumnOf(RecordInterface $record): string
153
    {
154
        return $this->orm->define(get_class($record), ORMInterface::R_PRIMARY_KEY);
155
    }
156
157
    /**
158
     * @param $value
159
     */
160
    protected function assertValid($value)
161
    {
162
        if (is_null($value)) {
163
            if (!$this->schema[Record::NULLABLE]) {
164
                throw new RelationException("Relation is not nullable");
165
            }
166
        } elseif (!is_object($value)) {
167
            throw new RelationException(
168
                "Must be an instance of '{$this->class}', '" . gettype($value) . "' given"
169
            );
170
        } elseif (!is_a($value, $this->class, false)) {
171
            throw new RelationException(
172
                "Must be an instance of '{$this->class}', '" . get_class($value) . "' given"
173
            );
174
        }
175
    }
176
177
    /**
178
     * If record not synced or can't be synced. Only work for PK based relations.
179
     *
180
     * @param RecordInterface $inner
181
     * @param RecordInterface $outer
182
     *
183
     * @return bool
184
     */
185
    protected function isSynced(RecordInterface $inner, RecordInterface $outer): bool
186
    {
187
        if (empty($outer->primaryKey())) {
188
            //Parent not saved
189
            return false;
190
        }
191
192
        //Comparing FK values
193
        return $outer->getField(
194
                $this->key(Record::OUTER_KEY)
195
            ) == $inner->getField(
196
                $this->key(Record::INNER_KEY)
197
            );
198
    }
199
}