From 5b899934f1525cf8aa5cf992ecb825ae7fd578d0 Mon Sep 17 00:00:00 2001
From: Carsten  Rose <carsten.rose@math.uzh.ch>
Date: Tue, 3 May 2016 09:46:02 +0200
Subject: [PATCH] Recode: fromelement.mode='readonly' new implemented on
 client, by using CSS attribute 'disabled'. The HTML atrribute 'readonly' is
 fine for pure 'input' elements, but does not work sufficient for 'select',
 'checkbox', 'radio'. Also, the label (left of input) and note (right of
 input) are now grayed out if set to 'disable'. FillStoreForm.php, Save.php:
 strings replaced by constants. New central function getfeMode() used by
 getJsonFeMode() and getAttributeFeMode()

---
 extension/qfq/qfq/AbstractBuildForm.php   | 106 +++++++++++++++-------
 extension/qfq/qfq/Constants.php           |  12 ++-
 extension/qfq/qfq/Save.php                |   2 +-
 extension/qfq/qfq/store/FillStoreForm.php |   2 +-
 extension/qfq/sql/formEditor.sql          |   8 +-
 extension/qfq/sql/testtables.sql          |   4 +-
 6 files changed, 93 insertions(+), 41 deletions(-)

diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index b5682ba8e..72b73b83d 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -429,7 +429,7 @@ abstract class AbstractBuildForm {
 
         $sipValue = $sip->queryStringToSip($queryString, RETURN_SIP);
 
-        $json[] = $this->getJsonElementUpdate(CLIENT_SIP, $sipValue, '');
+        $json[] = $this->getJsonElementUpdate(CLIENT_SIP, $sipValue, FE_MODE_SHOW);
 
         return $this->buildNativeHidden(CLIENT_SIP, $sipValue);
     }
@@ -437,20 +437,64 @@ abstract class AbstractBuildForm {
     /**
      * @param $htmlFormElementId
      * @param string|array $value
-     * @param string $mode disabled|readonly|''
+     * @param string $feMode disabled|readonly|''
      * @return array
      */
-    private function getJsonElementUpdate($htmlFormElementId, $value, $mode) {
-        $json = array();
+    private function getJsonElementUpdate($htmlFormElementId, $value, $feMode) {
+        $json = $this->getJsonFeMode($feMode);
 
         $json['form-element'] = $htmlFormElementId;
         $json['value'] = $value;
-        $json['disabled'] = ($mode === 'disabled');
-        $json['readonly'] = ($mode === 'readonly');
+//        $json['disabled'] = ($feMode === 'disabled');
+//        $json['readonly'] = ($feMode === 'readonly');
 
         return $json;
     }
 
+    /**
+     * Set corresponding JSON attributes readonly/required/disabled, based on $formElement[FE_MODE].
+     *
+     * @param array $feMode
+     * @return array
+     * @throws UserFormException
+     */
+    private function getJsonFeMode($feMode) {
+
+        $this->getFeMode($feMode, $hidden, $disabled, $required);
+
+        return [API_JSON_HIDDEN => $hidden === 'yes', API_JSON_DISABLED => $disabled === 'yes', API_JSON_REQUIRED => $required === 'yes'];
+    }
+
+    /**
+     * @param $feMode
+     * @param $hidden
+     * @param $disabled
+     * @param $required
+     * @throws \qfq\UserFormException
+     */
+    private function getFeMode($feMode, &$hidden, &$disabled, &$required) {
+        $hidden = 'no';
+        $disabled = 'no';
+        $required = 'no';
+
+        switch ($feMode) {
+            case FE_MODE_SHOW:
+                break;
+            case FE_MODE_REQUIRED:
+                $required = 'yes';
+                break;
+            case FE_MODE_READONLY:
+                $disabled = 'yes';  // convert the UI status 'readonly' to the HTML/CSS status disabled.
+                break;
+            case FE_MODE_HIDDEN:
+                $hidden = 'yes';
+                break;
+            default:
+                throw new UserFormException("Unknown mode '$feMode'", ERROR_UNKNOWN_MODE);
+                break;
+        }
+    }
+
     /**
      * Builds a real HTML hidden form element. Useful for checkboxes, Multiple-Select and Radios.
      *
@@ -564,7 +608,7 @@ abstract class AbstractBuildForm {
         $attribute .= Support::doAttribute('title', $formElement['tooltip']);
         $attribute .= $this->getInputCheckPattern($formElement['checkType'], $formElement['checkPattern']);
 
-        $attribute .= $this->getAttributeMode($formElement);
+        $attribute .= $this->getAttributeFeMode($formElement[FE_MODE]);
 
         $json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement[FE_MODE]);
 
@@ -716,34 +760,32 @@ abstract class AbstractBuildForm {
     /**
      * Set corresponding html attributes readonly/required/disabled, based on $formElement[FE_MODE].
      *
-     * @param array $formElement
+     * @param string $feMode
      * @return string
      * @throws UserFormException
      */
-    private function getAttributeMode(array $formElement) {
+    private function getAttributeFeMode($feMode) {
         $attribute = '';
 
-        switch ($formElement[FE_MODE]) {
-            case 'show':
-                break;
-            case 'readonly':
-                $attribute .= Support::doAttribute('readonly', 'readonly');
-                break;
-            case 'required':
-                $attribute .= Support::doAttribute('required', 'required');
-                break;
-            case 'lock':
+        $this->getFeMode($feMode, $hidden, $disabled, $required);
+
+        switch ($feMode) {
+            case FE_MODE_HIDDEN:
+            case FE_MODE_SHOW:
                 break;
-            case 'disabled':
-                $attribute .= Support::doAttribute('disabled', 'disabled');
+            case FE_MODE_REQUIRED:
+            case FE_MODE_READONLY:
+                $attribute .= Support::doAttribute($feMode, $feMode);
                 break;
             default:
-                // Preparation for Log, Debug
-                $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($formElement), STORE_SYSTEM);
-                $this->store->setVar(SYSTEM_FORM_ELEMENT_COLUMN, FE_MODE, STORE_SYSTEM);
-                throw new UserFormException("Unknown mode '" . $formElement[FE_MODE] . "'", ERROR_UNKNOWN_MODE);
+                throw new UserFormException("Unknown mode '$feMode'", ERROR_UNKNOWN_MODE);
                 break;
         }
+
+        $attribute .= Support::doAttribute(DATA_DISABLED, $disabled);
+        $attribute .= Support::doAttribute(DATA_HIDDEN, $hidden);
+        $attribute .= Support::doAttribute(DATA_REQUIRED, $required);
+
         return $attribute;
     }
 
@@ -789,7 +831,7 @@ abstract class AbstractBuildForm {
             $this->prepareCheckboxCheckedUncheckedValue($itemKey, $formElement);
         }
 
-        $attributeBase = $this->getAttributeMode($formElement);
+        $attributeBase = $this->getAttributeFeMode($formElement[FE_MODE]);
         $attributeBase .= Support::doAttribute('type', $formElement[FE_TYPE]);
 
         switch ($formElement['checkBoxMode']) {
@@ -1097,7 +1139,7 @@ abstract class AbstractBuildForm {
         // Fill $itemKey & $itemValue
         $this->getKeyValueListFromSqlEnumSpec($formElement, $itemKey, $itemValue);
 
-        $attributeBase = $this->getAttributeMode($formElement);
+        $attributeBase = $this->getAttributeFeMode($formElement[FE_MODE]);
         $attributeBase .= Support::doAttribute('name', $htmlFormElementId);
         $attributeBase .= Support::doAttribute('type', $formElement[FE_TYPE]);
         $attributeBase .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
@@ -1158,7 +1200,7 @@ abstract class AbstractBuildForm {
         // Fill $itemKey & $itemValue
         $this->getKeyValueListFromSqlEnumSpec($formElement, $itemKey, $itemValue);
 
-        $attribute = $this->getAttributeMode($formElement);
+        $attribute = $this->getAttributeFeMode($formElement[FE_MODE]);
         $attribute .= Support::doAttribute('name', $htmlFormElementId);
         $attribute .= Support::doAttribute('class', 'form-control');
         $attribute .= Support::doAttribute('title', $formElement['tooltip']);
@@ -1577,10 +1619,10 @@ abstract class AbstractBuildForm {
         } else {
             $textDeleteClass = '';
             $uploadClass = 'hidden';
-            $formElement[FE_MODE] = 'disabled';
+            $formElement[FE_MODE] = FE_MODE_HIDDEN;
         }
 
-        $attribute .= $this->getAttributeMode($formElement);
+        $attribute .= $this->getAttributeFeMode($formElement[FE_MODE]);
         $attribute .= Support::doAttribute('class', $uploadClass, true);
         $htmlInputFile = '<input ' . $attribute . '>' . $this->getHelpBlock();
 
@@ -1641,7 +1683,7 @@ abstract class AbstractBuildForm {
         $attribute .= Support::doAttribute('title', $formElement['tooltip']);
         $attribute .= $this->getInputCheckPattern($formElement['checkType'], $formElement['checkPattern']);
 
-        $attribute .= $this->getAttributeMode($formElement);
+        $attribute .= $this->getAttributeFeMode($formElement[FE_MODE]);
 
         $json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement[FE_MODE]);
 
@@ -1741,7 +1783,7 @@ abstract class AbstractBuildForm {
             $attribute .= Support::doAttribute('max', $arrMinMax[1]);
         }
 
-        $attribute .= $this->getAttributeMode($formElement);
+        $attribute .= $this->getAttributeFeMode($formElement[FE_MODE]);
 
         $json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement[FE_MODE]);
 
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index c5eb3e0ba..75d55a89c 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -314,7 +314,7 @@ const RANDOM_LENGTH = 32;
 const SQL_LOG_MODE_ALL = 'all';
 const SQL_LOG_MODE_MODIFY = 'modify';
 
-// api/save.php, api/delete.php
+// api/save.php, api/delete.php, api/load.php
 const API_STATUS = 'status';
 const API_MESSAGE = 'message';
 const API_REDIRECT = 'redirect';
@@ -323,6 +323,14 @@ const API_FIELD_NAME = 'field-name';
 const API_FIELD_MESSAGE = 'field-message';
 const API_FORM_UPDATE = 'form-update';
 
+const API_JSON_HIDDEN = 'hidden';
+const API_JSON_DISABLED = 'disabled';
+const API_JSON_REQUIRED = 'required';
+
+const DATA_HIDDEN = 'data-hidden';
+const DATA_DISABLED = 'data-disabled';
+const DATA_REQUIRED = 'data-required';
+
 const API_ANSWER_STATUS_SUCCESS = 'success';
 const API_ANSWER_STATUS_ERROR = 'error';
 const API_ANSWER_REDIRECT_CLIENT = 'client';
@@ -365,7 +373,7 @@ const GLYPH_ICON_CHECK = 'glyphicon glyphicon-ok';
 const FE_MODE_SHOW = 'show';
 const FE_MODE_READONLY = 'readonly';
 const FE_MODE_REQUIRED = 'required';
-const FE_MODE_DISABLED = 'disabled';
+const FE_MODE_HIDDEN = 'hidden';
 
 const FE_SUBRECORD_ROW_CLASS = '_rowClass';
 const FE_SUBRECORD_ROW_TITLE = '_rowTitle';
diff --git a/extension/qfq/qfq/Save.php b/extension/qfq/qfq/Save.php
index d2bcbb5f3..7e3e58c08 100644
--- a/extension/qfq/qfq/Save.php
+++ b/extension/qfq/qfq/Save.php
@@ -100,7 +100,7 @@ class Save {
             // Some modes means: do not save this column.
             switch ($formElement[FE_MODE]) {
                 case FE_MODE_READONLY:
-                case FE_MODE_DISABLED:
+                case FE_MODE_HIDDEN:
                     continue 2;  // 1 for switch, 2 for continue foreach.
                 default:
                     break;
diff --git a/extension/qfq/qfq/store/FillStoreForm.php b/extension/qfq/qfq/store/FillStoreForm.php
index 72f3f7092..34b959b53 100644
--- a/extension/qfq/qfq/store/FillStoreForm.php
+++ b/extension/qfq/qfq/store/FillStoreForm.php
@@ -167,7 +167,7 @@ class FillStoreForm {
                     break;
 
                 case FE_MODE_READONLY:
-                case FE_MODE_DISABLED:
+                case FE_MODE_HIDDEN:
                     continue;
                 default:
                     throw new CodeException("Unknown mode: " . $formElement[FE_MODE], ERROR_UNKNOWN_MODE);
diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql
index d796a85b5..a64929718 100644
--- a/extension/qfq/sql/formEditor.sql
+++ b/extension/qfq/sql/formEditor.sql
@@ -63,7 +63,7 @@ CREATE TABLE IF NOT EXISTS `FormElement` (
   `name`            VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
   `label`           VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
 
-  `mode`           ENUM('show', 'required', 'readonly', 'disabled') NOT NULL  DEFAULT 'show',
+  `mode`           ENUM('show', 'required', 'readonly', 'hidden') NOT NULL  DEFAULT 'show',
   `class`           ENUM('native', 'action', 'container')                                                   NOT NULL  DEFAULT 'native',
   `type`            ENUM('checkbox', 'date', 'datetime', 'dateJQW', 'datetimeJQW', 'gridJQW', 'hidden', 'text', 'time',
                          'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill',
@@ -81,9 +81,9 @@ CREATE TABLE IF NOT EXISTS `FormElement` (
 
   `size`            VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
   `maxLength`       VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
-  `bsLabelColumns` VARCHAR(255)                                     NOT NULL  DEFAULT '',
-  `bsInputColumns` VARCHAR(255)                                     NOT NULL  DEFAULT '',
-  `bsNoteColumns`  VARCHAR(255)                                     NOT NULL  DEFAULT '',
+  `bsLabelColumns` VARCHAR(255)                                   NOT NULL  DEFAULT '',
+  `bsInputColumns` VARCHAR(255)                                   NOT NULL  DEFAULT '',
+  `bsNoteColumns`  VARCHAR(255)                                   NOT NULL  DEFAULT '',
   `note`            TEXT                                                                                    NOT NULL,
   `tooltip`         VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
   `placeholder`     VARCHAR(255)                                                                            NOT NULL  DEFAULT '',
diff --git a/extension/qfq/sql/testtables.sql b/extension/qfq/sql/testtables.sql
index 5d8c224b8..392c4573c 100644
--- a/extension/qfq/sql/testtables.sql
+++ b/extension/qfq/sql/testtables.sql
@@ -64,7 +64,9 @@ VALUES
   (503, 5, 'datumZeit', 'Datum & Zeit', 'show', 'datetime', 'alnumx', 'native', 50, 0, 0, '', '', '', '', '', '', 0,
    ''),
   (504, 5, 'zeit', 'Zeit', 'show', 'time', 'alnumx', 'native', 60, 0, 0, '', '', '', '', '', '', 0, ''),
-  (505, 5, 'picture', 'Picture', 'show', 'upload', 'allbut', 'native', 70, 0, 0, '', '', '', '', '', '', 0, '');
+  (505, 5, 'picture', 'Picture', 'show', 'upload', 'allbut', 'native', 70, 0, 0, '', '', '', '', '',
+   'pathFileName={{SELECT ''fileadmin/user/pictures/'', p.name, ''-{{_filename}}'' FROM Person AS p WHERE p.id={{r}} }}',
+   0, '');
 
 # ----------------------------------------------------------------------
 #
-- 
GitLab