WP-Query-Builder/Table.php
2025-02-05 12:29:49 +01:00

143 lines
4.7 KiB
PHP

<?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;
class Table
{
public string $tableName;
public array $columns = [];
public array $primaryKey;
public array $foreignKeys = [];
// Table settings
protected EngineTypes $engine = EngineTypes::INNODB;
protected CharsetTypes $charset = CharsetTypes::UTF8;
protected CollationTypes $collation = CollationTypes::UTF8_GENERAL_CI;
public function __construct(string $tableName) {
Database::standardizeTableNames($tableName);
$this->tableName = $tableName;
}
public function column(string $colName, ColumnTypes $colType, mixed $default = null, bool $nullable = false, bool $unique = false): Table {
if(isset($this->columns[$colName]))
throw new InvalidArgumentException('Column name already exists.');
$this->columns[$colName] = [
'colName' => $colName,
'defaultVal' => $default,
'colType' => $colType,
'nullable' => $nullable,
'unique' => $unique
];
return $this;
}
public function primary(string $colName, ColumnTypes $colType, bool $autoInc = false): Table {
if(isset($this->primaryKey))
throw new InvalidArgumentException('Primary column already exists.');
$this->primaryKey = [
'colName' => $colName,
'colType' => $colType,
'autoincrement' => $autoInc
];
return $this->column($colName, $colType);
}
public function referenceColumn(Table $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table {
$colName = $foreignTable->primaryKey['colName'];
if(isset($this->columns[$colName]))
throw new InvalidArgumentException('Column name already exists.');
$this->foreignKeys[] = [
'colName' => $colName,
'tableName' => $foreignTable->tableName,
'onDelete' => $onDelete,
'onUpdate' => $onUpdate
];
$this->columns[$colName] = $foreignTable->columns[$colName];
return $this;
}
public function engine(EngineTypes $engine): Table {
$this->engine = $engine;
return $this;
}
public function charset(CharsetTypes $charset): Table {
$this->charset = $charset;
return $this;
}
public function collation(CollationTypes $collation): Table {
$this->collation = $collation;
return $this;
}
public function toSql(): string {
$sql = "CREATE TABLE `{$this->tableName}` (\n";
// Add primary key constraint if present
if (!empty($this->primaryKey))
$sql .= " PRIMARY KEY (`{$this->primaryKey['colName']}`),\n";
foreach ($this->columns as $column) {
if ($column['colName'] !== $this->primaryKey['colName']) {
$sql .= " `{$column['colName']}` {$column['colType']->value}";
// Handle nulls, uniqueness, and defaults
if (!$column['nullable'])
$sql .= " NOT NULL";
if ($column['unique'])
$sql .= " UNIQUE";
if ($column['defaultVal'] !== null) {
$default = is_string($column['defaultVal']) ? "'{$column['defaultVal']}'" : $column['defaultVal'];
$sql .= " DEFAULT $default";
}
$sql .= ",\n";
}
}
// Add secondary constraints if present
foreach ($this->foreignKeys as $foreignKey) {
$sql .= " FOREIGN KEY (`{$foreignKey['colName']}`) REFERENCES `{$foreignKey['tableName']}` (`{$foreignKey['colName']}`)";
$sql .= " ON DELETE {$foreignKey['onDelete']->type()} ON UPDATE {$foreignKey['onUpdate']->type()},\n";
}
// Close the SQL string and add constraints
$sql = rtrim($sql, ",\n") . "\n";
$sql .= ") ENGINE={$this->engine->type()} CHARSET={$this->charset->type()} COLLATE={$this->collation->type()};";
return esc_sql($sql);
}
public function create(): Table {
global $wpdb;
if (empty($this->primaryKey))
throw new InvalidArgumentException('A primary key must be defined.');
$table_name = $wpdb->prefix . $this->tableName;
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
$sql = $this->toSql();
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
return $this;
}
}