Completed
Branch feature/pre-split (c69968)
by Anton
21:25
created

HasOneRelation::queueRelated()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 22
rs 9.2
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\CommandInterface;
10
use Spiral\ORM\Commands\NullCommand;
11
use Spiral\ORM\Commands\TransactionalCommand;
12
use Spiral\ORM\ContextualCommandInterface;
13
use Spiral\ORM\Entities\Relations\Traits\LookupTrait;
14
use Spiral\ORM\Record;
15
use Spiral\ORM\RecordInterface;
16
17
class HasOneRelation extends SingularRelation
18
{
19
    use LookupTrait;
20
21
    /** Automatically create related model when empty. */
22
    const CREATE_PLACEHOLDER = true;
23
24
    /**
25
     * Previously binded instance, to be deleted.
26
     *
27
     * @var RecordInterface
28
     */
29
    private $previous = null;
30
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public function setRelated($value)
35
    {
36
        //Make sure value is accepted
37
        $this->assertValid($value);
38
39
        $this->loaded = true;
40
        if (empty($this->previous)) {
41
            //We are only keeping reference to the oldest (ie loaded) instance
42
            $this->previous = $this->instance;
43
        }
44
45
        $this->instance = $value;
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function queueCommands(ContextualCommandInterface $parentCommand): CommandInterface
52
    {
53
        if (!empty($this->previous)) {
54
            $transaction = new TransactionalCommand();
55
56
            //Delete old entity
57
            $transaction->addCommand($this->previous->queueDelete());
58
59
            //Store new entity if any (leading)
60
            $transaction->addCommand($this->queueRelated($parentCommand), true);
61
62
            //We don't need previous reference anymore
63
            $this->previous = null;
64
65
            return $transaction;
66
        }
67
68
        return $this->queueRelated($parentCommand);
69
    }
70
71
    /**
72
     * Store related instance.
73
     *
74
     * @param ContextualCommandInterface $parentCommand
75
     *
76
     * @return CommandInterface
77
     */
78
    private function queueRelated(ContextualCommandInterface $parentCommand): CommandInterface
79
    {
80
        if (empty($this->instance)) {
81
            return new NullCommand();
82
        }
83
84
        //Related entity store command
85
        $innerCommand = $this->instance->queueStore(true);
86
87
        //Inversed version of BelongsTo
88
        if (!$this->isSynced($this->parent, $this->instance)) {
89
            //Syncing FKs after primary command been executed
90
            $parentCommand->onExecute(function ($outerCommand) use ($innerCommand) {
91
                $innerCommand->addContext(
92
                    $this->key(Record::OUTER_KEY),
93
                    $this->lookupKey(Record::INNER_KEY, $this->parent, $outerCommand)
94
                );
95
            });
96
        }
97
98
        return $innerCommand;
99
    }
100
}