Browse Source

Tests + Bugfix

Roman 1 year ago
parent
commit
9ecbb2775d

+ 8 - 4
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 {

+ 48 - 5
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() {
+
+  }
 }

+ 92 - 0
test/DatabaseEntity.test.php

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