Passed
Push — master ( 6dedbf...e08e26 )
by Anton
01:45
created

HasOne::render()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 4
nop 1
dl 0
loc 23
rs 9.8666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
namespace Cycle\Schema\Relation;
11
12
use Cycle\ORM\Relation;
13
use Cycle\Schema\Registry;
14
use Cycle\Schema\Relation\Traits\FieldTrait;
15
16
class HasOne extends RelationSchema
17
{
18
    use FieldTrait;
19
20
    protected const RELATION_TYPE = Relation::HAS_ONE;
21
22
    protected const OPTION_SCHEMA = [
23
        // save with parent
24
        Relation::CASCADE            => true,
25
26
        // use outer entity constrain by default
27
        Relation::CONSTRAIN          => true,
28
29
        // not nullable by default
30
        Relation::NULLABLE           => false,
31
32
        // link to parent entity primary key by default
33
        Relation::INNER_KEY          => '{source:primaryKey}',
34
35
        // default field name for inner key
36
        Relation::OUTER_KEY          => '{source:role}_{innerKey}',
37
38
        // rendering options
39
        RelationSchema::FK_CREATE    => true,
40
        RelationSchema::FK_ACTION    => 'CASCADE',
41
        RelationSchema::INDEX_CREATE => true,
42
    ];
43
44
    /**
45
     * @param Registry $registry
46
     */
47
    public function compute(Registry $registry)
48
    {
49
        parent::compute($registry);
50
51
        $source = $registry->getEntity($this->source);
52
        $target = $registry->getEntity($this->target);
53
54
        // create target outer field
55
        $this->ensureField(
56
            $target,
57
            $this->options->get(Relation::OUTER_KEY),
58
            $this->getField($source, Relation::INNER_KEY)
59
        );
60
    }
61
62
    /**
63
     * @param Registry $registry
64
     */
65
    public function render(Registry $registry)
66
    {
67
        $source = $registry->getEntity($this->source);
68
        $target = $registry->getEntity($this->target);
69
70
        $innerField = $this->getField($source, Relation::INNER_KEY);
71
        $outerField = $this->getField($target, Relation::OUTER_KEY);
72
73
        $table = $registry->getTableSchema($target);
74
75
        if ($this->options->get(self::INDEX_CREATE)) {
76
            $table->index([$outerField->getColumn()]);
77
        }
78
79
        if ($this->options->get(self::FK_CREATE)) {
80
            $fk = $table->foreignKey($outerField->getColumn());
81
82
            // todo: what if database is different?
83
84
            $fk->references($registry->getTable($source), $innerField->getColumn());
85
86
            $fk->onUpdate($this->options->get(self::FK_ACTION));
87
            $fk->onDelete($this->options->get(self::FK_ACTION));
88
        }
89
    }
90
}