NMRelation cleanup / improvement
This commit is contained in:
@@ -2,135 +2,65 @@
|
||||
|
||||
namespace Core\Objects\DatabaseEntity\Controller;
|
||||
|
||||
# TODO: Allow more than 2 relations here?
|
||||
|
||||
use Core\Driver\SQL\Query\CreateTable;
|
||||
use Core\Driver\SQL\SQL;
|
||||
use Core\Driver\SQL\Strategy\CascadeStrategy;
|
||||
|
||||
class NMRelation implements Persistable {
|
||||
|
||||
private DatabaseEntityHandler $handlerA;
|
||||
private DatabaseEntityHandler $handlerB;
|
||||
private array $properties;
|
||||
private DatabaseEntityHandler $thisHandler;
|
||||
private DatabaseEntityHandler $otherHandler;
|
||||
private \ReflectionProperty $property;
|
||||
private string $tableName;
|
||||
|
||||
public function __construct(DatabaseEntityHandler $handlerA, DatabaseEntityHandler $handlerB) {
|
||||
$this->handlerA = $handlerA;
|
||||
$this->handlerB = $handlerB;
|
||||
$tableNameA = $handlerA->getTableName();
|
||||
$tableNameB = $handlerB->getTableName();
|
||||
if ($tableNameA === $tableNameB) {
|
||||
throw new \Exception("Cannot create N:M Relation with only one table");
|
||||
}
|
||||
|
||||
$this->properties = [
|
||||
$tableNameA => [],
|
||||
$tableNameB => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function addProperty(DatabaseEntityHandler $src, \ReflectionProperty $property): void {
|
||||
$this->properties[$src->getTableName()][$property->getName()] = $property;
|
||||
public function __construct(DatabaseEntityHandler $thisHandler, \ReflectionProperty $thisProperty, DatabaseEntityHandler $otherHandler) {
|
||||
$this->thisHandler = $thisHandler;
|
||||
$this->otherHandler = $otherHandler;
|
||||
$this->property = $thisProperty;
|
||||
$this->tableName = "NM_" . $thisHandler->getTableName() . "_" .
|
||||
DatabaseEntityHandler::buildColumnName($thisProperty->getName());
|
||||
}
|
||||
|
||||
public function getIdColumn(DatabaseEntityHandler $handler): string {
|
||||
return DatabaseEntityHandler::buildColumnName($handler->getTableName()) . "_id";
|
||||
}
|
||||
|
||||
public function getDataColumns(): array {
|
||||
|
||||
$referenceCount = 0;
|
||||
$columnsNeeded = false;
|
||||
|
||||
// if in one of the relations we have multiple references, we need to differentiate
|
||||
foreach ($this->properties as $refProperties) {
|
||||
$referenceCount += count($refProperties);
|
||||
if ($referenceCount > 1) {
|
||||
$columnsNeeded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
if ($columnsNeeded) {
|
||||
foreach ($this->properties as $tableName => $properties) {
|
||||
$columns[$tableName] = [];
|
||||
foreach ($properties as $property) {
|
||||
$columnName = DatabaseEntityHandler::buildColumnName($tableName) . "_" .
|
||||
DatabaseEntityHandler::buildColumnName($property->getName());
|
||||
$columns[$tableName][$property->getName()] = $columnName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function getAllColumns(): array {
|
||||
$relIdA = $this->getIdColumn($this->handlerA);
|
||||
$relIdB = $this->getIdColumn($this->handlerB);
|
||||
|
||||
$columns = [$relIdA, $relIdB];
|
||||
|
||||
foreach ($this->getDataColumns() as $dataColumns) {
|
||||
foreach ($dataColumns as $columnName) {
|
||||
$columns[] = $columnName;
|
||||
}
|
||||
}
|
||||
|
||||
return $columns;
|
||||
public function getProperty(): \ReflectionProperty {
|
||||
return $this->property;
|
||||
}
|
||||
|
||||
public function getTableQuery(SQL $sql): CreateTable {
|
||||
|
||||
$tableNameA = $this->handlerA->getTableName();
|
||||
$tableNameB = $this->handlerB->getTableName();
|
||||
$thisTable = $this->thisHandler->getTableName();
|
||||
$otherTable = $this->otherHandler->getTableName();
|
||||
$thisIdColumn = $this->getIdColumn($this->thisHandler);
|
||||
$otherIdColumn = $this->getIdColumn($this->otherHandler);
|
||||
|
||||
$columns = $this->getAllColumns();
|
||||
list ($relIdA, $relIdB) = $columns;
|
||||
$dataColumns = array_slice($columns, 2);
|
||||
$query = $sql->createTable(self::buildTableName($tableNameA, $tableNameB))
|
||||
->addInt($relIdA)
|
||||
->addInt($relIdB)
|
||||
->foreignKey($relIdA, $tableNameA, "id", new CascadeStrategy())
|
||||
->foreignKey($relIdB, $tableNameB, "id", new CascadeStrategy());
|
||||
|
||||
foreach ($dataColumns as $dataColumn) {
|
||||
$query->addBool($dataColumn, false);
|
||||
}
|
||||
|
||||
$query->unique(...$columns);
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function buildTableName(string ...$tables): string {
|
||||
// in case of class passed here
|
||||
$tables = array_map(function ($t) { return isClass($t) ? getClassName($t) : $t; }, $tables);
|
||||
sort($tables);
|
||||
return "NM_" . implode("_", $tables);
|
||||
return $sql->createTable($this->tableName)
|
||||
->addInt($thisIdColumn)
|
||||
->addInt($otherIdColumn)
|
||||
->foreignKey($thisIdColumn, $thisTable, "id", new CascadeStrategy())
|
||||
->foreignKey($otherIdColumn, $otherTable, "id", new CascadeStrategy())
|
||||
->unique($thisIdColumn, $otherIdColumn);
|
||||
}
|
||||
|
||||
public function dependsOn(): array {
|
||||
return [$this->handlerA->getTableName(), $this->handlerB->getTableName()];
|
||||
return [$this->thisHandler->getTableName(), $this->otherHandler->getTableName()];
|
||||
}
|
||||
|
||||
public function getTableName(): string {
|
||||
return self::buildTableName(...$this->dependsOn());
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
public function getCreateQueries(SQL $sql): array {
|
||||
return [$this->getTableQuery($sql)];
|
||||
}
|
||||
|
||||
public function getProperties(DatabaseEntityHandler $handler): array {
|
||||
return $this->properties[$handler->getTableName()];
|
||||
}
|
||||
|
||||
public function getOtherHandler(DatabaseEntityHandler $handler): DatabaseEntityHandler {
|
||||
if ($handler === $this->handlerA) {
|
||||
return $this->handlerB;
|
||||
if ($handler === $this->thisHandler) {
|
||||
return $this->thisHandler;
|
||||
} else {
|
||||
return $this->handlerA;
|
||||
return $this->otherHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user