table = new Schema($tableName); } public function column(string $name, ColumnTypes $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Table { if(isset($this->columns[$name])) throw new InvalidArgumentException('Column name already exists.'); $this->table->columns[$name] = [ 'name' => $name, 'default' => $default, 'type' => $type, 'isNullable' => $isNullable, 'isUnique' => $isUnique ]; return $this; } public function primary(string $name, ColumnTypes $type, bool $autoInc = false): Table { if(isset($this->primaryKey)) throw new InvalidArgumentException('Primary column already exists.'); $this->table->primaryKey = [ 'name' => $name, 'autoInc' => $autoInc ]; return $this->column($name, $type); } public function reference(Schema $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table { $name = $foreignTable->primaryKey(); if(isset($this->columns[$name])) throw new InvalidArgumentException('Column name already exists.'); $this->table->foreignKeys[] = [ 'name' => $name, 'table' => $foreignTable->name, 'onDelete' => $onDelete, 'onUpdate' => $onUpdate ]; $this->table->columns[$name] = $foreignTable->columns[$name]; return $this; } public function engine(DatabaseEngines $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 { $primaryKey = $this->table->primaryKey(); $sql = "CREATE TABLE `{$this->table->name}` (\n"; $sql .= " PRIMARY KEY (`$primaryKey`),\n"; foreach ($this->table->columns as $col) { if ($col['name'] !== $primaryKey) { $sql .= " `{$col['name']}` {$col['type']->toString()}"; // Handle nulls, uniqueness, and defaults if (!$col['isNullable']) $sql .= " NOT NULL"; if ($col['isUnique']) $sql .= " UNIQUE"; if ($col['default'] !== null) { $default = is_string($col['default']) ? "'{$col['default']}'" : $col['default']; $sql .= " DEFAULT $default"; } $sql .= ",\n"; } } // Add secondary constraints if present 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"; } // Close the SQL string and add constraints $sql = rtrim($sql, ",\n") . "\n) "; $sql .= "ENGINE={$this->table->engine->toString()} "; $sql .= "CHARSET={$this->table->charset->toString()} "; $sql -= "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; } }