132 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace DatabaseHelper;
 | 
						|
 | 
						|
use DatabaseHelper\enums\Propagation;
 | 
						|
use DatabaseHelper\enums\Charset;
 | 
						|
use DatabaseHelper\enums\Collation;
 | 
						|
use DatabaseHelper\enums\Type;
 | 
						|
use DatabaseHelper\enums\Engine;
 | 
						|
use InvalidArgumentException;
 | 
						|
 | 
						|
class Table
 | 
						|
{
 | 
						|
    protected Schema $table;
 | 
						|
 | 
						|
    public function __construct(string $tableName) {
 | 
						|
        Database::standardizeTableNames($tableName);
 | 
						|
        $this->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;
 | 
						|
    }
 | 
						|
}
 |