Failed Conditions
Pull Request — master (#7799)
by Guilherme
10:54
created

buildUniqueConstraints()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7.0572

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 20
nc 9
nop 1
dl 0
loc 36
ccs 17
cts 19
cp 0.8947
crap 7.0572
rs 8.6666
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping\Builder;
6
7
use Doctrine\ORM\Annotation;
8
use Doctrine\ORM\Mapping;
9
use RuntimeException;
10
use function array_merge;
11
use function array_unique;
12
use function assert;
13
use function count;
14
use function reset;
15
use function sprintf;
16
17
class OneToOneAssociationMetadataBuilder extends ToOneAssociationMetadataBuilder
18
{
19
    /** @var Annotation\OneToOne */
20
    private $oneToOneAnnotation;
21
22 117
    public function withOneToOneAnnotation(Annotation\OneToOne $oneToOneAnnotation) : OneToOneAssociationMetadataBuilder
23
    {
24 117
        $this->oneToOneAnnotation = $oneToOneAnnotation;
25
26 117
        return $this;
27
    }
28
29
    /**
30
     * @internal Association metadata order of definition settings is important.
31
     */
32 117
    public function build() : Mapping\OneToOneAssociationMetadata
33
    {
34
        // Validate required fields
35 117
        assert($this->componentMetadata !== null);
36 117
        assert($this->oneToOneAnnotation !== null);
37 117
        assert($this->fieldName !== null);
38
39 117
        $componentClassName  = $this->componentMetadata->getClassName();
40 117
        $associationMetadata = new Mapping\OneToOneAssociationMetadata($this->fieldName);
41
42 117
        $associationMetadata->setSourceEntity($componentClassName);
43 117
        $associationMetadata->setTargetEntity($this->getTargetEntity($this->oneToOneAnnotation->targetEntity));
44 117
        $associationMetadata->setCascade($this->getCascade($this->oneToOneAnnotation->cascade));
45 117
        $associationMetadata->setFetchMode($this->getFetchMode($this->oneToOneAnnotation->fetch));
46
47 117
        if ($this->oneToOneAnnotation->orphanRemoval) {
48 7
            $associationMetadata->setOrphanRemoval($this->oneToOneAnnotation->orphanRemoval);
49
50
            // Orphan removal also implies a cascade remove
51 7
            $associationMetadata->setCascade(array_unique(array_merge(['remove'], $associationMetadata->getCascade())));
52
        }
53
54 117
        if (! empty($this->oneToOneAnnotation->mappedBy)) {
55 43
            $associationMetadata->setMappedBy($this->oneToOneAnnotation->mappedBy);
56 43
            $associationMetadata->setOwningSide(false);
57
        }
58
59 117
        if (! empty($this->oneToOneAnnotation->inversedBy)) {
60 55
            $associationMetadata->setInversedBy($this->oneToOneAnnotation->inversedBy);
61 55
            $associationMetadata->setOwningSide(true);
62
        }
63
64 117
        $this->buildCache($associationMetadata);
65 117
        $this->buildPrimaryKey($associationMetadata);
66
67
        // Check for owning side to consider join column
68 117
        if (! $associationMetadata->isOwningSide()) {
69 43
            return $associationMetadata;
70
        }
71
72 109
        $this->buildJoinColumns($associationMetadata);
73
74
        // @todo guilhermeblanco The below block of code modifies component metadata properties, and it should be moved
75
        //                       to the component metadata builder instead of here.
76
77
        // Set unique constraint for owning side in all columns
78 109
        if ($associationMetadata->isOwningSide()) {
79 109
            $this->buildUniqueConstraints($associationMetadata);
80
        }
81
82 109
        return $associationMetadata;
83
    }
84
85 109
    private function buildUniqueConstraints(Mapping\OneToOneAssociationMetadata $associationMetadata) : void
86
    {
87 109
        $joinColumns = $associationMetadata->getJoinColumns();
88
89 109
        if (count($joinColumns) === 1) {
90 107
            $joinColumn = reset($joinColumns);
91
92 107
            if (! $associationMetadata->isPrimaryKey()) {
93 97
                $joinColumn->setUnique(true);
94
            }
95
96 107
            return;
97
        }
98
99 2
        $tableMetadata = $this->componentMetadata->table;
100
101 2
        if (! $tableMetadata) {
0 ignored issues
show
introduced by
$tableMetadata is of type Doctrine\ORM\Mapping\TableMetadata, thus it always evaluated to true.
Loading history...
102
            $exception = 'ClassMetadata::setTable() has to be called before defining a one to one relationship.';
103
104
            throw new RuntimeException($exception);
105
        }
106
107 2
        $uniqueConstraintColumns = [];
108
109 2
        foreach ($joinColumns as $joinColumnMetadata) {
110 2
            if ($this->componentMetadata->inheritanceType !== Mapping\InheritanceType::SINGLE_TABLE) {
111 2
                $uniqueConstraintColumns[] = $joinColumnMetadata->getColumnName();
112
            }
113
        }
114
115 2
        if ($uniqueConstraintColumns) {
116 2
            $tableMetadata->addUniqueConstraint([
117 2
                'name'    => sprintf('%s_uniq', $this->fieldName),
118 2
                'columns' => $uniqueConstraintColumns,
119
                'options' => [],
120
                'flags'   => [],
121
            ]);
122
        }
123
    }
124
}