From 29703314a36ecd0627ce31fc218b543e59b44841 Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Wed, 12 Feb 2025 15:03:39 +0100 Subject: [PATCH] move from old repository --- Conditionable.php | 49 +++++++++++++++ Database.php | 54 ++++++++++++++++ Deletion.php | 62 +++++++++++++++++++ Insertion.php | 84 +++++++++++++++++++++++++ Migration.php | 139 ++++++++++++++++++++++++++++++++++++++++++ Query.php | 109 +++++++++++++++++++++++++++++++++ Schema.php | 78 ++++++++++++++++++++++++ Table.php | 131 +++++++++++++++++++++++++++++++++++++++ Update.php | 69 +++++++++++++++++++++ build.php | 42 +++++++++++++ enums/Charset.php | 40 ++++++++++++ enums/Collation.php | 32 ++++++++++ enums/Engine.php | 15 +++++ enums/Join.php | 20 ++++++ enums/Operator.php | 37 +++++++++++ enums/Order.php | 16 +++++ enums/Propagation.php | 21 +++++++ enums/Type.php | 46 ++++++++++++++ index.php | 53 ++++++++++++++++ 19 files changed, 1097 insertions(+) create mode 100644 Conditionable.php create mode 100644 Database.php create mode 100644 Deletion.php create mode 100644 Insertion.php create mode 100644 Migration.php create mode 100644 Query.php create mode 100644 Schema.php create mode 100644 Table.php create mode 100644 Update.php create mode 100644 build.php create mode 100644 enums/Charset.php create mode 100644 enums/Collation.php create mode 100644 enums/Engine.php create mode 100644 enums/Join.php create mode 100644 enums/Operator.php create mode 100644 enums/Order.php create mode 100644 enums/Propagation.php create mode 100644 enums/Type.php create mode 100644 index.php diff --git a/Conditionable.php b/Conditionable.php new file mode 100644 index 0000000..912b021 --- /dev/null +++ b/Conditionable.php @@ -0,0 +1,49 @@ +addCondition($col, $operator, $val, "AND"); + } + + public function andWhere(string $col, string|Operator $operator, mixed $val): self { + return $this->addCondition($col, $operator, $val, "AND"); + } + + public function orWhere(string $col, string|Operator $operator, mixed $val): self { + return $this->addCondition($col, $operator, $val, "OR"); + } + + protected function addCondition(string $col, string|Operator $operator, mixed $val, string $prefix): self { + $this->schema->requireColumn($col); + + // Convert the operator string to a ConditionOperator enum if needed. + if (is_string($operator)) + $operator = Operator::fromString($operator); + + $columnType = $this->schema->columnType($col); + $castedValue = $columnType->dbCast($val); + + if (!empty($this->conditions)) + $this->conditions[] = $prefix; + $this->conditions[] = "$col " . $operator->toString() . " $castedValue"; + + return $this; + } + + public function isConditioned(): bool { + return !empty($this->conditions); + } + + protected function combineConditions(): string { + if ($this->isConditioned()) + return implode(" ", $this->conditions); + return ""; + } +} diff --git a/Database.php b/Database.php new file mode 100644 index 0000000..c3d2ea4 --- /dev/null +++ b/Database.php @@ -0,0 +1,54 @@ +prefix; + + foreach ($tableName as &$name) + if (!str_starts_with($name, $dbPrefix)) + $name = $dbPrefix . $name; + } +} \ No newline at end of file diff --git a/Deletion.php b/Deletion.php new file mode 100644 index 0000000..97f3c38 --- /dev/null +++ b/Deletion.php @@ -0,0 +1,62 @@ +table = $table; + } + + /** + * Generates the SQL statement. + * @return string SQL query. + * @throws InvalidArgumentException + */ + public function toSql(): string { + $table = $this->table->name; + $whereClause = $this->combineConditions(); + + if (!$this->isConditioned()) + throw new InvalidArgumentException("Deletions need to be conditioned."); + + return esc_sql("DELETE FROM $table WHERE $whereClause"); + } + + /** + * Executes the DELETE query. + * @return int Number of affected rows. + * @throws Exception + */ + public function delete(): int { + global $wpdb; + $query = $this->toSql(); + $result = $wpdb->query($query); + + if ($result === false) + throw new Exception("Deletion failed: " . $wpdb->last_error . "."); + return intval($result); + } + + /** + * Clears all entries from the table. + * @return int Number of affected rows. + * @throws Exception + */ + public function truncate(): int { + global $wpdb; + $table = $this->table->name; + $query = esc_sql("TRUNCATE TABLE $table"); + $result = $wpdb->query($query); + + if ($result === false) + throw new Exception("Truncation failed: " . $wpdb->last_error . "."); + return intval($result); + } +} diff --git a/Insertion.php b/Insertion.php new file mode 100644 index 0000000..dd90f36 --- /dev/null +++ b/Insertion.php @@ -0,0 +1,84 @@ +table = $table; + } + + /** + * Adds a single column-value pair to the row. + * @param string $col Column name. + * @param mixed $val Value to insert. + * @return Insertion Current instance for method chaining. + * @throws InvalidArgumentException + */ + public function data(string $col, mixed $val): Insertion { + if (!isset($this->table->columns[$col])) + throw new InvalidArgumentException("Column '$col' does not exist."); + + $columnType = $this->table->columns[$col]['colType']; + $this->currentRow[$col] = $columnType->dbCast($val); + + return $this; + } + + /** + * Adds multiple column-value pairs to the row. + * @param array $data Associative array of column-value pairs. + * @return Insertion Current instance for method chaining. + * @throws InvalidArgumentException + */ + public function batchData(array $data): Insertion { + foreach ($data as $key => $value) + $this->data($key, $value); + return $this; + } + + /** + * Finalizes the current row and stacks it for insertion. + * @return Insertion Current instance for method chaining. + */ + public function stack(): Insertion { + if (!empty($this->currentRow)) + $this->stackForInsertion(); + return $this; + } + + private function stackForInsertion(): void { + $this->batchRows[] = $this->currentRow; + $this->currentRow = []; + } + + /** + * Executes the insertion of all batched rows into the database. + * @throws InvalidArgumentException + */ + public function insert(): bool { + global $wpdb; + + // Convert single to batch queries. + if (!empty($this->currentRow)) + $this->stackForInsertion(); + + if (empty($this->batchRows)) + throw new InvalidArgumentException("No data set for insertion."); + + foreach ($this->batchRows as $row) { + if (!empty($row)) { + $result = $wpdb->insert($this->table->name, $row); + if ($result === false) + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/Migration.php b/Migration.php new file mode 100644 index 0000000..fbd0136 --- /dev/null +++ b/Migration.php @@ -0,0 +1,139 @@ +table = $table->copy(); + } + + public function addColumn(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Migration { + $this->table->columns[$name] = [ + 'name' => $name, + 'type' => $type, + 'default' => $default, + 'isNullable' => $isNullable, + 'isUnique' => $isUnique + ]; + $this->columnsToAdd[] = $name; + return $this; + } + + public function modifyColumn(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Migration { + if (!isset($this->table->columns[$name])) { + throw new InvalidArgumentException("Column $name does not exist."); + } + $this->table->columns[$name] = [ + 'name' => $name, + 'type' => $type, + 'default' => $default, + 'isNullable' => $isNullable, + 'isUnique' => $isUnique + ]; + $this->columnsToModify[] = $name; + return $this; + } + + public function dropColumn(string $name): Migration { + if (!isset($this->table->columns[$name])) { + throw new InvalidArgumentException("Column $name does not exist."); + } + unset($this->table->columns[$name]); + $this->columnsToDrop[] = $name; + return $this; + } + + public function changePrimaryKey(string $name, bool $autoInc = false): Migration { + if (!isset($this->table->columns[$name])) { + throw new InvalidArgumentException("Column $name does not exist."); + } + $this->table->primaryKey = [ + 'name' => $name, + 'autoInc' => $autoInc + ]; + $this->primaryKey = $name; + return $this; + } + + public function addForeignKey(string $column, string $referencedTable, string $referencedColumn, Propagation $onDelete, Propagation $onUpdate): Migration { + if (!isset($this->table->columns[$column])) { + throw new InvalidArgumentException("Column $column does not exist."); + } + $this->table->foreignKeys[$column] = [ + 'referencedTable' => $referencedTable, + 'referencedColumn' => $referencedColumn, + 'onDelete' => $onDelete, + 'onUpdate' => $onUpdate + ]; + $this->foreignKeysToAdd[] = $column; + return $this; + } + + public function dropForeignKey(string $name): Migration { + if (!isset($this->table->foreignKeys[$name])) { + throw new InvalidArgumentException("Foreign key $name does not exist."); + } + unset($this->table->foreignKeys[$name]); + $this->foreignKeysToDrop[] = $name; + return $this; + } + + public function toSql(): string { + $sql = "ALTER TABLE `{$this->table->name}` "; + $statements = []; + + foreach ($this->columnsToAdd as $name) { + $col = $this->table->columns[$name]; + $statements[] = "ADD COLUMN `{$col['name']}` {$col['type']->toString()}" . + ($col['isNullable'] ? "" : " NOT NULL") . + ($col['isUnique'] ? " UNIQUE" : "") . + ($col['default'] !== null ? " DEFAULT " . (is_string($col['default']) ? "'{$col['default']}'" : $col['default']) : ""); + } + + foreach ($this->columnsToModify as $name) { + $col = $this->table->columns[$name]; + $statements[] = "MODIFY COLUMN `{$col['name']}` {$col['type']->toString()}" . + ($col['isNullable'] ? "" : " NOT NULL") . + ($col['isUnique'] ? " UNIQUE" : "") . + ($col['default'] !== null ? " DEFAULT " . (is_string($col['default']) ? "'{$col['default']}'" : $col['default']) : ""); + } + + foreach ($this->columnsToDrop as $name) { + $statements[] = "DROP COLUMN `$name`"; + } + + foreach ($this->foreignKeysToDrop as $name) { + $statements[] = "DROP FOREIGN KEY `$name`"; + } + + foreach ($this->foreignKeysToAdd as $column) { + $fk = $this->table->foreignKeys[$column]; + $statements[] = "ADD CONSTRAINT `fk_{$column}` FOREIGN KEY (`$column`) REFERENCES `{$fk['referencedTable']}` (`{$fk['referencedColumn']}`) ON DELETE {$fk['onDelete']->toString()} ON UPDATE {$fk['onUpdate']->toString()}"; + } + + return $sql . implode(", ", $statements) . ";"; + } + + public function drop(): null { + + } + + public function migrate(): Schema { + global $wpdb; + $sql = $this->toSql(); + $wpdb->query($sql); + return $this->table; + } +} diff --git a/Query.php b/Query.php new file mode 100644 index 0000000..efeaf10 --- /dev/null +++ b/Query.php @@ -0,0 +1,109 @@ +schema = $table; + } + + public function select(string ...$cols): Query { + if (!empty($cols)) + $this->columns = $cols; + foreach ($cols as $col) + $this->schema->requireColumn($col); + return $this; + } + + public function orderBy(string $col, Order $order): Query { + $this->schema->requireColumn($col); + $this->orderBy = [ + 'name' => $col, + 'order' => $order + ]; + return $this; + } + + public function join(Schema $other, Join $join): Query { + $foreignKey = null; + if($this->schema->existsReference($other)) + $foreignKey = $this->schema->foreignKeys[$other->name]; + if ($other->existsReference($this->schema)) + $foreignKey = $other->foreignKeys[$this->schema->name]; + + if (is_null($foreignKey)) + throw new InvalidArgumentException('Joins can only applied to referencing columns.'); + + // TODO: Implement include instead of merge + $this->schema->include($other); + $this->joins[] = [ + 'table' => $other->name, + 'type' => $join + ]; + + return $this; + } + + protected function isOrdered(): bool { + return !empty($this->orderBy); + } + + protected function isJoined(): bool { + return !empty($this->joins); + } + + public function toSql(): string { + // Build the SELECT clause. + $columns = implode(", ", $this->columns); + $primaryTable = $this->schema->name; + $sqlStatement = "SELECT $columns FROM $primaryTable"; + + // Append join clauses, if any. + if ($this->isJoined()) { + foreach ($this->joins as $join) { + $sqlStatement .= " " . $join['type']->toString() . " NATURAL JOIN " . $join['table']; + } + } + + // Append the WHERE clause if conditions exist. + if ($this->isConditioned()) { + $whereClause = $this->combineConditions(); + $sqlStatement .= " WHERE $whereClause"; + } + + // Append the ORDER BY clause if ordering is set. + if ($this->isOrdered()) { + $orderClause = $this->orderBy['name'] . ' ' . $this->orderBy['order']; + $sqlStatement .= " ORDER BY $orderClause"; + } + + return esc_sql($sqlStatement); + } + + public function query(): array { + global $wpdb; + $query = $this->toSql(); + $results = $wpdb->get_results($query, ARRAY_A); + return $this->castResults($results); + } + + protected function castResults(array $results): array { + foreach ($results as &$row) + foreach ($row as $column => &$value) + if (isset($this->columnTypes[$column])) + $value = $this->columnTypes[$column]->valCast($value); + return $results; + } +} diff --git a/Schema.php b/Schema.php new file mode 100644 index 0000000..041b0b0 --- /dev/null +++ b/Schema.php @@ -0,0 +1,78 @@ +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 columnType(string $col) { + return $this->columns[$col]['type']; + } + + public function primaryKey() { + return $this->columns['primary']['name']; + } + + /** + * Creates a deep copy of this instance. + * @return Schema + */ + 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 new file mode 100644 index 0000000..6f438a9 --- /dev/null +++ b/Table.php @@ -0,0 +1,131 @@ +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(); + + $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; + } +} diff --git a/Update.php b/Update.php new file mode 100644 index 0000000..9e88c55 --- /dev/null +++ b/Update.php @@ -0,0 +1,69 @@ +table = $table; + } + + /** + * Sets a new value for a column. + * @param string $col Column name. + * @param mixed $val Value to set. + * @return self Current instance for method chaining. + * @throws InvalidArgumentException + */ + public function set(string $col, mixed $val): self { + $this->table->requireColumn($col); + + $columnType = $this->table->columnType($col); + $castedValue = $columnType->dbCast($val); + $this->values[$col] = $castedValue; + return $this; + } + + /** + * Generates the SQL statement. + * @return string SQL query. + * @throws InvalidArgumentException + */ + public function toSql(): string { + if (empty($this->values)) + throw new InvalidArgumentException("No values have been set for the Update."); + + $table = $this->table->name; + $setParts = []; + foreach ($this->values as $col => $value) + $setParts[] = "$col = $value"; + $setClause = implode(", ", $setParts); + + // FINAL SQL STATEMENT + $sqlStatement = "UPDATE $table SET $setClause"; + if($this->isConditioned()) { + $whereClause = $this->combineConditions(); + $sqlStatement .= " WHERE $whereClause"; + } + return esc_sql($sqlStatement); + } + + /** + * Executes the SQL UPDATE query. + * @return bool Returns true on success. + */ + public function update(): bool { + global $wpdb; + $query = $this->toSql(); + $result = $wpdb->query($query); + return boolval($result); + } +} diff --git a/build.php b/build.php new file mode 100644 index 0000000..6e17047 --- /dev/null +++ b/build.php @@ -0,0 +1,42 @@ + $value) + $copy[$key] = genericDeepCopy($value); + return $copy; + } + elseif (is_object($data)) { + // If the object supports a copy method. + if (method_exists($data, 'copy')) + return $data->copy(); + // Use PHP's clone as fallback. + return clone $data; + } + else { + // Scalar variables. + return $data; + } +} + +// Require all enums +require './enums/Propagation.php'; +require './enums/Operator.php'; +require './enums/Order.php'; +require './enums/Charset.php'; +require './enums/Collation.php'; +require './enums/Type.php'; +require './enums/Engine.php'; +require './enums/Join.php'; + +// Require all classes +require './Database.php'; +require './Conditionable.php'; +require './Deletion.php'; +require './Insertion.php'; +require './Migration.php'; +require './Query.php'; +require './Schema.php'; +require './Table.php'; +require './Update.php'; diff --git a/enums/Charset.php b/enums/Charset.php new file mode 100644 index 0000000..b2112a8 --- /dev/null +++ b/enums/Charset.php @@ -0,0 +1,40 @@ + 'utf8', + self::UTF8MB4 => 'utf8mb4', + self::LATIN1 => 'latin1', + self::ASCII => 'ascii', + self::UTF16 => 'utf16', + self::UTF32 => 'utf32', + self::LATIN2 => 'latin2', + self::LATIN5 => 'latin5', + self::CP1251 => 'cp1251', + self::CP850 => 'cp850', + self::TIS620 => 'tis620', + self::GREEK => 'greek', + self::HEBREW => 'hebrew', + self::BINARY => 'binary', + }; + } +} + diff --git a/enums/Collation.php b/enums/Collation.php new file mode 100644 index 0000000..2f1fa9d --- /dev/null +++ b/enums/Collation.php @@ -0,0 +1,32 @@ + 'utf8_general_ci', + self::UTF8_UNICODE_CI => 'utf8_unicode_ci', + self::UTF8_SPANISH_CI => 'utf8_spanish_ci', + self::UTF8MB4_UNICODE_CI => 'utf8mb4_unicode_ci', + self::UTF8MB4_GENERAL_CI => 'utf8mb4_general_ci', + self::UTF8MB4_UNICODE_520_CI => 'utf8mb4_unicode_520_ci', + self::LATIN1_SWEDISH_CI => 'latin1_swedish_ci', + self::UTF8MB4_BIN => 'utf8mb4_bin', + self::UTF8_BIN => 'utf8_bin', + self::LATIN1_BIN => 'latin1_bin', + }; + } +} + diff --git a/enums/Engine.php b/enums/Engine.php new file mode 100644 index 0000000..2f6bbb2 --- /dev/null +++ b/enums/Engine.php @@ -0,0 +1,15 @@ + 'InnoDB', + self::MYISAM => 'MyISAM', + }; + } +} \ No newline at end of file diff --git a/enums/Join.php b/enums/Join.php new file mode 100644 index 0000000..d15a617 --- /dev/null +++ b/enums/Join.php @@ -0,0 +1,20 @@ + 'INNER JOIN', + self::LEFT => 'LEFT JOIN', + self::RIGHT => 'RIGHT JOIN', + self::FULL => 'FULL JOIN', + }; + } +} + diff --git a/enums/Operator.php b/enums/Operator.php new file mode 100644 index 0000000..58433e4 --- /dev/null +++ b/enums/Operator.php @@ -0,0 +1,37 @@ + self::EQUAL, + '!=' => self::NOT_EQUAL, + '>' => self::GREATER, + '>=' => self::GREATER_EQUAL, + '<' => self::LESS, + '<=' => self::LESS_EQUAL, + default => throw new InvalidArgumentException("Invalid operator: $operator"), + }; + } + + public function toString(): string { + return match ($this) { + self::EQUAL => '=', + self::NOT_EQUAL => '!=', + self::GREATER => '>', + self::GREATER_EQUAL => '>=', + self::LESS => '<', + self::LESS_EQUAL => '<=', + }; + } +} diff --git a/enums/Order.php b/enums/Order.php new file mode 100644 index 0000000..8c29a3e --- /dev/null +++ b/enums/Order.php @@ -0,0 +1,16 @@ + 'ASC', + self::DESC => 'DESC', + }; + } +} + diff --git a/enums/Propagation.php b/enums/Propagation.php new file mode 100644 index 0000000..bc9e673 --- /dev/null +++ b/enums/Propagation.php @@ -0,0 +1,21 @@ + 'CASCADE', + self::SET_NULL => 'SET NULL', + self::NO_ACTION => 'NO ACTION', + self::RESTRICT => 'RESTRICT', + self::SET_DEFAULT => 'SET DEFAULT', + }; + } +} \ No newline at end of file diff --git a/enums/Type.php b/enums/Type.php new file mode 100644 index 0000000..ad36a6e --- /dev/null +++ b/enums/Type.php @@ -0,0 +1,46 @@ + (int) $value, + self::FLOAT => (float) $value, + self::STRING => (string) $value, + self::BOOL => filter_var($value, FILTER_VALIDATE_BOOLEAN), + self::ARRAY => is_array($value) ? $value : (json_decode($value, true) ?? []), + self::DATE => $value instanceof DateTime ? $value : (strtotime($value) ? new DateTime($value) : null), + }; + } + + public function dbCast(mixed $value): mixed { + return match ($this) { + self::INT => intval($value), + self::FLOAT => floatval($value), + self::STRING => esc_sql($value), + self::BOOL => filter_var($value, FILTER_VALIDATE_BOOLEAN) ? "TRUE" : "FALSE", + self::ARRAY => json_encode($value), + self::DATE => $value instanceof DateTime ? $value->format('Y-m-d H:i:s') : json_encode($value) + }; + } + + public function toString(): string { + return match ($this) { + self::INT => 'INTEGER', + self::FLOAT => 'FLOAT', + self::STRING => 'VARCHAR(255)', + self::BOOL => 'BOOLEAN', + self::ARRAY => 'JSON', + self::DATE => 'DATETIME', + }; + } +} diff --git a/index.php b/index.php new file mode 100644 index 0000000..ad71f1a --- /dev/null +++ b/index.php @@ -0,0 +1,53 @@ +primary('col-primary', Type::INT, autoInc: true) + ->column('col-one', Type::BOOL) + ->column('col-two', Type::STRING) + ->create(); + + $batches = [ + [ + ['col-one', true], + ['col-two', 'EXPLODING!!!'] + ], + [ + ['col-one', false], + ['col-two', 'EXPLODING!!!'] + ], + ]; + + $batchInsert = Database::makeInsertion($table); + foreach($batches as $batch) { + $batchInsert->batchData($batch)->stack(); + } + $batchInsert->insert(); + + Database::makeUpdate($table) + ->where('col-primary', '=', 1) + ->set('col-one', false) + ->update(); + + $results = Database::makeQuery($table) + ->select('col-primary', 'col-one') + ->where('col-one', '=', true) + ->orderBy('col-one', Order::DESC) + ->query(); +} +catch ( Exception $e ) { + echo $e->getMessage(); +}