Переглянути джерело

Composer deps fixed + DB entity relations

Roman 1 рік тому
батько
коміт
fc5c279cd4

+ 21 - 0
core/Configuration/CreateDatabase.class.php

@@ -265,6 +265,7 @@ class CreateDatabase extends DatabaseScript {
       ->addRow("Contact/get", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to see messages within a contact request");
 
     self::loadPatches($queries, $sql);
+    self::loadEntities($queries, $sql);
 
     return $queries;
   }
@@ -286,4 +287,24 @@ class CreateDatabase extends DatabaseScript {
       }
     }
   }
+
+  private static function loadEntities(&$queries, $sql) {
+    $entityDirectory = './core/Objects/DatabaseEntity/';
+    if (file_exists($entityDirectory) && is_dir($entityDirectory)) {
+      $scan_arr = scandir($entityDirectory);
+      $files_arr = array_diff($scan_arr, array('.', '..'));
+      foreach ($files_arr as $file) {
+        $suffix = ".class.php";
+        if (endsWith($file, $suffix)) {
+          $className = substr($file, 0, strlen($file) - strlen($suffix));
+          if (!in_array($className, ["DatabaseEntity", "DatabaseEntityHandler"])) {
+            $className = "\\Objects\\DatabaseEntity\\$className";
+            $method = "$className::getHandler";
+            $handler = call_user_func($method, $sql);
+            $queries[] = $handler->getTableQuery();
+          }
+        }
+      }
+    }
+  }
 }

+ 2 - 2
core/External/composer.json

@@ -4,8 +4,8 @@
         "twig/twig": "^3.0",
         "chillerlan/php-qrcode": "^4.3",
         "christian-riesen/base32": "^1.6",
-        "spomky-labs/cbor-php": "2.0.1",
-        "web-auth/cose-lib": "^3.3",
+        "spomky-labs/cbor-php": "2.1.0",
+        "web-auth/cose-lib": "3.3.12",
         "firebase/php-jwt": "^6.2"
     },
     "require-dev": {

+ 41 - 28
core/External/composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "edfe59e1489b0594cfe6ff0276be3419",
+    "content-hash": "af894b476b8bab945acf32399608ac5f",
     "packages": [
         {
             "name": "beberlei/assert",
@@ -533,16 +533,16 @@
         },
         {
             "name": "php-mqtt/client",
-            "version": "v1.3.0",
+            "version": "v1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-mqtt/client.git",
-                "reference": "5813fd257f27e1e9537cd29c0152102e129437d0"
+                "reference": "d54381306e68baf7c2c089392c0c6d1d06e278c6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-mqtt/client/zipball/5813fd257f27e1e9537cd29c0152102e129437d0",
-                "reference": "5813fd257f27e1e9537cd29c0152102e129437d0",
+                "url": "https://api.github.com/repos/php-mqtt/client/zipball/d54381306e68baf7c2c089392c0c6d1d06e278c6",
+                "reference": "d54381306e68baf7c2c089392c0c6d1d06e278c6",
                 "shasum": ""
             },
             "require": {
@@ -584,36 +584,36 @@
             ],
             "support": {
                 "issues": "https://github.com/php-mqtt/client/issues",
-                "source": "https://github.com/php-mqtt/client/tree/v1.3.0"
+                "source": "https://github.com/php-mqtt/client/tree/v1.4.0"
             },
-            "time": "2022-05-26T17:31:01+00:00"
+            "time": "2022-06-15T19:19:03+00:00"
         },
         {
             "name": "psr/log",
-            "version": "3.0.0",
+            "version": "1.1.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-fig/log.git",
-                "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+                "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
-                "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+                "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
                 "shasum": ""
             },
             "require": {
-                "php": ">=8.0.0"
+                "php": ">=5.3.0"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.x-dev"
+                    "dev-master": "1.1.x-dev"
                 }
             },
             "autoload": {
                 "psr-4": {
-                    "Psr\\Log\\": "src"
+                    "Psr\\Log\\": "Psr/Log/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -634,34 +634,43 @@
                 "psr-3"
             ],
             "support": {
-                "source": "https://github.com/php-fig/log/tree/3.0.0"
+                "source": "https://github.com/php-fig/log/tree/1.1.4"
             },
-            "time": "2021-07-14T16:46:02+00:00"
+            "time": "2021-05-03T11:20:27+00:00"
         },
         {
             "name": "spomky-labs/cbor-php",
-            "version": "v2.0.1",
+            "version": "v2.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Spomky-Labs/cbor-php.git",
-                "reference": "9776578000be884cd7864eeb7c37a4ac92d8c995"
+                "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/9776578000be884cd7864eeb7c37a4ac92d8c995",
-                "reference": "9776578000be884cd7864eeb7c37a4ac92d8c995",
+                "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/28e2712cfc0b48fae661a48ffc6896d7abe83684",
+                "reference": "28e2712cfc0b48fae661a48ffc6896d7abe83684",
                 "shasum": ""
             },
             "require": {
                 "brick/math": "^0.8.15|^0.9.0",
+                "ext-mbstring": "*",
                 "php": ">=7.3"
             },
             "require-dev": {
-                "phpstan/phpstan": "^0.12",
-                "phpstan/phpstan-beberlei-assert": "^0.12",
-                "phpstan/phpstan-deprecation-rules": "^0.12",
-                "phpstan/phpstan-phpunit": "^0.12",
-                "phpstan/phpstan-strict-rules": "^0.12"
+                "ekino/phpstan-banned-code": "^1.0",
+                "ext-json": "*",
+                "infection/infection": "^0.18|^0.25",
+                "phpstan/extension-installer": "^1.1",
+                "phpstan/phpstan": "^1.0",
+                "phpstan/phpstan-beberlei-assert": "^1.0",
+                "phpstan/phpstan-deprecation-rules": "^1.0",
+                "phpstan/phpstan-phpunit": "^1.0",
+                "phpstan/phpstan-strict-rules": "^1.0",
+                "phpunit/phpunit": "^9.5",
+                "rector/rector": "^0.12",
+                "roave/security-advisories": "dev-latest",
+                "symplify/easy-coding-standard": "^10.0"
             },
             "suggest": {
                 "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags",
@@ -695,15 +704,19 @@
             ],
             "support": {
                 "issues": "https://github.com/Spomky-Labs/cbor-php/issues",
-                "source": "https://github.com/Spomky-Labs/cbor-php/tree/v2.0.1"
+                "source": "https://github.com/Spomky-Labs/cbor-php/tree/v2.1.0"
             },
             "funding": [
+                {
+                    "url": "https://github.com/Spomky",
+                    "type": "github"
+                },
                 {
                     "url": "https://www.patreon.com/FlorentMorselli",
                     "type": "patreon"
                 }
             ],
-            "time": "2020-08-31T20:08:03+00:00"
+            "time": "2021-12-13T12:46:26+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
@@ -3035,5 +3048,5 @@
     "prefer-lowest": false,
     "platform": [],
     "platform-dev": [],
-    "plugin-api-version": "2.3.0"
+    "plugin-api-version": "2.2.0"
 }

+ 11 - 13
core/Objects/DatabaseEntity/DatabaseEntity.class.php

@@ -2,7 +2,6 @@
 
 namespace Objects\DatabaseEntity;
 
-use Driver\Logger\Logger;
 use Driver\SQL\Condition\Condition;
 use Driver\SQL\SQL;
 
@@ -16,18 +15,18 @@ abstract class DatabaseEntity {
   }
 
   public static function find(SQL $sql, int $id): ?DatabaseEntity {
-    $handler = self::getHandler();
-    return $handler->fetchOne($sql, $id);
+    $handler = self::getHandler($sql);
+    return $handler->fetchOne($id);
   }
 
   public static function findAll(SQL $sql, ?Condition $condition): ?array {
-    $handler = self::getHandler();
-    return $handler->fetchMultiple($sql, $condition);
+    $handler = self::getHandler($sql);
+    return $handler->fetchMultiple($condition);
   }
 
   public function save(SQL $sql): bool {
-    $handler = self::getHandler();
-    $res = $handler->insertOrUpdate($sql, $this);
+    $handler = self::getHandler($sql);
+    $res = $handler->insertOrUpdate($this);
     if ($res === false) {
       return false;
     } else if ($this->id === null) {
@@ -38,17 +37,16 @@ abstract class DatabaseEntity {
   }
 
   public function delete(SQL $sql): bool {
-    $handler = self::getHandler();
+    $handler = self::getHandler($sql);
     if ($this->id === null) {
-      $className = $handler->getReflection()->getName();
-      (new Logger("DatabaseEntity", $sql))->error("Cannot delete entity of class '$className' without id");
+      $handler->getLogger()->error("Cannot delete entity without id");
       return false;
     }
 
-    return $handler->delete($sql, $this->id);
+    return $handler->delete($this->id);
   }
 
-  public static function getHandler($obj_or_class = null): DatabaseEntityHandler {
+  public static function getHandler(SQL $sql, $obj_or_class = null): DatabaseEntityHandler {
 
     if (!$obj_or_class) {
       $obj_or_class = get_called_class();
@@ -62,7 +60,7 @@ abstract class DatabaseEntity {
 
     $handler = self::$handlers[$class->getShortName()] ?? null;
     if (!$handler) {
-      $handler = new DatabaseEntityHandler($class);
+      $handler = new DatabaseEntityHandler($sql, $class);
       self::$handlers[$class->getShortName()] = $handler;
     }
 

+ 46 - 21
core/Objects/DatabaseEntity/DatabaseEntityHandler.php

@@ -2,6 +2,7 @@
 
 namespace Objects\DatabaseEntity;
 
+use Driver\Logger\Logger;
 use Driver\SQL\Column\BoolColumn;
 use Driver\SQL\Column\DateTimeColumn;
 use Driver\SQL\Column\IntColumn;
@@ -11,6 +12,7 @@ use Driver\SQL\Condition\Condition;
 use Driver\SQL\Column\DoubleColumn;
 use Driver\SQL\Column\FloatColumn;
 use Driver\SQL\Constraint\ForeignKey;
+use Driver\SQL\Query\CreateTable;
 use Driver\SQL\SQL;
 use Driver\SQL\Strategy\CascadeStrategy;
 use Driver\SQL\Strategy\SetNullStrategy;
@@ -22,13 +24,17 @@ class DatabaseEntityHandler {
   private string $tableName;
   private array $columns;
   private array $properties;
+  private SQL $sql;
+  private Logger $logger;
 
-  public function __construct(\ReflectionClass $entityClass) {
+  public function __construct(SQL $sql, \ReflectionClass $entityClass) {
+    $this->sql = $sql;
     $className = $entityClass->getName();
+    $this->logger = new Logger($entityClass->getShortName(), $sql);
     $this->entityClass = $entityClass;
     if (!$this->entityClass->isSubclassOf(DatabaseEntity::class) ||
       !$this->entityClass->isInstantiable()) {
-      throw new Exception("Cannot persist class '$className': Not an instance of DatabaseEntity or not instantiable.");
+      $this->raiseError("Cannot persist class '$className': Not an instance of DatabaseEntity or not instantiable.");
     }
 
     $this->tableName = $this->entityClass->getShortName();
@@ -41,7 +47,7 @@ class DatabaseEntityHandler {
       $propertyType = $property->getType();
       $columnName = self::getColumnName($propertyName);
       if (!($propertyType instanceof \ReflectionNamedType)) {
-        throw new Exception("Cannot persist class '$className': Property '$propertyName' has no valid type");
+        $this->raiseError("Cannot persist class '$className': Property '$propertyName' has no valid type");
       }
 
       $nullable = $propertyType->allowsNull();
@@ -63,13 +69,13 @@ class DatabaseEntityHandler {
           $requestedClass = new \ReflectionClass($propertyTypeName);
           if ($requestedClass->isSubclassOf(DatabaseEntity::class)) {
             $requestedHandler = ($requestedClass->getName() === $this->entityClass->getName()) ?
-              $this : DatabaseEntity::getHandler($requestedClass);
+              $this : DatabaseEntity::getHandler($this->sql, $requestedClass);
             $strategy = $nullable ? new SetNullStrategy() : new CascadeStrategy();
             $this->columns[$propertyName] = new IntColumn($columnName, $nullable);
             $this->relations[$propertyName] = new ForeignKey($columnName, $requestedHandler->tableName, "id", $strategy);
           }
         } catch (\Exception $ex) {
-          throw new Exception("Cannot persist class '$className': Property '$propertyName' has non persist-able type: $propertyTypeName");
+          $this->raiseError("Cannot persist class '$className': Property '$propertyName' has non persist-able type: $propertyTypeName");
         }
       }
 
@@ -88,16 +94,25 @@ class DatabaseEntityHandler {
     return $this->entityClass;
   }
 
+  public function getLogger(): Logger {
+    return $this->logger;
+  }
+
   private function entityFromRow(array $row): DatabaseEntity {
-    $entity = $this->entityClass->newInstanceWithoutConstructor();
-    foreach ($this->columns as $propertyName => $column) {
-      $this->properties[$propertyName]->setValue($entity, $row[$column]);
+    try {
+      $entity = $this->entityClass->newInstanceWithoutConstructor();
+      foreach ($this->columns as $propertyName => $column) {
+        $this->properties[$propertyName]->setValue($entity, $row[$column]);
+      }
+      return $entity;
+    } catch (\Exception $exception) {
+      $this->logger->error("Error creating entity from database row: " . $exception->getMessage());
+      throw $exception;
     }
-    return $entity;
   }
 
-  public function fetchOne(SQL $sql, int $id): ?DatabaseEntity {
-    $res = $sql->select(...array_keys($this->columns))
+  public function fetchOne(int $id): ?DatabaseEntity {
+    $res = $this->sql->select(...array_keys($this->columns))
       ->from($this->tableName)
       ->where(new Compare("id", $id))
       ->first()
@@ -110,8 +125,8 @@ class DatabaseEntityHandler {
     }
   }
 
-  public function fetchMultiple(SQL $sql, ?Condition $condition = null): ?array {
-    $query = $sql->select(...array_keys($this->columns))
+  public function fetchMultiple(?Condition $condition = null): ?array {
+    $query = $this->sql->select(...array_keys($this->columns))
       ->from($this->tableName);
 
     if ($condition) {
@@ -130,8 +145,8 @@ class DatabaseEntityHandler {
     }
   }
 
-  public function createTable(SQL $sql): bool {
-    $query = $sql->createTable($this->tableName)
+  public function getTableQuery(): CreateTable {
+    $query = $this->sql->createTable($this->tableName)
       ->onlyIfNotExists()
       ->addSerial("id")
       ->primaryKey("id");
@@ -144,10 +159,15 @@ class DatabaseEntityHandler {
       $query->addConstraint($constraint);
     }
 
+    return $query;
+  }
+
+  public function createTable(): bool {
+    $query = $this->getTableQuery();
     return $query->execute();
   }
 
-  public function insertOrUpdate(SQL $sql, DatabaseEntity $entity) {
+  public function insertOrUpdate(DatabaseEntity $entity) {
     $id = $entity->getId();
     if ($id === null) {
       $columns = [];
@@ -158,18 +178,18 @@ class DatabaseEntityHandler {
         $row[] = $this->properties[$propertyName]->getValue($entity);
       }
 
-      $res = $sql->insert($this->tableName, $columns)
+      $res = $this->sql->insert($this->tableName, $columns)
         ->addRow(...$row)
         ->returning("id")
         ->execute();
 
       if ($res !== false) {
-        return $sql->getLastInsertId();
+        return $this->sql->getLastInsertId();
       } else {
         return false;
       }
     } else {
-      $query = $sql->update($this->tableName)
+      $query = $this->sql->update($this->tableName)
         ->where(new Compare("id", $id));
 
       foreach ($this->columns as $propertyName => $column) {
@@ -182,7 +202,12 @@ class DatabaseEntityHandler {
     }
   }
 
-  public function delete(SQL $sql, int $id) {
-    return $sql->delete($this->tableName)->where(new Compare("id", $id))->execute();
+  public function delete(int $id) {
+    return $this->sql->delete($this->tableName)->where(new Compare("id", $id))->execute();
+  }
+
+  private function raiseError(string $message) {
+    $this->logger->error($message);
+    throw new Exception($message);
   }
 }