Passed
Push — master ( 0ea13e...268b05 )
by Anton
01:37
created

AbstractRelation::getConstrain()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 0
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Cycle\ORM\Relation;
10
11
use Cycle\ORM\Exception\RelationException;
12
use Cycle\ORM\Heap\Node;
13
use Cycle\ORM\MapperInterface;
14
use Cycle\ORM\ORMInterface;
15
use Cycle\ORM\Promise\PromiseInterface;
16
use Cycle\ORM\Promise\ReferenceInterface;
17
use Cycle\ORM\Relation;
18
use Cycle\ORM\Schema;
19
use Cycle\ORM\Select\SourceInterface;
20
use Cycle\ORM\Select\SourceProviderInterface;
21
22
abstract class AbstractRelation implements RelationInterface
23
{
24
    use Traits\ContextTrait;
25
26
    /** @var ORMInterface|SourceProviderInterface @internal */
27
    protected $orm;
28
29
    /** @var string */
30
    protected $name;
31
32
    /** @var string */
33
    protected $target;
34
35
    /** @var array */
36
    protected $schema;
37
38
    /** @var string */
39
    protected $innerKey;
40
41
    /** @var string */
42
    protected $outerKey;
43
44
    /**
45
     * @param ORMInterface $orm
46
     * @param string       $name
47
     * @param string       $target
48
     * @param array        $schema
49
     */
50
    public function __construct(ORMInterface $orm, string $name, string $target, array $schema)
51
    {
52
        $this->orm = $orm;
53
        $this->name = $name;
54
        $this->target = $target;
55
        $this->schema = $schema;
56
        $this->innerKey = $schema[Relation::INNER_KEY];
57
        $this->outerKey = $schema[Relation::OUTER_KEY];
58
    }
59
60
    /**
61
     * @inheritdoc
62
     */
63
    public function getName(): string
64
    {
65
        return $this->name;
66
    }
67
68
    /**
69
     * @inheritdoc
70
     */
71
    public function isCascade(): bool
72
    {
73
        return $this->schema[Relation::CASCADE] ?? false;
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function init(array $data): array
80
    {
81
        $item = $this->orm->make($this->target, $data, Node::MANAGED);
0 ignored issues
show
Bug introduced by
The method make() does not exist on Cycle\ORM\Select\SourceProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Cycle\ORM\Select\SourceProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

81
        /** @scrutinizer ignore-call */ 
82
        $item = $this->orm->make($this->target, $data, Node::MANAGED);
Loading history...
82
83
        return [$item, $item];
84
    }
85
86
    /**
87
     * @inheritdoc
88
     */
89
    public function extract($data)
90
    {
91
        return $data;
92
    }
93
94
    /**
95
     * @return string
96
     */
97
    public function __toString()
98
    {
99
        // this is incorrect class
100
        return sprintf("%s(%s)->%s", $this->name, get_class($this), $this->target);
101
    }
102
103
    /**
104
     * Indicates that relation can not be nullable.
105
     *
106
     * @return bool
107
     */
108
    protected function isRequired(): bool
109
    {
110
        if (array_key_exists(Relation::NULLABLE, $this->schema)) {
111
            return !$this->schema[Relation::NULLABLE];
112
        }
113
114
        return true;
115
    }
116
117
    /**
118
     * Get Node for the given entity. Null if entity does not exists. Automatically
119
     * register entity claims.
120
     *
121
     * @param object $entity
122
     * @param int    $claim
123
     * @return Node|null
124
     */
125
    protected function getNode($entity, int $claim = 0): ?Node
126
    {
127
        if (is_null($entity)) {
128
            return null;
129
        }
130
131
        if ($entity instanceof ReferenceInterface) {
132
            return new Node(Node::PROMISED, $entity->__scope(), $entity->__role());
133
        }
134
135
        $node = $this->orm->getHeap()->get($entity);
0 ignored issues
show
Bug introduced by
The method getHeap() does not exist on Cycle\ORM\Select\SourceProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Cycle\ORM\Select\SourceProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        $node = $this->orm->/** @scrutinizer ignore-call */ getHeap()->get($entity);
Loading history...
136
137
        if (is_null($node)) {
138
            $node = new Node(Node::NEW, [], $this->orm->getMapper($entity)->getRole());
0 ignored issues
show
Bug introduced by
The method getMapper() does not exist on Cycle\ORM\Select\SourceProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Cycle\ORM\Select\SourceProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

138
            $node = new Node(Node::NEW, [], $this->orm->/** @scrutinizer ignore-call */ getMapper($entity)->getRole());
Loading history...
139
            $this->orm->getHeap()->attach($entity, $node);
140
        }
141
142
        if ($claim === 1) {
143
            $node->getState()->addClaim();
144
        }
145
146
        if ($claim === -1) {
147
            $node->getState()->decClaim();
148
        }
149
150
        return $node;
151
    }
152
153
    /**
154
     * Get the source associated with the role.
155
     *
156
     * @param string|null $role
157
     * @return SourceInterface
158
     */
159
    protected function getSource(string $role = null): SourceInterface
160
    {
161
        return $this->orm->getSource($role ?? $this->target);
162
    }
163
164
    /**
165
     * Get the mapper associated with a role.
166
     *
167
     * @param string|null $role
168
     * @return MapperInterface
169
     */
170
    protected function getMapper(string $role = null): MapperInterface
171
    {
172
        return $this->orm->getMapper($role ?? $this->target);
173
    }
174
175
    /**
176
     * @param Node   $node
177
     * @param string $field
178
     * @return string
179
     */
180
    protected function columnName(Node $node, string $field): string
181
    {
182
        return $this->orm->getSchema()->define($node->getRole(), Schema::COLUMNS)[$field] ?? $field;
0 ignored issues
show
Bug introduced by
The method getSchema() does not exist on Cycle\ORM\Select\SourceProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Cycle\ORM\Select\SourceProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

182
        return $this->orm->/** @scrutinizer ignore-call */ getSchema()->define($node->getRole(), Schema::COLUMNS)[$field] ?? $field;
Loading history...
183
    }
184
185
    /**
186
     * Assert that given entity is allowed for the relation.
187
     *
188
     * @param Node $relNode
189
     *
190
     * @throws RelationException
191
     */
192
    protected function assertValid(Node $relNode)
193
    {
194
        if ($relNode->getRole() != $this->target) {
195
            throw new RelationException(sprintf("Unable to link %s, given `%s`", $this, $relNode->getRole()));
196
        }
197
    }
198
199
    /**
200
     * Resolve the reference to the object.
201
     *
202
     * @param ReferenceInterface $reference
203
     * @return mixed|null
204
     */
205
    protected function resolve(ReferenceInterface $reference)
206
    {
207
        if ($reference instanceof PromiseInterface) {
208
            return $reference->__resolve();
209
        }
210
211
        $scope = $reference->__scope();
212
        return $this->orm->get($reference->__role(), key($scope), current($scope), true);
0 ignored issues
show
Bug introduced by
The method get() does not exist on Cycle\ORM\Select\SourceProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Cycle\ORM\Select\SourceProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

212
        return $this->orm->/** @scrutinizer ignore-call */ get($reference->__role(), key($scope), current($scope), true);
Loading history...
213
    }
214
}