-
Notifications
You must be signed in to change notification settings - Fork 0
/
DbIdentifierNameGenerator.php
124 lines (115 loc) · 4.25 KB
/
DbIdentifierNameGenerator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
namespace Effiana\MigrationBundle\Tools;
class DbIdentifierNameGenerator
{
/**
* Gets the max size of an identifier
*
* @return int
*/
public function getMaxIdentifierSize()
{
return 50;
}
/**
* Builds an index name
*
* @param string $tableName
* @param string[] $columnNames
* @param bool $uniqueIndex
* @param bool $forceHash If FALSE a human readable name is generated if it is possible
* If TRUE a name is generated based on a hash (Doctrine standard behaviour)
* @return string
*/
public function generateIndexName($tableName, $columnNames, $uniqueIndex = false, $forceHash = false)
{
return $this->generateIdentifierName(
$tableName,
$columnNames,
$uniqueIndex ? 'UNIQ' : 'IDX',
null,
$forceHash
);
}
/**
* Builds a foreign key constraint name
*
* @param string $tableName
* @param string[] $columnNames
* @param bool $forceHash If FALSE a human readable name is generated if it is possible
* If TRUE a name is generated based on a hash (Doctrine standard behaviour)
* @return string
*/
public function generateForeignKeyConstraintName($tableName, $columnNames, $forceHash = false)
{
return $this->generateIdentifierName(
$tableName,
$columnNames,
'FK',
null,
$forceHash
);
}
/**
* Generates an identifier from a list of column names obeying a certain string length.
*
* This is especially important for Oracle, since it does not allow identifiers larger than 30 chars,
* however building identifiers automatically for foreign keys, composite keys or such can easily create
* very long names.
*
* @param string|string[] $tableNames A table name or a list of table names
* @param string[] $columnNames
* @param string $prefix
* @param bool|null $upperCase If TRUE the returned string is in upper case;
* If FALSE the returned string is in lower case;
* If NULL the encoded name id in upper case, not encoded is in lower case
* @param bool $forceHash If FALSE a human readable name is generated if it is possible
* If TRUE a name is generated based on a hash (Doctrine standard behaviour)
* @return string
* @throws \InvalidArgumentException
*
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function generateIdentifierName(
$tableNames,
$columnNames,
$prefix = '',
$upperCase = null,
$forceHash = false
) {
if (empty($tableNames) || (is_array($tableNames) && count($tableNames) === 1 && empty($tableNames[0]))) {
throw new \InvalidArgumentException('A table name must not be empty.');
}
if (!is_array($tableNames)) {
$tableNames = [$tableNames];
}
if (!$forceHash) {
$columns = implode('_', $columnNames);
$tables = implode('_', $tableNames);
if (strlen($prefix) + strlen($tables) + strlen($columns) + 2 <= $this->getMaxIdentifierSize()) {
$result = $prefix . '_' . $tables . '_' . $columns;
return $upperCase === true ? strtoupper($result) : strtolower($result);
}
}
$result = $prefix . '_' .
implode(
'',
array_merge(
array_map(
function ($name) {
return dechex(crc32($name));
},
$tableNames
),
array_map(
function ($name) {
return dechex(crc32($name));
},
$columnNames
)
)
);
$result = substr($result, 0, $this->getMaxIdentifierSize());
return $upperCase === false ? strtolower($result) : strtoupper($result);
}
}