mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-26 22:50:29 +01:00
166 lines
4.1 KiB
PHP
166 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Xentral\Components\SchemaCreator;
|
|
|
|
use Xentral\Components\Database\Database;
|
|
use Xentral\Components\Database\Exception\DatabaseExceptionInterface;
|
|
use Xentral\Components\Database\Exception\EscapingException;
|
|
use Xentral\Components\Database\Exception\TransactionException;
|
|
use Xentral\Components\SchemaCreator\Exception\SchemaCreatorTableException;
|
|
use Xentral\Components\SchemaCreator\Interfaces\DriverInterface;
|
|
use Xentral\Components\SchemaCreator\Schema\TableSchema;
|
|
|
|
final class SchemaCreator
|
|
{
|
|
|
|
/** @var Database $db */
|
|
private $db;
|
|
|
|
/** @var DriverInterface $driver */
|
|
private $driver;
|
|
|
|
/**
|
|
* @param Database $db
|
|
* @param DriverInterface $driver
|
|
*/
|
|
public function __construct(Database $db, DriverInterface $driver)
|
|
{
|
|
$this->db = $db;
|
|
$this->driver = $driver;
|
|
}
|
|
|
|
/**
|
|
* @param TableSchema $targetSchema
|
|
*
|
|
* @throws EscapingException
|
|
* @throws Exception\LineGeneratorException
|
|
* @throws SchemaCreatorTableException
|
|
* @throws TransactionException
|
|
*
|
|
* @return void
|
|
*/
|
|
public function ensureSchema(TableSchema $targetSchema): void
|
|
{
|
|
$this->applyTableSchema($targetSchema);
|
|
}
|
|
|
|
/**
|
|
* @param TableSchema $currentSchema
|
|
* @param TableSchema $targetSchema
|
|
*
|
|
* @throws EscapingException
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getDiffSQL(TableSchema $currentSchema, TableSchema $targetSchema): string
|
|
{
|
|
return $this->driver->generateTableSchemaDiff($currentSchema, $targetSchema);
|
|
}
|
|
|
|
/**
|
|
* @param string $table
|
|
*
|
|
* @throws Exception\LineGeneratorException
|
|
* @throws SchemaCreatorTableException
|
|
*
|
|
* @return TableSchema
|
|
*/
|
|
public function createFromExistingTable(string $table): TableSchema
|
|
{
|
|
return $this->driver->loadFromTable($table);
|
|
}
|
|
|
|
/**
|
|
* @param TableSchema $targetSchema
|
|
*
|
|
* @throws EscapingException
|
|
* @throws Exception\LineGeneratorException
|
|
* @throws SchemaCreatorTableException
|
|
* @throws TransactionException
|
|
*
|
|
* @return void
|
|
*/
|
|
private function applyTableSchema(TableSchema $targetSchema): void
|
|
{
|
|
$sqlSchema = $this->getSqlSchema($targetSchema);
|
|
$this->applySqlSchema($sqlSchema);
|
|
}
|
|
|
|
/**
|
|
* Check whether the table exists
|
|
*
|
|
* @param string $tableName
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function hasTable(string $tableName): bool
|
|
{
|
|
$tables = $this->db->fetchCol('SHOW TABLES');
|
|
|
|
return in_array($tableName, $tables, true);
|
|
}
|
|
|
|
/**
|
|
* @param TableSchema $schema
|
|
*
|
|
* @throws EscapingException
|
|
*
|
|
* @return string
|
|
*/
|
|
private function generateSQLDefinition(TableSchema $schema): string
|
|
{
|
|
return $this->driver->getTableDefinition($schema);
|
|
}
|
|
|
|
/**
|
|
* @param TableSchema $schema
|
|
*
|
|
* @throws EscapingException
|
|
* @throws Exception\LineGeneratorException
|
|
* @throws SchemaCreatorTableException
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSqlSchema(TableSchema $schema): string
|
|
{
|
|
$table = $schema->getTable();
|
|
if (!$this->hasTable($table)) {
|
|
return $this->generateSQLDefinition($schema);
|
|
}
|
|
|
|
$currentSchema = $this->createFromExistingTable($table);
|
|
$diffSQL = $this->getDiffSQL($currentSchema, $schema);
|
|
|
|
if (empty($diffSQL)) {
|
|
return '';
|
|
}
|
|
|
|
return $diffSQL;
|
|
}
|
|
|
|
/**
|
|
* @param string $sql
|
|
*
|
|
* @throws SchemaCreatorTableException
|
|
* @throws TransactionException
|
|
*
|
|
* @return void
|
|
*/
|
|
private function applySqlSchema(string $sql): void
|
|
{
|
|
if (empty($sql)) {
|
|
return;
|
|
}
|
|
$this->db->beginTransaction();
|
|
try {
|
|
$this->db->exec($sql);
|
|
$this->db->commit();
|
|
} catch (DatabaseExceptionInterface $e) {
|
|
$this->db->rollBack();
|
|
throw new SchemaCreatorTableException($e->getMessage(), (int)$e->getCode(), $e);
|
|
}
|
|
}
|
|
}
|