From 092e6deb58257565982fd8f3d1cbd175d7a0abe0 Mon Sep 17 00:00:00 2001 From: Carsten Rose <carsten.rose@math.uzh.ch> Date: Wed, 13 Apr 2016 16:34:31 +0200 Subject: [PATCH] Preparation to update Form after saving values. save.php: return JSON with updated values of all fields. AbstractBuildForm.php: updated to deliver values of all form elements Constants.php: constants to distinguish all or specific values of FEs. QUERY_TYPE_* Database.php: doSQL now returns affectedrows or lastinsertid in case of udpate/inset. Typos fixed. QuickFormQuery.php: deliver Values as JSON after save. Save.php: return lastinsertid or affectedrows. --- extension/qfq/api/save.php | 4 +- extension/qfq/qfq/AbstractBuildForm.php | 9 +-- extension/qfq/qfq/Constants.php | 16 ++++- extension/qfq/qfq/Database.php | 95 ++++++++++++++----------- extension/qfq/qfq/QuickFormQuery.php | 36 +++++----- extension/qfq/qfq/Save.php | 22 +++--- 6 files changed, 108 insertions(+), 74 deletions(-) diff --git a/extension/qfq/api/save.php b/extension/qfq/api/save.php index f58dc9270..8dafb8f64 100644 --- a/extension/qfq/api/save.php +++ b/extension/qfq/api/save.php @@ -58,11 +58,13 @@ $answer[API_MESSAGE] = ''; try { $qfq = new \qfq\QuickFormQuery(['bodytext' => ""]); - $qfq->saveForm(); + $data = $qfq->saveForm(); $answer[API_REDIRECT] = $qfq->getForwardMode($answer[API_REDIRECT_URL]); $answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS; $answer[API_MESSAGE] = 'save: success'; + $answer[API_FORM_UPDATE] = $data; + } catch (qfq\UserFormException $e) { $answer[API_MESSAGE] = $e->formatMessage(); diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index f468ab779..43990df36 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -124,6 +124,7 @@ abstract class AbstractBuildForm { $htmlSubrecords = ''; $htmlElements = ''; $json = array(); + $modeCollectFe = ($mode === FORM_SAVE) ? FLAG_ALL : FLAG_DYNAMIC_UPDATE; // <form> if ($mode === FORM_LOAD) { @@ -140,11 +141,11 @@ abstract class AbstractBuildForm { foreach ($parentRecords as $row) { $this->store->setVarArray($row, STORE_PARENT_RECORD, true); $jsonTmp = array(); - $htmlElements = $this->elements($row['_id'], $filter, 0, $jsonTmp); + $htmlElements = $this->elements($row['_id'], $filter, 0, $jsonTmp, $modeCollectFe); $json[] = $jsonTmp; } } else { - $htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json); + $htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json, $modeCollectFe); } // </form> @@ -299,7 +300,7 @@ abstract class AbstractBuildForm { * @throws DbException * @throws \qfq\UserFormException */ - public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json) { + public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json, $modeCollectFe = FLAG_DYNAMIC_UPDATE) { $html = ''; // get current data record @@ -348,7 +349,7 @@ abstract class AbstractBuildForm { } } else { // for non container elements: just add the current json status - if ($fe['dynamicUpdate'] == 'yes') { + if ($modeCollectFe === FLAG_ALL || ($modeCollectFe == FLAG_DYNAMIC_UPDATE && $fe['dynamicUpdate'] == 'yes')) { $json[] = $jsonElement; } } diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 04202e5c7..339fa0e67 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -161,8 +161,9 @@ const ERROR_DB_COUNT_DO_NOT_MATCH = 2008; const ERROR_DB_CLOSE_MYSQLI_RESULT = 2009; const ERROR_DB_CLOSE_MYSQLI_STMT = 2010; const ERROR_DB_UNKNOWN_COLUMN = 2011; -const ERROR_DB_MISSING_COLUMN_ID = 2012; -const ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE = 2013; +const ERROR_DB_UNKNOWN_COMMAND = 2012; +const ERROR_DB_MISSING_COLUMN_ID = 2013; +const ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE = 2014; // // Store Names: Identifier // @@ -333,4 +334,13 @@ const GLYPH_ICON_CHECK = 'glyphicon glyphicon-ok'; // SUPPORT const PARAM_T3_ALL = 't3 all'; -const PARAM_T3_NO_ID = "t3 no id"; \ No newline at end of file +const PARAM_T3_NO_ID = "t3 no id"; + +// AbstractBuildForm +const FLAG_ALL = 'flagAll'; +const FLAG_DYNAMIC_UPDATE = 'flagDynamicUpdate'; + + +const QUERY_TYPE_SELECT = 'type: select,show,describe,explain'; +const QUERY_TYPE_INSERT = 'type: insert'; +const QUERY_TYPE_UPDATE = 'type: update,replace,delete'; \ No newline at end of file diff --git a/extension/qfq/qfq/Database.php b/extension/qfq/qfq/Database.php index 0ab2685ca..823fd5a82 100644 --- a/extension/qfq/qfq/Database.php +++ b/extension/qfq/qfq/Database.php @@ -201,11 +201,15 @@ class Database { * @param string $mode * @param array $parameterArray * @param string $specificMessage - * @return mixed|null If no record found, empty string ( ROW_EXPECT_0_1, ROW_EXPECT_1) or empty array (all other modes) + * @return mixed|null + * SELECT | SHOW | DESCRIBE | EXPLAIN: If no record found, empty string ( ROW_EXPECT_0_1, ROW_EXPECT_1) or empty array (all other modes) + * INSERT: last_insert_id + * UPDATE | DELETE | REPLACE: affected rows * @throws \qfq\CodeException * @throws \qfq\DbException */ public function sql($sql, $mode = ROW_REGULAR, array $parameterArray = array(), $specificMessage = '', array &$keys = array()) { + $queryType = ''; $result = array(); $this->closeMysqliStmt(); @@ -217,48 +221,52 @@ class Database { if ($specificMessage) $specificMessage .= " "; - $count = $this->prepareExecute($sql, $parameterArray); + $count = $this->prepareExecute($sql, $parameterArray, $queryType); if ($count === false) { throw new DbException($specificMessage . "No idea why this error happens - please take some time and check this: $sql", ERROR_DB_GENERIC_CHECK); } - switch ($mode) { - case ROW_IMPLODE_ALL: - $result = $this->fetchAll($mode); - break; - case ROW_KEYS: - case ROW_REGULAR: - $result = $this->fetchAll($mode, $keys); - break; - case ROW_EXPECT_0: - if ($count === 0) - $result = array(); - else - throw new DbException($specificMessage . "Expected no record, got $count rows: $sql", ERROR_DB_TOO_MANY_ROWS); - break; - case ROW_EXPECT_1: - if ($count === 1) - $result = $this->fetchAll($mode)[0]; - else - throw new DbException($specificMessage . "Expected one record, got $count: $sql", ERROR_DB_COUNT_DO_NOT_MATCH); - break; - case ROW_EXPECT_0_1: - if ($count === 1) - $result = $this->fetchAll($mode)[0]; - elseif ($count === 0) - $result = array(); - else - throw new DbException($specificMessage . "Expected no record, got $count rows: $sql", ERROR_DB_TOO_MANY_ROWS); - break; - case ROW_EXPECT_GE_1: - if ($count > 0) + if ($queryType === QUERY_TYPE_SELECT) { + switch ($mode) { + case ROW_IMPLODE_ALL: $result = $this->fetchAll($mode); - else - throw new DbException($specificMessage . "Expected at least one record, got nothing: $sql", ERROR_DB_TOO_FEW_ROWS); - break; + break; + case ROW_KEYS: + case ROW_REGULAR: + $result = $this->fetchAll($mode, $keys); + break; + case ROW_EXPECT_0: + if ($count === 0) + $result = array(); + else + throw new DbException($specificMessage . "Expected no record, got $count rows: $sql", ERROR_DB_TOO_MANY_ROWS); + break; + case ROW_EXPECT_1: + if ($count === 1) + $result = $this->fetchAll($mode)[0]; + else + throw new DbException($specificMessage . "Expected one record, got $count: $sql", ERROR_DB_COUNT_DO_NOT_MATCH); + break; + case ROW_EXPECT_0_1: + if ($count === 1) + $result = $this->fetchAll($mode)[0]; + elseif ($count === 0) + $result = array(); + else + throw new DbException($specificMessage . "Expected no record, got $count rows: $sql", ERROR_DB_TOO_MANY_ROWS); + break; + case ROW_EXPECT_GE_1: + if ($count > 0) + $result = $this->fetchAll($mode); + else + throw new DbException($specificMessage . "Expected at least one record, got nothing: $sql", ERROR_DB_TOO_FEW_ROWS); + break; - default: - throw new DbException($specificMessage . "Unknown mode: $mode", ERROR_UNKNOWN_MODE); + default: + throw new DbException($specificMessage . "Unknown mode: $mode", ERROR_UNKNOWN_MODE); + } + } else { + $result = $count; } $this->closeMysqliStmt(); @@ -293,12 +301,13 @@ class Database { * * @param string $sql SQL statement with prepared statement variable. * @param array $parameterArray parameter array for prepared statement execution. + * @param string $queryType returns QUERY_TYPE_SELECT | QUERY_TYPE_UPDATE | QUERY_TYPE_INSERT, depending on the query. * @return int|mixed * @throws \qfq\CodeException * @throws \qfq\DbException * @throws \qfq\UserFormException */ - private function prepareExecute($sql, array $parameterArray = array()) { + private function prepareExecute($sql, array $parameterArray = array(), &$queryType = '') { $result = 0; $this->store->setVar(SYSTEM_SQL_FINAL, $sql, STORE_SYSTEM); $this->store->setVar(SYSTEM_SQL_PARAM_ARRAY, $parameterArray, STORE_SYSTEM); @@ -332,21 +341,25 @@ class Database { if (false === ($result = $this->mysqli_stmt->get_result())) { throw new DbException('[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error, ERROR_DB_EXECUTE); } + $queryType = QUERY_TYPE_SELECT; $this->mysqli_result = $result; $count = $this->mysqli_result->num_rows; $msg = 'Read rows: ' . $count; break; case 'INSERT': + $queryType = QUERY_TYPE_INSERT; $count = $this->mysqli->insert_id; $msg = 'ID: ' . $count; break; case 'UPDATE': case 'REPLACE': case 'DELETE': + $queryType = QUERY_TYPE_UPDATE; $count = $this->mysqli->affected_rows; $msg = 'Affected rows: ' . $count; break; default: + throw new DbException('Unknown comand: "' . $command . '"', ERROR_DB_UNKNOWN_COMMAND); break; } @@ -359,7 +372,7 @@ class Database { } /** - * Decide if the SQL statement has to be logged.If yes, create a timestamp and do the log. + * Decide if the SQL statement has to be logged. If yes, create a timestamp and do the log. * * @param $sql * @param array $parameterArray @@ -447,12 +460,12 @@ class Database { * * mode: * ROW_IMPLODE_ALL: Return string. All cells of all rows imploded to one string. - * ROW_KEYS: Retrun num array with column names in $keys + * ROW_KEYS: Return num array with column names in $keys * default: Return 2-dimensional assoc array * * @param string $mode * @param array $keys - * @return array|bool|mixed|string false in case of error. + * @return array|bool|mixed|string false in case of an error. * Empty string is returned if the query didn't yield any rows. * All rows as Multi Assoc array if $mode!=IMPLODE_ALL. * All rows and all columns imploded to one string if $mode=IMPLODE_ALL diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index a40638a6f..399c3892d 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -178,7 +178,7 @@ class QuickFormQuery { * $mode=FORM_UPDATE: States and values of all form elements will be returned as JSON. * $mode=FORM_SAVE: The submitted form will be saved. Return Failure or Success as JSON. * - * @param $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE + * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE * @return array|string * @throws CodeException * @throws UserFormException @@ -203,22 +203,23 @@ class QuickFormQuery { } $this->store->fillStoreTableDefaultColumnType($this->formSpec['tableName']); + switch ($this->formSpec['render']) { + case 'plain': + $build = new BuildFormPlain($this->formSpec, $this->feSpecAction, $this->feSpecNative); + break; + case 'table': + $build = new BuildFormTable($this->formSpec, $this->feSpecAction, $this->feSpecNative); + break; + case 'bootstrap': + $build = new BuildFormBootstrap($this->formSpec, $this->feSpecAction, $this->feSpecNative); + break; + default: + throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN); + } + switch ($mode) { case FORM_LOAD: case FORM_UPDATE: - switch ($this->formSpec['render']) { - case 'plain': - $build = new BuildFormPlain($this->formSpec, $this->feSpecAction, $this->feSpecNative); - break; - case 'table': - $build = new BuildFormTable($this->formSpec, $this->feSpecAction, $this->feSpecNative); - break; - case 'bootstrap': - $build = new BuildFormBootstrap($this->formSpec, $this->feSpecAction, $this->feSpecNative); - break; - default: - throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN); - } $data = $build->process($mode); break; @@ -226,6 +227,9 @@ class QuickFormQuery { case FORM_SAVE: $save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative); $save->process(); + + // Retrieve FE Values as JSON + $data = $build->process($mode); break; default: @@ -437,9 +441,9 @@ class QuickFormQuery { */ public function saveForm() { - $html = $this->doForm(FORM_SAVE); + $json = $this->doForm(FORM_SAVE); - return $html; + return $json; } /** diff --git a/extension/qfq/qfq/Save.php b/extension/qfq/qfq/Save.php index bcd8394b4..38a261fdf 100644 --- a/extension/qfq/qfq/Save.php +++ b/extension/qfq/qfq/Save.php @@ -125,7 +125,7 @@ class Save { public function insertRecord($tableName, array $values) { if (count($values) === 0) - return 0; + return 0; // nothing to write, last insert id=0 $paramList = str_repeat('?, ', count($values)); $paramList = substr($paramList, 0, strlen($paramList) - 2); @@ -133,27 +133,29 @@ class Save { $sql = 'INSERT INTO ' . $tableName . ' ( ' . $columnList . ' ) VALUES ( ' . $paramList . ' )'; - $this->db->sql($sql, ROW_REGULAR, array_values($values)); + $rc = $this->db->sql($sql, ROW_REGULAR, array_values($values)); - return $this->db->getLastInsertId(); + return $rc; } /** + * @param string $tableName * @param array $values - * @param $recordId - * @return string + * @param int $recordId + * @return bool|int false if $values is empty + * @throws CodeException * @throws DbException */ public function updateRecord($tableName, array $values, $recordId) { if (count($values) === 0) - return; + return 0; // nothing to write, 0 rows affected if ($recordId === 0) throw new CodeException('RecordId=0 - this is not possible for update.', ERROR_RECORDID_0_FORBIDDEN); - $paramList = str_repeat('?, ', count($values)); - $paramList = substr($paramList, 0, strlen($paramList) - 2); +// $paramList = str_repeat('?, ', count($values)); +// $paramList = substr($paramList, 0, strlen($paramList) - 2); $sql = 'UPDATE `' . $tableName . '` SET '; @@ -165,7 +167,9 @@ class Save { $sql = substr($sql, 0, strlen($sql) - 2) . ' WHERE id = ?'; $values[] = $recordId; - $this->db->sql($sql, ROW_REGULAR, array_values($values)); + $rc = $this->db->sql($sql, ROW_REGULAR, array_values($values)); + + return $rc; } } \ No newline at end of file -- GitLab