parent
b73dfe3624
commit
88859f3347
20 changed files with 523 additions and 98 deletions
|
@ -61,7 +61,7 @@ class Tools {
|
|||
|
||||
# Asserting DB file exists
|
||||
if(!file_exists(PROJECT_SQLITE_FILE)) {
|
||||
throw new \Exception("DB file does not exist. To create it, please copy 'Core/Resources/db.empty.sqlite' to '" . PROJECT_SQLITE_FILE . "'");
|
||||
throw new \Exception("DB file does not exist. To create it, please copy 'Core/Resources/Db/db.empty.sqlite' to '" . PROJECT_SQLITE_FILE . "'");
|
||||
}
|
||||
|
||||
# Asserting DB file is readable
|
||||
|
|
|
@ -202,7 +202,7 @@ abstract class Config extends \Flake\Core\Model\NoDb {
|
|||
|
||||
asort($aNewConfig);
|
||||
asort($aWrittenConfig);
|
||||
|
||||
|
||||
if($aNewConfig != $aWrittenConfig) {
|
||||
throw new \Exception("New config does not correspond to expected config. Aborting, nothing has been changed.");
|
||||
}
|
||||
|
|
|
@ -50,6 +50,21 @@ class System extends \Baikal\Model\Config {
|
|||
"PROJECT_SQLITE_FILE" => array(
|
||||
"type" => "litteral",
|
||||
),
|
||||
"PROJECT_DB_MYSQL" => array(
|
||||
"type" => "boolean",
|
||||
),
|
||||
"PROJECT_DB_MYSQL_HOST" => array(
|
||||
"type" => "string",
|
||||
),
|
||||
"PROJECT_DB_MYSQL_DBNAME" => array(
|
||||
"type" => "string",
|
||||
),
|
||||
"PROJECT_DB_MYSQL_USERNAME" => array(
|
||||
"type" => "string",
|
||||
),
|
||||
"PROJECT_DB_MYSQL_PASSWORD" => array(
|
||||
"type" => "string",
|
||||
),
|
||||
);
|
||||
|
||||
protected $aData = array(
|
||||
|
@ -60,6 +75,11 @@ class System extends \Baikal\Model\Config {
|
|||
"BAIKAL_STANDALONE_ALLOWED" => "",
|
||||
"BAIKAL_STANDALONE_PORT" => "",
|
||||
"PROJECT_SQLITE_FILE" => "",
|
||||
"PROJECT_DB_MYSQL" => "",
|
||||
"PROJECT_DB_MYSQL_HOST" => "",
|
||||
"PROJECT_DB_MYSQL_DBNAME" => "",
|
||||
"PROJECT_DB_MYSQL_USERNAME" => "",
|
||||
"PROJECT_DB_MYSQL_PASSWORD" => "",
|
||||
);
|
||||
|
||||
public function formMorphologyForThisModelInstance() {
|
||||
|
@ -130,7 +150,35 @@ class System extends \Baikal\Model\Config {
|
|||
"inputclass" => "input-xxlarge",
|
||||
"help" => "The absolute server path to the SQLite file",
|
||||
)));
|
||||
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Checkbox(array(
|
||||
"prop" => "PROJECT_DB_MYSQL",
|
||||
"label" => "Use MySQL",
|
||||
"help" => "If checked, Baïkal will use MySQL instead of SQLite.",
|
||||
"refreshonchange" => TRUE,
|
||||
)));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text(array(
|
||||
"prop" => "PROJECT_DB_MYSQL_HOST",
|
||||
"label" => "MySQL host",
|
||||
"help" => "Host ip or name, including ':portnumber' if port is not the default one (3306)"
|
||||
)));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text(array(
|
||||
"prop" => "PROJECT_DB_MYSQL_DBNAME",
|
||||
"label" => "MySQL database name",
|
||||
)));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text(array(
|
||||
"prop" => "PROJECT_DB_MYSQL_USERNAME",
|
||||
"label" => "MySQL username",
|
||||
)));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Password(array(
|
||||
"prop" => "PROJECT_DB_MYSQL_PASSWORD",
|
||||
"label" => "MySQL password",
|
||||
)));
|
||||
|
||||
return $oMorpho;
|
||||
}
|
||||
|
||||
|
|
|
@ -201,6 +201,21 @@ define("BAIKAL_CAL_BASEURI", PROJECT_BASEURI . "cal.php/");
|
|||
# Define path to Baïkal Database SQLite file
|
||||
define("PROJECT_SQLITE_FILE", PROJECT_PATH_SPECIFIC . "db/db.sqlite");
|
||||
|
||||
# Mysql > Use mysql instead of SQLite ?
|
||||
define("PROJECT_DB_MYSQL", FALSE);
|
||||
|
||||
# MySQL > Host, including ':portnumber' if port is not the default one (3306)
|
||||
define("PROJECT_DB_MYSQL_HOST", "");
|
||||
|
||||
# MySQL > Database name
|
||||
define("PROJECT_DB_MYSQL_DBNAME", "");
|
||||
|
||||
# MySQL > Username
|
||||
define("PROJECT_DB_MYSQL_USERNAME", "");
|
||||
|
||||
# MySQL > Password
|
||||
define("PROJECT_DB_MYSQL_PASSWORD", "");
|
||||
|
||||
CODE;
|
||||
$sCode = trim($sCode);
|
||||
return $sCode;
|
||||
|
|
|
@ -37,7 +37,9 @@ class System extends \Flake\Core\Controller {
|
|||
}
|
||||
|
||||
$this->oForm = $this->oModel->formForThisModelInstance(array(
|
||||
"close" => FALSE
|
||||
"close" => FALSE,
|
||||
"hook.morphology" => array($this, "morphologyHook"),
|
||||
"hook.validation" => array($this, "validationHook"),
|
||||
));
|
||||
|
||||
if($this->oForm->submitted()) {
|
||||
|
@ -58,4 +60,52 @@ class System extends \Flake\Core\Controller {
|
|||
|
||||
return $oView->render();
|
||||
}
|
||||
|
||||
public function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if($oForm->submitted()) {
|
||||
$bMySQL = (intval($oForm->postValue("PROJECT_DB_MYSQL")) === 1);
|
||||
} else {
|
||||
$bMySQL = PROJECT_DB_MYSQL;
|
||||
}
|
||||
|
||||
if($bMySQL === TRUE) {
|
||||
$oMorpho->remove("PROJECT_SQLITE_FILE");
|
||||
} else {
|
||||
|
||||
$oMorpho->remove("PROJECT_DB_MYSQL_HOST");
|
||||
$oMorpho->remove("PROJECT_DB_MYSQL_DBNAME");
|
||||
$oMorpho->remove("PROJECT_DB_MYSQL_USERNAME");
|
||||
$oMorpho->remove("PROJECT_DB_MYSQL_PASSWORD");
|
||||
}
|
||||
}
|
||||
|
||||
public function validationHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if(intval($oForm->modelInstance()->get("PROJECT_DB_MYSQL")) === 1) {
|
||||
|
||||
# We have to check the MySQL connection
|
||||
$sHost = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_HOST");
|
||||
$sDbName = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_DBNAME");
|
||||
$sUsername = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_USERNAME");
|
||||
$sPassword = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_PASSWORD");
|
||||
|
||||
try {
|
||||
$oDB = new \Flake\Core\Database\Mysql(
|
||||
$sHost,
|
||||
$sDbName,
|
||||
$sUsername,
|
||||
$sPassword
|
||||
);
|
||||
|
||||
unset($oDB);
|
||||
} catch(\Exception $e) {
|
||||
$sMessage = "<strong>MySQL error:</strong> " . $e->getMessage();
|
||||
$sMessage .= "<br /><strong>Nothing has been saved</strong>";
|
||||
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_HOST"), $sMessage);
|
||||
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_DBNAME"));
|
||||
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_USERNAME"));
|
||||
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_PASSWORD"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,13 +51,14 @@ class Collection extends \Flake\Core\FLObject implements \Iterator {
|
|||
return ($key !== NULL && $key !== FALSE);
|
||||
}
|
||||
|
||||
public function getForKey($sKey) {
|
||||
public function &getForKey($sKey) {
|
||||
$aKeys = $this->keys();
|
||||
if(!in_array($sKey, $aKeys)) {
|
||||
throw new \Exception("\Flake\Core\Collection->getForKey(): key '" . $sKey . "' not found in Collection");
|
||||
}
|
||||
|
||||
return $this->aCollection[$sKey];
|
||||
$oRes = $this->aCollection[$sKey];
|
||||
return $oRes;
|
||||
}
|
||||
|
||||
public function &each() {
|
||||
|
@ -155,6 +156,16 @@ class Collection extends \Flake\Core\FLObject implements \Iterator {
|
|||
return $oNewColl;
|
||||
}
|
||||
|
||||
public function remove($sKey) {
|
||||
$aKeys = $this->keys();
|
||||
if(!in_array($sKey, $aKeys)) {
|
||||
throw new \Exception("\Flake\Core\Collection->remove(): key '" . $sKey . "' not found in Collection");
|
||||
}
|
||||
|
||||
unset($this->aCollection[$sKey]);
|
||||
$this->aCollection = array_values($this->aCollection);
|
||||
}
|
||||
|
||||
public function &__call($sName, $aArguments) {
|
||||
if(
|
||||
strlen($sName) > 7 &&
|
||||
|
|
|
@ -30,16 +30,16 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
|
||||
/* common stuff */
|
||||
|
||||
function messageAndDie($sMessage) {
|
||||
protected function messageAndDie($sMessage) {
|
||||
$sError = "<h2>" . get_class($this) . ": " . $sMessage . "</h2>";
|
||||
die($sError);
|
||||
}
|
||||
|
||||
function exec_INSERTquery($table,$fields_values,$no_quote_fields=FALSE) {
|
||||
public function exec_INSERTquery($table,$fields_values,$no_quote_fields=FALSE) {
|
||||
return $this->query($this->INSERTquery($table,$fields_values,$no_quote_fields));
|
||||
}
|
||||
|
||||
function INSERTquery($table,$fields_values,$no_quote_fields=FALSE) {
|
||||
public function INSERTquery($table,$fields_values,$no_quote_fields=FALSE) {
|
||||
|
||||
// Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
|
||||
if (is_array($fields_values) && count($fields_values)) {
|
||||
|
@ -63,11 +63,11 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
}
|
||||
}
|
||||
|
||||
function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE) {
|
||||
public function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE) {
|
||||
return $this->query($this->UPDATEquery($table,$where,$fields_values,$no_quote_fields));
|
||||
}
|
||||
|
||||
function UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE) {
|
||||
public function UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE) {
|
||||
|
||||
// Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
|
||||
if (is_string($where)) {
|
||||
|
@ -99,11 +99,11 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
}
|
||||
}
|
||||
|
||||
function exec_DELETEquery($table,$where) {
|
||||
public function exec_DELETEquery($table,$where) {
|
||||
return $this->query($this->DELETEquery($table,$where));
|
||||
}
|
||||
|
||||
function DELETEquery($table,$where) {
|
||||
public function DELETEquery($table,$where) {
|
||||
if (is_string($where)) {
|
||||
|
||||
// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
|
||||
|
@ -119,11 +119,11 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
}
|
||||
}
|
||||
|
||||
function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') {
|
||||
public function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') {
|
||||
return $this->query($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit));
|
||||
}
|
||||
|
||||
function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') {
|
||||
public function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') {
|
||||
|
||||
// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
|
||||
// Build basic query:
|
||||
|
@ -154,11 +154,11 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
return $query;
|
||||
}
|
||||
|
||||
function fullQuote($str, $table) {
|
||||
public function fullQuote($str, $table) {
|
||||
return '\''.$this->quote($str, $table).'\'';
|
||||
}
|
||||
|
||||
function fullQuoteArray($arr, $table, $noQuote=FALSE) {
|
||||
public function fullQuoteArray($arr, $table, $noQuote=FALSE) {
|
||||
if (is_string($noQuote)) {
|
||||
$noQuote = explode(',',$noQuote);
|
||||
} elseif (!is_array($noQuote)) { // sanity check
|
||||
|
@ -173,11 +173,34 @@ abstract class Database extends \Flake\Core\FLObject {
|
|||
return $arr;
|
||||
}
|
||||
|
||||
/* fonctions abstraites */
|
||||
/* Should be abstract, but we provide a body anyway as PDO abstracts these methods for us */
|
||||
|
||||
abstract function query($sSql);
|
||||
public function query($sSql) {
|
||||
if(($stmt = $this->oDb->query($sSql)) === FALSE) {
|
||||
$sMessage = print_r($this->oDb->errorInfo(), TRUE);
|
||||
throw new \Exception("SQL ERROR in: '" . $sSql . "'; Message: " . $sMessage);
|
||||
}
|
||||
|
||||
return new \Flake\Core\Database\Statement($stmt);
|
||||
}
|
||||
|
||||
abstract function lastInsertId();
|
||||
public function lastInsertId() {
|
||||
return $this->oDb->lastInsertId();
|
||||
}
|
||||
|
||||
abstract function quote($str);
|
||||
public function quote($str) {
|
||||
return substr($this->oDb->quote($str), 1, -1); # stripping first and last quote
|
||||
}
|
||||
|
||||
public function getPDO() {
|
||||
return $this->oDb;
|
||||
}
|
||||
|
||||
public function close() {
|
||||
$this->oDb = null;
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
$this->close();
|
||||
}
|
||||
}
|
52
CoreVersions/0.2.1/Frameworks/Flake/Core/Database/Mysql.php
Normal file
52
CoreVersions/0.2.1/Frameworks/Flake/Core/Database/Mysql.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
#################################################################
|
||||
# Copyright notice
|
||||
#
|
||||
# (c) 2012 Jérôme Schneider <mail@jeromeschneider.fr>
|
||||
# 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 Mysql 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(
|
||||
'mysql:host=' . $this->sHost . ';dbname=' . $this->sDbName,
|
||||
$this->sUsername,
|
||||
$this->sPassword
|
||||
);
|
||||
}
|
||||
}
|
|
@ -37,44 +37,5 @@ class Sqlite extends \Flake\Core\Database {
|
|||
public function __construct($sDbPath) {
|
||||
$this->sDbPath = $sDbPath;
|
||||
$this->oDb = new \PDO('sqlite:' . $this->sDbPath);
|
||||
# $this->oDb->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
}
|
||||
|
||||
public function query($sSql) {
|
||||
if(($stmt = $this->oDb->query($sSql)) === FALSE) {
|
||||
$sMessage = print_r($this->oDb->errorInfo(), TRUE);
|
||||
throw new \Exception("SQL ERROR in: '" . $sSql . "'; Message: " . $sMessage);
|
||||
}
|
||||
|
||||
return new \Flake\Core\Database\SqliteStatement($stmt);
|
||||
}
|
||||
|
||||
public function lastInsertId() {
|
||||
return $this->oDb->lastInsertId();
|
||||
}
|
||||
|
||||
public function quote($str) {
|
||||
return substr($this->oDb->quote($str), 1, -1); # stripping first and last quote
|
||||
}
|
||||
|
||||
public function getPDO() {
|
||||
return $this->oDb;
|
||||
}
|
||||
}
|
||||
|
||||
Class SqliteStatement {
|
||||
|
||||
protected $stmt = null;
|
||||
|
||||
public function __construct($stmt) {
|
||||
$this->stmt = $stmt;
|
||||
}
|
||||
|
||||
public function fetch() {
|
||||
if($this->stmt !== FALSE) {
|
||||
return $this->stmt->fetch(\PDO::FETCH_ASSOC, \PDO::FETCH_ORI_FIRST);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
#################################################################
|
||||
# Copyright notice
|
||||
#
|
||||
# (c) 2012 Jérôme Schneider <mail@jeromeschneider.fr>
|
||||
# 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 Statement extends \Flake\Core\FLObject {
|
||||
protected $stmt = null;
|
||||
|
||||
public function __construct($stmt) {
|
||||
$this->stmt = $stmt;
|
||||
}
|
||||
|
||||
public function fetch() {
|
||||
if($this->stmt !== FALSE) {
|
||||
return $this->stmt->fetch(\PDO::FETCH_ASSOC, \PDO::FETCH_ORI_FIRST);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
|
@ -166,6 +166,14 @@ class Framework extends \Flake\Core\Framework {
|
|||
|
||||
protected static function initDb() {
|
||||
|
||||
if(defined("PROJECT_DB_MYSQL") && PROJECT_DB_MYSQL === TRUE) {
|
||||
self::initDbMysql();
|
||||
} else {
|
||||
self::initDbSqlite();
|
||||
}
|
||||
}
|
||||
|
||||
protected static function initDbSqlite() {
|
||||
# Asserting DB filepath is set
|
||||
if(!defined("PROJECT_SQLITE_FILE")) {
|
||||
return;
|
||||
|
@ -173,7 +181,7 @@ class Framework extends \Flake\Core\Framework {
|
|||
|
||||
# Asserting DB file exists
|
||||
if(!file_exists(PROJECT_SQLITE_FILE)) {
|
||||
die("<h3>DB file does not exist. To create it, please copy '<span style='font-family: monospace; background: yellow;'>Core/Resources/db.empty.sqlite</span>' to '<span style='font-family: monospace;background: yellow;'>" . PROJECT_SQLITE_FILE . "</span>'</h3>");
|
||||
die("<h3>DB file does not exist. To create it, please copy '<span style='font-family: monospace; background: yellow;'>Core/Resources/Db/db.empty.sqlite</span>' to '<span style='font-family: monospace;background: yellow;'>" . PROJECT_SQLITE_FILE . "</span>'</h3>");
|
||||
}
|
||||
|
||||
# Asserting DB file is readable
|
||||
|
@ -190,4 +198,37 @@ class Framework extends \Flake\Core\Framework {
|
|||
$GLOBALS["DB"] = new \Flake\Core\Database\Sqlite(PROJECT_SQLITE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function initDbMysql() {
|
||||
|
||||
if(!defined("PROJECT_DB_MYSQL_HOST")) {
|
||||
die("<h3>The constant PROJECT_DB_MYSQL_HOST, containing the MySQL host name, is not set.<br />You should set it in Specific/config.system.php</h3>");
|
||||
}
|
||||
|
||||
if(!defined("PROJECT_DB_MYSQL_DBNAME")) {
|
||||
die("<h3>The constant PROJECT_DB_MYSQL_DBNAME, containing the MySQL database name, is not set.<br />You should set it in Specific/config.system.php</h3>");
|
||||
}
|
||||
|
||||
if(!defined("PROJECT_DB_MYSQL_USERNAME")) {
|
||||
die("<h3>The constant PROJECT_DB_MYSQL_USERNAME, containing the MySQL database username, is not set.<br />You should set it in Specific/config.system.php</h3>");
|
||||
}
|
||||
|
||||
if(!defined("PROJECT_DB_MYSQL_PASSWORD")) {
|
||||
die("<h3>The constant PROJECT_DB_MYSQL_PASSWORD, containing the MySQL database password, is not set.<br />You should set it in Specific/config.system.php</h3>");
|
||||
}
|
||||
|
||||
try {
|
||||
$GLOBALS["DB"] = new \Flake\Core\Database\Mysql(
|
||||
PROJECT_DB_MYSQL_HOST,
|
||||
PROJECT_DB_MYSQL_DBNAME,
|
||||
PROJECT_DB_MYSQL_USERNAME,
|
||||
PROJECT_DB_MYSQL_PASSWORD
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
die("<h3>Baïkal was not able to establish a connexion to the configured MySQL database (as configured in Specific/config.system.php).</h3>");
|
||||
}
|
||||
|
||||
# We now setup the connexion to use UTF8
|
||||
$GLOBALS["DB"]->query("SET NAMES UTF8");
|
||||
}
|
||||
}
|
|
@ -105,12 +105,29 @@ class Tools extends \Flake\Core\FLObject {
|
|||
|
||||
public static function debug($var="",$brOrHeader=0) {
|
||||
if($brOrHeader === 0) {
|
||||
$trail = debug_backtrace();
|
||||
$trail = array_reverse($trail);
|
||||
array_pop($trail); // la ligne d'appel à debug
|
||||
array_pop($trail); // la ligne d'appel à debug
|
||||
$aLastNode = array_pop($trail); // l'appel qui nous intéresse
|
||||
$brOrHeader = @strval($aLastNode['class']).@strval($aLastNode['type']).@strval($aLastNode['function']);
|
||||
try {
|
||||
$trail = debug_backtrace();
|
||||
$trail = array_reverse($trail);
|
||||
array_pop($trail); // la ligne d'appel à debug
|
||||
array_pop($trail); // la ligne d'appel à debug
|
||||
$aLastNode = array_pop($trail); // l'appel qui nous intéresse
|
||||
|
||||
if(array_key_exists("class", $aLastNode)) {
|
||||
$sClass = @strval($aLastNode["class"]);
|
||||
} else {
|
||||
$sClass = "";
|
||||
}
|
||||
|
||||
if(array_key_exists("type", $aLastNode)) {
|
||||
$sType = @strval($aLastNode["type"]);
|
||||
} else {
|
||||
$sType = "";
|
||||
}
|
||||
|
||||
$brOrHeader = $sClass.$sType.@strval($aLastNode['function']);
|
||||
} catch(\Exception $e) {
|
||||
$brOrHeader = "Undetermined context";
|
||||
}
|
||||
}
|
||||
|
||||
if ($brOrHeader) {
|
||||
|
|
|
@ -37,6 +37,7 @@ abstract class Element {
|
|||
"placeholder" => "",
|
||||
"help" => "",
|
||||
"popover" => "",
|
||||
"refreshonchange" => FALSE,
|
||||
);
|
||||
|
||||
protected $sValue = "";
|
||||
|
@ -81,5 +82,19 @@ abstract class Element {
|
|||
return get_class($this) . "<" . $this->option("label") . ">";
|
||||
}
|
||||
|
||||
public function renderWitness() {
|
||||
return '<input type="hidden" name="witness[' . $this->option("prop") . ']" value="1" />';
|
||||
}
|
||||
|
||||
public function posted() {
|
||||
$aPost = \Flake\Util\Tools::POST("witness");
|
||||
if(is_array($aPost)) {
|
||||
$sProp = $this->option("prop");
|
||||
return (array_key_exists($sProp, $aPost)) && (intval($aPost[$sProp]) === 1);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public abstract function render();
|
||||
}
|
|
@ -37,14 +37,15 @@ class Checkbox extends \Formal\Element {
|
|||
$disabled = "";
|
||||
$inputclass = "";
|
||||
$groupclass = "";
|
||||
$onchange = "";
|
||||
$helpblock = "";
|
||||
$popover = "";
|
||||
|
||||
$value = $this->value();
|
||||
|
||||
$checked = ($value === TRUE ? " checked=\"checked\" " : "");
|
||||
$label = $this->option("label");
|
||||
$prop = $this->option("prop");
|
||||
$helpblock = "";
|
||||
$popover = "";
|
||||
|
||||
if($this->option("readonly") === TRUE) {
|
||||
$inputclass .= " disabled";
|
||||
|
@ -65,15 +66,19 @@ class Checkbox extends \Formal\Element {
|
|||
$popover .= " data-content=\"" . htmlspecialchars($aPopover["content"]) . "\" ";
|
||||
}
|
||||
|
||||
if($this->option("refreshonchange") === TRUE) {
|
||||
$onchange = " onchange=\"document.getElementsByTagName('form')[0].submit();\" ";
|
||||
}
|
||||
|
||||
$sHtml =<<<HTML
|
||||
<div class="control-group{$groupclass}">
|
||||
<label class="control-label" for="{$prop}">{$label}</label>
|
||||
<div class="controls">
|
||||
<input type="checkbox" class="input-xlarge{$inputclass}" id="{$prop}" name="{$prop}" value="1"{$checked}{$disabled}{$popover}/>
|
||||
<input type="checkbox" class="input-xlarge{$inputclass}" id="{$prop}" name="data[{$prop}]" value="1"{$checked}{$disabled}{$popover}{$onchange}/>
|
||||
{$helpblock}
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
return $sHtml;
|
||||
return $sHtml . $this->renderWitness();
|
||||
}
|
||||
}
|
|
@ -92,13 +92,13 @@ class Listbox extends \Formal\Element {
|
|||
<div class="control-group{$groupclass}">
|
||||
<label class="control-label" for="{$prop}">{$label}</label>
|
||||
<div class="controls">
|
||||
<select class="{$inputclass}" id="{$prop}" name="{$prop}"{$disabled}{$popover}>
|
||||
<select class="{$inputclass}" id="{$prop}" name="data[{$prop}]"{$disabled}{$popover}>
|
||||
{$sRenderedOptions}
|
||||
</select>
|
||||
{$helpblock}
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
return $sHtml;
|
||||
return $sHtml . $this->renderWitness();
|
||||
}
|
||||
}
|
|
@ -91,11 +91,11 @@ class Text extends \Formal\Element {
|
|||
<div class="control-group{$groupclass}">
|
||||
<label class="control-label" for="{$prop}">{$label}</label>
|
||||
<div class="controls">
|
||||
<input type="{$sInputType}" class="{$inputclass}" id="{$prop}" name="{$prop}" value="{$clientvalue}"{$disabled}{$placeholder}{$popover}/>
|
||||
<input type="{$sInputType}" class="{$inputclass}" id="{$prop}" name="data[{$prop}]" value="{$clientvalue}"{$disabled}{$placeholder}{$popover}/>
|
||||
{$helpblock}
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
return $sHtml;
|
||||
return $sHtml . $this->renderWitness();
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ class Form {
|
|||
"action" => "",
|
||||
"close" => TRUE,
|
||||
"closeurl" => "",
|
||||
"hook.validation" => FALSE,
|
||||
"hook.morphology" => FALSE,
|
||||
);
|
||||
protected $oModelInstance = null;
|
||||
protected $oElements = null;
|
||||
|
@ -42,6 +44,8 @@ class Form {
|
|||
protected $sDisplayTitle = ""; # Displayed form title; generated in setModelInstance()
|
||||
protected $sDisplayMessage = ""; # Displayed confirm message; generated in execute()
|
||||
|
||||
protected $oMorpho = null;
|
||||
|
||||
public function __construct($sModelClass, $aOptions = array()) {
|
||||
$this->sModelClass = $sModelClass;
|
||||
$this->aOptions = array_merge($this->aOptions, $aOptions);
|
||||
|
@ -66,6 +70,21 @@ class Form {
|
|||
return $aOptions;
|
||||
}
|
||||
|
||||
public function getMorpho() {
|
||||
if(!is_null($this->oMorpho)) {
|
||||
return $this->oMorpho;
|
||||
}
|
||||
|
||||
$this->oMorpho = $this->modelInstance()->formMorphologyForThisModelInstance();
|
||||
|
||||
# Calling validation hook if defined
|
||||
if(($aHook = $this->option("hook.morphology")) !== FALSE) {
|
||||
call_user_func($aHook, $this, $this->oMorpho);
|
||||
}
|
||||
|
||||
return $this->oMorpho;
|
||||
}
|
||||
|
||||
public function setModelInstance($oModelInstance) {
|
||||
if(!\Flake\Util\Tools::is_a($oModelInstance, $this->sModelClass)) {
|
||||
throw new \Exception("\Formal\Core->setModelInstance(): Given instance is not of class '" . $this->sModelClass . "'");
|
||||
|
@ -104,7 +123,7 @@ class Form {
|
|||
|
||||
public function execute() {
|
||||
# Obtaining morphology from model object
|
||||
$oMorpho = $this->modelInstance()->formMorphologyForThisModelInstance();
|
||||
$oMorpho = $this->getMorpho();
|
||||
|
||||
$this->aErrors = array();
|
||||
$oMorpho->elements()->reset();
|
||||
|
@ -117,15 +136,24 @@ class Form {
|
|||
$sPropName = $oElement->option("prop");
|
||||
|
||||
# posted value is fetched, then passes to element before persistance
|
||||
$sPostValue = $this->postValue($sPropName);
|
||||
$oElement->setValue($sPostValue);
|
||||
|
||||
$sValue = $oElement->value();
|
||||
|
||||
$this->modelInstance()->set(
|
||||
$sPropName,
|
||||
$sValue
|
||||
);
|
||||
if($oElement->posted()) {
|
||||
|
||||
$sPostValue = $this->postValue($sPropName);
|
||||
$oElement->setValue($sPostValue);
|
||||
|
||||
$sValue = $oElement->value();
|
||||
|
||||
$this->modelInstance()->set(
|
||||
$sPropName,
|
||||
$sValue
|
||||
);
|
||||
} else {
|
||||
$oElement->setValue(
|
||||
$this->modelInstance()->get(
|
||||
$sPropName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$oMorpho->elements()->reset();
|
||||
|
@ -162,18 +190,17 @@ class Form {
|
|||
}
|
||||
|
||||
if($mValid !== TRUE) {
|
||||
$this->aErrors[] = array(
|
||||
"element" => $oElement,
|
||||
"message" => $mValid,
|
||||
);
|
||||
|
||||
$oElement->setOption("error", TRUE);
|
||||
|
||||
$this->declareError($oElement, $mValid);
|
||||
break; # one error per element per submit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Calling validation hook if defined
|
||||
if(($aHook = $this->option("hook.validation")) !== FALSE) {
|
||||
call_user_func($aHook, $this, $oMorpho);
|
||||
}
|
||||
|
||||
if(empty($this->aErrors)) {
|
||||
|
||||
# Model object is persisted
|
||||
|
@ -198,7 +225,7 @@ class Form {
|
|||
$this->modelInstance()->persist();
|
||||
if($bWasFloating === FALSE) {
|
||||
# Title is generated now, as submitted data might have changed the model instance label
|
||||
$this->sDisplayTitle = "Editing " . $this->modelInstance()->humanName() . "<strong><i class=" . $this->modelInstance()->mediumicon() . "></i><strong>" . $this->modelInstance()->label() . "</strong>";
|
||||
$this->sDisplayTitle = "Editing " . $this->modelInstance()->humanName() . "<i class=" . $this->modelInstance()->mediumicon() . "></i><strong>" . $this->modelInstance()->label() . "</strong>";
|
||||
}
|
||||
$this->bPersisted = TRUE;
|
||||
} else {
|
||||
|
@ -206,6 +233,16 @@ class Form {
|
|||
}
|
||||
}
|
||||
|
||||
# public, as it may be called from a hook
|
||||
public function declareError(\Formal\Element $oElement, $sMessage = "") {
|
||||
$this->aErrors[] = array(
|
||||
"element" => $oElement,
|
||||
"message" => $sMessage,
|
||||
);
|
||||
|
||||
$oElement->setOption("error", TRUE);
|
||||
}
|
||||
|
||||
public function persisted() {
|
||||
if($this->submitted()) {
|
||||
if(is_null($this->bPersisted)) {
|
||||
|
@ -279,13 +316,19 @@ class Form {
|
|||
}
|
||||
|
||||
public function postValue($sPropName) {
|
||||
return \Flake\Util\Tools::POST($sPropName);
|
||||
$aData = \Flake\Util\Tools::POST("data");
|
||||
|
||||
if(is_array($aData) && array_key_exists($sPropName, $aData)) {
|
||||
return $aData[$sPropName];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$aHtml = array();
|
||||
|
||||
$oMorpho = $this->modelInstance()->formMorphologyForThisModelInstance();
|
||||
$oMorpho = $this->getMorpho();
|
||||
|
||||
$oMorpho->elements()->reset();
|
||||
foreach($oMorpho->elements() as $oElement) {
|
||||
|
@ -320,6 +363,10 @@ class Form {
|
|||
$aMessages = array();
|
||||
reset($this->aErrors);
|
||||
foreach($this->aErrors as $aError) {
|
||||
if(trim($aError["message"]) === "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$aMessages[] = $aError["message"];
|
||||
}
|
||||
|
||||
|
|
|
@ -38,18 +38,35 @@ class Morphology {
|
|||
$this->oElements->push($oElement);
|
||||
}
|
||||
|
||||
public function element($sPropName) {
|
||||
protected function keyForPropName($sPropName) {
|
||||
$aKeys = $this->oElements->keys();
|
||||
reset($aKeys);
|
||||
foreach($aKeys as $sKey) {
|
||||
$oElement = $this->oElements->getForKey($sKey);
|
||||
|
||||
if($oElement->option("prop") === $sPropName) {
|
||||
return $oElement;
|
||||
return $sKey;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Exception("\Formal\Form\Morphology->element(): Element prop='" . $sPropName . "' not found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public function &element($sPropName) {
|
||||
if(($sKey = $this->keyForPropName($sPropName)) === FALSE) {
|
||||
throw new \Exception("\Formal\Form\Morphology->element(): Element prop='" . $sPropName . "' not found");
|
||||
}
|
||||
|
||||
$oElement = $this->oElements->getForKey($sKey);
|
||||
return $oElement;
|
||||
}
|
||||
|
||||
public function remove($sPropName) {
|
||||
if(($sKey = $this->keyForPropName($sPropName)) === FALSE) {
|
||||
throw new \Exception("\Formal\Form\Morphology->element(): Element prop='" . $sPropName . "' not found");
|
||||
}
|
||||
|
||||
$this->oElements->remove($sKey);
|
||||
}
|
||||
|
||||
public function elements() {
|
||||
|
|
80
CoreVersions/0.2.1/Resources/Db/db.empty.mysql.sql
Normal file
80
CoreVersions/0.2.1/Resources/Db/db.empty.mysql.sql
Normal file
|
@ -0,0 +1,80 @@
|
|||
#
|
||||
# This is the empty database schema for Baïkal
|
||||
# Corresponds to the MySQL Schema definition of project SabreDAV 1.6.4
|
||||
# http://code.google.com/p/sabredav/
|
||||
#
|
||||
|
||||
CREATE TABLE users (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARCHAR(50),
|
||||
digesta1 VARCHAR(32),
|
||||
UNIQUE(username)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE principals (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
email VARCHAR(80),
|
||||
displayname VARCHAR(80),
|
||||
vcardurl VARCHAR(80),
|
||||
UNIQUE(uri)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principal_id INTEGER UNSIGNED NOT NULL,
|
||||
member_id INTEGER UNSIGNED NOT NULL,
|
||||
UNIQUE(principal_id, member_id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE locks (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER UNSIGNED,
|
||||
created INTEGER,
|
||||
token VARCHAR(100),
|
||||
scope TINYINT,
|
||||
depth TINYINT,
|
||||
uri text
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE calendarobjects (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
calendardata MEDIUMBLOB,
|
||||
uri VARCHAR(200),
|
||||
calendarid INTEGER UNSIGNED NOT NULL,
|
||||
lastmodified INT(11),
|
||||
UNIQUE(calendarid, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARCHAR(100),
|
||||
displayname VARCHAR(100),
|
||||
uri VARCHAR(200),
|
||||
ctag INTEGER UNSIGNED NOT NULL DEFAULT '0',
|
||||
description TEXT,
|
||||
calendarorder INTEGER UNSIGNED NOT NULL DEFAULT '0',
|
||||
calendarcolor VARCHAR(10),
|
||||
timezone TEXT,
|
||||
components VARCHAR(20),
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE addressbooks (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARCHAR(255),
|
||||
displayname VARCHAR(255),
|
||||
uri VARCHAR(200),
|
||||
description TEXT,
|
||||
ctag INT(11) UNSIGNED NOT NULL DEFAULT '1',
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE cards (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
addressbookid INT(11) UNSIGNED NOT NULL,
|
||||
carddata MEDIUMBLOB,
|
||||
uri VARCHAR(200),
|
||||
lastmodified INT(11) UNSIGNED
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
0
CoreVersions/0.2.1/Resources/db.empty.sqlite → CoreVersions/0.2.1/Resources/Db/db.empty.sqlite
Executable file → Normal file
0
CoreVersions/0.2.1/Resources/db.empty.sqlite → CoreVersions/0.2.1/Resources/Db/db.empty.sqlite
Executable file → Normal file
Loading…
Add table
Reference in a new issue