table = new Schema($tableName); } public function column(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Table { $this->table->columns[$name] = [ 'name' => $name, 'default' => $default, 'type' => $type, 'isNullable' => $isNullable, 'isUnique' => $isUnique ]; return $this; } public function primary(string $name, Type $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, Propagation $onDelete = Propagation::CASCADE, Propagation $onUpdate = Propagation::CASCADE): Table { $name = $foreignTable->primaryKey(); if(isset($this->columns[$name])) throw new InvalidArgumentException('Column name already exists.'); $this->table->foreignKeys[$name] = [ 'name' => $name, 'table' => $foreignTable->name, 'onDelete' => $onDelete, 'onUpdate' => $onUpdate ]; $this->table->columns[$name] = $foreignTable->columns[$name]; return $this; } public function engine(Engine $engine): Table { $this->table->engine = $engine; return $this; } public function charset(Charset $charset): Table { $this->table->charset = $charset; return $this; } public function collation(Collation $collation): Table { $this->table->collation = $collation; return $this; } /** * Generates the SQL statement. * @return string SQL query. * @throws InvalidArgumentException */ public function toSql(): string { $primaryKey = $this->table->primaryKey(); $clause = "CREATE TABLE `{$this->table->name}` (\n"; $clause .= " PRIMARY KEY (`$primaryKey`),\n"; foreach ($this->table->columns as $col) { if ($col['name'] !== $primaryKey) { $clause .= " `{$col['name']}` {$col['type']->toString()}"; $clause .= !$col['isNullable'] ? ' NOT NULL' : ''; $clause .= $col['isUnique'] ? ' UNIQUE' : ''; if (!is_null($col['default'])) { $default = is_string($col['default']) ? "'{$col['default']}'" : $col['default']; $clause .= " DEFAULT $default"; } $clause .= ",\n"; } } // Add foreign keys foreach ($this->table->foreignKeys as $key) { $clause .= " FOREIGN KEY (`{$key['name']}`)"; $clause .= " REFERENCES `{$key['table']}` (`{$key['name']}`)"; $clause .= " ON DELETE {$key['onDelete']->toString()}"; $clause .= " ON UPDATE {$key['onUpdate']->toString()},\n"; } // Close the SQL string and add constraints $clause = rtrim($clause, ",\n") . "\n) "; $clause .= "ENGINE={$this->table->engine->toString()} "; $clause .= "CHARSET={$this->table->charset->toString()} "; $clause -= "COLLATE={$this->table->collation->toString()};"; return $clause; } 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; } }