diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst index 2ed0d3d4dd812aded1ae49e66624c7a94d971369..9d45c5b2db1c56abe36575cff74b514cc5334c82 100644 --- a/extension/Documentation/UsersManual/Index.rst +++ b/extension/Documentation/UsersManual/Index.rst @@ -557,6 +557,8 @@ parameter +------------------------+--------+----------------------------------------------------------------------------------------------------------+ | submitButtonText | string | Show save button, with the <submitButtonText> at the bottom of the form | +------------------------+--------+----------------------------------------------------------------------------------------------------------+ +| extraDeleteForm | string | Name of a form which specifies how to delete the primary record and optional slave records | ++------------------------+--------+----------------------------------------------------------------------------------------------------------+ * Example: @@ -611,6 +613,25 @@ classBody * Predefined background colors: `qfq-color-white`, `qfq-color-grey-1` (dark), `qfq-color-grey-2` (light), `qfq-color-blue-1` (dark), `qfq-color-blue-2`. (light) +submitButtonText +'''''''''''''''' + +If specified and non empty, display a regular submit button at the bottom of the page with the given text. +This gives the form a ordinary HTML-form look'n' feel. With this option, the standard buttons on the top right border +should be hided to not confuse the user. + +extraDeleteForm +''''''''''''''' + +Depending on the database definition, it might be necessary to delete the primary record *and* corresponding slave records. +To not repeat such 'slave record delete definition', an 'extraDeleteForm' could be specified. If the user open's a record +in a form and clicks on the 'delete' button, a defined 'extraDeleteForm'-form will be used to delete primary and slave +records instead of using the current form. +E.g. if there are multiple different forms to work on the same table, all of theses forms might reference to the same +'extraDeleteForm'-form. This simplifies the maintenance. + +The 'extraDeleteForm' parameter might be specified for a 'form' and/or for 'subrecords' + FormElements ------------ * Each *form* contains one or more *FormElement*. @@ -1048,6 +1069,7 @@ will be rendered inside the form as a HTML table. * *form*: Target form, e.g. *form=person* * *page*: Target page with detail form. If none specified, use the current page. * *title*: Title displayed over the table in the current form. + * *extraDeleteForm*: Optional. The per row delete Button will reference such form (for deleting) instead of *form* (default). * *detail*: Mapping of values from the primary form to the target form (defined via `form=...`). * Syntax:: diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index ba875bf14089f884263ea52753910d6fba1c40a2..218cf93ea4f10d1445c61aa2d7f426c89fc77769 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -1403,6 +1403,9 @@ abstract class AbstractBuildForm { if (isset($formElement[SUBRECORD_PARAMETER_FORM])) { + Support::setIfNotSet($formElement, F_EXTRA_DELETE_FORM, ''); + $formElement[F_FINAL_DELETE_FORM] = $formElement[F_EXTRA_DELETE_FORM] != '' ? $formElement[F_EXTRA_DELETE_FORM] : $formElement[SUBRECORD_PARAMETER_FORM]; + $linkNew = Support::wrapTag('<th>', $this->createFormLink($formElement, 0, $primaryRecord, $this->symbol[SYMBOL_NEW], 'New')); // Decode settings in subrecordOption @@ -1423,8 +1426,9 @@ abstract class AbstractBuildForm { $columns .= '<th>' . implode('</th><th>', $control['title']) . '</th>'; } - if ($flagDelete) + if ($flagDelete) { $columns .= '<th></th>'; + } // Table head $html = Support::wrapTag('<tr>', $columns); @@ -1449,17 +1453,16 @@ abstract class AbstractBuildForm { $toolTip = 'Delete'; if ($this->showDebugInfo) { - $toolTip .= PHP_EOL . "form = '" . $this->formSpec[F_NAME] . "'" . PHP_EOL . "table = '" . $this->formSpec[F_TABLE_NAME] . "'" . PHP_EOL . "r = '" . $row[$nameColumnId] . "'"; + $toolTip .= PHP_EOL . "form = '" . $formElement[F_FINAL_DELETE_FORM] . "'" . PHP_EOL . "r = '" . $row[$nameColumnId] . "'"; } // $buttonDelete = $this->buildButtonCode('delete-button', $toolTip, GLYPH_ICON_DELETE, $disabled); - $s = $this->createDeleteUrl($formElement[SUBRECORD_PARAMETER_FORM], $targetTableName, $row[$nameColumnId], RETURN_SIP); + $s = $this->createDeleteUrl($formElement[F_FINAL_DELETE_FORM], '', $row[$nameColumnId], RETURN_SIP); // $rowHtml .= Support::wrapTag('<td>', Support::wrapTag("<button type='button' class='record-delete btn btn-default' data-sip='$s'>", '<span class="glyphicon ' . GLYPH_ICON_DELETE . '"></span>')); $rowHtml .= Support::wrapTag('<td>', Support::wrapTag("<button type='button' class='record-delete btn btn-default' data-sip='$s' " . Support::doAttribute('title', $toolTip) . ">", '<span class="glyphicon ' . GLYPH_ICON_DELETE . '"></span>')); - } Support::setIfNotSet($row, FE_SUBRECORD_ROW_CLASS); @@ -1753,15 +1756,19 @@ abstract class AbstractBuildForm { */ public function createDeleteUrl($formName, $tableName, $recordId, $mode = RETURN_URL) { - //TODO: Umstellen auf Benutzung der Link Klasse. - $queryStringArray = [ - SIP_FORM => $formName, - SIP_TABLE => $tableName, SIP_RECORD_ID => $recordId, SIP_MODE_ANSWER => MODE_JSON ]; + if ($formName !== '') { + $queryStringArray[SIP_FORM] = $formName; + } + + if ($tableName !== '') { + $queryStringArray[SIP_TABLE] = $tableName; + } + $queryString = Support::arrayToQueryString($queryStringArray); $sip = $this->store->getSipInstance(); diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php index 0a14ebf3d8e0a7d515e6ed0ca93e5515160a61e6..5e3e999afc1fb25ae0775ee9eb87a9b3f5d63a8d 100644 --- a/extension/qfq/qfq/BuildFormBootstrap.php +++ b/extension/qfq/qfq/BuildFormBootstrap.php @@ -158,10 +158,6 @@ class BuildFormBootstrap extends AbstractBuildForm { if (Support::findInSet(FORM_BUTTON_CLOSE, $this->formSpec['showButton'])) { $toolTip = 'Close'; - if ($this->showDebugInfo) { - $toolTip .= PHP_EOL . "table = '" . $this->formSpec[F_TABLE_NAME] . "'" . PHP_EOL . "r = '" . $recordId . "'"; - } - $buttonClose = $this->buildButtonCode('close-button', 'Close', GLYPH_ICON_CLOSE); } @@ -170,7 +166,7 @@ class BuildFormBootstrap extends AbstractBuildForm { $toolTip = 'Delete'; if ($this->showDebugInfo && $recordId > 0) { - $toolTip .= PHP_EOL . "form = '" . $this->formSpec[F_NAME] . "'" . PHP_EOL . "table = '" . $this->formSpec[F_TABLE_NAME] . "'" . PHP_EOL . "r = '" . $recordId . "'"; + $toolTip .= PHP_EOL . "form = '" . $this->formSpec[F_FINAL_DELETE_FORM] . "'" . PHP_EOL . "r = '" . $recordId . "'"; } $disabled = ($recordId > 0) ? '' : 'disabled'; @@ -345,7 +341,7 @@ class BuildFormBootstrap extends AbstractBuildForm { $tabId = $this->getTabId(); if (0 < ($recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP))) { - $deleteUrl = $this->createDeleteUrl($this->formSpec[F_NAME], $this->formSpec[F_TABLE_NAME], $recordId); + $deleteUrl = $this->createDeleteUrl($this->formSpec[F_FINAL_DELETE_FORM], '', $recordId); } $actionUpload = FILE_ACTION . '=' . FILE_ACTION_UPLOAD; diff --git a/extension/qfq/qfq/BuildFormTable.php b/extension/qfq/qfq/BuildFormTable.php index f4e5a1ef0dd0a7eebb68f526004b2e1f8ee60752..4149457d713053c10b13d4355fd892b5c630282f 100644 --- a/extension/qfq/qfq/BuildFormTable.php +++ b/extension/qfq/qfq/BuildFormTable.php @@ -77,7 +77,7 @@ class BuildFormTable extends AbstractBuildForm { $formEditUrl = $this->createFormEditUrl(); $html .= "<p><a " . Support::doAttribute('href', $formEditUrl) . ">Edit</a><small>[$sipParamString]</small></p>"; - $deleteUrl = $this->createDeleteUrl($this->formSpec[F_NAME], $this->formSpec[F_TABLE_NAME], $this->store->getVar(SIP_RECORD_ID, STORE_SIP)); + $deleteUrl = $this->createDeleteUrl($this->formSpec[F_FINAL_DELETE_FORM], '', $this->store->getVar(SIP_RECORD_ID, STORE_SIP)); $html .= "<p><a " . Support::doAttribute('href', $deleteUrl) . ">Delete</a>"; $html .= $this->wrapItem(WRAP_SETUP_TITLE, $this->formSpec['title'], true); diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 444951bbf83f8492face9ee35a17f48329d9c010..30d7ddb85678e8510b4631b2c79004080b5bed35 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -443,8 +443,11 @@ const GLYPH_ICON_CLOSE = 'glyphicon-remove'; // FORM const F_NAME = 'name'; +const F_TITLE = 'title'; const F_TABLE_NAME = 'tableName'; const F_REQUIRED_PARAMETER = 'requiredParameter'; +const F_EXTRA_DELETE_FORM = 'extraDeleteForm'; +const F_FINAL_DELETE_FORM = 'finalDeleteForm'; const F_SUBMIT_BUTTON_TEXT = 'submitButtonText'; diff --git a/extension/qfq/qfq/Database.php b/extension/qfq/qfq/Database.php index 53e9e11d20eefc1466cd8266e08dc65a1fbf89d7..6294700aefc07b498b668142a6513f83c897d58b 100644 --- a/extension/qfq/qfq/Database.php +++ b/extension/qfq/qfq/Database.php @@ -238,6 +238,7 @@ class Database { $sqlLogMode = $this->isSqlModify($sql) ? SQL_LOG_MODE_MODIFY : SQL_LOG_MODE_ALL;; $result = 0; $stat = array(); + $debugSql = ''; $this->store->setVar(SYSTEM_SQL_FINAL, $sql, STORE_SYSTEM); $this->store->setVar(SYSTEM_SQL_PARAM_ARRAY, $parameterArray, STORE_SYSTEM); @@ -245,18 +246,26 @@ class Database { // Logfile $this->dbLog($sqlLogMode, $sql, $parameterArray); + // If BE User is logged in: report the broken SQL as well. + + //TODO: im Fall von delete.php, save.php, kann hier der BE_USER nicht abgefragt werden (laeuft nicht durch T3) - Loesung finden. + + if (true) { + $debugSql = '[' . $sql . ']'; + } + if (false === ($this->mysqli_stmt = $this->mysqli->prepare($sql))) { - throw new DbException('[ mysqli: ' . $this->mysqli->errno . ' ] ' . $this->mysqli->error, ERROR_DB_PREPARE); + throw new DbException('[ mysqli: ' . $this->mysqli->errno . ' ] ' . $this->mysqli->error . $debugSql, ERROR_DB_PREPARE); } if (count($parameterArray) > 0) { if (false === $this->prepareBindParam($parameterArray)) { - throw new DbException('[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error, ERROR_DB_BIND); + throw new DbException('[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error . $debugSql, ERROR_DB_BIND); } } if (false === $this->mysqli_stmt->execute()) { - throw new DbException('[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error, ERROR_DB_EXECUTE); + throw new DbException('[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error . $debugSql, ERROR_DB_EXECUTE); } $msg = ''; diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index be437ca653be754bcd8b8a98ea1b6dc620c8883b..c21158561fe4e0cc2c7504aa3671a25e8b4b61e0 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -233,7 +233,7 @@ class QuickFormQuery { $sipFound = $this->validateForm($foundInStore, $formMode); } else { - // FORM_DELETE without a form definition: Fake the form wiht only a tableName. + // FORM_DELETE without a form definition: Fake the form with only a tableName. $table = $this->store->getVar(SIP_TABLE, STORE_SIP); if ($table === false) { throw new UserFormException("No 'form' and no 'table' definition found.", ERROR_MISSING_VALUE); @@ -378,6 +378,8 @@ class QuickFormQuery { $form = $this->db->sql("SELECT * FROM Form AS f WHERE f." . F_NAME . " LIKE ? AND f.deleted='no'", ROW_EXPECT_1, [$formName], 'Form not found or multiple forms with the same name.'); + $form = $this->modeAdjustFormConfig($mode, $form); + $this->formSpec = $this->eval->parseArray($form); HelperFormElement::explodeParameter($this->formSpec); @@ -388,6 +390,10 @@ class QuickFormQuery { Support::setIfNotSet($this->formSpec, F_BS_NOTE_COLUMNS, 3, ''); Support::setIfNotSet($this->formSpec, F_SUBMIT_BUTTON_TEXT, ''); + Support::setIfNotSet($this->formSpec, F_EXTRA_DELETE_FORM, ''); + + // Set F_FINAL_DELETE_FORM + $this->formSpec[F_FINAL_DELETE_FORM] = $this->formSpec[F_EXTRA_DELETE_FORM] != '' ? $this->formSpec[F_EXTRA_DELETE_FORM] : $this->formSpec[F_NAME]; // Take default from config.ini $class = $this->store->getVar(SYSTEM_CSS_CLASS_QFQ_FORM_PILL, STORE_SYSTEM); @@ -491,6 +497,27 @@ class QuickFormQuery { return $formName; } + /** + * Depending on $mode various formSpec fields might be adjusted. + * E.g.: the form title is not important during a delete. + * + * @param $mode + * @param array $form + * @return array + */ + private function modeAdjustFormConfig($mode, array $form) { + + switch ($mode) { + case FORM_DELETE: + $form[F_TITLE] = ''; + break; + default: + break; + } + + return $form; + } + /** * Check if loading of the given form is permitted. If not, throw an exception. *