v2.4.4: DatabaseEntity migration and bugfixes
This commit is contained in:
parent
b96d0d053c
commit
037f0fae91
@ -63,7 +63,6 @@ namespace Core\API\Settings {
|
|||||||
public function _execute(): bool {
|
public function _execute(): bool {
|
||||||
$key = $this->getParam("key");
|
$key = $this->getParam("key");
|
||||||
$sql = $this->context->getSQL();
|
$sql = $this->context->getSQL();
|
||||||
$siteSettings = $this->context->getSettings();
|
|
||||||
|
|
||||||
$settings = Settings::getAll($sql, $key, $this->isExternalCall());
|
$settings = Settings::getAll($sql, $key, $this->isExternalCall());
|
||||||
if ($settings !== null) {
|
if ($settings !== null) {
|
||||||
|
@ -3,12 +3,24 @@
|
|||||||
namespace Core\Configuration;
|
namespace Core\Configuration;
|
||||||
|
|
||||||
use Core\API\Request;
|
use Core\API\Request;
|
||||||
|
use Core\Driver\Logger\Logger;
|
||||||
|
use Core\Driver\SQL\Query\CreateTable;
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;
|
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;
|
||||||
use PHPUnit\Util\Exception;
|
use PHPUnit\Util\Exception;
|
||||||
|
|
||||||
class CreateDatabase {
|
class CreateDatabase {
|
||||||
|
|
||||||
|
private static ?Logger $logger = null;
|
||||||
|
|
||||||
|
public static function getLogger(SQL $sql): Logger {
|
||||||
|
if (self::$logger === null) {
|
||||||
|
self::$logger = new Logger("CreateDatabase", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$logger;
|
||||||
|
}
|
||||||
|
|
||||||
public static function createQueries(SQL $sql): array {
|
public static function createQueries(SQL $sql): array {
|
||||||
$queries = array();
|
$queries = array();
|
||||||
|
|
||||||
@ -51,35 +63,54 @@ class CreateDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function loadEntities(SQL $sql, array &$queries): void {
|
private static function getCreatedTables(SQL $sql, array $queries): ?array {
|
||||||
|
$createdTables = $sql->listTables();
|
||||||
|
|
||||||
|
if ($createdTables !== null) {
|
||||||
|
foreach ($queries as $query) {
|
||||||
|
if ($query instanceof CreateTable) {
|
||||||
|
$tableName = $query->getTableName();
|
||||||
|
if (!in_array($tableName, $createdTables)) {
|
||||||
|
$createdTables[] = $tableName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self::getLogger($sql)->warning("Error querying existing tables: " . $sql->getLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $createdTables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createEntityQueries(SQL $sql, array $entityClasses, array &$queries, bool $skipExisting = false): void {
|
||||||
|
|
||||||
|
if (empty($entityClasses)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first, check what tables are already created
|
||||||
|
$createdTables = self::getCreatedTables($sql, $queries);
|
||||||
|
if ($createdTables === null) {
|
||||||
|
throw new \Exception("Error querying existing tables");
|
||||||
|
}
|
||||||
|
|
||||||
|
// then collect all persistable entities (tables, relations, etc.)
|
||||||
$persistables = [];
|
$persistables = [];
|
||||||
$baseDirs = ["Core", "Site"];
|
foreach ($entityClasses as $className) {
|
||||||
foreach ($baseDirs as $baseDir) {
|
|
||||||
$entityDirectory = "./$baseDir/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));
|
|
||||||
$className = "\\$baseDir\\Objects\\DatabaseEntity\\$className";
|
|
||||||
$reflectionClass = new \ReflectionClass($className);
|
$reflectionClass = new \ReflectionClass($className);
|
||||||
if ($reflectionClass->isSubclassOf(DatabaseEntity::class)) {
|
if ($reflectionClass->isSubclassOf(DatabaseEntity::class)) {
|
||||||
$method = "$className::getHandler";
|
$handler = ("$className::getHandler")($sql, null, true);
|
||||||
$handler = call_user_func($method, $sql, null, true);
|
|
||||||
$persistables[$handler->getTableName()] = $handler;
|
$persistables[$handler->getTableName()] = $handler;
|
||||||
foreach ($handler->getNMRelations() as $nmTableName => $nmRelation) {
|
foreach ($handler->getNMRelations() as $nmTableName => $nmRelation) {
|
||||||
$persistables[$nmTableName] = $nmRelation;
|
$persistables[$nmTableName] = $nmRelation;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
throw new \Exception("Class '$className' is not a subclass of DatabaseEntity");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now order the persistable entities so all dependencies are met.
|
||||||
$tableCount = count($persistables);
|
$tableCount = count($persistables);
|
||||||
$createdTables = [];
|
|
||||||
while (!empty($persistables)) {
|
while (!empty($persistables)) {
|
||||||
$prevCount = $tableCount;
|
$prevCount = $tableCount;
|
||||||
$unmetDependenciesTotal = [];
|
$unmetDependenciesTotal = [];
|
||||||
@ -88,7 +119,7 @@ class CreateDatabase {
|
|||||||
$dependsOn = $persistable->dependsOn();
|
$dependsOn = $persistable->dependsOn();
|
||||||
$unmetDependencies = array_diff($dependsOn, $createdTables);
|
$unmetDependencies = array_diff($dependsOn, $createdTables);
|
||||||
if (empty($unmetDependencies)) {
|
if (empty($unmetDependencies)) {
|
||||||
$queries = array_merge($queries, $persistable->getCreateQueries($sql));
|
$queries = array_merge($queries, $persistable->getCreateQueries($sql, $skipExisting));
|
||||||
$createdTables[] = $tableName;
|
$createdTables[] = $tableName;
|
||||||
unset($persistables[$tableName]);
|
unset($persistables[$tableName]);
|
||||||
} else {
|
} else {
|
||||||
@ -104,6 +135,32 @@ class CreateDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function loadEntities(SQL $sql, array &$queries): void {
|
||||||
|
|
||||||
|
$classes = [];
|
||||||
|
$baseDirs = ["Core", "Site"];
|
||||||
|
foreach ($baseDirs as $baseDir) {
|
||||||
|
$entityDirectory = "./$baseDir/Objects/DatabaseEntity/";
|
||||||
|
if (file_exists($entityDirectory) && is_dir($entityDirectory)) {
|
||||||
|
$scan_arr = scandir($entityDirectory);
|
||||||
|
$files_arr = array_diff($scan_arr, [".", ".."]);
|
||||||
|
foreach ($files_arr as $file) {
|
||||||
|
$suffix = ".class.php";
|
||||||
|
if (endsWith($file, $suffix)) {
|
||||||
|
$className = substr($file, 0, strlen($file) - strlen($suffix));
|
||||||
|
$className = "\\$baseDir\\Objects\\DatabaseEntity\\$className";
|
||||||
|
$reflectionClass = new \ReflectionClass($className);
|
||||||
|
if ($reflectionClass->isSubclassOf(DatabaseEntity::class)) {
|
||||||
|
$classes[] = $className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self::createEntityQueries($sql, $classes, $queries);
|
||||||
|
}
|
||||||
|
|
||||||
public static function loadDefaultACL(SQL $sql, array &$queries): void {
|
public static function loadDefaultACL(SQL $sql, array &$queries): void {
|
||||||
$query = $sql->insert("ApiPermission", ["method", "groups", "description", "is_core"]);
|
$query = $sql->insert("ApiPermission", ["method", "groups", "description", "is_core"]);
|
||||||
|
|
||||||
|
@ -62,7 +62,14 @@ class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function getAll(?SQL $sql, ?string $pattern = null, bool $external = false): ?array {
|
public static function getAll(?SQL $sql, ?string $pattern = null, bool $external = false): ?array {
|
||||||
$query = $sql->select("name", "value")->from("Settings");
|
|
||||||
|
// We do not have a Settings table yet, we might still be in installation phase
|
||||||
|
if (!$sql->tableExists("Settings")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = $sql->select("name", "value")
|
||||||
|
->from("Settings");
|
||||||
|
|
||||||
if ($pattern) {
|
if ($pattern) {
|
||||||
$query->where(new CondRegex(new Column("name"), $pattern));
|
$query->where(new CondRegex(new Column("name"), $pattern));
|
||||||
|
@ -19,7 +19,6 @@ namespace Documents\Install {
|
|||||||
|
|
||||||
use Core\Configuration\Configuration;
|
use Core\Configuration\Configuration;
|
||||||
use Core\Configuration\CreateDatabase;
|
use Core\Configuration\CreateDatabase;
|
||||||
use Core\Driver\SQL\Expression\Count;
|
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
use Core\Elements\Body;
|
use Core\Elements\Body;
|
||||||
use Core\Elements\Head;
|
use Core\Elements\Head;
|
||||||
@ -187,7 +186,7 @@ namespace Documents\Install {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sql = $context->getSQL();
|
$sql = $context->getSQL();
|
||||||
if (!$sql || !$sql->isConnected()) {
|
if (!$sql || !$sql->isConnected() || !$sql->tableExists(User::getHandler($sql)->getTableName())) {
|
||||||
return self::DATABASE_CONFIGURATION;
|
return self::DATABASE_CONFIGURATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,9 +438,12 @@ namespace Documents\Install {
|
|||||||
$context = $this->getDocument()->getContext();
|
$context = $this->getDocument()->getContext();
|
||||||
if ($this->getParameter("prev") === "true") {
|
if ($this->getParameter("prev") === "true") {
|
||||||
// TODO: drop the previous database here?
|
// TODO: drop the previous database here?
|
||||||
|
/*
|
||||||
$success = $context->getConfig()->delete("\\Site\\Configuration\\Database");
|
$success = $context->getConfig()->delete("\\Site\\Configuration\\Database");
|
||||||
$msg = $success ? "" : error_get_last();
|
$msg = $success ? "" : error_get_last();
|
||||||
return ["success" => $success, "msg" => $msg];
|
return ["success" => $success, "msg" => $msg];
|
||||||
|
*/
|
||||||
|
return ["success" => false, "msg" => "Cannot revert this installation step."];
|
||||||
}
|
}
|
||||||
|
|
||||||
$username = $this->getParameter("username");
|
$username = $this->getParameter("username");
|
||||||
@ -755,7 +757,7 @@ namespace Documents\Install {
|
|||||||
["title" => "Password", "name" => "password", "type" => "password", "required" => true],
|
["title" => "Password", "name" => "password", "type" => "password", "required" => true],
|
||||||
["title" => "Confirm Password", "name" => "confirmPassword", "type" => "password", "required" => true],
|
["title" => "Confirm Password", "name" => "confirmPassword", "type" => "password", "required" => true],
|
||||||
],
|
],
|
||||||
"previousButton" => true
|
"previousButton" => false,
|
||||||
],
|
],
|
||||||
self::ADD_MAIL_SERVICE => [
|
self::ADD_MAIL_SERVICE => [
|
||||||
"title" => "Optional: Add Mail Service",
|
"title" => "Optional: Add Mail Service",
|
||||||
|
@ -6,7 +6,7 @@ use Core\Driver\SQL\Column\Column;
|
|||||||
use Core\Driver\SQL\MySQL;
|
use Core\Driver\SQL\MySQL;
|
||||||
use Core\Driver\SQL\PostgreSQL;
|
use Core\Driver\SQL\PostgreSQL;
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
use Core\External\PHPMailer\Exception;
|
use Exception;
|
||||||
|
|
||||||
class DateAdd extends Expression {
|
class DateAdd extends Expression {
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use Core\Driver\SQL\Column\Column;
|
|||||||
use Core\Driver\SQL\MySQL;
|
use Core\Driver\SQL\MySQL;
|
||||||
use Core\Driver\SQL\PostgreSQL;
|
use Core\Driver\SQL\PostgreSQL;
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
use Core\External\PHPMailer\Exception;
|
use Exception;
|
||||||
|
|
||||||
class DateSub extends Expression {
|
class DateSub extends Expression {
|
||||||
|
|
||||||
|
@ -375,7 +375,10 @@ class MySQL extends SQL {
|
|||||||
list ($name, $alias) = $parts;
|
list ($name, $alias) = $parts;
|
||||||
return "`$name` $alias";
|
return "`$name` $alias";
|
||||||
} else {
|
} else {
|
||||||
return "`$table`";
|
$parts = explode(".", $table);
|
||||||
|
return implode(".", array_map(function ($n) {
|
||||||
|
return "`$n`";
|
||||||
|
}, $parts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,6 +487,27 @@ class MySQL extends SQL {
|
|||||||
|
|
||||||
return $res && $res[0]["count"] > 0;
|
return $res && $res[0]["count"] > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function listTables(): ?array {
|
||||||
|
$tableSchema = $this->connectionData->getProperty("database");
|
||||||
|
$res = $this->select("TABLE_NAME")
|
||||||
|
->from("information_schema.TABLES")
|
||||||
|
->where(new Compare("TABLE_SCHEMA", $tableSchema, "=", true))
|
||||||
|
->where(new CondLike(new Column("TABLE_TYPE"), "BASE TABLE"))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if ($res !== false) {
|
||||||
|
$tableNames = [];
|
||||||
|
|
||||||
|
foreach ($res as $row) {
|
||||||
|
$tableNames[] = $row["TABLE_NAME"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tableNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RowIteratorMySQL extends RowIterator {
|
class RowIteratorMySQL extends RowIterator {
|
||||||
|
@ -334,7 +334,10 @@ class PostgreSQL extends SQL {
|
|||||||
list ($name, $alias) = $parts;
|
list ($name, $alias) = $parts;
|
||||||
return "\"$name\" $alias";
|
return "\"$name\" $alias";
|
||||||
} else {
|
} else {
|
||||||
return "\"$table\"";
|
$parts = explode(".", $table);
|
||||||
|
return implode(".", array_map(function ($n) {
|
||||||
|
return "\"$n\"";
|
||||||
|
}, $parts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,6 +466,28 @@ class PostgreSQL extends SQL {
|
|||||||
|
|
||||||
return $res && $res[0]["count"] > 0;
|
return $res && $res[0]["count"] > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function listTables(): ?array {
|
||||||
|
$tableSchema = $this->connectionData->getProperty("database");
|
||||||
|
$res = $this->select("tablename")
|
||||||
|
->from("pg_tables")
|
||||||
|
->where(new Compare("schemaname", $tableSchema))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if ($res !== false) {
|
||||||
|
$tableNames = [];
|
||||||
|
|
||||||
|
foreach ($res as $row) {
|
||||||
|
$tableNames[] = $row["tablename"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tableNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RowIteratorPostgreSQL extends RowIterator {
|
class RowIteratorPostgreSQL extends RowIterator {
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace Core\Driver\SQL\Query;
|
namespace Core\Driver\SQL\Query;
|
||||||
|
|
||||||
|
use Core\Driver\SQL\MySQL;
|
||||||
|
use Core\Driver\SQL\PostgreSQL;
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class CreateTrigger extends Query {
|
class CreateTrigger extends Query {
|
||||||
|
|
||||||
@ -11,6 +14,9 @@ class CreateTrigger extends Query {
|
|||||||
private string $event;
|
private string $event;
|
||||||
private string $tableName;
|
private string $tableName;
|
||||||
private array $parameters;
|
private array $parameters;
|
||||||
|
|
||||||
|
private bool $ifNotExist;
|
||||||
|
|
||||||
private ?CreateProcedure $procedure;
|
private ?CreateProcedure $procedure;
|
||||||
|
|
||||||
public function __construct(SQL $sql, string $triggerName) {
|
public function __construct(SQL $sql, string $triggerName) {
|
||||||
@ -21,6 +27,7 @@ class CreateTrigger extends Query {
|
|||||||
$this->event = "";
|
$this->event = "";
|
||||||
$this->parameters = [];
|
$this->parameters = [];
|
||||||
$this->procedure = null;
|
$this->procedure = null;
|
||||||
|
$this->ifNotExist = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function before(): CreateTrigger {
|
public function before(): CreateTrigger {
|
||||||
@ -28,6 +35,11 @@ class CreateTrigger extends Query {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onlyIfNotExist(): CreateTrigger {
|
||||||
|
$this->ifNotExist = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function after(): CreateTrigger {
|
public function after(): CreateTrigger {
|
||||||
$this->time = "AFTER";
|
$this->time = "AFTER";
|
||||||
return $this;
|
return $this;
|
||||||
@ -70,7 +82,20 @@ class CreateTrigger extends Query {
|
|||||||
$tableName = $this->sql->tableName($this->getTable());
|
$tableName = $this->sql->tableName($this->getTable());
|
||||||
|
|
||||||
$params = array();
|
$params = array();
|
||||||
$query = "CREATE TRIGGER $name $time $event ON $tableName FOR EACH ROW ";
|
|
||||||
|
if ($this->sql instanceof MySQL) {
|
||||||
|
$query = "CREATE TRIGGER";
|
||||||
|
if ($this->ifNotExist) {
|
||||||
|
$query .= " IF NOT EXISTS";
|
||||||
|
}
|
||||||
|
} else if ($this->sql instanceof PostgreSQL) {
|
||||||
|
$ifNotExists = $this->ifNotExist ? " OR REPLACE" : "";
|
||||||
|
$query = "CREATE$ifNotExists TRIGGER";
|
||||||
|
} else {
|
||||||
|
throw new Exception("CreateTrigger Not implemented for driver type: " . get_class($this->sql));
|
||||||
|
}
|
||||||
|
|
||||||
|
$query .= " $name $time $event ON $tableName FOR EACH ROW ";
|
||||||
$triggerBody = $this->sql->createTriggerBody($this, $this->parameters);
|
$triggerBody = $this->sql->createTriggerBody($this, $this->parameters);
|
||||||
if ($triggerBody === null) {
|
if ($triggerBody === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -130,6 +130,8 @@ abstract class SQL {
|
|||||||
// Schema
|
// Schema
|
||||||
public abstract function tableExists(string $tableName): bool;
|
public abstract function tableExists(string $tableName): bool;
|
||||||
|
|
||||||
|
public abstract function listTables(): ?array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Query $query
|
* @param Query $query
|
||||||
* @param int $fetchType
|
* @param int $fetchType
|
||||||
|
@ -125,11 +125,15 @@ class Context {
|
|||||||
|
|
||||||
public function parseCookies(): void {
|
public function parseCookies(): void {
|
||||||
|
|
||||||
if ($this->sql) {
|
$settings = $this->getSettings();
|
||||||
|
if (!$settings->isInstalled()) {
|
||||||
|
// we cannot process user sessions or localization yet.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_COOKIE['session']) && is_string($_COOKIE['session']) && !empty($_COOKIE['session'])) {
|
if (isset($_COOKIE['session']) && is_string($_COOKIE['session']) && !empty($_COOKIE['session'])) {
|
||||||
$this->loadSession($_COOKIE['session']);
|
$this->loadSession($_COOKIE['session']);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set language by priority: 1. GET parameter, 2. cookie, 3. user's settings, 4. accept-language header
|
// set language by priority: 1. GET parameter, 2. cookie, 3. user's settings, 4. accept-language header
|
||||||
if (isset($_GET['lang']) && is_string($_GET["lang"]) && !empty($_GET["lang"])) {
|
if (isset($_GET['lang']) && is_string($_GET["lang"]) && !empty($_GET["lang"])) {
|
||||||
|
@ -713,13 +713,13 @@ class DatabaseEntityHandler implements Persistable {
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCreateQueries(SQL $sql): array {
|
public function getCreateQueries(SQL $sql, bool $canExist = false): array {
|
||||||
|
|
||||||
$queries = [];
|
$queries = [];
|
||||||
$table = $this->getTableName();
|
$table = $this->getTableName();
|
||||||
|
|
||||||
// Create Table
|
// Create Table
|
||||||
$queries[] = $this->getTableQuery($sql);
|
$queries[] = $this->getTableQuery($sql, $canExist);
|
||||||
|
|
||||||
// pre defined values
|
// pre defined values
|
||||||
$getPredefinedValues = $this->entityClass->getMethod("getPredefinedValues");
|
$getPredefinedValues = $this->entityClass->getMethod("getPredefinedValues");
|
||||||
@ -733,43 +733,64 @@ class DatabaseEntityHandler implements Persistable {
|
|||||||
$entityLogConfig = $entityLogConfig->getValue();
|
$entityLogConfig = $entityLogConfig->getValue();
|
||||||
|
|
||||||
if (isset($entityLogConfig["insert"]) && $entityLogConfig["insert"] === true) {
|
if (isset($entityLogConfig["insert"]) && $entityLogConfig["insert"] === true) {
|
||||||
$queries[] = $sql->createTrigger("${table}_trg_insert")
|
$trigger = $sql->createTrigger("${table}_trg_insert")
|
||||||
->after()->insert($table)
|
->after()->insert($table)
|
||||||
->exec(new CreateProcedure($sql, "InsertEntityLog"), [
|
->exec(new CreateProcedure($sql, "InsertEntityLog"), [
|
||||||
"tableName" => new CurrentTable(),
|
"tableName" => new CurrentTable(),
|
||||||
"entityId" => new CurrentColumn("id"),
|
"entityId" => new CurrentColumn("id"),
|
||||||
"lifetime" => $entityLogConfig["lifetime"] ?? 90,
|
"lifetime" => $entityLogConfig["lifetime"] ?? 90,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($canExist) {
|
||||||
|
$trigger->onlyIfNotExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
$queries[] = $trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($entityLogConfig["update"]) && $entityLogConfig["update"] === true) {
|
if (isset($entityLogConfig["update"]) && $entityLogConfig["update"] === true) {
|
||||||
$queries[] = $sql->createTrigger("${table}_trg_update")
|
$trigger = $sql->createTrigger("${table}_trg_update")
|
||||||
->after()->update($table)
|
->after()->update($table)
|
||||||
->exec(new CreateProcedure($sql, "UpdateEntityLog"), [
|
->exec(new CreateProcedure($sql, "UpdateEntityLog"), [
|
||||||
"tableName" => new CurrentTable(),
|
"tableName" => new CurrentTable(),
|
||||||
"entityId" => new CurrentColumn("id"),
|
"entityId" => new CurrentColumn("id"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($canExist) {
|
||||||
|
$trigger->onlyIfNotExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
$queries[] = $trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($entityLogConfig["delete"]) && $entityLogConfig["delete"] === true) {
|
if (isset($entityLogConfig["delete"]) && $entityLogConfig["delete"] === true) {
|
||||||
$queries[] = $sql->createTrigger("${table}_trg_delete")
|
$trigger = $sql->createTrigger("${table}_trg_delete")
|
||||||
->after()->delete($table)
|
->after()->delete($table)
|
||||||
->exec(new CreateProcedure($sql, "DeleteEntityLog"), [
|
->exec(new CreateProcedure($sql, "DeleteEntityLog"), [
|
||||||
"tableName" => new CurrentTable(),
|
"tableName" => new CurrentTable(),
|
||||||
"entityId" => new CurrentColumn("id"),
|
"entityId" => new CurrentColumn("id"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($canExist) {
|
||||||
|
$trigger->onlyIfNotExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
$queries[] = $trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $queries;
|
return $queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTableQuery(SQL $sql): CreateTable {
|
public function getTableQuery(SQL $sql, bool $canExist = false): CreateTable {
|
||||||
$query = $sql->createTable($this->tableName)
|
$query = $sql->createTable($this->tableName)
|
||||||
->onlyIfNotExists()
|
|
||||||
->addSerial("id")
|
->addSerial("id")
|
||||||
->primaryKey("id");
|
->primaryKey("id");
|
||||||
|
|
||||||
|
if ($canExist) {
|
||||||
|
$query->onlyIfNotExists();
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->columns as $column) {
|
foreach ($this->columns as $column) {
|
||||||
$query->addColumn($column);
|
$query->addColumn($column);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ if (is_file($autoLoad)) {
|
|||||||
require_once $autoLoad;
|
require_once $autoLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WEBBASE_VERSION = "2.4.3";
|
const WEBBASE_VERSION = "2.4.4";
|
||||||
|
|
||||||
spl_autoload_extensions(".php");
|
spl_autoload_extensions(".php");
|
||||||
spl_autoload_register(function ($class) {
|
spl_autoload_register(function ($class) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
use Core\API\Parameter\Parameter;
|
use Core\API\Parameter\Parameter;
|
||||||
use Core\Driver\SQL\Query\CreateTable;
|
use Core\Driver\SQL\Query\CreateTable;
|
||||||
use Core\Driver\SQL\SQL;
|
use Core\Driver\SQL\SQL;
|
||||||
@ -100,6 +102,28 @@ class DatabaseEntityTest extends \PHPUnit\Framework\TestCase {
|
|||||||
public function testDropTable() {
|
public function testDropTable() {
|
||||||
$this->assertTrue(self::$SQL->drop(self::$HANDLER->getTableName())->execute());
|
$this->assertTrue(self::$SQL->drop(self::$HANDLER->getTableName())->execute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTableNames() {
|
||||||
|
$sql = self::$SQL;
|
||||||
|
$this->assertEquals("TestEntity", TestEntity::getHandler($sql, null, true)->getTableName());
|
||||||
|
$this->assertEquals("TestEntityInherit", TestEntityInherit::getHandler($sql, null, true)->getTableName());
|
||||||
|
$this->assertEquals("TestEntityInherit", OverrideNameSpace\TestEntityInherit::getHandler($sql, null, true)->getTableName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateQueries() {
|
||||||
|
$queries = [];
|
||||||
|
$entities = [TestEntity::class, TestEntityInherit::class, OverrideNameSpace\TestEntityInherit::class];
|
||||||
|
\Core\Configuration\CreateDatabase::createEntityQueries(self::$SQL, $entities, $queries);
|
||||||
|
$this->assertCount(2, $queries);
|
||||||
|
|
||||||
|
$tables = [];
|
||||||
|
foreach ($queries as $query) {
|
||||||
|
$this->assertInstanceOf(CreateTable::class, $query);
|
||||||
|
$tables[] = $query->getTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals(["TestEntity", "TestEntityInherit"], $tables);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestEntity extends DatabaseEntity {
|
class TestEntity extends DatabaseEntity {
|
||||||
@ -110,3 +134,15 @@ class TestEntity extends DatabaseEntity {
|
|||||||
public \DateTime $e;
|
public \DateTime $e;
|
||||||
public ?int $f;
|
public ?int $f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestEntityInherit extends DatabaseEntity {
|
||||||
|
public TestEntity $rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace OverrideNameSpace {
|
||||||
|
class TestEntityInherit extends \TestEntityInherit {
|
||||||
|
public int $new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user