Completed
Push — master ( 21f22a...492613 )
by Nikola
11:38
created

UnderscoredBundleNamePrefix::joinKeyColumnName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RunOpenCode\Bundle\DoctrineNamingStrategy\NamingStrategy;
6
7
use Doctrine\ORM\Mapping\NamingStrategy;
8
use RunOpenCode\Bundle\DoctrineNamingStrategy\Exception\RuntimeException;
9
use Symfony\Component\HttpKernel\KernelInterface;
10
11
/**
12
 * @psalm-suppress UnusedClass
13
 */
14
final class UnderscoredBundleNamePrefix implements NamingStrategy
15
{
16
    private int $case;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
17
18
    private bool $joinTableFieldSuffix;
19
20
    /** @var array<string, string> */
21
    private array $map;
22
23
    /**
24
     * @psalm-param array{case?: int, map?: array<string, string>, blacklist?: string[], whitelist?: string[], join_table_field_suffix?: bool } $options
25
     *
26
     * @throws RuntimeException
27
     * @throws \ReflectionException
28
     */
29
    public function __construct(KernelInterface $kernel, array $options = [])
30
    {
31
        /**
32
         * @psalm-var array{case: int, map: array<string, string>, blacklist: string[], whitelist: string[], join_table_field_suffix: bool } $options
33
         */
34
        $options = \array_merge([
35
            'case'                    => CASE_LOWER,
36
            'map'                     => [],
37
            'whitelist'               => [],
38
            'blacklist'               => [],
39
            'join_table_field_suffix' => true,
40
        ], $options);
41
42
        if (\count($options['whitelist']) > 0 && \count($options['blacklist']) > 0) {
43
            throw new RuntimeException('You can use whitelist or blacklist or none of mentioned lists, but not booth.');
44
        }
45 25
46
        $this->case                 = $options['case'];
47 25
        $this->joinTableFieldSuffix = $options['join_table_field_suffix'];
48 25
        $this->map                  = $this->getNamingMap($kernel, $options);
49
    }
50
51
    /**
52
     * {@inheritdoc}
53 25
     */
54
    public function classToTableName($className): string
55 25
    {
56 1
        $prefix   = $this->getTableNamePrefix($className);
57
        $position = \strpos($className, '\\');
58
59 24
        if (false !== $position) {
60 24
            /** @psalm-suppress PossiblyFalseOperand */
61
            $className = \substr($className, \strrpos($className, '\\') + 1);
62 24
        }
63 24
64
        return $prefix . $this->underscore($className);
65
    }
66
67
    /**
68 15
     * {@inheritdoc}
69
     */
70 15
    public function propertyToColumnName($propertyName, $className = null): string
71
    {
72 15
        return $this->underscore($propertyName);
73 15
    }
74
75
    /**
76 15
     * {@inheritdoc}
77
     */
78
    public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null): string
79
    {
80
        return $this->underscore($propertyName) . '_' . $this->underscore($embeddedColumnName);
81
    }
82 5
83
    /**
84 5
     * {@inheritdoc}
85
     */
86
    public function referenceColumnName(): string
87
    {
88
        return $this->case === CASE_UPPER ? 'ID' : 'id';
89
    }
90 3
91
    /**
92 3
     * {@inheritdoc}
93
     */
94
    public function joinColumnName($propertyName): string
95
    {
96
        return $this->underscore($propertyName) . '_' . $this->referenceColumnName();
97
    }
98 6
99
    /**
100 6
     * {@inheritdoc}
101
     */
102
    public function joinTableName($sourceEntity, $targetEntity, $propertyName = null): string
103
    {
104
        $tableName = $this->classToTableName($sourceEntity) . '_' . $this->classToTableName($targetEntity);
105
106 2
        return
107
            $tableName
108 2
            .
109
            (($this->joinTableFieldSuffix && null !== $propertyName) ? '_' . $this->propertyToColumnName($propertyName, $sourceEntity) : '');
110
    }
111
112
    /**
113
     * {@inheritdoc}
114 3
     */
115
    public function joinKeyColumnName($entityName, $referencedColumnName = null): string
116 3
    {
117
        return $this->classToTableName($entityName) . '_' .
118
            ($referencedColumnName ? $this->underscore($referencedColumnName) : $this->referenceColumnName());
119
    }
120
121 3
    /**
122
     * @psalm-param array{map: array<string, string>, blacklist: string[], whitelist: string[] } $configuration
123
     *
124
     * @return array<string, string>
125
     *
126
     * @throws \ReflectionException
127 2
     */
128
    private function getNamingMap(KernelInterface $kernel, array $configuration): array
129 2
    {
130 2
        $map = [];
131
132
        foreach ($kernel->getBundles() as $bundle) {
133
            $bundleName = $bundle->getName();
134
135
            if (\count($configuration['blacklist']) > 0 && \in_array($bundleName, $configuration['blacklist'], true)) {
136
                continue;
137
            }
138
139
            if (\count($configuration['whitelist']) > 0 && !\in_array($bundleName, $configuration['whitelist'], true)) {
140
                continue;
141 24
            }
142
143 24
            $bundleNamespace = (new \ReflectionClass(\get_class($bundle)))->getNamespaceName();
144
145
            if (isset($configuration['map'][$bundleName])) {
146
                $map[$this->underscore($configuration['map'][$bundleName])] = $bundleNamespace;
147
                continue;
148 24
            }
149
150 24
            /** @var string $bundleName */
151 1
            $bundleName = \preg_replace('/Bundle$/', '', $bundleName);
152
153
            if (isset($configuration['map'][$bundleName])) {
154 24
                $map[$this->underscore($configuration['map'][$bundleName])] = $bundleNamespace;
155 1
                continue;
156
            }
157
158 24
            $map[$this->underscore($bundleName)] = $bundleNamespace;
159 24
        }
160
161 24
        return $map;
162 16
    }
163 16
164
    private function getTableNamePrefix(string $className): string
165
    {
166 23
        $className = \ltrim($className, '\\');
167
168 23
        foreach ($this->map as $prefix => $namespace) {
169 16
            if (0 === \strpos($className, $namespace)) {
170 16
                return $prefix . '_';
171
            }
172
        }
173 23
174
        return '';
175
    }
176 24
177
    private function underscore(string $literal): string
178
    {
179
        /** @var string $literal */
180
        $literal = \preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $literal);
181
182
        if (CASE_UPPER === $this->case) {
183
            return \strtoupper($literal);
184
        }
185 15
186
        return \strtolower($literal);
187 15
    }
188
}
189