DB_Delta_Translator::translate_columns()   A
last analyzed

Complexity

Conditions 4
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
nc 1
nop 1
dl 0
loc 15
rs 9.9
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Interface for the translators.
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @since 0.3.0
21
 * @author Glynn Quelch <[email protected]>
22
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
23
 * @package PinkCrab\Table_Builder
24
 */
25
26
namespace PinkCrab\Table_Builder\Engines\WPDB_DB_Delta;
27
28
use PinkCrab\Table_Builder\Index;
29
use PinkCrab\Table_Builder\Column;
30
use PinkCrab\Table_Builder\Schema;
31
use PinkCrab\Table_Builder\Foreign_Key;
32
33
class DB_Delta_Translator {
34
35
	/**
36
	 * Returns the parsed strings for all columns based on the schema passed.
37
	 *
38
	 * @param \PinkCrab\Table_Builder\Schema $schema
39
	 * @return array<string>
40
	 */
41
	public function translate_columns( Schema $schema ): array {
42
		return array_map(
43
			function( Column $column ): string {
44
45
				return sprintf(
46
					'%s %s%s%s%s%s',
47
					$column->get_name(),
48
					$this->type_mapper( $column->get_type() ?? '', $column->get_length(), $column->get_precision() ),
49
					$column->is_unsigned() ? ' UNSIGNED' : '',
50
					$column->is_nullable() ? ' NULL' : ' NOT NULL',
51
					$column->is_auto_increment() ? ' AUTO_INCREMENT' : '',
52
					$this->parse_default( $column->get_type() ?? '', $column->get_default() )
53
				);
54
			},
55
			$schema->get_columns()
56
		);
57
	}
58
59
	/**
60
	 * Returns the parsed strings for all indexes based on the schema passed.
61
	 * Should translate all Primary, Indexes and Foreign Keys
62
	 *
63
	 * @param \PinkCrab\Table_Builder\Schema $schema
64
	 * @return array<string>
65
	 */
66
	public function translate_indexes( Schema $schema ): array {
67
		return array_merge(
68
			$this->transform_primary( $schema ),
69
			$this->transform_indexes( $schema ),
70
			$this->transform_foreign_keys( $schema )
71
		);
72
	}
73
74
		/**
75
	 * Maps types with length if set.
76
	 *
77
	 * @param string $type
78
	 * @param int|null $length
79
	 * @return string
80
	 */
81
	protected function type_mapper( string $type, ?int $length, ?int $precision ): string {
82
		$type = strtoupper( $type );
83
		switch ( $type ) {
84
			// With length
85
			case 'CHAR':
86
			case 'VARCHAR':
87
			case 'BINARY':
88
			case 'VARBINARY':
89
			case 'TEXT':
90
			case 'BLOB':
91
				// Int
92
			case 'BIT':
93
			case 'TINYINT':
94
			case 'SMALLINT':
95
			case 'MEDIUMINT':
96
			case 'INT':
97
			case 'INTEGER':
98
			case 'BIGINT':
99
				// Date
100
			case 'DATETIME':
101
			case 'TIMESTAMP':
102
			case 'TIME':
103
				return is_null( $length ) ? $type : "{$type}({$length})";
104
105
			// Floats
106
			case 'FLOAT':
107
			case 'DOUBLE':
108
			case 'DOUBLE PRECISION':
109
			case 'DECIMAL':
110
			case 'DEC':
111
				$precision = $precision ?? 1;
112
				return is_null( $length ) ? $type : "{$type}({$length},{$precision})";
113
114
			default:
115
				return $type;
116
		}
117
	}
118
119
	/**
120
	 * Parses the default value based on column type.
121
	 *
122
	 * @param string $type
123
	 * @param mixed|null $default
124
	 * @return string
125
	 */
126
	protected function parse_default( string $type, $default ): string {
127
		if ( is_null( $default ) ) {
128
			return '';
129
		}
130
131
		$type = strtoupper( $type );
132
133
		// String values.
134
		if ( in_array( $type, array( 'JSON', 'CHAR', 'VARCHAR', 'BINARY', 'VARBINARY', 'TEXT', 'BLOB' ), true ) ) {
135
			return " DEFAULT '{$default}'";
136
		}
137
138
		return " DEFAULT {$default}";
139
	}
140
141
		/**
142
	 * Parses the primary key from the defined schema.
143
	 *
144
	 * This should only return an array with a single value if any.
145
	 *
146
	 * @param \PinkCrab\Table_Builder\Schema $schema
147
	 * @return array<string>
148
	 */
149
	protected function transform_primary( Schema $schema ): array {
150
		return array_map(
151
			function( $index ) {
152
				return "PRIMARY KEY  ({$index->get_column()})";
153
			},
154
			array_filter(
155
				$schema->get_indexes(),
156
				function( $index ): bool {
157
					return $index->is_primary();
158
				}
159
			)
160
		);
161
	}
162
163
	/**
164
	 * Parses the indexes into a SQL strings.
165
	 *
166
	 * @param \PinkCrab\Table_Builder\Schema $schema
167
	 * @return array<string>
168
	 */
169
	protected function transform_indexes( Schema $schema ): array {
170
		return array_map(
171
			/** @param Index[] $index_group */
172
			function( array $index_group ): string {
173
174
				// Extract all parts from group.
175
				$key_name   = $index_group[0]->get_key_name();
176
				$index_type = $index_group[0]->get_type();
177
				$columns    = array_map(
178
					function( $e ) {
179
						return $e->get_column();
180
					},
181
					$index_group
182
				);
183
184
				return sprintf(
185
					'%sINDEX %s (%s)',
186
					\strlen( $index_type ) !== 0 ? \strtoupper( $index_type ) . ' ' : '',
187
					$key_name,
188
					join( ', ', $columns )
189
				);
190
191
			},
192
			$this->group_indexes( $schema )
193
		);
194
	}
195
196
	/**
197
	 * Parses the foreign key index to SQL strings
198
	 *
199
	 * @param \PinkCrab\Table_Builder\Schema $schema
200
	 * @return array<string>
201
	 */
202
	protected function transform_foreign_keys( Schema $schema ): array {
203
		return array_map(
204
			function( Foreign_Key $foreign_key ): string {
205
				return \sprintf(
206
					'FOREIGN KEY %s(%s) REFERENCES %s(%s)%s%s',
207
					$foreign_key->get_key_name(),
208
					$foreign_key->get_column(),
209
					$foreign_key->get_reference_table(),
210
					$foreign_key->get_reference_column(),
211
					\strlen( $foreign_key->get_on_update() ) ? " ON UPDATE {$foreign_key->get_on_update()}" : '',
212
					\strlen( $foreign_key->get_on_delete() ) ? " ON DELETE {$foreign_key->get_on_delete()}" : ''
213
				);
214
			},
215
			$schema->get_foreign_keys()
216
		);
217
	}
218
219
	/**
220
	 * Groups the indexes by key_name and type.
221
	 *
222
	 * @param \PinkCrab\Table_Builder\Schema $schema
223
	 * @return array<string, Index[]>
224
	 */
225
	protected function group_indexes( Schema $schema ): array {
226
		return array_reduce(
227
			$schema->get_indexes(),
228
			function( array $carry, Index $index ): array {
229
				// Remove all primiary keys.
230
				if ( $index->is_primary() ) {
231
					return $carry;
232
				}
233
234
				$carry[ $index->get_key_name() . '_' . $index->get_type() ][] = $index;
235
236
				return $carry;
237
			},
238
			array()
239
		);
240
	}
241
}
242