Tests + Bugfix
This commit is contained in:
parent
fc5c279cd4
commit
9ecbb2775d
@ -8,10 +8,9 @@ use Driver\SQL\SQL;
|
|||||||
abstract class DatabaseEntity {
|
abstract class DatabaseEntity {
|
||||||
|
|
||||||
private static array $handlers = [];
|
private static array $handlers = [];
|
||||||
private ?int $id;
|
private ?int $id = null;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->id = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function find(SQL $sql, int $id): ?DatabaseEntity {
|
public static function find(SQL $sql, int $id): ?DatabaseEntity {
|
||||||
@ -19,7 +18,7 @@ abstract class DatabaseEntity {
|
|||||||
return $handler->fetchOne($id);
|
return $handler->fetchOne($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function findAll(SQL $sql, ?Condition $condition): ?array {
|
public static function findAll(SQL $sql, ?Condition $condition = null): ?array {
|
||||||
$handler = self::getHandler($sql);
|
$handler = self::getHandler($sql);
|
||||||
return $handler->fetchMultiple($condition);
|
return $handler->fetchMultiple($condition);
|
||||||
}
|
}
|
||||||
@ -43,7 +42,12 @@ abstract class DatabaseEntity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $handler->delete($this->id);
|
if ($handler->delete($this->id)) {
|
||||||
|
$this->id = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getHandler(SQL $sql, $obj_or_class = null): DatabaseEntityHandler {
|
public static function getHandler(SQL $sql, $obj_or_class = null): DatabaseEntityHandler {
|
||||||
|
@ -21,9 +21,11 @@ use PHPUnit\Util\Exception;
|
|||||||
class DatabaseEntityHandler {
|
class DatabaseEntityHandler {
|
||||||
|
|
||||||
private \ReflectionClass $entityClass;
|
private \ReflectionClass $entityClass;
|
||||||
|
private static \ReflectionProperty $ID_FIELD;
|
||||||
private string $tableName;
|
private string $tableName;
|
||||||
private array $columns;
|
private array $columns;
|
||||||
private array $properties;
|
private array $properties;
|
||||||
|
private array $relations;
|
||||||
private SQL $sql;
|
private SQL $sql;
|
||||||
private Logger $logger;
|
private Logger $logger;
|
||||||
|
|
||||||
@ -42,6 +44,10 @@ class DatabaseEntityHandler {
|
|||||||
$this->properties = [];
|
$this->properties = [];
|
||||||
$this->relations = [];
|
$this->relations = [];
|
||||||
|
|
||||||
|
if (!isset(self::$ID_FIELD)) {
|
||||||
|
self::$ID_FIELD = (new \ReflectionClass(DatabaseEntity::class))->getProperty("id");
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->entityClass->getProperties() as $property) {
|
foreach ($this->entityClass->getProperties() as $property) {
|
||||||
$propertyName = $property->getName();
|
$propertyName = $property->getName();
|
||||||
$propertyType = $property->getType();
|
$propertyType = $property->getType();
|
||||||
@ -98,12 +104,26 @@ class DatabaseEntityHandler {
|
|||||||
return $this->logger;
|
return $this->logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTableName(): string {
|
||||||
|
return $this->tableName;
|
||||||
|
}
|
||||||
|
|
||||||
private function entityFromRow(array $row): DatabaseEntity {
|
private function entityFromRow(array $row): DatabaseEntity {
|
||||||
try {
|
try {
|
||||||
$entity = $this->entityClass->newInstanceWithoutConstructor();
|
$entity = $this->entityClass->newInstanceWithoutConstructor();
|
||||||
foreach ($this->columns as $propertyName => $column) {
|
foreach ($this->columns as $propertyName => $column) {
|
||||||
$this->properties[$propertyName]->setValue($entity, $row[$column]);
|
$value = $row[$column->getName()];
|
||||||
|
$property = $this->properties[$propertyName];
|
||||||
|
|
||||||
|
if ($property->getType()->getName() === "DateTime") {
|
||||||
|
$value = new \DateTime($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$property->setValue($entity, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::$ID_FIELD->setAccessible(true);
|
||||||
|
self::$ID_FIELD->setValue($entity, $row["id"]);
|
||||||
return $entity;
|
return $entity;
|
||||||
} catch (\Exception $exception) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Error creating entity from database row: " . $exception->getMessage());
|
$this->logger->error("Error creating entity from database row: " . $exception->getMessage());
|
||||||
@ -112,7 +132,7 @@ class DatabaseEntityHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function fetchOne(int $id): ?DatabaseEntity {
|
public function fetchOne(int $id): ?DatabaseEntity {
|
||||||
$res = $this->sql->select(...array_keys($this->columns))
|
$res = $this->sql->select("id", ...array_keys($this->columns))
|
||||||
->from($this->tableName)
|
->from($this->tableName)
|
||||||
->where(new Compare("id", $id))
|
->where(new Compare("id", $id))
|
||||||
->first()
|
->first()
|
||||||
@ -126,7 +146,7 @@ class DatabaseEntityHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function fetchMultiple(?Condition $condition = null): ?array {
|
public function fetchMultiple(?Condition $condition = null): ?array {
|
||||||
$query = $this->sql->select(...array_keys($this->columns))
|
$query = $this->sql->select("id", ...array_keys($this->columns))
|
||||||
->from($this->tableName);
|
->from($this->tableName);
|
||||||
|
|
||||||
if ($condition) {
|
if ($condition) {
|
||||||
@ -175,7 +195,17 @@ class DatabaseEntityHandler {
|
|||||||
|
|
||||||
foreach ($this->columns as $propertyName => $column) {
|
foreach ($this->columns as $propertyName => $column) {
|
||||||
$columns[] = $column->getName();
|
$columns[] = $column->getName();
|
||||||
$row[] = $this->properties[$propertyName]->getValue($entity);
|
$property = $this->properties[$propertyName];
|
||||||
|
if ($property->isInitialized($entity)) {
|
||||||
|
$value = $property->getValue($entity);
|
||||||
|
} else if (!$this->columns[$propertyName]->notNull()) {
|
||||||
|
$value = null;
|
||||||
|
} else {
|
||||||
|
$this->logger->error("Cannot insert entity: property '$propertyName' was not initialized yet.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row[] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $this->sql->insert($this->tableName, $columns)
|
$res = $this->sql->insert($this->tableName, $columns)
|
||||||
@ -194,7 +224,16 @@ class DatabaseEntityHandler {
|
|||||||
|
|
||||||
foreach ($this->columns as $propertyName => $column) {
|
foreach ($this->columns as $propertyName => $column) {
|
||||||
$columnName = $column->getName();
|
$columnName = $column->getName();
|
||||||
$value = $this->properties[$propertyName]->getValue($entity);
|
$property = $this->properties[$propertyName];
|
||||||
|
if ($property->isInitialized($entity)) {
|
||||||
|
$value = $property->getValue($entity);
|
||||||
|
} else if (!$this->columns[$propertyName]->notNull()) {
|
||||||
|
$value = null;
|
||||||
|
} else {
|
||||||
|
$this->logger->error("Cannot update entity: property '$propertyName' was not initialized yet.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$query->set($columnName, $value);
|
$query->set($columnName, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,4 +249,8 @@ class DatabaseEntityHandler {
|
|||||||
$this->logger->error($message);
|
$this->logger->error($message);
|
||||||
throw new Exception($message);
|
throw new Exception($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPropertyValue() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// TODO: disable logging for tests
|
||||||
|
class DatabaseEntityTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
|
static \Objects\User $USER;
|
||||||
|
static \Driver\SQL\SQL $SQL;
|
||||||
|
static \Objects\DatabaseEntity\DatabaseEntityHandler $HANDLER;
|
||||||
|
|
||||||
|
public static function setUpBeforeClass(): void {
|
||||||
|
parent::setUpBeforeClass();
|
||||||
|
self::$USER = new Objects\User(new \Configuration\Configuration());
|
||||||
|
self::$SQL = self::$USER->getSQL();
|
||||||
|
self::$HANDLER = TestEntity::getHandler(self::$SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateTable() {
|
||||||
|
$this->assertInstanceOf(\Driver\SQL\Query\CreateTable::class, self::$HANDLER->getTableQuery());
|
||||||
|
$this->assertTrue(self::$HANDLER->createTable());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInsertEntity() {
|
||||||
|
|
||||||
|
$entity = new TestEntity();
|
||||||
|
$entity->a = 1;
|
||||||
|
$entity->b = "test";
|
||||||
|
$entity->c = true;
|
||||||
|
$entity->d = 1.23;
|
||||||
|
$entity->e = new DateTime();
|
||||||
|
$entity->f = null;
|
||||||
|
|
||||||
|
// insert
|
||||||
|
$this->assertTrue($entity->save(self::$SQL));
|
||||||
|
$entityId = $entity->getId();
|
||||||
|
$this->assertNotNull($entityId);
|
||||||
|
|
||||||
|
// fetch
|
||||||
|
$entity2 = TestEntity::find(self::$SQL, $entityId);
|
||||||
|
$this->assertNotNull($entity2);
|
||||||
|
$this->assertEquals($entity2->a, $entity->a);
|
||||||
|
$this->assertEquals($entity2->b, $entity->b);
|
||||||
|
$this->assertEquals($entity2->c, $entity->c);
|
||||||
|
$this->assertEquals($entity2->d, $entity->d);
|
||||||
|
$this->assertNotNull($entity2->e);
|
||||||
|
$this->assertEquals(
|
||||||
|
$entity2->e->format(\Api\Parameter\Parameter::DATE_TIME_FORMAT),
|
||||||
|
$entity->e->format(\Api\Parameter\Parameter::DATE_TIME_FORMAT)
|
||||||
|
);
|
||||||
|
$this->assertNull($entity2->f);
|
||||||
|
|
||||||
|
// update
|
||||||
|
$entity2->a = 100;
|
||||||
|
$this->assertTrue($entity2->save(self::$SQL));
|
||||||
|
$this->assertEquals($entity2->getId(), $entityId);
|
||||||
|
|
||||||
|
// re-fetch
|
||||||
|
$this->assertEquals($entity2->a, TestEntity::find(self::$SQL, $entityId)->a);
|
||||||
|
|
||||||
|
// check table contents
|
||||||
|
$allEntities = TestEntity::findAll(self::$SQL);
|
||||||
|
$this->assertIsArray($allEntities);
|
||||||
|
$this->assertCount(1, $allEntities);
|
||||||
|
$this->assertEquals($entityId, $allEntities[0]->getId());
|
||||||
|
|
||||||
|
// delete
|
||||||
|
$this->assertTrue($entity->delete(self::$SQL));
|
||||||
|
$this->assertNull($entity->getId());
|
||||||
|
|
||||||
|
// check table contents
|
||||||
|
$allEntities = TestEntity::findAll(self::$SQL);
|
||||||
|
$this->assertIsArray($allEntities);
|
||||||
|
$this->assertCount(0, $allEntities);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInsertFail() {
|
||||||
|
$entity = new TestEntity();
|
||||||
|
$this->assertFalse($entity->save(self::$SQL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDropTable() {
|
||||||
|
$this->assertTrue(self::$SQL->drop(self::$HANDLER->getTableName())->execute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestEntity extends \Objects\DatabaseEntity\DatabaseEntity {
|
||||||
|
public int $a;
|
||||||
|
public string $b;
|
||||||
|
public bool $c;
|
||||||
|
public float $d;
|
||||||
|
public \DateTime $e;
|
||||||
|
public ?int $f;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user