OpenXE/classes/Components/SchemaCreator/SchemaCreator.php
2021-05-21 08:49:41 +02:00

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);
}
}
}