ManyToOne   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 19
eloc 63
c 2
b 0
f 0
dl 0
loc 126
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A attachEntities() 0 19 4
A applyDefaults() 0 12 3
A joinSubselect() 0 12 1
A detachEntities() 0 22 3
A attachMatchesToEntity() 0 12 2
A addActionOnSave() 0 13 3
A addActionOnDelete() 0 15 3
1
<?php
2
3
namespace Sirius\Orm\Relation;
4
5
use Sirius\Orm\Action\BaseAction;
6
use Sirius\Orm\Collection\Collection;
7
use Sirius\Orm\Entity\EntityInterface;
8
use Sirius\Orm\Entity\StateEnum;
9
use Sirius\Orm\Query;
10
11
class ManyToOne extends Relation
12
{
13
    protected function applyDefaults(): void
14
    {
15
        parent::applyDefaults();
16
17
        $foreignKey = $this->foreignMapper->getPrimaryKey();
18
        if (! isset($this->options[RelationConfig::FOREIGN_KEY])) {
19
            $this->options[RelationConfig::FOREIGN_KEY] = $foreignKey;
20
        }
21
22
        if (! isset($this->options[RelationConfig::NATIVE_KEY])) {
23
            $nativeKey                                 = $this->getKeyColumn($this->name, $foreignKey);
24
            $this->options[RelationConfig::NATIVE_KEY] = $nativeKey;
25
        }
26
    }
27
28
    public function joinSubselect(Query $query, string $reference)
29
    {
30
        $subselect = $query->subSelectForJoinWith()
31
                           ->from($this->foreignMapper->getTable())
32
                           ->columns($this->foreignMapper->getTable() . '.*')
33
                           ->as($reference);
34
35
        $subselect = $this->applyQueryCallback($subselect);
36
37
        $subselect = $this->applyForeignGuards($subselect);
38
39
        return $query->join('INNER', $subselect->getStatement(), $this->getJoinOnForSubselect());
40
    }
41
42
    public function attachMatchesToEntity(EntityInterface $nativeEntity, array $result)
43
    {
44
        // no point in linking entities if the native one is deleted
45
        if ($nativeEntity->getPersistenceState() == StateEnum::DELETED) {
46
            return;
47
        }
48
49
        $nativeId = $this->getEntityId($this->nativeMapper, $nativeEntity, array_keys($this->keyPairs));
50
51
        $found = $result[$nativeId] ?? [];
52
53
        $this->attachEntities($nativeEntity, $found[0] ?? null);
54
    }
55
56
    /**
57
     * @param EntityInterface $nativeEntity
58
     * @param EntityInterface $foreignEntity
59
     */
60
    public function attachEntities(EntityInterface $nativeEntity, EntityInterface $foreignEntity = null): void
61
    {
62
        // no point in linking entities if the native one is deleted
63
        if ($nativeEntity->getPersistenceState() == StateEnum::DELETED) {
64
            return;
65
        }
66
67
        $nativeKey  = (array)$this->getOption(RelationConfig::NATIVE_KEY);
68
        $foreignKey = (array)$this->getOption(RelationConfig::FOREIGN_KEY);
69
70
        foreach ($nativeKey as $k => $col) {
71
            $this->nativeMapper->setEntityAttribute(
72
                $nativeEntity,
73
                $col,
74
                $foreignEntity ? $this->foreignMapper->getEntityAttribute($foreignEntity, $foreignKey[$k]) : null
75
            );
76
        }
77
78
        $this->nativeMapper->setEntityAttribute($nativeEntity, $this->name, $foreignEntity);
79
    }
80
81
    public function detachEntities(EntityInterface $nativeEntity, EntityInterface $foreignEntity)
82
    {
83
        if ($nativeEntity->getPersistenceState() == StateEnum::DELETED) {
84
            return;
85
        }
86
87
        // required for DELETED entities that throw errors if they are changed
88
        $state = $foreignEntity->getPersistenceState();
89
        $foreignEntity->setPersistenceState(StateEnum::SYNCHRONIZED);
90
91
        $nativeKey  = (array)$this->getOption(RelationConfig::NATIVE_KEY);
92
93
        foreach ($nativeKey as $k => $col) {
94
            $this->nativeMapper->setEntityAttribute(
95
                $nativeEntity,
96
                $col,
97
                null
98
            );
99
        }
100
101
        $this->nativeMapper->setEntityAttribute($nativeEntity, $this->name, null);
102
        $foreignEntity->setPersistenceState($state);
103
    }
104
105
    protected function addActionOnDelete(BaseAction $action)
106
    {
107
        // no cascade delete? treat it as a save
108
        if (! $this->isCascade()) {
109
            $this->addActionOnSave($action);
110
        } else {
111
            $foreignEntity = $this->nativeMapper
112
                                  ->getEntityAttribute($action->getEntity(), $this->name);
113
114
            if ($foreignEntity) {
115
                $remainingRelations = $this->getRemainingRelations($action->getOption('relations'));
116
                $deleteAction       = $this->foreignMapper
117
                    ->newDeleteAction($foreignEntity, ['relations' => $remainingRelations]);
118
                $action->prepend($deleteAction);
119
                $action->prepend($this->newSyncAction($action->getEntity(), $foreignEntity, 'delete'));
120
            }
121
        }
122
    }
123
124
    protected function addActionOnSave(BaseAction $action)
125
    {
126
        if (!$this->relationWasChanged($action->getEntity())) {
127
            return;
128
        }
129
        $foreignEntity = $this->nativeMapper->getEntityAttribute($action->getEntity(), $this->name);
130
        if ($foreignEntity) {
131
            $remainingRelations = $this->getRemainingRelations($action->getOption('relations'));
132
            $saveAction         = $this->foreignMapper
133
                ->newSaveAction($foreignEntity, ['relations' => $remainingRelations]);
134
            $saveAction->addColumns($this->getExtraColumnsForAction());
135
            $action->prepend($saveAction);
136
            $action->prepend($this->newSyncAction($action->getEntity(), $foreignEntity, 'save'));
137
        }
138
    }
139
}
140