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

UnderscoredClassNamespacePrefix::getTableNamePrefix()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 28
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 12
cts 12
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 12
nc 15
nop 1
crap 8
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
10
/**
11
 * @psalm-suppress UnusedClass
12
 */
13
final class UnderscoredClassNamespacePrefix implements NamingStrategy
14
{
15
    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...
16
17
    protected bool $joinTableFieldSuffix;
18
19
    /**
20
     * @var string[]
21
     */
22
    protected array $whitelist;
23
24
    /**
25
     * @var string[]
26
     */
27
    protected array $blacklist;
28
29
    /**
30
     * @var array<string, string>
31
     */
32
    protected array $map;
33
34
    /**
35
     * @psalm-param array{case?: int, map?: array<string, string>, blacklist?: string[], whitelist?: string[], join_table_field_suffix?: bool } $configuration
36
     *
37
     * @throws RuntimeException
38
     */
39
    public function __construct(array $configuration = [])
40
    {
41
        /**
42
         * @psalm-var array{case: int, map: array<string, string>, blacklist: string[], whitelist: string[], join_table_field_suffix: bool } $configuration
43
         */
44
        $configuration = array_merge([
45
            'case'                    => CASE_LOWER,
46
            'map'                     => [],
47
            'whitelist'               => [],
48
            'blacklist'               => [],
49
            'join_table_field_suffix' => true,
50
        ], $configuration);
51
52 25
        if (\count($configuration['whitelist']) > 0 && \count($configuration['blacklist']) > 0) {
53
            throw new RuntimeException('You can use whitelist or blacklist or none of mentioned lists, but not booth.');
54 25
        }
55 25
56
        $this->case = $configuration['case'];
57
        /**
58
         * @psalm-suppress MixedPropertyTypeCoercion
59
         */
60 25
        $this->map       = \array_map(\Closure::bind(function (string $prefix) {
61
            return $this->underscore($prefix);
62 25
        }, $this), $configuration['map']);
63 1
        $this->blacklist = \array_map(static function (string $class) {
64
            return \ltrim($class, '\\');
65
        }, $configuration['blacklist']);
66 24
        $this->whitelist = \array_map(static function (string $class) {
67 24
            return \ltrim($class, '\\');
68 17
        }, $configuration['whitelist']);
69 24
70 24
        $this->joinTableFieldSuffix = $configuration['join_table_field_suffix'];
71 1
    }
72 24
73 24
    /**
74 1
     * {@inheritdoc}
75 24
     */
76 24
    public function classToTableName($className): string
77 24
    {
78
        $prefix   = $this->getTableNamePrefix($className);
79
        $position = \strrpos($className, '\\');
80
81
        if (false !== $position) {
82 15
            $className = \substr($className, ($position + 1));
83
        }
84 15
85
        return $prefix . $this->underscore($className);
86 15
    }
87 15
88
    /**
89
     * {@inheritdoc}
90 15
     */
91
    public function propertyToColumnName($propertyName, $className = null): string
92
    {
93
        return $this->underscore($propertyName);
94
    }
95
96 7
    /**
97
     * {@inheritdoc}
98 7
     */
99
    public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null): string
100
    {
101
        return $this->underscore($propertyName) . '_' . $this->underscore($embeddedColumnName);
102
    }
103
104 3
    /**
105
     * {@inheritdoc}
106 3
     */
107
    public function referenceColumnName(): string
108
    {
109
        return $this->case === CASE_UPPER ? 'ID' : 'id';
110
    }
111
112 7
    /**
113
     * {@inheritdoc}
114 7
     */
115
    public function joinColumnName($propertyName): string
116
    {
117
        return $this->underscore($propertyName) . '_' . $this->referenceColumnName();
118
    }
119
120 3
    /**
121
     * {@inheritdoc}
122 3
     */
123
    public function joinTableName($sourceEntity, $targetEntity, $propertyName = null): string
124
    {
125
        $tableName = $this->classToTableName($sourceEntity) . '_' . $this->classToTableName($targetEntity);
126
        $suffix    = $this->joinTableFieldSuffix && null !== $propertyName ? '_' . $this->propertyToColumnName($propertyName, $sourceEntity) : '';
127
128 3
        return $tableName . $suffix;
129
    }
130 3
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function joinKeyColumnName($entityName, $referencedColumnName = null): string
135 3
    {
136
        return $this->classToTableName($entityName) . '_' .
137
            ($referencedColumnName ? $this->underscore($referencedColumnName) : $this->referenceColumnName());
138
    }
139
140
    private function getTableNamePrefix(string $className): string
141 2
    {
142
        $className = \ltrim($className, '\\');
143 2
144 2
        foreach ($this->blacklist as $blacklist) {
145
            if (0 === \strpos($className, $blacklist)) {
146
                return '';
147
            }
148
        }
149
150
        foreach ($this->map as $namespace => $prefix) {
151
            if (0 === \strpos($className, $namespace)) {
152
                foreach ($this->whitelist as $whitelistedNamespace) {
153 15
                    if (0 === \strpos($className, $whitelistedNamespace)) {
154
                        return $prefix . '_';
155 15
                    }
156
                }
157 15
158
                return 0 === \count($this->whitelist) ? ($prefix . '_') : '';
159 1
            }
160 1
        }
161
162
        return '';
163
    }
164 14
165
    private function underscore(string $literal): string
166 14
    {
167
        /** @var string $literal */
168 14
        $literal = \preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $literal);
169
170 1
        if (CASE_UPPER === $this->case) {
171 1
            return \strtoupper($literal);
172
        }
173
174
        return \strtolower($literal);
175 14
    }
176
}
177