NMRelation cleanup / improvement

This commit is contained in:
2023-01-10 22:12:05 +01:00
parent f14a7a4762
commit 13f7866d42
13 changed files with 303 additions and 272 deletions

View File

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