PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.3
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.3
6.0.3 6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 All 34 releases
← All changes | libraries/ct/includes/class-ct-database-schema.php +496 -0 5.7.7 → 6.0.3 View file →
@@ -1,0 +1,496 @@
1 +<?php
2 +/**
3 + * Database Table Schema class
4 + *
5 + * @author GamiPress <[email protected]>, Ruben Garcia <[email protected]>
6 + *
7 + * @since 1.0.0
8 + */
9 +// Exit if accessed directly
10 +defined( 'ABSPATH' ) || exit;
11 +
12 +if ( ! class_exists( 'CT_DataBase_Schema' ) ) :
13 +
14 + class CT_DataBase_Schema {
15 +
16 + /**
17 + * @var array Fields schema definition
18 + */
19 + public $fields = array();
20 +
21 + /**
22 + * @var array Keys schema definition
23 + */
24 + public $keys = array();
25 +
26 + public $primary_key = '';
27 +
28 + public function __construct( $schema ) {
29 +
30 + $this->keys = array();
31 +
32 + if( gettype( $schema ) === 'string' ) {
33 + $schema = $this->string_schema_to_array( $schema );
34 + }
35 +
36 + if( is_array( $schema ) ) {
37 +
38 + foreach( $schema as $field_id => $field_args ) {
39 + $field_args = wp_parse_args( $field_args, array(
40 + 'type' => '',
41 + 'length' => 0,
42 + 'decimals' => 0, // numeric fields
43 + 'format' => '', // time fields
44 + 'options' => array(), // ENUM and SET types
45 + 'nullable' => false,
46 + 'unsigned' => null, // numeric field
47 + 'zerofill' => null, // numeric field
48 + 'binary' => null, // text fields
49 + 'charset' => false, // text fields
50 + 'collate' => false, // text fields
51 + 'default' => false,
52 + 'auto_increment' => false,
53 + 'unique' => false,
54 + 'primary_key' => false,
55 + 'key' => false,
56 + ) );
57 +
58 + $this->fields[$field_id] = $field_args;
59 + }
60 +
61 + }
62 +
63 + }
64 +
65 + public function __toString() {
66 +
67 + $fields_def = array();
68 +
69 + foreach( $this->fields as $field_id => $field_args ) {
70 + // Turn field array to schema
71 + $fields_def[] = $this->field_array_to_schema( $field_id, $field_args );
72 + }
73 +
74 + // Setup PRIMARY KEY definition
75 + $sql = implode( ', ', $fields_def ) . ', '
76 + . 'PRIMARY KEY (`' . $this->primary_key . '`)'; // Add two spaces to avoid issues
77 +
78 + // Setup KEY definitions
79 + if( ! empty( $this->keys ) ) {
80 + $sql .= ', ' . implode( ', ', $this->keys );
81 + }
82 +
83 + return $sql;
84 + }
85 +
86 + /**
87 + * Convert a field definition into a schema string
88 + *
89 + * @param string $field_id
90 + * @param array $field_args
91 + *
92 + * @return string A schema string like: field type(length,decimals) UNSIGNED NOT NULL
93 + */
94 + public function field_array_to_schema( $field_id, $field_args ) {
95 +
96 + $schema = '';
97 +
98 + // Field name
99 + $schema .= '`' . $field_id . '` ';
100 +
101 + // Type definition
102 + $schema .= $field_args['type'];
103 +
104 + // Type definition args
105 + switch( strtoupper( $field_args['type'] ) ) {
106 + case 'ENUM':
107 + case 'SET':
108 + if( is_array( $field_args['options'] ) ) {
109 + $schema .= '(' . implode( ',', $field_args['options'] ) . ')';
110 + } else {
111 + $schema .= '(' . $field_args['options'] . ')';
112 + }
113 + break;
114 + case 'REAL':
115 + case 'DOUBLE':
116 + case 'FLOAT':
117 + case 'DECIMAL':
118 + case 'NUMERIC':
119 + if( $field_args['length'] !== 0 ) {
120 + $schema .= '(' . $field_args['length'] . ',' . $field_args['decimals'] . ')';
121 + }
122 + break;
123 + case 'TIME':
124 + case 'TIMESTAMP':
125 + case 'DATETIME':
126 + if( $field_args['format'] !== '' ) {
127 + $schema .= '(' . $field_args['format'] . ')';
128 + }
129 + break;
130 + default:
131 + if( $field_args['length'] !== 0 ) {
132 + $schema .= '(' . $field_args['length'] . ')';
133 + }
134 + break;
135 + }
136 +
137 + $schema .= ' ';
138 +
139 + // Type specific definitions
140 + switch( strtoupper( $field_args['type'] ) ) {
141 + case 'TINYINT':
142 + case 'SMALLINT':
143 + case 'MEDIUMINT':
144 + case 'INT':
145 + case 'INTEGER':
146 + case 'BIGINT':
147 + case 'REAL':
148 + case 'DOUBLE':
149 + case 'FLOAT':
150 + case 'DECIMAL':
151 + case 'NUMERIC':
152 + // UNSIGNED definition
153 + if( $field_args['unsigned'] !== null ) {
154 + if( $field_args['unsigned'] ) {
155 + $schema .= 'UNSIGNED ';
156 + } else {
157 + $schema .= 'SIGNED ';
158 + }
159 + }
160 +
161 + // ZEROFILL definition
162 + if( $field_args['zerofill'] !== null && $field_args['zerofill'] ) {
163 + $schema .= 'ZEROFILL ';
164 + }
165 + break;
166 + case 'CHAR':
167 + case 'VARCHAR':
168 + case 'TINYTEXT':
169 + case 'TEXT':
170 + case 'MEDIUMTEXT':
171 + case 'LONGTEXT':
172 + case 'ENUM':
173 + case 'SET':
174 + // BINARY definition
175 + if( $field_args['binary'] !== null && $field_args['binary']) {
176 + $schema .= 'BINARY ';
177 + }
178 +
179 + // CHARACTER SET definition
180 + if( $field_args['charset'] !== false ) {
181 + $schema .= 'CHARACTER SET ' . $field_args['charset'] . ' ';
182 + }
183 +
184 + // COLLATE definition
185 + if( $field_args['collate'] !== false ) {
186 + $schema .= 'COLLATE ' . $field_args['collate'] . ' ';
187 + }
188 + break;
189 + }
190 +
191 +
192 + // NULL definition
193 + if( $field_args['nullable'] ) {
194 + $schema .= 'NULL ';
195 + } else {
196 + $schema .= 'NOT NULL ';
197 + }
198 +
199 + // DEFAULT definition
200 + if( $field_args['default'] !== false ) {
201 +
202 + if( gettype( $field_args['default'] ) === 'string' ) {
203 + $field_args['default'] = "'" . $field_args['default'] . "'";
204 + }
205 +
206 + if( $field_args['default'] === null ) {
207 + $field_args['default'] = 'NULL';
208 + }
209 +
210 + $schema .= 'DEFAULT ' . $field_args['default'] . ' ';
211 + }
212 +
213 + // UNIQUE definition
214 + if( $field_args['unique'] ) {
215 + $schema .= 'UNIQUE ';
216 + }
217 +
218 + // AUTO_INCREMENT definition
219 + if( $field_args['auto_increment'] ) {
220 + $schema .= 'AUTO_INCREMENT ';
221 + }
222 +
223 + // PRIMARY KEY definition
224 + if( $field_args['primary_key'] ) {
225 + $this->primary_key = $field_id;
226 + }
227 +
228 + // KEY definition
229 + if( $field_args['key'] ) {
230 +
231 + /*
232 + * Indexes have a maximum size of 767 bytes. WordPress 4.2 was moved to utf8mb4, which uses 4 bytes per character.
233 + * This means that an index which used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
234 + */
235 + $max_index_length = 191;
236 + $length = min( $field_args['length'], $max_index_length );
237 +
238 + // Ensure that length has a value
239 + if( $length === 0 ) {
240 + $length = $max_index_length;
241 + }
242 +
243 + if( $this->is_numeric( $field_args['type'] ) || strtoupper( $field_args['type'] ) === 'DATETIME' ) {
244 + $this->keys[] = 'KEY `' . $field_id . '`(`' . $field_id . '`)';
245 + } else {
246 + $this->keys[] = 'KEY `' . $field_id . '`(`' . $field_id . '`(' . $length . '))';
247 + }
248 + }
249 +
250 + return $schema;
251 +
252 + }
253 +
254 + /**
255 + * Convert a schema string into an array of fields definitions
256 + *
257 + * @param string $schema
258 + *
259 + * @return array
260 + */
261 + public function string_schema_to_array( $schema ) {
262 +
263 + $schema_array = explode( ',', trim( $schema ) );
264 + $new_schema = array();
265 +
266 + foreach( $schema_array as $field_def ) {
267 +
268 + $field_id = '';
269 + $field_args = array();
270 +
271 + $field_def_parts = explode( ' ', trim( $field_def ) );
272 +
273 + foreach( $field_def_parts as $index => $field_def_part ) {
274 +
275 +
276 + if( $index === 0 ) {
277 +
278 + // Field id at index 0
279 + if( $field_def_part !== 'PRIMARY' && $field_def_part !== 'KEY' ) {
280 + $field_id = $field_def_part;
281 + continue;
282 + }
283 +
284 + // PRIMARY KEY at index 0
285 + if( $field_def_part === 'PRIMARY' ) {
286 + if( isset( $field_def_parts[$index+1] ) && strtoupper( $field_def_parts[$index+1] ) === 'KEY' && isset( $field_def_parts[$index+2] ) ) {
287 + $primary_key_field = str_replace( array( '(', ')' ), '', $field_def_parts[$index+2] );
288 +
289 + if( isset( $this->fields[$primary_key_field] ) ) {
290 + $this->fields[$primary_key_field]['primary_key'] = true;
291 + continue;
292 + }
293 + }
294 + }
295 + }
296 +
297 + // NOT NULL definition
298 + if( strtoupper( $field_def_part ) === 'NOT' ) {
299 + if( isset( $field_def_parts[$index+1] ) && strtoupper( $field_def_parts[$index+1] ) === 'NULL' ) {
300 + $field_args['nullable'] = false;
301 + continue;
302 + }
303 + }
304 +
305 + // NULL definition
306 + if( strtoupper( $field_def_part ) === 'NULL' ) {
307 + if( isset( $field_def_parts[$index-1] ) && strtoupper( $field_def_parts[$index-1] ) !== 'NOT' ) {
308 + $field_args['nullable'] = true;
309 + continue;
310 + }
311 + }
312 +
313 + // UNSIGNED definition
314 + if( strtoupper( $field_def_part ) === 'UNSIGNED' ) {
315 + $field_args['unsigned'] = true;
316 + continue;
317 + }
318 +
319 + // SIGNED definition
320 + if( strtoupper( $field_def_part ) === 'SIGNED' ) {
321 + $field_args['unsigned'] = false;
322 + continue;
323 + }
324 +
325 + // ZEROFILL definition
326 + if( strtoupper( $field_def_part ) === 'ZEROFILL' ) {
327 + $field_args['zerofill'] = true;
328 + continue;
329 + }
330 +
331 + // BINARY definition
332 + if( strtoupper( $field_def_part ) === 'BINARY' ) {
333 + $field_args['binary'] = true;
334 + continue;
335 + }
336 +
337 + // CHARACTER SET definition
338 + if( strtoupper( $field_def_part ) === 'CHARACTER' ) {
339 + if( isset( $field_def_parts[$index+1] ) && strtoupper( $field_def_parts[$index+1] ) === 'SET' ) {
340 + $field_args['charset'] = $field_def_parts[$index+2];
341 + continue;
342 + }
343 + }
344 +
345 + // COLLATE definition
346 + if( strtoupper( $field_def_part ) === 'COLLATE' ) {
347 + if( isset( $field_def_parts[$index+1] ) ) {
348 + $field_args['collate'] = $field_def_parts[$index+1];
349 + continue;
350 + }
351 + }
352 +
353 + // DEFAULT definition
354 + if( strtoupper( $field_def_part ) === 'DEFAULT' ) {
355 + if( isset( $field_def_parts[$index+1] ) ) {
356 + $field_args['default'] = $field_def_parts[$index+1];
357 + continue;
358 + }
359 + }
360 +
361 + // UNIQUE definition
362 + if( strtoupper( $field_def_part ) === 'UNIQUE' ) {
363 + $field_args['unique'] = true;
364 + continue;
365 + }
366 +
367 + // AUTO_INCREMENT definition
368 + if( strtoupper( $field_def_part ) === 'AUTO_INCREMENT' ) {
369 + $field_args['auto_increment'] = true;
370 + continue;
371 + }
372 +
373 + // PRIMARY KEY definition
374 + if( strtoupper( $field_def_part ) === 'PRIMARY' ) {
375 + if( isset( $field_def_parts[$index+1] ) && strtoupper( $field_def_parts[$index+1] ) === 'KEY' ) {
376 + $field_args['primary_key'] = true;
377 + continue;
378 + }
379 + }
380 +
381 + $type_parts = explode( '(', $field_def_part );
382 +
383 + // Possible field type
384 + if( in_array( strtoupper( $field_def_part ), $this->allowed_field_types() ) ) {
385 + $field_args['type'] = strtoupper( $field_def_part );
386 + continue;
387 + } else if( isset( $type_parts[0] ) && in_array( strtoupper( $type_parts[0] ), $this->allowed_field_types() ) ) {
388 + $field_args['type'] = strtoupper( $type_parts[0] );
389 +
390 + if( isset( $type_parts[1] ) ) {
391 + $type_def = explode( ',', str_replace(')', '', $type_parts[1] ) );
392 +
393 + switch( $field_args['type'] ) {
394 + case 'ENUM':
395 + case 'SET':
396 + $field_args['options'] = $type_def;
397 + break;
398 + case 'REAL':
399 + case 'DOUBLE':
400 + case 'FLOAT':
401 + case 'DECIMAL':
402 + case 'NUMERIC':
403 + $field_args['length'] = $type_def[0];
404 +
405 + if( isset( $type_def[1] ) ) {
406 + $field_args['decimals'] = $type_def[1];
407 + }
408 + break;
409 + case 'TIME':
410 + case 'TIMESTAMP':
411 + case 'DATETIME':
412 + $field_args['format'] = $type_def[0];
413 + break;
414 + default:
415 + $field_args['length'] = $type_def[0];
416 + break;
417 + }
418 + }
419 + }
420 + }
421 +
422 + if( ! empty( $field_id ) && ! empty( $field_args ) ) {
423 + $new_schema[$field_id] = $field_args;
424 + }
425 + }
426 +
427 + return $new_schema;
428 +
429 + }
430 +
431 + /**
432 + * Get the list of allowed types
433 + *
434 + * @return array
435 + */
436 + public function allowed_field_types() {
437 + return array(
438 + 'BIT',
439 + 'TINYINT',
440 + 'SMALLINT',
441 + 'MEDIUMINT',
442 + 'INT',
443 + 'INTEGER',
444 + 'BIGINT',
445 + 'REAL',
446 + 'DOUBLE',
447 + 'FLOAT',
448 + 'DECIMAL',
449 + 'NUMERIC',
450 + 'DATE',
451 + 'TIME',
452 + 'TIMESTAMP',
453 + 'DATETIME',
454 + 'YEAR',
455 + 'CHAR',
456 + 'VARCHAR',
457 + 'BINARY',
458 + 'VARBINARY',
459 + 'TINYBLOB',
460 + 'BLOB',
461 + 'MEDIUMBLOB',
462 + 'LONGBLOB',
463 + 'TINYTEXT',
464 + 'TEXT',
465 + 'JSON'
466 + );
467 + }
468 +
469 + /**
470 + * Check if given type is numeric
471 + *
472 + * @param string $type
473 + *
474 + * @return bool
475 + */
476 + public function is_numeric( $type ) {
477 +
478 + return in_array( strtoupper( $type ), array(
479 + 'TINYINT',
480 + 'SMALLINT',
481 + 'MEDIUMINT',
482 + 'INT',
483 + 'INTEGER',
484 + 'BIGINT',
485 + 'REAL',
486 + 'DOUBLE',
487 + 'FLOAT',
488 + 'DECIMAL',
489 + 'NUMERIC',
490 + ) );
491 +
492 + }
493 +
494 + }
495 +
496 +endif;