table = new Schema($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->table->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->table->primaryKey = [ 'colName' => $colName, 'colType' => $colType, 'autoincrement' => $autoInc ]; return $this->column($colName, $colType); } public function reference(Schema $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->table->foreignKeys[] = [ 'colName' => $colName, 'tableName' => $foreignTable->name, 'onDelete' => $onDelete, 'onUpdate' => $onUpdate ]; $this->table->columns[$colName] = $foreignTable->columns[$colName]; return $this; } public function engine(EngineTypes $engine): Table { $this->table->engine = $engine; return $this; } public function charset(CharsetTypes $charset): Table { $this->table->charset = $charset; return $this; } public function collation(CollationTypes $collation): Table { $this->table->collation = $collation; return $this; } public function toSql(): string { $sql = "CREATE TABLE `{$this->table->name}` (\n"; // Add primary key constraint if present if (!empty($this->primaryKey)) $sql .= " PRIMARY KEY (`{$this->primaryKey['colName']}`),\n"; foreach ($this->table->columns as $column) { if ($column['colName'] !== $this->table->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->table->foreignKeys as $foreignKey) { $sql .= " FOREIGN KEY (`{$foreignKey['colName']}`) REFERENCES `{$foreignKey['tableName']}` (`{$foreignKey['colName']}`)"; $sql .= " ON DELETE {$foreignKey['onDelete']->toString()} ON UPDATE {$foreignKey['onUpdate']->toString()},\n"; } // Close the SQL string and add constraints $sql = rtrim($sql, ",\n") . "\n"; $sql .= ") ENGINE={$this->table->engine->toString()} CHARSET={$this->table->charset->toString()} COLLATE={$this->table->collation->toString()};"; return esc_sql($sql); } public function create(): Schema { global $wpdb; if (empty($this->primaryKey)) throw new InvalidArgumentException('A primary key must be defined.'); $table_name = $wpdb->prefix . $this->table->name; 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->table; } }