SQL expression rewrite, Pagination, some frontend stuff
This commit is contained in:
@@ -2,10 +2,14 @@
|
||||
|
||||
namespace Core\Objects\DatabaseEntity\Controller;
|
||||
|
||||
use ArrayAccess;
|
||||
use Core\Driver\SQL\Condition\Condition;
|
||||
use Core\Driver\SQL\Expression\Count;
|
||||
use Core\Driver\SQL\SQL;
|
||||
use Core\Objects\DatabaseEntity\Attribute\Transient;
|
||||
use JsonSerializable;
|
||||
|
||||
abstract class DatabaseEntity {
|
||||
abstract class DatabaseEntity implements ArrayAccess, JsonSerializable {
|
||||
|
||||
protected static array $entityLogConfig = [
|
||||
"insert" => false,
|
||||
@@ -16,11 +20,38 @@ abstract class DatabaseEntity {
|
||||
|
||||
private static array $handlers = [];
|
||||
protected ?int $id;
|
||||
#[Transient] protected array $customData = [];
|
||||
|
||||
public function __construct(?int $id = null) {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function offsetExists(mixed $offset): bool {
|
||||
return property_exists($this, $offset) || array_key_exists($offset, $this->customData);
|
||||
}
|
||||
|
||||
public function offsetGet(mixed $offset): mixed {
|
||||
if (property_exists($this, $offset)) {
|
||||
return $this->{$offset};
|
||||
} else {
|
||||
return $this->customData[$offset];
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void {
|
||||
if (property_exists($this, $offset)) {
|
||||
$this->{$offset} = $value;
|
||||
} else {
|
||||
$this->customData[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetUnset(mixed $offset): void {
|
||||
if (array_key_exists($offset, $this->customData)) {
|
||||
unset($this->customData[$offset]);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract function jsonSerialize(): array;
|
||||
|
||||
public function preInsert(array &$row) { }
|
||||
@@ -49,7 +80,7 @@ abstract class DatabaseEntity {
|
||||
|
||||
public static function exists(SQL $sql, int $id): bool {
|
||||
$handler = self::getHandler($sql);
|
||||
$res = $sql->select($sql->count())
|
||||
$res = $sql->select(new Count())
|
||||
->from($handler->getTableName())
|
||||
->whereEq($handler->getTableName() . ".id", $id)
|
||||
->execute();
|
||||
@@ -148,7 +179,7 @@ abstract class DatabaseEntity {
|
||||
|
||||
public static function count(SQL $sql, ?Condition $condition = null): int|bool {
|
||||
$handler = self::getHandler($sql);
|
||||
$query = $sql->select($sql->count())
|
||||
$query = $sql->select(new Count())
|
||||
->from($handler->getTableName());
|
||||
|
||||
if ($condition) {
|
||||
|
||||
@@ -269,7 +269,7 @@ class DatabaseEntityHandler implements Persistable {
|
||||
return $rel_row;
|
||||
}
|
||||
|
||||
private function getValueFromRow(array $row, string $propertyName, mixed &$value): bool {
|
||||
private function getValueFromRow(array $row, string $propertyName, mixed &$value, bool $initEntities = false): bool {
|
||||
$column = $this->columns[$propertyName] ?? null;
|
||||
if (!$column) {
|
||||
return false;
|
||||
@@ -290,8 +290,12 @@ class DatabaseEntityHandler implements Persistable {
|
||||
if (array_key_exists($relColumnPrefix . "id", $row)) {
|
||||
$relId = $row[$relColumnPrefix . "id"];
|
||||
if ($relId !== null) {
|
||||
$relationHandler = $this->relations[$propertyName];
|
||||
$value = $relationHandler->entityFromRow(self::getPrefixedRow($row, $relColumnPrefix));
|
||||
if ($initEntities) {
|
||||
$relationHandler = $this->relations[$propertyName];
|
||||
$value = $relationHandler->entityFromRow(self::getPrefixedRow($row, $relColumnPrefix), [], true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (!$column->notNull()) {
|
||||
$value = null;
|
||||
} else {
|
||||
@@ -305,7 +309,7 @@ class DatabaseEntityHandler implements Persistable {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function entityFromRow(array $row): ?DatabaseEntity {
|
||||
public function entityFromRow(array $row, array $additionalColumns = [], bool $initEntities = false): ?DatabaseEntity {
|
||||
try {
|
||||
|
||||
$constructorClass = $this->entityClass;
|
||||
@@ -324,12 +328,18 @@ class DatabaseEntityHandler implements Persistable {
|
||||
}
|
||||
|
||||
foreach ($this->properties as $property) {
|
||||
if ($this->getValueFromRow($row, $property->getName(), $value)) {
|
||||
if ($this->getValueFromRow($row, $property->getName(), $value, $initEntities)) {
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($entity, $value);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($additionalColumns as $column) {
|
||||
if (!in_array($column, $this->columns) && !isset($this->properties[$column])) {
|
||||
$entity[$column] = $row[$column];
|
||||
}
|
||||
}
|
||||
|
||||
// init n:m / 1:n properties with empty arrays
|
||||
foreach ($this->nmRelations as $nmRelation) {
|
||||
foreach ($nmRelation->getProperties($this) as $property) {
|
||||
@@ -453,9 +463,12 @@ class DatabaseEntityHandler implements Persistable {
|
||||
if ($recursive) {
|
||||
foreach ($entities as $entity) {
|
||||
foreach ($this->relations as $propertyName => $relHandler) {
|
||||
$relEntity = $this->properties[$propertyName]->getValue($entity);
|
||||
if ($relEntity) {
|
||||
$relHandler->fetchNMRelations([$relEntity->getId() => $relEntity], true);
|
||||
$property = $this->properties[$propertyName];
|
||||
if ($property->isInitialized($entity) || true) {
|
||||
$relEntity = $this->properties[$propertyName]->getValue($entity);
|
||||
if ($relEntity) {
|
||||
$relHandler->fetchNMRelations([$relEntity->getId() => $relEntity], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -483,10 +496,10 @@ class DatabaseEntityHandler implements Persistable {
|
||||
->addJoin(new InnerJoin($nmTable, "$nmTable.$refIdColumn", "$refTableName.id"))
|
||||
->where(new CondIn(new Column($thisIdColumn), $entityIds));
|
||||
|
||||
$relEntityQuery->addColumn($thisIdColumn);
|
||||
$relEntityQuery->addSelectValue(new Column($thisIdColumn));
|
||||
foreach ($dataColumns as $tableDataColumns) {
|
||||
foreach ($tableDataColumns as $columnName) {
|
||||
$relEntityQuery->addColumn($columnName);
|
||||
$relEntityQuery->addSelectValue(new Column($columnName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +513,7 @@ class DatabaseEntityHandler implements Persistable {
|
||||
foreach ($rows as $row) {
|
||||
$relId = $row["id"];
|
||||
if (!isset($relEntities[$relId])) {
|
||||
$relEntity = $otherHandler->entityFromRow($row);
|
||||
$relEntity = $otherHandler->entityFromRow($row, [], $recursive);
|
||||
$relEntities[$relId] = $relEntity;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
namespace Core\Objects\DatabaseEntity\Controller;
|
||||
|
||||
use Core\Driver\Logger\Logger;
|
||||
use Core\Driver\SQL\Column\Column;
|
||||
use Core\Driver\SQL\Expression\Alias;
|
||||
use Core\Driver\SQL\Query\Select;
|
||||
use Core\Driver\SQL\SQL;
|
||||
use Core\External\PHPMailer\Exception;
|
||||
|
||||
/**
|
||||
* this class is similar to \Driver\SQL\Query\Select but with reduced functionality
|
||||
@@ -20,6 +23,7 @@ class DatabaseEntityQuery extends Select {
|
||||
private DatabaseEntityHandler $handler;
|
||||
private int $resultType;
|
||||
private bool $logVerbose;
|
||||
private array $additionalColumns;
|
||||
|
||||
private int $fetchSubEntities;
|
||||
|
||||
@@ -29,6 +33,7 @@ class DatabaseEntityQuery extends Select {
|
||||
$this->logger = new Logger("DB-EntityQuery", $handler->getSQL());
|
||||
$this->resultType = $resultType;
|
||||
$this->logVerbose = false;
|
||||
$this->additionalColumns = [];
|
||||
|
||||
$this->from($handler->getTableName());
|
||||
$this->fetchSubEntities = self::FETCH_NONE;
|
||||
@@ -37,6 +42,26 @@ class DatabaseEntityQuery extends Select {
|
||||
}
|
||||
}
|
||||
|
||||
public function addCustomValue(mixed $selectValue): Select {
|
||||
if (is_string($selectValue)) {
|
||||
$this->additionalColumns[] = $selectValue;
|
||||
} else if ($selectValue instanceof Alias) {
|
||||
$this->additionalColumns[] = $selectValue->getAlias();
|
||||
} else if ($selectValue instanceof Column) {
|
||||
$this->additionalColumns[] = $selectValue->getName();
|
||||
} else {
|
||||
$this->logger->debug("Cannot get selected column name from custom value of type: " . get_class($selectValue));
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->addSelectValue($selectValue);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHandler(): DatabaseEntityHandler {
|
||||
return $this->handler;
|
||||
}
|
||||
|
||||
public function debug(): DatabaseEntityQuery {
|
||||
$this->logVerbose = true;
|
||||
return $this;
|
||||
@@ -112,7 +137,7 @@ class DatabaseEntityQuery extends Select {
|
||||
if ($this->resultType === SQL::FETCH_ALL) {
|
||||
$entities = [];
|
||||
foreach ($res as $row) {
|
||||
$entity = $this->handler->entityFromRow($row);
|
||||
$entity = $this->handler->entityFromRow($row, $this->additionalColumns, $this->fetchSubEntities !== self::FETCH_NONE);
|
||||
if ($entity) {
|
||||
$entities[$entity->getId()] = $entity;
|
||||
}
|
||||
@@ -124,7 +149,7 @@ class DatabaseEntityQuery extends Select {
|
||||
|
||||
return $entities;
|
||||
} else if ($this->resultType === SQL::FETCH_ONE) {
|
||||
$entity = $this->handler->entityFromRow($res);
|
||||
$entity = $this->handler->entityFromRow($res, $this->additionalColumns, $this->fetchSubEntities !== self::FETCH_NONE);
|
||||
if ($entity instanceof DatabaseEntity && $this->fetchSubEntities !== self::FETCH_NONE) {
|
||||
$this->handler->fetchNMRelations([$entity->getId() => $entity], $this->fetchSubEntities === self::FETCH_RECURSIVE);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,8 @@ class NMRelation implements Persistable {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user