Commit d1b203dd authored by Carsten  Rose's avatar Carsten Rose
Browse files

#3679: Automatic DB Update

Fixed: unnecessary exception if there is no Form / FormElement table
Database.php: New function playSqlFile().
DatabaseUpdate.php: missing table Form won't throw an exception anymore.
Manual.rst: note that formEditor.sql will be played automatically.
parent 6086b8e3
......@@ -123,7 +123,8 @@ Setup
* Copy/rename the file *<Documentroot>/typo3conf/ext/<ext_dir>/config.example.qfq.ini* to
*<Documentroot>/typo3conf/config.qfq.ini* and configure the necessary values: `config.qfq.ini`_
The configuration file is outside the extension directory to not loose it during updates.
* Play the SQL File *<ext_dir>/qfq/sql/formEditor.sql* to fill the database with the *FormEditor* records.
* When the QFQ Extension is called the first time on the Typo3 Frontend, the file *<ext_dir>/qfq/sql/formEditor.sql* will
played and fills the database with the *FormEditor* records. This also happens automatically after each software update of QFQ.
* Configure Typoscript to include Bootstrap, jQuery, QFQ javascript and CSS files.
::
......
......@@ -167,7 +167,7 @@ const ERROR_HTML_TOKEN_TOO_SHORT = 1076;
const ERROR_MISSING_PRINTF_ARGUMENTS = 1077;
const ERROR_MISSING_DEFINITON = 1078;
const ERROR_QFQ_VERSION = 1079;
const ERROR_PLAY_FORM_EDITOR_SQL = 1080;
const ERROR_PLAY_SQL_FILE = 1080;
// Subrecord
const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100;
......@@ -238,6 +238,7 @@ const ERROR_DB_UNKNOWN_COMMAND = 2012;
const ERROR_DB_MISSING_COLUMN_ID = 2013;
const ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE = 2014;
const ERROR_DB_SET_CHARSET = 2015;
const ERROR_DB_MULTI_QUERY_FAILED = 2016;
// onArray
const ERROR_SUBSTITUTE_FOUND = 2100;
......
......@@ -757,4 +757,25 @@ class Database {
public function realEscapeString($value) {
return $this->mysqli->real_escape_string($value);
}
/**
* @param $filename
* @throws \qfq\CodeException
*/
public function playSqlFile($filename) {
$sqlStatements = file_get_contents($filename);
if (false === $this->mysqli->multi_query($sqlStatements)) {
throw new CodeException("Error playing $filename", ERROR_PLAY_SQL_FILE);
}
// discard all results: this is important - if missed, following calls on $mysqli will fail.
do {
if ($res = $this->mysqli->store_result()) {
$res->free();
}
} while ($this->mysqli->more_results() && $this->mysqli->next_result());
}
}
\ No newline at end of file
......@@ -15,11 +15,12 @@ require_once(__DIR__ . '/Database.php');
* Read the extension version number.
* Read the QFQ database version number: stored in the comment field of table 'Form'. Format: Version=x.y.z
* If versions different:
* * Import the update table 'DatabaseUpdateData.php'.
* * Play all changes after 'old' upto 'new'.
* * Read the update array 'DatabaseUpdateData.php'.
* * Play all changes from the update array after 'old' upto 'new'.
* * Save new QFQ database version in the comment field of table 'Form'
*
* In a new QFQ installation, the comment field of table 'Form' is empty. On the first call of QFQ, the version string will be set.
* In a new QFQ installation, the comment field of table 'Form' is empty. On the first call of QFQ, the version string
* will be set. Also the 'formEditor.sql' will be played initially.
*
*/
......@@ -57,15 +58,19 @@ class DatabaseUpdate {
}
/**
* @return bool
* @return bool|string false if there is no table 'Form' or if there is no comment set in table 'Form'.
* @throws CodeException
* @throws DbException
*/
private function getDatabaseVersion() {
$row = $this->db->sql("SHOW TABLE STATUS WHERE Name='Form'", ROW_EXPECT_1);
$row = $this->db->sql("SHOW TABLE STATUS WHERE Name='Form'", ROW_EXPECT_0_1);
$arr = explode('=', $row['Comment']);
if (count($arr) != 2 || $arr[0] != 'Version' || $arr[1] == '') {
if (count($row) == 1) {
$arr = explode('=', $row['Comment']);
if (count($arr) != 2 || $arr[0] != 'Version' || $arr[1] == '') {
return false;
}
} else {
return false;
}
......@@ -86,31 +91,33 @@ class DatabaseUpdate {
/**
* @throws CodeException
*/
public function checkNupdate($host, $user, $password, $database) {
public function checkNupdate() {
$new = $this->getExtensionVersion();
$old = $this->getDatabaseVersion();
if ($new != $old) {
$this->dbUpdateStatements($old, $new);
$this->playFormEditorSql($host, $user, $password, $database);
$this->db->playSqlFile(__DIR__ . '/../../sql/formEditor.sql');
$this->setDatabaseVersion($new);
}
}
/**
* @return null
* @param $path
* @return array
* @throws CodeException
*/
private function readUpdateData() {
private function readUpdateData($path) {
$path = __DIR__ . '/DatabaseUpdateData.php';
if (!@file_exists($path)) {
throw new CodeException("File '$path'' not found", ERROR_IO_OPEN);
}
$UPDATE_ARRAY = null;
include $path;
return $UPDATE_ARRAY;
}
......@@ -125,7 +132,7 @@ class DatabaseUpdate {
if ($new == '' || $old === false) {
return;
}
$updateArray = $this->readUpdateData();
$updateArray = $this->readUpdateData(__DIR__ . '/DatabaseUpdateData.php');
$apply = false;
foreach ($updateArray as $key => $sqlStatements) {
......@@ -144,30 +151,4 @@ class DatabaseUpdate {
}
}
}
/**
* @param $host
* @param $user
* @param $password
* @param $database
* @throws CodeException
*/
private function playFormEditorSql($host, $user, $password, $database) {
$output = array();
$return_var = 0;
$host = escapeshellarg($host);
$user = escapeshellarg($user);
$password = escapeshellarg($password);
$database = escapeshellarg($database);
$cmd = "mysql -u $user --password=$password -h $host $database < " . __DIR__ . '/../../sql/formEditor.sql';
exec($cmd, $output, $return_var);
if ($return_var != 0) {
$msg = implode("\n", $output);
throw new CodeException("Error playing formEditor.sql: $msg", ERROR_PLAY_FORM_EDITOR_SQL);
}
}
}
\ No newline at end of file
......@@ -38,8 +38,8 @@ $UPDATE_ARRAY = array(
"ALTER TABLE `FormElement` ADD `encode` ENUM( 'none', 'specialchar' ) NOT NULL DEFAULT 'specialchar' AFTER `subrecordOption`",
"UPDATE `FormElement` SET encode='none' WHERE class='native' AND type='editor'",
"ALTER TABLE `Form` ADD `escapeTypeDefault` ENUM( '', 's', 'd', 'l', 'L', 'm', '-' ) NOT NULL DEFAULT '' AFTER `permitEdit`",
"UPDATE `Form` SET `escapeTypeDefault`='-'",
"ALTER TABLE `Form` ADD `escapeTypeDefault` ENUM( '', 's - single', 'd - double', 'l - ldap search', 'L - ldap value', 'm - mysqlRealEscapeString', '- none' ) NOT NULL DEFAULT '' AFTER `permitEdit`",
"UPDATE `Form` SET `escapeTypeDefault`='- none'",
],
);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment