public static function prepareSpecialValueForSave($varValue, $arrData, $strTable = null, $intId = 0, $varDefault = null, &$arrWidgetErrors = array())
 {
     // Convert date formats into timestamps
     if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) {
         try {
             $objDate = new \Date($varValue, \Config::get($arrData['eval']['rgxp'] . 'Format'));
             $varValue = $objDate->tstamp;
         } catch (\OutOfBoundsException $e) {
             $arrWidgetErrors[] = sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varValue);
             return $varDefault;
         }
     }
     if ($arrData['eval']['multiple'] && isset($arrData['eval']['csv'])) {
         $varValue = implode($arrData['eval']['csv'], deserialize($varValue, true));
     }
     if ($arrData['inputType'] == 'tag' && in_array('tags_plus', \ModuleLoader::getActive())) {
         $varValue = \HeimrichHannot\TagsPlus\TagsPlus::loadTags($strTable, $intId);
     }
     if ($arrData['eval']['encrypt']) {
         $varValue = \Encryption::encrypt($varValue);
     }
     return $varValue;
 }
 protected function generateField($strName, $arrData, $skipValidation = false)
 {
     $strClass = $GLOBALS['TL_FFL'][$arrData['inputType']];
     // overwrite the widget in readonly mode
     if ($this->viewMode == FORMHYBRID_VIEW_MODE_READONLY || $this->viewMode == FORMHYBRID_VIEW_MODE_DEFAULT && $this->addReadOnly && in_array($strName, $this->arrReadOnly)) {
         $strClass = 'HeimrichHannot\\FormHybrid\\FormReadonlyField';
         $skipValidation = true;
     }
     $strInputMethod = $this->strInputMethod;
     // Continue if the class is not defined
     if (!class_exists($strClass)) {
         return false;
     }
     $arrWidgetErrors = array();
     // contains the load_callback!
     $varDefault = $this->getDefaultFieldValue($strName, $arrData);
     $varValue = $varDefault;
     if ($this->isSubmitted && !$skipValidation) {
         $varValue = \Input::$strInputMethod($strName) !== null ? \Input::$strInputMethod($strName) : $varValue;
         $varValue = FormSubmission::prepareSpecialValueForSave($varValue, $arrData, $this->strTable, $this->intId, $varDefault, $arrWidgetErrors);
     }
     // overwrite required fields
     if ($this->overwriteRequired) {
         // set mandatory to false
         $arrData['eval']['mandatory'] = false;
         // overwrite mandatory by config
         if (!$arrData['eval']['mandatory'] && in_array($strName, $this->arrRequired)) {
             $arrData['eval']['mandatory'] = true;
         }
     }
     // prevent name for GET and submit widget, otherwise url will have submit name in
     if ($this->strMethod == FORMHYBRID_METHOD_GET && $arrData['inputType'] == 'submit') {
         $strName = '';
     }
     $arrData['eval']['tagTable'] = $this->strTable;
     // always disable validation for filter form
     if ($this->isFilterForm) {
         $arrData['eval']['mandatory'] = false;
     }
     // to make captcha form related, add the form id without entity id
     if ($arrData['inputType'] == 'captcha') {
         $strName .= '_' . $this->getFormId(false);
     }
     $this->strField = $strName;
     $this->strInputName = $strName;
     $this->varValue = is_array($varValue) ? $varValue : \Controller::replaceInsertTags($varValue);
     $arrWidget = \Widget::getAttributesFromDca($arrData, $strName, is_array($varValue) ? $varValue : \Controller::replaceInsertTags($varValue), $strName, $this->strTable, $this);
     $this->updateWidget($arrWidget, $arrData);
     list($blnActive, $strSubPalette, $arrFields, $arrSubPaletteFields, $blnAutoSubmit, $blnToggleSubpalette) = $this->retrieveSubpaletteWithState($strName, array_keys($this->arrFields));
     // support submitOnChange as form submission
     if ($arrData['eval']['submitOnChange'] && $blnToggleSubpalette) {
         if ($blnAutoSubmit) {
             $arrWidget['onchange'] = $this->async ? 'FormhybridAjaxRequest.asyncSubmit(this.form);' : "this.form.submit();";
         } else {
             $strEvent = 'onclick';
             switch ($arrData['inputType']) {
                 case 'select':
                     $strEvent = 'onchange';
                     break;
             }
             $arrWidget[$strEvent] = "FormhybridAjaxRequest.toggleSubpalette(this, 'sub_" . $strName . "', '" . $strName . "', '" . AjaxAction::generateUrl(Form::FORMHYBRID_NAME, 'toggleSubpalette') . "')";
             unset($arrWidget['submitOnChange']);
         }
     } else {
         if ($arrWidget['submitOnChange']) {
             $strEvent = null;
             if ($arrWidget['onchange']) {
                 $strEvent = 'onchange';
             } else {
                 if ($arrWidget['onclick']) {
                     $strEvent = 'onclick';
                 }
             }
             if ($strEvent !== null) {
                 $arrWidget[$strEvent] = "FormhybridAjaxRequest.reload('" . $this->getFormId() . "', '" . AjaxAction::generateUrl(Form::FORMHYBRID_NAME, 'reload') . "')";
                 unset($arrWidget['submitOnChange']);
             }
         }
     }
     $objWidget = new $strClass($arrWidget);
     if (isset($arrData['formHybridOptions'])) {
         $arrFormHybridOptions = $arrData['formHybridOptions'];
         $this->import($arrFormHybridOptions[0]);
         $objWidget->options = $this->{$arrFormHybridOptions}[0]->{$arrFormHybridOptions}[1]();
     }
     if ($objWidget instanceof \uploadable) {
         $this->hasUpload = true;
     }
     // always xss clean the user input (also if filter, non-model submission, ...) -> done another time
     // FrontendWidget::validateGetAndPost() in
     $objWidget->value = FormHelper::xssClean($objWidget->value, $arrData['eval']['allowHtml']);
     if ($this->isSubmitted) {
         // add filter class if filter is active
         if ($objWidget->value && $this->isFilterForm) {
             $objWidget->class = 'filtered';
         }
         // do not validate fields if not submitted or skipvalidation issset
         // do not submit if ajax request and group is not formhybrid, for example multifileupload (otherwise captcha fields will be validated does not match visible one)
         if (!($this->isSkipValidation() || $skipValidation) && Ajax::isRelated(Form::FORMHYBRID_NAME) !== false) {
             FrontendWidget::validateGetAndPost($objWidget, $this->strMethod, $this->getFormId(), $arrData);
             if (is_array($arrWidgetErrors)) {
                 foreach ($arrWidgetErrors as $strError) {
                     $objWidget->addError($strError);
                 }
             }
             // Make sure unique fields are unique
             if ($arrData['eval']['unique'] && $varValue != '' && !\Database::getInstance()->isUniqueValue($this->strTable, $strName, $varValue, $this->intId > 0 ? $this->intId : null)) {
                 $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrData['label'][0] ?: $strName));
             }
             // trigger save_callbacks before assertion of the new value to objActiveRecord
             if (is_array($arrData['save_callback'])) {
                 foreach ($arrData['save_callback'] as $callback) {
                     if (is_array($callback)) {
                         $this->import($callback[0]);
                         $varValue = $this->{$callback}[0]->{$callback}[1]($varValue, $this);
                     } elseif (is_callable($callback)) {
                         $varValue = $callback($varValue, $this);
                     }
                 }
             }
             if ($objWidget->hasErrors()) {
                 $this->doNotSubmit = true;
                 $this->arrInvalidFields[] = $strName;
             } elseif ($arrData['inputType'] == 'tag' && in_array('tags_plus', \ModuleLoader::getActive())) {
                 $varValue = deserialize($objWidget->value);
                 if (!is_array($varValue)) {
                     $varValue = array($varValue);
                 }
                 if ($this->intId) {
                     \HeimrichHannot\TagsPlus\TagsPlus::saveTags($this->strTable, $this->intId, array_map('urldecode', $varValue));
                 }
             } elseif ($objWidget->submitInput()) {
                 // save non escaped to database
                 if (is_array($objWidget->value)) {
                     $this->objActiveRecord->{$strName} = array_map(function ($varVal) use($arrData) {
                         $varVal = FormSubmission::prepareSpecialValueForSave($varVal, $arrData, $this->strTable, $this->intId);
                         if (is_array($varVal)) {
                             foreach ($varVal as $key => $val) {
                                 $varVal[$key] = html_entity_decode($val);
                             }
                         } else {
                             $varVal = html_entity_decode($varVal);
                         }
                         return $varVal;
                     }, $objWidget->value);
                 } else {
                     $this->objActiveRecord->{$strName} = html_entity_decode(FormSubmission::prepareSpecialValueForSave($objWidget->value, $arrData, $this->strTable, $this->intId));
                 }
             } elseif ($objWidget instanceof \uploadable && $arrData['inputType'] == 'multifileupload') {
                 $strMethod = strtolower($this->strMethod);
                 if (\Input::$strMethod($strName)) {
                     $arrValue = json_decode(\Input::$strMethod($strName));
                     if (!empty($arrValue)) {
                         $arrValue = array_map(function ($val) {
                             return \String::uuidToBin($val);
                         }, $arrValue);
                         $this->objActiveRecord->{$strName} = serialize($arrValue);
                     } else {
                         $this->objActiveRecord->{$strName} = serialize($arrValue);
                     }
                 }
                 // delete the files scheduled for deletion
                 $objWidget->deleteScheduledFiles(json_decode(\Input::$strMethod('deleted_' . $strName)));
             } elseif ($objWidget instanceof \uploadable && isset($_SESSION['FILES'][$strName]) && \Validator::isUuid($_SESSION['FILES'][$strName]['uuid'])) {
                 $this->objActiveRecord->{$strName} = $_SESSION['FILES'][$strName]['uuid'];
             }
         }
     }
     return $objWidget;
 }