From 16408b47a4ea8f85cf7cf08762b2d325abe76cdb Mon Sep 17 00:00:00 2001 From: Carsten Rose <carsten.rose@math.uzh.ch> Date: Thu, 14 Apr 2016 08:10:47 +0200 Subject: [PATCH] After creating a new record and still open form: a new sip is created and transfered to client. Attention: 'new + save + modify + save again' still create two records (error). AbstractBuildForm.php: buildNewSip() renamed to buildHiddenSip(). Call of buildHiddenSip() moved from tail() to process(). buildHiddenSip() returns JSON code too. BuildFormBootstrap.php, BuildFromPlain.php, BuildFormTable.php : removed call buildNewSip() QuickFormQuery.php: After save, reload current record and create new sip Save.php: process() returns id of affected record. --- extension/qfq/qfq/AbstractBuildForm.php | 115 +++++++++++++---------- extension/qfq/qfq/BuildFormBootstrap.php | 4 +- extension/qfq/qfq/BuildFormPlain.php | 2 +- extension/qfq/qfq/BuildFormTable.php | 2 +- extension/qfq/qfq/QuickFormQuery.php | 56 ++++++++++- extension/qfq/qfq/Save.php | 22 +++-- 6 files changed, 135 insertions(+), 66 deletions(-) diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index 43990df36..6af125ba2 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -118,7 +118,7 @@ abstract class AbstractBuildForm { * @throws DbException * @throws \qfq\UserFormException */ - public function process($mode) { + public function process($mode, $htmlElementNameIdZero = false) { $htmlHead = ''; $htmlTail = ''; $htmlSubrecords = ''; @@ -145,12 +145,14 @@ abstract class AbstractBuildForm { $json[] = $jsonTmp; } } else { - $htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json, $modeCollectFe); + $htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json, $modeCollectFe, $htmlElementNameIdZero); } + $htmlSip = $this->buildHiddenSip($json); + // </form> - return ($mode === FORM_LOAD) ? $htmlHead . $htmlElements . $htmlTail . $htmlSubrecords : $json; + return ($mode === FORM_LOAD) ? $htmlHead . $htmlElements . $htmlSip . $htmlTail . $htmlSubrecords : $json; } /** @@ -300,7 +302,8 @@ abstract class AbstractBuildForm { * @throws DbException * @throws \qfq\UserFormException */ - public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json, $modeCollectFe = FLAG_DYNAMIC_UPDATE) { + public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json, + $modeCollectFe = FLAG_DYNAMIC_UPDATE, $htmlElementNameIdZero = false) { $html = ''; // get current data record @@ -328,9 +331,12 @@ abstract class AbstractBuildForm { $formElement = $evaluate->parseArray($fe, $debugStack); // Get default value - $value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], STORE_USE_DEFAULT, $formElement['checkType']) : $formElement['value']; + $value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], STORE_USE_DEFAULT, + $formElement['checkType']) : $formElement['value']; - $htmlFormElementId = HelperFormElement::buildFormElementId($formElement['name'], $recordId); + // Typically: $htmlElementNameIdZero = true + // After Saving a record, staying on the form, the FormElements on the Client are still known as '<feName>:0'. + $htmlFormElementId = HelperFormElement::buildFormElementId($formElement['name'], ($htmlElementNameIdZero) ? 0 : $recordId); // Construct Marshaller Name: buildElement $buildElementFunctionName = 'build' . $this->buildElementFunctionName[$formElement['type']]; @@ -373,6 +379,57 @@ abstract class AbstractBuildForm { return $html; } + /** + * Create a hidden sip, based on latest STORE_SIP Values. Return complete HTML 'hidden' element. + * + * @param $json + * @return string <input type='hidden' name='s' value='<sip>'> + * @throws CodeException + * @throws \qfq\UserFormException + */ + public function buildHiddenSip(&$json) { + $sipArray = $this->store->getStore(STORE_SIP); + unset($sipArray[SIP_SIP]); + unset($sipArray[SIP_URLPARAM]); + + $queryString = Support::arrayToQueryString($sipArray); + $sip = $this->store->getSipInstance(); + + $sipValue = $sip->queryStringToSip($queryString, RETURN_SIP); + + $json[] = $this->getJsonElementUpdate(CLIENT_SIP, $sipValue, ''); + + return $this->buildNativeHidden(CLIENT_SIP, $sipValue); + } + + /** + * @param $htmlFormElementId + * @param string|array $value + * @param string $mode disabled|readonly|'' + * @return array + */ + private function getJsonElementUpdate($htmlFormElementId, $value, $mode) { + $json = array(); + + $json['form-element'] = $htmlFormElementId; + $json['value'] = $value; + $json['disabled'] = ($mode === 'disabled'); + $json['readonly'] = ($mode === 'readonly'); + + return $json; + } + + /** + * Builds a real HTML hidden form element. Useful for checkboxes, Multiple-Select and Radios. + * + * @param $htmlFormElementId + * @param $value + * @return string + */ + public function buildNativeHidden($htmlFormElementId, $value) { + return '<input type="hidden" name="' . $htmlFormElementId . '" value="' . htmlentities($value) . '">'; + } + /** * Takes the current SIP ('form' and additional parameter), set SIP_RECORD_ID=0 and create a new 'NewRecordUrl'. * @@ -621,23 +678,6 @@ abstract class AbstractBuildForm { return $attribute; } - /** - * @param $htmlFormElementId - * @param string|array $value - * @param $mode - * @return array - */ - private function getJsonElementUpdate($htmlFormElementId, $value, $mode) { - $json = array(); - - $json['form-element'] = $htmlFormElementId; - $json['value'] = $value; - $json['disabled'] = ($mode === 'disabled'); - $json['readonly'] = ($mode === 'readonly'); - - return $json; - } - /** * Builds HTML 'checkbox' element. * @@ -879,17 +919,6 @@ abstract class AbstractBuildForm { return $html; } - /** - * Builds a real HTML hidden form element. Useful for checkboxes, Multiple-Select and Radios. - * - * @param $htmlFormElementId - * @param $value - * @return string - */ - public function buildNativeHidden($htmlFormElementId, $value) { - return '<input type="hidden" name="' . $htmlFormElementId . '" value="' . htmlentities($value) . '">'; - } - /** * Build as many Checkboxes as items. * @@ -1513,24 +1542,6 @@ abstract class AbstractBuildForm { return $html; } - /** - * Create a new sip, based on latest STORE_SIP Values. Return complete HTML 'hidden' element. - * - * @return string - */ - public function buildNewSip() { - $sipArray = $this->store->getStore(STORE_SIP); - unset($sipArray[SIP_SIP]); - unset($sipArray[SIP_URLPARAM]); - - $queryString = Support::arrayToQueryString($sipArray); - $sip = $this->store->getSipInstance(); - - $sipValue = $sip->queryStringToSip($queryString, RETURN_SIP); - - return $this->buildNativeHidden(CLIENT_SIP, $sipValue); - } - /** * @param $table * @param $recordId diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php index ff688059f..14cb2ebea 100644 --- a/extension/qfq/qfq/BuildFormBootstrap.php +++ b/extension/qfq/qfq/BuildFormBootstrap.php @@ -296,13 +296,11 @@ class BuildFormBootstrap extends AbstractBuildForm { */ public function tail() { $html = ''; - $html .= $this->buildNewSip(); +// $html .= $this->buildNewSip(); $deleteUrl = ''; $formId = $this->getFormId(); - // TODO: bootstrap. See BuildFormTable.tail() - $html .= '</div> <!--class="tab-content" -->'; // <div class="tab-content"> // $html .= '<input type="submit" value="Submit">'; diff --git a/extension/qfq/qfq/BuildFormPlain.php b/extension/qfq/qfq/BuildFormPlain.php index b115932ec..72d59b0aa 100644 --- a/extension/qfq/qfq/BuildFormPlain.php +++ b/extension/qfq/qfq/BuildFormPlain.php @@ -87,7 +87,7 @@ class BuildFormPlain extends AbstractBuildForm { public function tail() { $html = ''; - $html .= $this->buildNewSip(); +// $html .= $this->buildNewSip(); $html .= $this->wrapItem(WRAP_SETUP_INPUT, '<input type="submit" value="Submit">'); $html = $this->wrapItem(WRAP_SETUP_ELEMENT, $html); diff --git a/extension/qfq/qfq/BuildFormTable.php b/extension/qfq/qfq/BuildFormTable.php index f97880371..e47e44627 100644 --- a/extension/qfq/qfq/BuildFormTable.php +++ b/extension/qfq/qfq/BuildFormTable.php @@ -130,7 +130,7 @@ class BuildFormTable extends AbstractBuildForm { $html .= $this->wrapItem(WRAP_SETUP_INPUT, '<input type="submit" value="Submit">'); $html = $this->wrapItem(WRAP_SETUP_ELEMENT, $html); $html .= '</table>'; - $html .= $this->buildNewSip(); +// $html .= $this->buildNewSip(); $html .= '</form>'; $html .= '</div>'; // main <div class=...> around everything diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index 399c3892d..9e5b70ffb 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -226,10 +226,23 @@ class QuickFormQuery { case FORM_SAVE: $save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative); - $save->process(); + $rc = $save->process(); + + // Reload fresh saved record and fill STORE_RECORD with it + $record = $this->db->sql("SELECT * FROM " . $this->formSpec['tableName'] . " WHERE id = ?", ROW_EXPECT_1, [$rc]); + $this->store->setVarArray($record, STORE_RECORD, true); + + $htmlElementNameIdZero = false; + // Retrieve current STORE_SIP. + $sipArray = $this->store->getStore(STORE_SIP); + if ($sipArray[SIP_RECORD_ID] == 0) { + // After insert: a new SIP for the new record id is required + $this->newRecordCreateSip($sipArray, $rc); + $htmlElementNameIdZero = true; + } // Retrieve FE Values as JSON - $data = $build->process($mode); + $data = $build->process($mode, $htmlElementNameIdZero); break; default: @@ -340,7 +353,7 @@ class QuickFormQuery { break; case FORM_SAVE: case FORM_UPDATE: - $store = STORE_SIP; + $store = STORE_SIP; break; default: throw new CodeException("Unknown mode: $mode.", ERROR_UNKNOWN_MODE); @@ -420,6 +433,43 @@ class QuickFormQuery { return $sipFound; } + /** + * @param $sipArray + * @param $recordId + */ + private function newRecordCreateSip($sipArray, $recordId) { + + $tmpParam = array(); + + foreach ($sipArray as $key => $value) { + switch ($key) { + case SIP_SIP: + case SIP_URLPARAM: + case SIP_TABLE: + continue; + + case SIP_RECORD_ID: + $tmpParam[SIP_RECORD_ID] = $recordId; + break; + default: + // further vars stored in old SIP (form, maybe default values) + $tmpParam[$key] = $value; + break; + } + } + + // Construct fake urlparam + $tmpUrlparam = OnArray::toString($tmpParam); + + // Create a SIP which has never been passed by URL - further processing might expect this to exist. + $sip = store::getSipInstance()->queryStringToSip($tmpUrlparam, RETURN_SIP); + $this->store->setVar(CLIENT_SIP, $sip, STORE_CLIENT); + + // Overwrite SIP Store + $tmpParam[SIP_SIP] = $sip; + $this->store->setVarArray($tmpParam, STORE_SIP, true); + } + /** * Process the SQL Queries from bodytext. Return the output. * diff --git a/extension/qfq/qfq/Save.php b/extension/qfq/qfq/Save.php index 38a261fdf..e4cc4c38b 100644 --- a/extension/qfq/qfq/Save.php +++ b/extension/qfq/qfq/Save.php @@ -52,22 +52,25 @@ class Save { * @throws UserFormException */ public function process() { + $rc = 0; if ($this->formSpec['multiMode'] !== 'none') { $parentRecords = $this->db->sql($this->formSpec['multiSql']); foreach ($parentRecords as $row) { $this->store->setVarArray($row, STORE_PARENT_RECORD, true); - $this->elements($row['_id']); + $rc = $this->elements($row['_id']); } } else { - $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO)); + $rc = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO)); } + + return $rc; } /** * @param $recordId - * @return string + * @return int record id (in case of insert, it's different from $recordId) * @throws CodeException * @throws DbException * @throws UserFormException @@ -98,7 +101,14 @@ class Save { } } - return ($recordId == 0) ? $this->insertRecord($this->formSpec['tableName'], $newValues) : $this->updateRecord($this->formSpec['tableName'], $newValues, $recordId); + if ($recordId == 0) { + $rc = $this->insertRecord($this->formSpec['tableName'], $newValues); + } else { + $this->updateRecord($this->formSpec['tableName'], $newValues, $recordId); + $rc = $recordId; + } + + return $rc; } /** @@ -119,7 +129,7 @@ class Save { * Insert new record in table $this->formSpec['tableName']. * * @param array $values - * @return string + * @return int last insert id * @throws DbException */ public function insertRecord($tableName, array $values) { @@ -142,7 +152,7 @@ class Save { * @param string $tableName * @param array $values * @param int $recordId - * @return bool|int false if $values is empty + * @return bool|int false if $values is empty, else affectedrows * @throws CodeException * @throws DbException */ -- GitLab