web-base/Core/Objects/DatabaseEntity/Controller/DatabaseEntity.class.php
2022-11-30 16:42:24 +01:00

166 lines
4.4 KiB
PHP

<?php
namespace Core\Objects\DatabaseEntity\Controller;
use Core\Driver\SQL\Condition\Condition;
use Core\Driver\SQL\SQL;
abstract class DatabaseEntity {
protected static array $entityLogConfig = [
"insert" => false,
"update" => false,
"delete" => false,
"lifetime" => null,
];
private static array $handlers = [];
protected ?int $id;
public function __construct(?int $id = null) {
$this->id = $id;
}
public abstract function jsonSerialize(): array;
public function preInsert(array &$row) { }
public function postFetch(SQL $sql, array $row) { }
public static function fromRow(SQL $sql, array $row): static {
$handler = self::getHandler($sql);
return $handler->entityFromRow($row);
}
public static function newInstance(\ReflectionClass $reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
}
public static function find(SQL $sql, int $id, bool $fetchEntities = false, bool $fetchRecursive = false): static|bool|null {
$handler = self::getHandler($sql);
if ($fetchEntities) {
return DatabaseEntityQuery::fetchOne(self::getHandler($sql))
->whereEq($handler->getTableName() . ".id", $id)
->fetchEntities($fetchRecursive)
->execute();
} else {
return $handler->fetchOne($id);
}
}
public static function exists(SQL $sql, int $id): bool {
$handler = self::getHandler($sql);
$res = $sql->select($sql->count())
->from($handler->getTableName())
->whereEq($handler->getTableName() . ".id", $id)
->execute();
return $res !== false && $res[0]["count"] !== 0;
}
public static function findBy(DatabaseEntityQuery $dbQuery): static|array|bool|null {
return $dbQuery->execute();
}
public static function findAll(SQL $sql, ?Condition $condition = null): ?array {
$handler = self::getHandler($sql);
return $handler->fetchMultiple($condition);
}
public static function createBuilder(SQL $sql, bool $one): DatabaseEntityQuery {
if ($one) {
return DatabaseEntityQuery::fetchOne(self::getHandler($sql));
} else {
return DatabaseEntityQuery::fetchAll(self::getHandler($sql));
}
}
// TODO: rather take property names here instead of $columns? and translate then using DatabaseEntityHandler::columns[$propertyName]
public function save(SQL $sql, ?array $columns = null, bool $saveNM = false): bool {
$handler = self::getHandler($sql);
$res = $handler->insertOrUpdate($this, $columns, $saveNM);
if ($res === false) {
return false;
} else if ($this->id === null) {
$this->id = $res;
$handler->insertNM($this);
}
return true;
}
public function insert(SQL $sql): bool {
$handler = self::getHandler($sql);
$res = $handler->insert($this);
if ($res === false) {
return false;
} else if ($this->id === null) {
$this->id = $res;
}
return true;
}
public function delete(SQL $sql): bool {
$handler = self::getHandler($sql);
if ($this->id === null) {
$handler->getLogger()->error("Cannot delete entity without id");
return false;
}
if ($handler->delete($this->id)) {
$this->id = null;
return true;
}
return false;
}
public static function getHandler(SQL $sql, $obj_or_class = null): DatabaseEntityHandler {
if (!$obj_or_class) {
$obj_or_class = get_called_class();
}
if (!($obj_or_class instanceof \ReflectionClass)) {
$class = new \ReflectionClass($obj_or_class);
} else {
$class = $obj_or_class;
}
// if we are in an extending context, get the database handler for the root entity,
// as we do not persist attributes of the inheriting class
while ($class->getParentClass()->getName() !== DatabaseEntity::class) {
$class = $class->getParentClass();
}
$handler = self::$handlers[$class->getShortName()] ?? null;
if (!$handler) {
$handler = new DatabaseEntityHandler($sql, $class);
self::$handlers[$class->getShortName()] = $handler;
}
return $handler;
}
public function getId(): ?int {
return $this->id;
}
public static function count(SQL $sql, ?Condition $condition = null): int|bool {
$handler = self::getHandler($sql);
$query = $sql->select($sql->count())
->from($handler->getTableName());
if ($condition) {
$query->where($condition);
}
$res = $query->execute();
if (!empty($res)) {
return $res[0]["count"];
}
return false;
}
}