2025-01-28 16:53:37 +01:00
|
|
|
<?php
|
|
|
|
namespace DatabaseHelper;
|
|
|
|
|
|
|
|
use DatabaseHelper\enums\CascadeTypes;
|
|
|
|
use DatabaseHelper\enums\CharsetTypes;
|
|
|
|
use DatabaseHelper\enums\CollationTypes;
|
|
|
|
use DatabaseHelper\enums\ColumnTypes;
|
|
|
|
use DatabaseHelper\enums\EngineTypes;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
|
2025-02-05 12:29:49 +01:00
|
|
|
class Table
|
2025-01-28 16:53:37 +01:00
|
|
|
{
|
2025-02-05 15:40:52 +01:00
|
|
|
public Schema $table;
|
2025-01-28 16:53:37 +01:00
|
|
|
|
|
|
|
public function __construct(string $tableName) {
|
2025-02-03 14:31:13 +01:00
|
|
|
Database::standardizeTableNames($tableName);
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table = new Schema($tableName);
|
2025-01-28 16:53:37 +01:00
|
|
|
}
|
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
public function column(string $name, ColumnTypes $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Table {
|
|
|
|
if(isset($this->columns[$name]))
|
2025-01-28 16:53:37 +01:00
|
|
|
throw new InvalidArgumentException('Column name already exists.');
|
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
$this->table->columns[$name] = [
|
|
|
|
'name' => $name,
|
|
|
|
'default' => $default,
|
|
|
|
'type' => $type,
|
|
|
|
'isNullable' => $isNullable,
|
|
|
|
'isUnique' => $isUnique
|
2025-01-28 16:53:37 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
public function primary(string $name, ColumnTypes $type, bool $autoInc = false): Table {
|
2025-01-28 16:53:37 +01:00
|
|
|
if(isset($this->primaryKey))
|
|
|
|
throw new InvalidArgumentException('Primary column already exists.');
|
|
|
|
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table->primaryKey = [
|
2025-02-05 16:10:30 +01:00
|
|
|
'name' => $name,
|
|
|
|
'autoInc' => $autoInc
|
2025-01-28 16:53:37 +01:00
|
|
|
];
|
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
return $this->column($name, $type);
|
2025-01-28 16:53:37 +01:00
|
|
|
}
|
|
|
|
|
2025-02-05 15:40:52 +01:00
|
|
|
public function reference(Schema $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table {
|
2025-02-05 16:10:30 +01:00
|
|
|
$name = $foreignTable->primaryKey();
|
|
|
|
if(isset($this->columns[$name]))
|
2025-01-28 16:53:37 +01:00
|
|
|
throw new InvalidArgumentException('Column name already exists.');
|
|
|
|
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table->foreignKeys[] = [
|
2025-02-05 16:10:30 +01:00
|
|
|
'name' => $name,
|
|
|
|
'table' => $foreignTable->name,
|
2025-01-28 16:53:37 +01:00
|
|
|
'onDelete' => $onDelete,
|
|
|
|
'onUpdate' => $onUpdate
|
|
|
|
];
|
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
$this->table->columns[$name] = $foreignTable->columns[$name];
|
2025-01-28 16:53:37 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2025-02-05 12:29:49 +01:00
|
|
|
public function engine(EngineTypes $engine): Table {
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table->engine = $engine;
|
2025-01-28 16:53:37 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2025-02-05 12:29:49 +01:00
|
|
|
public function charset(CharsetTypes $charset): Table {
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table->charset = $charset;
|
2025-01-28 16:53:37 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2025-02-05 12:29:49 +01:00
|
|
|
public function collation(CollationTypes $collation): Table {
|
2025-02-05 15:40:52 +01:00
|
|
|
$this->table->collation = $collation;
|
2025-01-28 16:53:37 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function toSql(): string {
|
2025-02-05 16:10:30 +01:00
|
|
|
$primaryKey = $this->table->primaryKey();
|
2025-01-28 16:53:37 +01:00
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
$sql = "CREATE TABLE `{$this->table->name}` (\n";
|
|
|
|
$sql .= " PRIMARY KEY (`$primaryKey`),\n";
|
2025-01-28 16:53:37 +01:00
|
|
|
|
2025-02-05 16:10:30 +01:00
|
|
|
foreach ($this->table->columns as $col) {
|
|
|
|
if ($col['name'] !== $primaryKey) {
|
|
|
|
$sql .= " `{$col['name']}` {$col['type']->toString()}";
|
2025-02-03 14:31:13 +01:00
|
|
|
// Handle nulls, uniqueness, and defaults
|
2025-02-05 16:10:30 +01:00
|
|
|
if (!$col['isNullable'])
|
2025-01-28 16:53:37 +01:00
|
|
|
$sql .= " NOT NULL";
|
2025-02-05 16:10:30 +01:00
|
|
|
if ($col['isUnique'])
|
2025-01-28 16:53:37 +01:00
|
|
|
$sql .= " UNIQUE";
|
2025-02-05 16:10:30 +01:00
|
|
|
if ($col['default'] !== null) {
|
|
|
|
$default = is_string($col['default']) ? "'{$col['default']}'" : $col['default'];
|
2025-01-28 16:53:37 +01:00
|
|
|
$sql .= " DEFAULT $default";
|
|
|
|
}
|
|
|
|
|
|
|
|
$sql .= ",\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-03 14:31:13 +01:00
|
|
|
// Add secondary constraints if present
|
2025-02-05 16:10:30 +01:00
|
|
|
foreach ($this->table->foreignKeys as $key) {
|
|
|
|
$sql .= " FOREIGN KEY (`{$key['name']}`) REFERENCES `{$key['table']}` (`{$key['name']}`)";
|
|
|
|
$sql .= " ON DELETE {$key['onDelete']->toString()} ON UPDATE {$key['onUpdate']->toString()},\n";
|
2025-01-28 16:53:37 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 14:31:13 +01:00
|
|
|
// Close the SQL string and add constraints
|
2025-02-05 16:10:30 +01:00
|
|
|
$sql = rtrim($sql, ",\n") . "\n) ";
|
|
|
|
$sql .= "ENGINE={$this->table->engine->toString()} ";
|
|
|
|
$sql .= "CHARSET={$this->table->charset->toString()} ";
|
|
|
|
$sql -= "COLLATE={$this->table->collation->toString()};";
|
2025-02-03 17:44:52 +01:00
|
|
|
return esc_sql($sql);
|
2025-01-28 16:53:37 +01:00
|
|
|
}
|
|
|
|
|
2025-02-05 15:40:52 +01:00
|
|
|
public function create(): Schema {
|
2025-02-03 17:44:52 +01:00
|
|
|
global $wpdb;
|
|
|
|
|
|
|
|
if (empty($this->primaryKey))
|
|
|
|
throw new InvalidArgumentException('A primary key must be defined.');
|
2025-02-05 15:40:52 +01:00
|
|
|
$table_name = $wpdb->prefix . $this->table->name;
|
2025-02-03 17:44:52 +01:00
|
|
|
|
|
|
|
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
|
|
|
|
$sql = $this->toSql();
|
|
|
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
|
|
dbDelta($sql);
|
|
|
|
}
|
2025-02-05 15:40:52 +01:00
|
|
|
return $this->table;
|
2025-01-28 16:53:37 +01:00
|
|
|
}
|
|
|
|
}
|