From 024e6e73cb74dc99a3cc3ed091fbe3f23eed93c1 Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Fri, 21 Feb 2025 19:06:16 +0100 Subject: [PATCH] schema with beans instead of arrays --- Conditionable.php | 1 + Database.php | 2 + Deletion.php | 1 + Insertion.php | 1 + Migration.php | 9 +++-- Query.php | 6 +-- Schema.php | 81 -------------------------------------- Table.php | 94 ++++++++++++++++++++------------------------- Update.php | 1 + beans/Column.php | 15 ++++++++ beans/Primary.php | 10 +++++ beans/Reference.php | 14 +++++++ beans/Schema.php | 28 ++++++++++++++ 13 files changed, 123 insertions(+), 140 deletions(-) delete mode 100644 Schema.php create mode 100644 beans/Column.php create mode 100644 beans/Primary.php create mode 100644 beans/Reference.php create mode 100644 beans/Schema.php diff --git a/Conditionable.php b/Conditionable.php index 912b021..47f9bba 100644 --- a/Conditionable.php +++ b/Conditionable.php @@ -1,6 +1,7 @@ schema->requireColumn($name); - if (isset($this->schema->foreignKeys[$name])) + if (isset($this->schema->references[$name])) throw new InvalidArgumentException('Referencing columns cannot be modified.'); $this->schema->columns[$name] = [ @@ -62,7 +63,7 @@ class Migration $name = $foreignTable->primaryKey(); $this->schema->requireColumn($name); - $this->schema->foreignKeys[$name] = [ + $this->schema->references[$name] = [ 'name' => $name, 'table' => $foreignTable->name, 'onDelete' => $onDelete, @@ -79,7 +80,7 @@ class Migration if ($this->schema->existsReference($foreignTable)) throw new InvalidArgumentException('Foreign table is not referenced.'); - unset($this->schema->foreignKeys[$name]); + unset($this->schema->references[$name]); $this->drop($name); $this->foreignKeysToDrop[] = $name; @@ -131,7 +132,7 @@ class Migration // Process foreign keys to add. foreach ($this->foreignKeysToAdd as $key) { - $foreignKey = $this->schema->foreignKeys[$key]; + $foreignKey = $this->schema->references[$key]; $clause = " ADD CONSTRAINT `fk_{$foreignKey['name']}`"; $clause .= " FOREIGN KEY (`{$foreignKey['name']}`)"; diff --git a/Query.php b/Query.php index ef9d76a..9ccc699 100644 --- a/Query.php +++ b/Query.php @@ -1,11 +1,11 @@ schema->existsReference($other)) - $foreignKey = $this->schema->foreignKeys[$other->name]; + $foreignKey = $this->schema->references[$other->name]; if ($other->existsReference($this->schema)) - $foreignKey = $other->foreignKeys[$this->schema->name]; + $foreignKey = $other->references[$this->schema->name]; if (is_null($foreignKey)) throw new InvalidArgumentException('Joins can only applied to referencing columns.'); diff --git a/Schema.php b/Schema.php deleted file mode 100644 index bfb8a85..0000000 --- a/Schema.php +++ /dev/null @@ -1,81 +0,0 @@ -name = $name; - } - - public function requireColumn(string $col): void { - if (!$this->existsColumn($col)) - throw new InvalidArgumentException("Column '$col' is not defined."); - } - - public function existsColumn(string $col): bool { - return isset($this->columns[$col]); - } - - public function existsReference(Schema $schema): bool { - foreach ($this->foreignKeys as $foreignKey) - if ($foreignKey['table'] == $schema->name) - return true; - return false; - } - - public function countEntries(): int { - return Database::makeQuery($this) - ->aggregate('*', 'count', Aggregation::COUNT) - ->query(); - } - - public function columnType(string $col) { - return $this->columns[$col]['type']; - } - - public function primaryKey() { - return $this->columns['primary']['name']; - } - - public function copy(): Schema { - $copy = new Schema($this->name); - $copy->columns = genericDeepCopy($this->columns); - $copy->primaryKey = genericDeepCopy($this->primaryKey); - $copy->foreignKeys = genericDeepCopy($this->foreignKeys); - $copy->engine = $this->engine; - $copy->charset = $this->charset; - $copy->collation = $this->collation; - return $copy; - } - - public function include(Schema $other): void { - // Create a copy of the other schema. - $otherCopy = $other->copy(); - - // Add any column that isn't already defined. - foreach ($otherCopy->columns as $colName => $colDef) - if (!isset($this->columns[$colName])) - $this->columns[$colName] = $colDef; - - // Add any foreign key that doesn't already exist. - foreach ($other->foreignKeys as $colName => $foreignKey) - if (!isset($this->foreignKeys[$colName])) - $this->foreignKeys[$colName] = $foreignKey; - } -} diff --git a/Table.php b/Table.php index 4892a8d..c0fb7de 100644 --- a/Table.php +++ b/Table.php @@ -1,6 +1,10 @@ table->columns[$name] = [ - 'name' => $name, - 'default' => $default, - 'type' => $type, - 'isNullable' => $isNullable, - 'isUnique' => $isUnique - ]; + $col = new Column; + $col->name = $name; + $col->default = $default; + $col->type = $type; + $col->isUnique = $isUnique; + $col->isNullable = $isNullable; + $this->table->columns[$name] = $col; 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); + protected function id(): Table { + $id = new Primary; + $id->name = $this->table->name . '_id'; + $this->table->primary = $id; + return $this; } 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.'); + $name = $foreignTable->primary->name; - $this->table->foreignKeys[$name] = [ - 'name' => $name, - 'table' => $foreignTable->name, - 'onDelete' => $onDelete, - 'onUpdate' => $onUpdate - ]; + $ref = new Reference; + $ref->name = $name; + $ref->otherTable = $foreignTable; + $ref->onDelete = $onDelete; + $ref->onUpdate = $onUpdate; - $this->table->columns[$name] = $foreignTable->columns[$name]; + $this->table->references[$name] = $ref; return $this; } @@ -72,26 +68,19 @@ class Table return $this; } - /** - * Generates the SQL statement. - * @return string SQL query. - * @throws InvalidArgumentException - */ public function toSql(): string { - $primaryKey = $this->table->primaryKey(); - + $primaryKey = $this->table->primary->name; $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()}"; + if ($col->name !== $primaryKey) { + $clause .= " `$col->name` {$col->type->toString()}"; + $clause .= !$col->isNullable ? ' NOT NULL' : ''; + $clause .= $col->isUnique ? ' UNIQUE' : ''; - $clause .= !$col['isNullable'] ? ' NOT NULL' : ''; - $clause .= $col['isUnique'] ? ' UNIQUE' : ''; - - if (!is_null($col['default'])) { - $default = is_string($col['default']) ? "'{$col['default']}'" : $col['default']; + if (!is_null($col->default)) { + $default = is_string($col->default) ? "'{$col->default}'" : $col->default; $clause .= " DEFAULT $default"; } @@ -100,33 +89,34 @@ class Table } // 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"; + foreach ($this->table->references as $ref) { + $clause .= " FOREIGN KEY (`{$ref->name}`)"; + $clause .= " REFERENCES `{$ref->otherTable->name}` (`{$ref->name}`)"; + $clause .= " ON DELETE {$ref->onDelete->toString()}"; + $clause .= " ON UPDATE {$ref->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()};"; + $clause .= "COLLATE={$this->table->collation->toString()};"; return $clause; } public function create(): Schema { global $wpdb; + $this->id(); - if (empty($this->primaryKey)) - throw new InvalidArgumentException('A primary key must be defined.'); - $table_name = $wpdb->prefix . $this->table->name; + Database::standardizeTableNames($this->table->name); + $tableName = $this->table->name; - if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) { + $foundTables = $wpdb->get_var("SHOW TABLES LIKE '$tableName'"); + if (is_null($foundTables)) { $sql = $this->toSql(); require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } return $this->table; } -} \ No newline at end of file +} diff --git a/Update.php b/Update.php index 05496c0..cbd9cba 100644 --- a/Update.php +++ b/Update.php @@ -1,6 +1,7 @@ + */ + public array $columns = []; + + /** + * @var array + */ + public array $references = []; + + public Engine $engine = Engine::INNODB; + public Charset $charset = Charset::UTF8; + public Collation $collation = Collation::UTF8_GENERAL_CI; +}