diff --git a/core/Objects/DatabaseEntity/DatabaseEntity.class.php b/core/Objects/DatabaseEntity/DatabaseEntity.class.php index 5508642..e6cfcc4 100644 --- a/core/Objects/DatabaseEntity/DatabaseEntity.class.php +++ b/core/Objects/DatabaseEntity/DatabaseEntity.class.php @@ -8,10 +8,9 @@ use Driver\SQL\SQL; abstract class DatabaseEntity { private static array $handlers = []; - private ?int $id; + private ?int $id = null; public function __construct() { - $this->id = null; } public static function find(SQL $sql, int $id): ?DatabaseEntity { @@ -19,7 +18,7 @@ abstract class DatabaseEntity { 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); return $handler->fetchMultiple($condition); } @@ -43,7 +42,12 @@ abstract class DatabaseEntity { 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 { diff --git a/core/Objects/DatabaseEntity/DatabaseEntityHandler.php b/core/Objects/DatabaseEntity/DatabaseEntityHandler.php index 8fd7aba..e84edb8 100644 --- a/core/Objects/DatabaseEntity/DatabaseEntityHandler.php +++ b/core/Objects/DatabaseEntity/DatabaseEntityHandler.php @@ -21,9 +21,11 @@ use PHPUnit\Util\Exception; class DatabaseEntityHandler { private \ReflectionClass $entityClass; + private static \ReflectionProperty $ID_FIELD; private string $tableName; private array $columns; private array $properties; + private array $relations; private SQL $sql; private Logger $logger; @@ -42,6 +44,10 @@ class DatabaseEntityHandler { $this->properties = []; $this->relations = []; + if (!isset(self::$ID_FIELD)) { + self::$ID_FIELD = (new \ReflectionClass(DatabaseEntity::class))->getProperty("id"); + } + foreach ($this->entityClass->getProperties() as $property) { $propertyName = $property->getName(); $propertyType = $property->getType(); @@ -98,12 +104,26 @@ class DatabaseEntityHandler { return $this->logger; } + public function getTableName(): string { + return $this->tableName; + } + private function entityFromRow(array $row): DatabaseEntity { try { $entity = $this->entityClass->newInstanceWithoutConstructor(); 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; } catch (\Exception $exception) { $this->logger->error("Error creating entity from database row: " . $exception->getMessage()); @@ -112,7 +132,7 @@ class DatabaseEntityHandler { } 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) ->where(new Compare("id", $id)) ->first() @@ -126,7 +146,7 @@ class DatabaseEntityHandler { } 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); if ($condition) { @@ -175,7 +195,17 @@ class DatabaseEntityHandler { foreach ($this->columns as $propertyName => $column) { $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) @@ -194,7 +224,16 @@ class DatabaseEntityHandler { foreach ($this->columns as $propertyName => $column) { $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); } @@ -210,4 +249,8 @@ class DatabaseEntityHandler { $this->logger->error($message); throw new Exception($message); } + + private function getPropertyValue() { + + } } \ No newline at end of file diff --git a/test/DatabaseEntity.test.php b/test/DatabaseEntity.test.php index e69de29..73c1509 100644 --- a/test/DatabaseEntity.test.php +++ b/test/DatabaseEntity.test.php @@ -0,0 +1,92 @@ +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; +} \ No newline at end of file