Compare commits
2 commits
cc3eca1dc5
...
cf7633ae87
Author | SHA1 | Date | |
---|---|---|---|
cf7633ae87 | |||
|
35a3d018f1 |
12 changed files with 457 additions and 46 deletions
|
@ -45,8 +45,8 @@ class Tools {
|
||||||
|
|
||||||
# Asserting PDO::SQLite or PDO::MySQL
|
# Asserting PDO::SQLite or PDO::MySQL
|
||||||
$aPDODrivers = \PDO::getAvailableDrivers();
|
$aPDODrivers = \PDO::getAvailableDrivers();
|
||||||
if (!in_array('sqlite', $aPDODrivers, true) && !in_array('mysql', $aPDODrivers, true)) {
|
if (!in_array('sqlite', $aPDODrivers, true) && !in_array('mysql', $aPDODrivers, true) && !in_array('pgsql', $aPDODrivers, true)) {
|
||||||
exit('<strong>Baikal Fatal Error</strong>: Both <strong>PDO::sqlite</strong> and <strong>PDO::mysql</strong> are unavailable. One of them at least is required by Baikal.');
|
exit('<strong>Baikal Fatal Error</strong>: None of <strong>PDO::sqlite</strong>, <strong>PDO::mysql</strong> or <strong>PDO::pgsql</strong> are available. One of them at least is required by Baikal.');
|
||||||
}
|
}
|
||||||
|
|
||||||
# Assert that the temp folder is writable
|
# Assert that the temp folder is writable
|
||||||
|
|
|
@ -244,7 +244,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
||||||
|
|
||||||
function hasInstances() {
|
function hasInstances() {
|
||||||
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
||||||
"count(*)",
|
"count(*) as count",
|
||||||
"calendarinstances",
|
"calendarinstances",
|
||||||
"calendarid='" . $this->aData["calendarid"] . "'"
|
"calendarid='" . $this->aData["calendarid"] . "'"
|
||||||
);
|
);
|
||||||
|
@ -254,7 +254,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
||||||
} else {
|
} else {
|
||||||
reset($aRs);
|
reset($aRs);
|
||||||
|
|
||||||
return $aRs["count(*)"] > 1;
|
return $aRs["count"] > 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
||||||
|
|
||||||
function hasInstances() {
|
function hasInstances() {
|
||||||
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
||||||
"count(*)",
|
"count(*) as count",
|
||||||
"calendarinstances",
|
"calendarinstances",
|
||||||
"calendarid='" . $this->aData["id"] . "'"
|
"calendarid='" . $this->aData["id"] . "'"
|
||||||
);
|
);
|
||||||
|
@ -48,7 +48,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
||||||
} else {
|
} else {
|
||||||
reset($aRs);
|
reset($aRs);
|
||||||
|
|
||||||
return $aRs["count(*)"] > 1;
|
return $aRs["count"] > 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,16 @@ class Database extends \Baikal\Model\Config {
|
||||||
# Default values
|
# Default values
|
||||||
protected $aData = [
|
protected $aData = [
|
||||||
"sqlite_file" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
|
"sqlite_file" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
|
||||||
"mysql" => false,
|
"backend" => "",
|
||||||
"mysql_host" => "",
|
"mysql_host" => "",
|
||||||
"mysql_dbname" => "",
|
"mysql_dbname" => "",
|
||||||
"mysql_username" => "",
|
"mysql_username" => "",
|
||||||
"mysql_password" => "",
|
"mysql_password" => "",
|
||||||
"encryption_key" => "",
|
"encryption_key" => "",
|
||||||
|
"pgsql_host" => "",
|
||||||
|
"pgsql_dbname" => "",
|
||||||
|
"pgsql_username" => "",
|
||||||
|
"pgsql_password" => "",
|
||||||
];
|
];
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
|
@ -46,6 +50,14 @@ class Database extends \Baikal\Model\Config {
|
||||||
function formMorphologyForThisModelInstance() {
|
function formMorphologyForThisModelInstance() {
|
||||||
$oMorpho = new \Formal\Form\Morphology();
|
$oMorpho = new \Formal\Form\Morphology();
|
||||||
|
|
||||||
|
$oMorpho->add(new \Formal\Element\Listbox([
|
||||||
|
"prop" => "backend",
|
||||||
|
"label" => "Database Backend",
|
||||||
|
"validation" => "required",
|
||||||
|
"options" => ['sqlite', 'mysql', 'pgsql'],
|
||||||
|
"refreshonchange" => true,
|
||||||
|
]));
|
||||||
|
|
||||||
$oMorpho->add(new \Formal\Element\Text([
|
$oMorpho->add(new \Formal\Element\Text([
|
||||||
"prop" => "sqlite_file",
|
"prop" => "sqlite_file",
|
||||||
"label" => "SQLite file path",
|
"label" => "SQLite file path",
|
||||||
|
@ -54,13 +66,6 @@ class Database extends \Baikal\Model\Config {
|
||||||
"help" => "The absolute server path to the SQLite file",
|
"help" => "The absolute server path to the SQLite file",
|
||||||
]));
|
]));
|
||||||
|
|
||||||
$oMorpho->add(new \Formal\Element\Checkbox([
|
|
||||||
"prop" => "mysql",
|
|
||||||
"label" => "Use MySQL",
|
|
||||||
"help" => "If checked, Baïkal will use MySQL instead of SQLite.",
|
|
||||||
"refreshonchange" => true,
|
|
||||||
]));
|
|
||||||
|
|
||||||
$oMorpho->add(new \Formal\Element\Text([
|
$oMorpho->add(new \Formal\Element\Text([
|
||||||
"prop" => "mysql_host",
|
"prop" => "mysql_host",
|
||||||
"label" => "MySQL host",
|
"label" => "MySQL host",
|
||||||
|
@ -82,6 +87,27 @@ class Database extends \Baikal\Model\Config {
|
||||||
"label" => "MySQL password",
|
"label" => "MySQL password",
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
$oMorpho->add(new \Formal\Element\Text([
|
||||||
|
"prop" => "pgsql_host",
|
||||||
|
"label" => "PostgreSQL host",
|
||||||
|
"help" => "Host ip or name, including <strong>':portnumber'</strong> if port is not the default one (?)",
|
||||||
|
]));
|
||||||
|
|
||||||
|
$oMorpho->add(new \Formal\Element\Text([
|
||||||
|
"prop" => "pgsql_dbname",
|
||||||
|
"label" => "PostgreSQL database name",
|
||||||
|
]));
|
||||||
|
|
||||||
|
$oMorpho->add(new \Formal\Element\Text([
|
||||||
|
"prop" => "pgsql_username",
|
||||||
|
"label" => "PostgreSQL username",
|
||||||
|
]));
|
||||||
|
|
||||||
|
$oMorpho->add(new \Formal\Element\Password([
|
||||||
|
"prop" => "pgsql_password",
|
||||||
|
"label" => "PostgreSQL password",
|
||||||
|
]));
|
||||||
|
|
||||||
return $oMorpho;
|
return $oMorpho;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,18 +38,22 @@ class Database extends \Flake\Core\Controller {
|
||||||
if (file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
|
if (file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
|
||||||
require_once PROJECT_PATH_SPECIFIC . "config.system.php";
|
require_once PROJECT_PATH_SPECIFIC . "config.system.php";
|
||||||
$this->oModel->set('sqlite_file', PROJECT_SQLITE_FILE);
|
$this->oModel->set('sqlite_file', PROJECT_SQLITE_FILE);
|
||||||
$this->oModel->set('mysql', PROJECT_DB_MYSQL);
|
$this->oModel->set('backend', PROJECT_DB_BACKEND);
|
||||||
$this->oModel->set('mysql_host', PROJECT_DB_MYSQL_HOST);
|
$this->oModel->set('mysql_host', PROJECT_DB_MYSQL_HOST);
|
||||||
$this->oModel->set('mysql_dbname', PROJECT_DB_MYSQL_DBNAME);
|
$this->oModel->set('mysql_dbname', PROJECT_DB_MYSQL_DBNAME);
|
||||||
$this->oModel->set('mysql_username', PROJECT_DB_MYSQL_USERNAME);
|
$this->oModel->set('mysql_username', PROJECT_DB_MYSQL_USERNAME);
|
||||||
$this->oModel->set('mysql_password', PROJECT_DB_MYSQL_PASSWORD);
|
$this->oModel->set('mysql_password', PROJECT_DB_MYSQL_PASSWORD);
|
||||||
|
$this->oModel->set('pgsql_host', PROJECT_DB_PGSQL_HOST);
|
||||||
|
$this->oModel->set('pgsql_dbname', PROJECT_DB_PGSQL_DBNAME);
|
||||||
|
$this->oModel->set('pgsql_username', PROJECT_DB_PGSQL_USERNAME);
|
||||||
|
$this->oModel->set('pgsql_password', PROJECT_DB_PGSQL_PASSWORD);
|
||||||
$this->oModel->set('encryption_key', BAIKAL_ENCRYPTION_KEY);
|
$this->oModel->set('encryption_key', BAIKAL_ENCRYPTION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->oForm = $this->oModel->formForThisModelInstance([
|
$this->oForm = $this->oModel->formForThisModelInstance([
|
||||||
"close" => false,
|
"close" => false,
|
||||||
"hook.validation" => [$this, "validateConnection"],
|
"hook.validation" => [$this, "validateSQLConnection"],
|
||||||
"hook.morphology" => [$this, "hideMySQLFieldWhenNeeded"],
|
"hook.morphology" => [$this, "hideSQLFieldWhenNeeded"],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($this->oForm->submitted()) {
|
if ($this->oForm->submitted()) {
|
||||||
|
@ -99,11 +103,11 @@ class Database extends \Flake\Core\Controller {
|
||||||
return $oView->render();
|
return $oView->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateConnection($oForm, $oMorpho) {
|
function validateMySQLConnection($oForm, $oMorpho) {
|
||||||
if ($oForm->refreshed()) {
|
if ($oForm->refreshed()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$bMySQLEnabled = $oMorpho->element("mysql")->value();
|
$bMySQLEnabled = $oMorpho->element("backend")->value() == 'mysql';
|
||||||
|
|
||||||
if ($bMySQLEnabled) {
|
if ($bMySQLEnabled) {
|
||||||
$sHost = $oMorpho->element("mysql_host")->value();
|
$sHost = $oMorpho->element("mysql_host")->value();
|
||||||
|
@ -129,7 +133,7 @@ class Database extends \Flake\Core\Controller {
|
||||||
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
|
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
|
||||||
|
|
||||||
$oForm->declareError(
|
$oForm->declareError(
|
||||||
$oMorpho->element("mysql"),
|
$oMorpho->element("backend"),
|
||||||
$sMessage
|
$sMessage
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,7 +146,7 @@ class Database extends \Flake\Core\Controller {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$oForm->declareError($oMorpho->element("mysql"),
|
$oForm->declareError($oMorpho->element("backend"),
|
||||||
"Baïkal was not able to establish a connexion to the MySQL database as configured.<br />MySQL says: " . $e->getMessage());
|
"Baïkal was not able to establish a connexion to the MySQL database as configured.<br />MySQL says: " . $e->getMessage());
|
||||||
$oForm->declareError($oMorpho->element("mysql_host"));
|
$oForm->declareError($oMorpho->element("mysql_host"));
|
||||||
$oForm->declareError($oMorpho->element("mysql_dbname"));
|
$oForm->declareError($oMorpho->element("mysql_dbname"));
|
||||||
|
@ -211,10 +215,10 @@ class Database extends \Flake\Core\Controller {
|
||||||
|
|
||||||
function hideMySQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
function hideMySQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||||
if ($oForm->submitted()) {
|
if ($oForm->submitted()) {
|
||||||
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
|
$bMySQL = ($oForm->postValue("backend") == 'mysql');
|
||||||
} else {
|
} else {
|
||||||
// oMorpho won't have the values from the model set on it yet
|
// oMorpho won't have the values from the model set on it yet
|
||||||
$bMySQL = $this->oModel->get("mysql");
|
$bMySQL = $this->oModel->get("backend") == 'mysql';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bMySQL === true) {
|
if ($bMySQL === true) {
|
||||||
|
@ -226,4 +230,103 @@ class Database extends \Flake\Core\Controller {
|
||||||
$oMorpho->remove("mysql_password");
|
$oMorpho->remove("mysql_password");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validatePgSQLConnection($oForm, $oMorpho) {
|
||||||
|
$bPgSqlEnabled = $oMorpho->element("backend")->value() == 'pgsql';
|
||||||
|
|
||||||
|
if ($bPgSqlEnabled) {
|
||||||
|
$sHost = $oMorpho->element("pgsql_host")->value();
|
||||||
|
$sDbname = $oMorpho->element("pgsql_dbname")->value();
|
||||||
|
$sUsername = $oMorpho->element("pgsql_username")->value();
|
||||||
|
$sPassword = $oMorpho->element("pgsql_password")->value();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$oDb = new \Flake\Core\Database\Pgsql(
|
||||||
|
$sHost,
|
||||||
|
$sDbname,
|
||||||
|
$sUsername,
|
||||||
|
$sPassword
|
||||||
|
);
|
||||||
|
|
||||||
|
if (($aMissingTables = \Baikal\Core\Tools::isDBStructurallyComplete($oDb)) !== true) {
|
||||||
|
# Checking if all tables are missing
|
||||||
|
$aRequiredTables = \Baikal\Core\Tools::getRequiredTablesList();
|
||||||
|
if (count($aRequiredTables) !== count($aMissingTables)) {
|
||||||
|
$sMessage = "<br /><p><strong>Database is not structurally complete.</strong></p>";
|
||||||
|
$sMessage .= "<p>Missing tables are: <strong>" . implode("</strong>, <strong>", $aMissingTables) . "</strong></p>";
|
||||||
|
$sMessage .= "<p>You will find the SQL definition of Baïkal tables in this file: <strong>Core/Resources/Db/PgSQL/db.sql</strong></p>";
|
||||||
|
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
|
||||||
|
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("backend"),
|
||||||
|
$sMessage
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
# All tables are missing
|
||||||
|
# We add these tables ourselves to the database, to initialize Baïkal
|
||||||
|
$sSqlDefinition = file_get_contents(PROJECT_PATH_CORERESOURCES . "Db/PgSQL/db.sql");
|
||||||
|
$oDb->getPDO()->exec($sSqlDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("backend"),
|
||||||
|
"Baïkal was not able to establish a connexion to the PostgreSQL database as configured.<br />PostgreSQL says: " . $e->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("pgsql_host")
|
||||||
|
);
|
||||||
|
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("pgsql_dbname")
|
||||||
|
);
|
||||||
|
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("pgsql_username")
|
||||||
|
);
|
||||||
|
|
||||||
|
$oForm->declareError(
|
||||||
|
$oMorpho->element("pgsql_password")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateSQLConnection($oForm, $oMorpho) {
|
||||||
|
if ($oMorpho->element("backend")->value() == 'mysql') {
|
||||||
|
$this->validateMySQLConnection($oForm, $oMorpho);
|
||||||
|
} elseif ($oMorpho->element("backend")->value() == 'pgsql') {
|
||||||
|
$this->validatePgSQLConnection($oForm, $oMorpho);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hideSqlFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||||
|
if ($oMorpho->element("backend")->value() == 'mysql') {
|
||||||
|
$this->hideMySQLFieldWhenNeeded($oForm, $oMorpho);
|
||||||
|
} elseif ($oMorpho->element("backend")->value() == 'pgsql') {
|
||||||
|
$this->hidePgSQLFieldWhenNeeded($oForm, $oMorpho);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hidePgSQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||||
|
if ($oForm->submitted()) {
|
||||||
|
$bPgSQL = ($oForm->postValue("backend")) == 'pgsql';
|
||||||
|
} else {
|
||||||
|
// oMorpho won't have the values from the model set on it yet
|
||||||
|
$bPgSQL = $this->oModel->get("backend") == 'pgsql';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($bPgSQL === true) {
|
||||||
|
$oMorpho->remove("sqlite_file");
|
||||||
|
$this->hideMySQLFieldWhenNeeded($oForm, $oMorpho);
|
||||||
|
} else {
|
||||||
|
$oMorpho->remove("pgsql_host");
|
||||||
|
$oMorpho->remove("pgsql_dbname");
|
||||||
|
$oMorpho->remove("pgsql_username");
|
||||||
|
$oMorpho->remove("pgsql_password");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,12 @@ class Initialize extends \Flake\Core\Controller {
|
||||||
|
|
||||||
# Default: PDO::SQLite or PDO::MySQL ?
|
# Default: PDO::SQLite or PDO::MySQL ?
|
||||||
$aPDODrivers = \PDO::getAvailableDrivers();
|
$aPDODrivers = \PDO::getAvailableDrivers();
|
||||||
if (!in_array('sqlite', $aPDODrivers)) { # PDO::MySQL is already asserted in \Baikal\Core\Tools::assertEnvironmentIsOk()
|
if (in_array('sqlite', $aPDODrivers)) { # PDO::MySQL is already asserted in \Baikal\Core\Tools::assertEnvironmentIsOk()
|
||||||
$oDatabaseConfig->set("mysql", true);
|
$oDatabaseConfig->set("backend", 'sqlite');
|
||||||
|
} elseif (in_array('mysql', $aPDODrivers)) {
|
||||||
|
$oDatabaseConfig->set("backend", 'mysql');
|
||||||
|
} else {
|
||||||
|
$oDatabaseConfig->set("backend", 'pgsql');
|
||||||
}
|
}
|
||||||
|
|
||||||
$oDatabaseConfig->persist();
|
$oDatabaseConfig->persist();
|
||||||
|
|
|
@ -505,6 +505,14 @@ SQL
|
||||||
$this->aSuccess[] = 'Updated default values in calendarinstances table';
|
$this->aSuccess[] = 'Updated default values in calendarinstances table';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version_compare($sVersionFrom, '0.10.0', '<')) {
|
||||||
|
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
|
||||||
|
|
||||||
|
$oConfig = new \Baikal\Model\Config\Database();
|
||||||
|
$oConfig->set("backend", intval($config['database']['mysql']) === 1 ? 'mysql' : 'sqlite');
|
||||||
|
$oConfig->persist();
|
||||||
|
}
|
||||||
|
|
||||||
$this->updateConfiguredVersion($sVersionTo);
|
$this->updateConfiguredVersion($sVersionTo);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -74,61 +74,81 @@ class Database extends \Flake\Core\Controller {
|
||||||
|
|
||||||
function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||||
if ($oForm->submitted()) {
|
if ($oForm->submitted()) {
|
||||||
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
|
$bMySQL = ($oForm->postValue("backend") == 'mysql');
|
||||||
|
$bPgSQL = ($oForm->postValue("backend") == 'pgsql');
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
|
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
|
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
$bMySQL = $config['database']['mysql'] ?? true;
|
$bMySQL = $config['database']['backend'] == 'mysql';
|
||||||
|
$bPgSQL = $config['database']['backend'] == 'pgsql';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bMySQL === true) {
|
if ($bMySQL === true || $bPgSQL === true) {
|
||||||
$oMorpho->remove("sqlite_file");
|
$oMorpho->remove("sqlite_file");
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!$bMySQL) {
|
||||||
$oMorpho->remove("mysql_host");
|
$oMorpho->remove("mysql_host");
|
||||||
$oMorpho->remove("mysql_dbname");
|
$oMorpho->remove("mysql_dbname");
|
||||||
$oMorpho->remove("mysql_username");
|
$oMorpho->remove("mysql_username");
|
||||||
$oMorpho->remove("mysql_password");
|
$oMorpho->remove("mysql_password");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$bPgSQL) {
|
||||||
|
$oMorpho->remove("pgsql_host");
|
||||||
|
$oMorpho->remove("pgsql_dbname");
|
||||||
|
$oMorpho->remove("pgsql_username");
|
||||||
|
$oMorpho->remove("pgsql_password");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validationHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
function validationHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||||
if ($oForm->refreshed()) {
|
if ($oForm->refreshed()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (intval($oForm->modelInstance()->get("mysql")) === 1) {
|
if ($oForm->modelInstance()->get("backend") == 'mysql' || $oForm->modelInstance()->get("backend") == 'pgsql') {
|
||||||
# We have to check the MySQL connection
|
$dbBackendName = $oForm->modelInstance()->get("backend") == 'pgsql' ? 'PostgreSQL' : 'MySQL';
|
||||||
$sHost = $oForm->modelInstance()->get("mysql_host");
|
$dbBackendPrefix = $oForm->modelInstance()->get("backend");
|
||||||
$sDbName = $oForm->modelInstance()->get("mysql_dbname");
|
|
||||||
$sUsername = $oForm->modelInstance()->get("mysql_username");
|
# We have to check the MySQL or PostgreSQL connection
|
||||||
$sPassword = $oForm->modelInstance()->get("mysql_password");
|
$sHost = $oForm->modelInstance()->get("{$dbBackendPrefix}_host");
|
||||||
|
$sDbName = $oForm->modelInstance()->get("{$dbBackendPrefix}_dbname");
|
||||||
|
$sUsername = $oForm->modelInstance()->get("{$dbBackendPrefix}_username");
|
||||||
|
$sPassword = $oForm->modelInstance()->get("{$dbBackendPrefix}_password");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$oDB = new \Flake\Core\Database\Mysql(
|
$oDB = (($oForm->modelInstance()->get("backend")) == 'pgsql'
|
||||||
|
) ? new \Flake\Core\Database\Pgsql(
|
||||||
|
$sHost,
|
||||||
|
$sDbName,
|
||||||
|
$sUsername,
|
||||||
|
$sPassword
|
||||||
|
) : new \Flake\Core\Database\Mysql(
|
||||||
$sHost,
|
$sHost,
|
||||||
$sDbName,
|
$sDbName,
|
||||||
$sUsername,
|
$sUsername,
|
||||||
$sPassword
|
$sPassword
|
||||||
);
|
);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$sMessage = "<strong>MySQL error:</strong> " . $e->getMessage();
|
$sMessage = "<strong>{$dbBackendName} error:</strong> " . $e->getMessage();
|
||||||
$sMessage .= "<br /><strong>Nothing has been saved</strong>";
|
$sMessage .= "<br /><strong>Nothing has been saved</strong>";
|
||||||
$oForm->declareError($oMorpho->element("mysql_host"), $sMessage);
|
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_host"), $sMessage);
|
||||||
$oForm->declareError($oMorpho->element("mysql_dbname"));
|
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_dbname"));
|
||||||
$oForm->declareError($oMorpho->element("mysql_username"));
|
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_username"));
|
||||||
$oForm->declareError($oMorpho->element("mysql_password"));
|
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_password"));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($aMissingTables = \Baikal\Core\Tools::isDBStructurallyComplete($oDB)) !== true) {
|
if (($aMissingTables = \Baikal\Core\Tools::isDBStructurallyComplete($oDB)) !== true) {
|
||||||
$sMessage = "<strong>MySQL error:</strong> These tables, required by Baïkal, are missing: <strong>" . implode(", ", $aMissingTables) . "</strong><br />";
|
$sMessage = "<strong>{$dbBackendName} error:</strong> These tables, required by Baïkal, are missing: <strong>" . implode(", ", $aMissingTables) . "</strong><br />";
|
||||||
$sMessage .= "You may want create these tables using the file <strong>Core/Resources/Db/MySQL/db.sql</strong>";
|
$sMessage .= "You may want create these tables using the file <strong>Core/Resources/Db/{$dbBackendName}/db.sql</strong>";
|
||||||
$sMessage .= "<br /><br /><strong>Nothing has been saved</strong>";
|
$sMessage .= "<br /><br /><strong>Nothing has been saved</strong>";
|
||||||
|
|
||||||
$oForm->declareError($oMorpho->element("mysql"), $sMessage);
|
$oForm->declareError($oMorpho->element("backend"), $sMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
68
Core/Frameworks/Flake/Core/Database/Pgsql.php
Normal file
68
Core/Frameworks/Flake/Core/Database/Pgsql.php
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Copyright notice
|
||||||
|
#
|
||||||
|
# (c) 2013 Kim Lidström <kim@dxtr.im>
|
||||||
|
# All rights reserved
|
||||||
|
#
|
||||||
|
# http://flake.codr.fr
|
||||||
|
#
|
||||||
|
# This script is part of the Flake project. The Flake
|
||||||
|
# project is free software; you can redistribute it
|
||||||
|
# and/or modify it under the terms of the GNU General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2 of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# The GNU General Public License can be found at
|
||||||
|
# http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
#
|
||||||
|
# This script is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# This copyright notice MUST APPEAR in all copies of the script!
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
namespace Flake\Core\Database;
|
||||||
|
|
||||||
|
class Pgsql extends \Flake\Core\Database {
|
||||||
|
protected $oDb = false; // current DB link
|
||||||
|
protected $debugOutput = false;
|
||||||
|
protected $store_lastBuiltQuery = true;
|
||||||
|
protected $debug_lastBuiltQuery = "";
|
||||||
|
protected $sHost = "";
|
||||||
|
protected $sDbName = "";
|
||||||
|
protected $sUsername = "";
|
||||||
|
protected $sPassword = "";
|
||||||
|
|
||||||
|
public function __construct($sHost, $sDbName, $sUsername, $sPassword) {
|
||||||
|
$this->sHost = $sHost;
|
||||||
|
$this->sDbName = $sDbName;
|
||||||
|
$this->sUsername = $sUsername;
|
||||||
|
$this->sPassword = $sPassword;
|
||||||
|
|
||||||
|
$this->oDb = new \PDO(
|
||||||
|
'pgsql:host=' . $this->sHost . ';dbname=' . $this->sDbName,
|
||||||
|
$this->sUsername,
|
||||||
|
$this->sPassword
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tables() {
|
||||||
|
$aTables = [];
|
||||||
|
|
||||||
|
$sSql = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public'";
|
||||||
|
$oStmt = $this->query($sSql);
|
||||||
|
|
||||||
|
while (($aRs = $oStmt->fetch()) !== false) {
|
||||||
|
$aTables[] = array_shift($aRs);
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($aTables);
|
||||||
|
reset($aTables);
|
||||||
|
|
||||||
|
return $aTables;
|
||||||
|
}
|
||||||
|
}
|
|
@ -273,8 +273,12 @@ class Framework extends \Flake\Core\Framework {
|
||||||
if (defined("BAIKAL_CONTEXT_INSTALL") && (!isset($config['system']['configured_version']) || $config['system']['configured_version'] === BAIKAL_VERSION)) {
|
if (defined("BAIKAL_CONTEXT_INSTALL") && (!isset($config['system']['configured_version']) || $config['system']['configured_version'] === BAIKAL_VERSION)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($config['database']['mysql'] === true) {
|
# Config key 'mysql' kept for backwards compatibility
|
||||||
|
$legacyMysql = key_exists('mysql', $config['database']) && $config['database']['mysql'] === true;
|
||||||
|
if ($legacyMysql || $config['database']['backend'] === 'mysql') {
|
||||||
self::initDbMysql($config);
|
self::initDbMysql($config);
|
||||||
|
} elseif ($config['database']['backend'] === 'pgsql') {
|
||||||
|
self::initDbPgsql($config);
|
||||||
} else {
|
} else {
|
||||||
self::initDbSqlite($config);
|
self::initDbSqlite($config);
|
||||||
}
|
}
|
||||||
|
@ -339,6 +343,38 @@ class Framework extends \Flake\Core\Framework {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function initDbPgsql(array $config) {
|
||||||
|
if (!$config['database']['pgsql_host']) {
|
||||||
|
exit("<h3>The constant PROJECT_DB_PGSQL_HOST, containing the PostgreSQL host name, is not set.<br />You should set it in config/baikal.yaml</h3>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$config['database']['pgsql_dbname']) {
|
||||||
|
exit("<h3>The constant PROJECT_DB_PGSQL_DBNAME, containing the PostgreSQL database name, is not set.<br />You should set it in config/baikal.yaml</h3>");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$GLOBALS["DB"] = new \Flake\Core\Database\Pgsql(
|
||||||
|
$config['database']['pgsql_host'],
|
||||||
|
$config['database']['pgsql_dbname'],
|
||||||
|
$config['database']['pgsql_username'],
|
||||||
|
$config['database']['pgsql_password']
|
||||||
|
);
|
||||||
|
|
||||||
|
$GLOBALS["DB"]->query("SET NAMES 'UTF8'");
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$message = "Baïkal was not able to establish a connection to the configured PostgreSQL database (as configured in config/baikal.yaml).";
|
||||||
|
if (!$config['database']['pgsql_username']) {
|
||||||
|
exit("<h3>$message Note: The constant PROJECT_DB_PGSQL_USERNAME, containing the PostgreSQL database username, is not set. If your database requires a username you should set it in config/baikal.yaml.</h3>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config['database']['pgsql_password'] === null) {
|
||||||
|
exit("<h3>$message Note: The constant PROJECT_DB_PGSQL_PASSWORD, containing the PostgreSQL database password, is not set. If your database requires a password you should set it in config/baikal.yaml.</h3>");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit("<h3>$message</h3>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static function isDBInitialized() {
|
static function isDBInitialized() {
|
||||||
return isset($GLOBALS["DB"]) && \Flake\Util\Tools::is_a($GLOBALS["DB"], "\Flake\Core\Database");
|
return isset($GLOBALS["DB"]) && \Flake\Util\Tools::is_a($GLOBALS["DB"], "\Flake\Core\Database");
|
||||||
}
|
}
|
||||||
|
|
142
Core/Resources/Db/PgSQL/db.sql
Normal file
142
Core/Resources/Db/PgSQL/db.sql
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
|
||||||
|
CREATE TABLE addressbooks (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
principaluri TEXT,
|
||||||
|
displayname VARCHAR(255),
|
||||||
|
uri TEXT,
|
||||||
|
description TEXT,
|
||||||
|
synctoken INT CHECK (synctoken > 0) NOT NULL DEFAULT '1'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE cards (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
addressbookid INT CHECK (addressbookid > 0) NOT NULL,
|
||||||
|
carddata TEXT,
|
||||||
|
uri TEXT,
|
||||||
|
lastmodified INT CHECK (lastmodified > 0),
|
||||||
|
etag TEXT,
|
||||||
|
size INT CHECK (size > 0) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE addressbookchanges (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uri TEXT NOT NULL,
|
||||||
|
synctoken INT CHECK (synctoken > 0) NOT NULL,
|
||||||
|
addressbookid INT CHECK (addressbookid > 0) NOT NULL,
|
||||||
|
operation SMALLINT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX addressbookid_synctoken ON addressbookchanges (addressbookid, synctoken);
|
||||||
|
|
||||||
|
CREATE TABLE calendarobjects (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
calendardata TEXT,
|
||||||
|
uri TEXT,
|
||||||
|
calendarid INTEGER CHECK (calendarid > 0) NOT NULL,
|
||||||
|
lastmodified INT CHECK (lastmodified > 0),
|
||||||
|
etag TEXT,
|
||||||
|
size INT CHECK (size > 0) NOT NULL,
|
||||||
|
componenttype TEXT,
|
||||||
|
firstoccurence INT CHECK (firstoccurence > 0),
|
||||||
|
lastoccurence INT CHECK (lastoccurence > 0),
|
||||||
|
uid TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE calendars (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
synctoken INTEGER CHECK (synctoken > 0) NOT NULL DEFAULT '1',
|
||||||
|
components TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE calendarinstances (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
calendarid INTEGER CHECK (calendarid > 0) NOT NULL,
|
||||||
|
principaluri TEXT,
|
||||||
|
access SMALLINT NOT NULL DEFAULT '1',
|
||||||
|
displayname VARCHAR(100),
|
||||||
|
uri TEXT,
|
||||||
|
description TEXT,
|
||||||
|
calendarorder INT CHECK (calendarorder >= 0) NOT NULL DEFAULT '0',
|
||||||
|
calendarcolor TEXT,
|
||||||
|
timezone TEXT,
|
||||||
|
transparent SMALLINT NOT NULL DEFAULT '0',
|
||||||
|
share_href TEXT,
|
||||||
|
share_displayname VARCHAR(100),
|
||||||
|
share_invitestatus SMALLINT NOT NULL DEFAULT '2'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE calendarchanges (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uri TEXT NOT NULL,
|
||||||
|
synctoken INT CHECK (synctoken > 0) NOT NULL,
|
||||||
|
calendarid INT CHECK (calendarid > 0) NOT NULL,
|
||||||
|
operation SMALLINT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX calendarid_synctoken ON calendarchanges (calendarid, synctoken);
|
||||||
|
|
||||||
|
CREATE TABLE calendarsubscriptions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uri TEXT NOT NULL,
|
||||||
|
principaluri TEXT NOT NULL,
|
||||||
|
source TEXT,
|
||||||
|
displayname VARCHAR(100),
|
||||||
|
refreshrate VARCHAR(10),
|
||||||
|
calendarorder INT CHECK (calendarorder >= 0) NOT NULL DEFAULT '0',
|
||||||
|
calendarcolor TEXT,
|
||||||
|
striptodos SMALLINT NULL,
|
||||||
|
stripalarms SMALLINT NULL,
|
||||||
|
stripattachments SMALLINT NULL,
|
||||||
|
lastmodified INT CHECK (lastmodified > 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE schedulingobjects (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
principaluri TEXT,
|
||||||
|
calendardata TEXT,
|
||||||
|
uri TEXT,
|
||||||
|
lastmodified INT CHECK (lastmodified > 0),
|
||||||
|
etag TEXT,
|
||||||
|
size INT CHECK (size > 0) NOT NULL
|
||||||
|
);
|
||||||
|
CREATE TABLE locks (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
owner VARCHAR(100),
|
||||||
|
timeout INTEGER CHECK (timeout > 0),
|
||||||
|
created INTEGER,
|
||||||
|
token TEXT,
|
||||||
|
scope SMALLINT,
|
||||||
|
depth SMALLINT,
|
||||||
|
uri TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ON locks (token);
|
||||||
|
CREATE INDEX ON locks (uri);
|
||||||
|
|
||||||
|
CREATE TABLE principals (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uri TEXT NOT NULL,
|
||||||
|
email TEXT,
|
||||||
|
displayname VARCHAR(80)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE groupmembers (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
principal_id INTEGER CHECK (principal_id > 0) NOT NULL,
|
||||||
|
member_id INTEGER CHECK (member_id > 0) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE propertystorage (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
valuetype INT CHECK (valuetype > 0),
|
||||||
|
value TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX path_property ON propertystorage (path, name);
|
||||||
|
CREATE TABLE users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username TEXT,
|
||||||
|
digesta1 TEXT
|
||||||
|
);
|
|
@ -11,9 +11,13 @@ system:
|
||||||
base_uri: ''
|
base_uri: ''
|
||||||
database:
|
database:
|
||||||
encryption_key: 5d3f0fa0192e3058ea70f1bb20924add
|
encryption_key: 5d3f0fa0192e3058ea70f1bb20924add
|
||||||
|
backend: 'mysql'
|
||||||
sqlite_file: "absolute/path/to/Specific/db/db.sqlite"
|
sqlite_file: "absolute/path/to/Specific/db/db.sqlite"
|
||||||
mysql: true
|
|
||||||
mysql_host: 'localhost'
|
mysql_host: 'localhost'
|
||||||
mysql_dbname: 'baikal'
|
mysql_dbname: 'baikal'
|
||||||
mysql_username: 'baikal'
|
mysql_username: 'baikal'
|
||||||
mysql_password: 'baikal'
|
mysql_password: 'baikal'
|
||||||
|
pgsql_host: 'localhost'
|
||||||
|
pgsql_dbname: 'baikal'
|
||||||
|
pgsql_username: 'baikal'
|
||||||
|
pgsql_password: 'baikal'
|
||||||
|
|
Loading…
Reference in a new issue