Exemple #1
0
 /**
  * Save the current value
  *
  * @param mixed $varValue
  *
  * @throws \Exception
  */
 protected function save($varValue)
 {
     if (\Input::post('FORM_SUBMIT') != $this->strTable) {
         return;
     }
     $arrData = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField];
     // Convert date formats into timestamps
     if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) {
         $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp']));
         $varValue = $objDate->tstamp;
     }
     // Make sure unique fields are unique
     if ($arrData['eval']['unique'] && $varValue != '' && !$this->Database->isUniqueValue($this->strTable, $this->strField, $varValue, $this->objActiveRecord->id)) {
         throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrData['label'][0] ?: $this->strField));
     }
     // Handle multi-select fields in "override all" mode
     if (\Input::get('act') == 'overrideAll' && ($arrData['inputType'] == 'checkbox' || $arrData['inputType'] == 'checkboxWizard') && $arrData['eval']['multiple']) {
         if ($this->objActiveRecord !== null) {
             $new = deserialize($varValue, true);
             $old = deserialize($this->objActiveRecord->{$this->strField}, true);
             // Call load_callback
             if (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'])) {
                 foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'] as $callback) {
                     if (is_array($callback)) {
                         $this->import($callback[0]);
                         $old = $this->{$callback[0]}->{$callback[1]}($old, $this);
                     } elseif (is_callable($callback)) {
                         $old = $callback($old, $this);
                     }
                 }
             }
             switch (\Input::post($this->strInputName . '_update')) {
                 case 'add':
                     $varValue = array_values(array_unique(array_merge($old, $new)));
                     break;
                 case 'remove':
                     $varValue = array_values(array_diff($old, $new));
                     break;
                 case 'replace':
                     $varValue = $new;
                     break;
             }
             if (!is_array($varValue) || empty($varValue)) {
                 $varValue = $arrData['eval']['nullIfEmpty'] ? null : '';
             } elseif (isset($arrData['eval']['csv'])) {
                 $varValue = implode($arrData['eval']['csv'], $varValue);
                 // see #2890
             } else {
                 $varValue = serialize($varValue);
             }
         }
     }
     // Convert arrays (see #2890)
     if ($arrData['eval']['multiple'] && isset($arrData['eval']['csv'])) {
         $varValue = implode($arrData['eval']['csv'], deserialize($varValue, true));
     }
     // Trigger the save_callback
     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);
             }
         }
     }
     // Save the value if there was no error
     if (($varValue != '' || !$arrData['eval']['doNotSaveEmpty']) && ($this->varValue !== $varValue || $arrData['eval']['alwaysSave'])) {
         // If the field is a fallback field, empty all other columns (see #6498)
         if ($arrData['eval']['fallback'] && $varValue != '') {
             if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4) {
                 $this->Database->prepare("UPDATE " . $this->strTable . " SET " . $this->strField . "='' WHERE pid=?")->execute($this->activeRecord->pid);
             } else {
                 $this->Database->execute("UPDATE " . $this->strTable . " SET " . $this->strField . "=''");
             }
         }
         // Set the correct empty value (see #6284, #6373)
         if ($varValue === '') {
             $varValue = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['sql']);
         }
         $arrValues = $this->values;
         array_unshift($arrValues, $varValue);
         $objUpdateStmt = $this->Database->prepare("UPDATE " . $this->strTable . " SET " . $this->strField . "=? WHERE " . implode(' AND ', $this->procedure))->execute($arrValues);
         if ($objUpdateStmt->affectedRows) {
             $this->blnCreateNewVersion = true;
             $this->varValue = deserialize($varValue);
             if (is_object($this->objActiveRecord)) {
                 $this->objActiveRecord->{$this->strField} = $this->varValue;
             }
         }
     }
 }
Exemple #2
0
 /**
  * Process form data, store it in the session and redirect to the jumpTo page
  *
  * @param array $arrSubmitted
  * @param array $arrLabels
  * @param array $arrFields
  */
 protected function processFormData($arrSubmitted, $arrLabels, $arrFields)
 {
     // HOOK: prepare form data callback
     if (isset($GLOBALS['TL_HOOKS']['prepareFormData']) && is_array($GLOBALS['TL_HOOKS']['prepareFormData'])) {
         foreach ($GLOBALS['TL_HOOKS']['prepareFormData'] as $callback) {
             $this->import($callback[0]);
             $this->{$callback}[0]->{$callback}[1]($arrSubmitted, $arrLabels, $arrFields, $this);
         }
     }
     // Send form data via e-mail
     if ($this->sendViaEmail) {
         $keys = array();
         $values = array();
         $fields = array();
         $message = '';
         foreach ($arrSubmitted as $k => $v) {
             if ($k == 'cc') {
                 continue;
             }
             $v = deserialize($v);
             // Skip empty fields
             if ($this->skipEmpty && !is_array($v) && !strlen($v)) {
                 continue;
             }
             // Add field to message
             $message .= (isset($arrLabels[$k]) ? $arrLabels[$k] : ucfirst($k)) . ': ' . (is_array($v) ? implode(', ', $v) : $v) . "\n";
             // Prepare XML file
             if ($this->format == 'xml') {
                 $fields[] = array('name' => $k, 'values' => is_array($v) ? $v : array($v));
             }
             // Prepare CSV file
             if ($this->format == 'csv') {
                 $keys[] = $k;
                 $values[] = is_array($v) ? implode(',', $v) : $v;
             }
         }
         $recipients = \StringUtil::splitCsv($this->recipient);
         // Format recipients
         foreach ($recipients as $k => $v) {
             $recipients[$k] = str_replace(array('[', ']', '"'), array('<', '>', ''), $v);
         }
         $email = new \Email();
         // Get subject and message
         if ($this->format == 'email') {
             $message = $arrSubmitted['message'];
             $email->subject = $arrSubmitted['subject'];
         }
         // Set the admin e-mail as "from" address
         $email->from = $GLOBALS['TL_ADMIN_EMAIL'];
         $email->fromName = $GLOBALS['TL_ADMIN_NAME'];
         // Get the "reply to" address
         if (strlen(\Input::post('email', true))) {
             $replyTo = \Input::post('email', true);
             // Add name
             if (strlen(\Input::post('name'))) {
                 $replyTo = '"' . \Input::post('name') . '" <' . $replyTo . '>';
             }
             $email->replyTo($replyTo);
         }
         // Fallback to default subject
         if (!strlen($email->subject)) {
             $email->subject = $this->replaceInsertTags($this->subject, false);
         }
         // Send copy to sender
         if (strlen($arrSubmitted['cc'])) {
             $email->sendCc(\Input::post('email', true));
             unset($_SESSION['FORM_DATA']['cc']);
         }
         // Attach XML file
         if ($this->format == 'xml') {
             /** @var \FrontendTemplate|object $objTemplate */
             $objTemplate = new \FrontendTemplate('form_xml');
             $objTemplate->fields = $fields;
             $objTemplate->charset = \Config::get('characterSet');
             $email->attachFileFromString($objTemplate->parse(), 'form.xml', 'application/xml');
         }
         // Attach CSV file
         if ($this->format == 'csv') {
             $email->attachFileFromString(\StringUtil::decodeEntities('"' . implode('";"', $keys) . '"' . "\n" . '"' . implode('";"', $values) . '"'), 'form.csv', 'text/comma-separated-values');
         }
         $uploaded = '';
         // Attach uploaded files
         if (!empty($_SESSION['FILES'])) {
             foreach ($_SESSION['FILES'] as $file) {
                 // Add a link to the uploaded file
                 if ($file['uploaded']) {
                     $uploaded .= "\n" . \Environment::get('base') . str_replace(TL_ROOT . '/', '', dirname($file['tmp_name'])) . '/' . rawurlencode($file['name']);
                     continue;
                 }
                 $email->attachFileFromString(file_get_contents($file['tmp_name']), $file['name'], $file['type']);
             }
         }
         $uploaded = strlen(trim($uploaded)) ? "\n\n---\n" . $uploaded : '';
         $email->text = \StringUtil::decodeEntities(trim($message)) . $uploaded . "\n\n";
         // Send the e-mail
         try {
             $email->sendTo($recipients);
         } catch (\Swift_SwiftException $e) {
             $this->log('Form "' . $this->title . '" could not be sent: ' . $e->getMessage(), __METHOD__, TL_ERROR);
         }
     }
     // Store the values in the database
     if ($this->storeValues && $this->targetTable != '') {
         $arrSet = array();
         // Add the timestamp
         if ($this->Database->fieldExists('tstamp', $this->targetTable)) {
             $arrSet['tstamp'] = time();
         }
         // Fields
         foreach ($arrSubmitted as $k => $v) {
             if ($k != 'cc' && $k != 'id') {
                 $arrSet[$k] = $v;
                 // Convert date formats into timestamps (see #6827)
                 if ($arrSet[$k] != '' && in_array($arrFields[$k]->rgxp, array('date', 'time', 'datim'))) {
                     $objDate = new \Date($arrSet[$k], \Date::getFormatFromRgxp($arrFields[$k]->rgxp));
                     $arrSet[$k] = $objDate->tstamp;
                 }
             }
         }
         // Files
         if (!empty($_SESSION['FILES'])) {
             foreach ($_SESSION['FILES'] as $k => $v) {
                 if ($v['uploaded']) {
                     $arrSet[$k] = str_replace(TL_ROOT . '/', '', $v['tmp_name']);
                 }
             }
         }
         // HOOK: store form data callback
         if (isset($GLOBALS['TL_HOOKS']['storeFormData']) && is_array($GLOBALS['TL_HOOKS']['storeFormData'])) {
             foreach ($GLOBALS['TL_HOOKS']['storeFormData'] as $callback) {
                 $this->import($callback[0]);
                 $arrSet = $this->{$callback}[0]->{$callback}[1]($arrSet, $this);
             }
         }
         // Set the correct empty value (see #6284, #6373)
         foreach ($arrSet as $k => $v) {
             if ($v === '') {
                 $arrSet[$k] = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->targetTable]['fields'][$k]['sql']);
             }
         }
         // Do not use Models here (backwards compatibility)
         $this->Database->prepare("INSERT INTO " . $this->targetTable . " %s")->set($arrSet)->execute();
     }
     // Store all values in the session
     foreach (array_keys($_POST) as $key) {
         $_SESSION['FORM_DATA'][$key] = $this->allowTags ? \Input::postHtml($key, true) : \Input::post($key, true);
     }
     $arrFiles = $_SESSION['FILES'];
     // HOOK: process form data callback
     if (isset($GLOBALS['TL_HOOKS']['processFormData']) && is_array($GLOBALS['TL_HOOKS']['processFormData'])) {
         foreach ($GLOBALS['TL_HOOKS']['processFormData'] as $callback) {
             $this->import($callback[0]);
             $this->{$callback}[0]->{$callback}[1]($arrSubmitted, $this->arrData, $arrFiles, $arrLabels, $this);
         }
     }
     $_SESSION['FILES'] = array();
     // DO NOT CHANGE
     // Add a log entry
     if (FE_USER_LOGGED_IN) {
         $this->import('FrontendUser', 'User');
         $this->log('Form "' . $this->title . '" has been submitted by "' . $this->User->username . '".', __METHOD__, TL_FORMS);
     } else {
         $this->log('Form "' . $this->title . '" has been submitted by ' . \System::anonymizeIp(\Environment::get('ip')) . '.', __METHOD__, TL_FORMS);
     }
     // Check whether there is a jumpTo page
     if (($objJumpTo = $this->objModel->getRelated('jumpTo')) !== null) {
         $this->jumpToOrReload($objJumpTo->row());
     }
     $this->reload();
 }
Exemple #3
0
 /**
  * Save the current value
  *
  * @param mixed $varValue
  *
  * @throws \Exception
  */
 protected function save($varValue)
 {
     if (\Input::post('FORM_SUBMIT') != $this->strTable) {
         return;
     }
     $arrData = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField];
     // File names
     if ($this->strField == 'name') {
         if (!file_exists(TL_ROOT . '/' . $this->strPath . '/' . $this->varValue . $this->strExtension) || !$this->isMounted($this->strPath . '/' . $this->varValue . $this->strExtension) || $this->varValue === $varValue) {
             return;
         }
         $this->import('Files');
         $varValue = utf8_romanize($varValue);
         // Trigger the save_callback
         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);
                 }
             }
         }
         // The target exists
         if (strcasecmp($this->strPath . '/' . $this->varValue . $this->strExtension, $this->strPath . '/' . $varValue . $this->strExtension) !== 0 && file_exists(TL_ROOT . '/' . $this->strPath . '/' . $varValue . $this->strExtension)) {
             throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['fileExists'], $varValue));
         }
         $arrImageTypes = trimsplit(',', strtolower(\Config::get('validImageTypes')));
         // Remove potentially existing thumbnails (see #6641)
         if (in_array(substr($this->strExtension, 1), $arrImageTypes)) {
             foreach (glob(TL_ROOT . '/assets/images/*/' . $this->varValue . '-*' . $this->strExtension) as $strThumbnail) {
                 $this->Files->delete(str_replace(TL_ROOT . '/', '', $strThumbnail));
             }
         }
         // Rename the file
         $this->Files->rename($this->strPath . '/' . $this->varValue . $this->strExtension, $this->strPath . '/' . $varValue . $this->strExtension);
         // New folders
         if (stristr($this->intId, '__new__') !== false) {
             // Update the database
             if ($this->blnIsDbAssisted && \Dbafs::shouldBeSynchronized($this->strPath . '/' . $varValue . $this->strExtension)) {
                 $this->objActiveRecord = \Dbafs::addResource($this->strPath . '/' . $varValue . $this->strExtension);
             }
             $this->log('Folder "' . $this->strPath . '/' . $varValue . $this->strExtension . '" has been created', __METHOD__, TL_FILES);
         } else {
             // Update the database
             if ($this->blnIsDbAssisted) {
                 $syncSource = \Dbafs::shouldBeSynchronized($this->strPath . '/' . $this->varValue . $this->strExtension);
                 $syncTarget = \Dbafs::shouldBeSynchronized($this->strPath . '/' . $varValue . $this->strExtension);
                 if ($syncSource && $syncTarget) {
                     \Dbafs::moveResource($this->strPath . '/' . $this->varValue . $this->strExtension, $this->strPath . '/' . $varValue . $this->strExtension);
                 } elseif ($syncSource) {
                     \Dbafs::deleteResource($this->strPath . '/' . $this->varValue . $this->strExtension);
                 } elseif ($syncTarget) {
                     \Dbafs::addResource($this->strPath . '/' . $varValue . $this->strExtension);
                 }
             }
             $this->log('File or folder "' . $this->strPath . '/' . $this->varValue . $this->strExtension . '" has been renamed to "' . $this->strPath . '/' . $varValue . $this->strExtension . '"', __METHOD__, TL_FILES);
         }
         // Set the new value so the input field can show it
         if (\Input::get('act') == 'editAll') {
             $session = $this->Session->getData();
             if (($index = array_search($this->strPath . '/' . $this->varValue . $this->strExtension, $session['CURRENT']['IDS'])) !== false) {
                 $session['CURRENT']['IDS'][$index] = $this->strPath . '/' . $varValue . $this->strExtension;
                 $this->Session->setData($session);
             }
         }
         $this->varValue = $varValue;
     } elseif ($this->blnIsDbAssisted && $this->objActiveRecord !== null) {
         // Convert date formats into timestamps
         if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) {
             $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp']));
             $varValue = $objDate->tstamp;
         }
         // Make sure unique fields are unique
         if ($arrData['eval']['unique'] && $varValue != '' && !$this->Database->isUniqueValue($this->strTable, $this->strField, $varValue, $this->objActiveRecord->id)) {
             throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrData['label'][0] ?: $this->strField));
         }
         // Handle multi-select fields in "override all" mode
         if (\Input::get('act') == 'overrideAll' && ($arrData['inputType'] == 'checkbox' || $arrData['inputType'] == 'checkboxWizard') && $arrData['eval']['multiple']) {
             if ($this->objActiveRecord !== null) {
                 $new = deserialize($varValue, true);
                 $old = deserialize($this->objActiveRecord->{$this->strField}, true);
                 switch (\Input::post($this->strInputName . '_update')) {
                     case 'add':
                         $varValue = array_values(array_unique(array_merge($old, $new)));
                         break;
                     case 'remove':
                         $varValue = array_values(array_diff($old, $new));
                         break;
                     case 'replace':
                         $varValue = $new;
                         break;
                 }
                 if (!is_array($varValue) || empty($varValue)) {
                     $varValue = '';
                 } elseif (isset($arrData['eval']['csv'])) {
                     $varValue = implode($arrData['eval']['csv'], $varValue);
                     // see #2890
                 } else {
                     $varValue = serialize($varValue);
                 }
             }
         }
         // Convert arrays (see #2890)
         if ($arrData['eval']['multiple'] && isset($arrData['eval']['csv'])) {
             $varValue = implode($arrData['eval']['csv'], deserialize($varValue, true));
         }
         // Trigger the save_callback
         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);
                 }
             }
         }
         // Save the value if there was no error
         if (($varValue != '' || !$arrData['eval']['doNotSaveEmpty']) && ($this->varValue != $varValue || $arrData['eval']['alwaysSave'])) {
             // If the field is a fallback field, empty all other columns
             if ($arrData['eval']['fallback'] && $varValue != '') {
                 $this->Database->execute("UPDATE " . $this->strTable . " SET " . $this->strField . "=''");
             }
             // Set the correct empty value (see #6284, #6373)
             if ($varValue === '') {
                 $varValue = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['sql']);
             }
             $this->objActiveRecord->{$this->strField} = $varValue;
             $this->objActiveRecord->save();
             $this->blnCreateNewVersion = true;
             $this->varValue = deserialize($varValue);
         }
     }
 }
Exemple #4
0
 /**
  * Restore a version
  *
  * @param integer $intVersion
  */
 public function restore($intVersion)
 {
     if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning']) {
         return;
     }
     $objData = $this->Database->prepare("SELECT * FROM tl_version WHERE fromTable=? AND pid=? AND version=?")->limit(1)->execute($this->strTable, $this->intPid, $intVersion);
     if ($objData->numRows) {
         $data = deserialize($objData->data);
         if (is_array($data)) {
             // Restore the content
             if ($this->strPath !== null) {
                 $objFile = new \File($this->strPath, true);
                 $objFile->write($data['content']);
                 $objFile->close();
             }
             // Get the currently available fields
             $arrFields = array_flip($this->Database->getFieldnames($this->strTable));
             // Unset fields that do not exist (see #5219)
             $data = array_intersect_key($data, $arrFields);
             $this->loadDataContainer($this->strTable);
             // Reset fields added after storing the version to their default value (see #7755)
             foreach (array_diff_key($arrFields, $data) as $k => $v) {
                 $data[$k] = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['sql']);
             }
             $this->Database->prepare("UPDATE " . $objData->fromTable . " %s WHERE id=?")->set($data)->execute($this->intPid);
             $this->Database->prepare("UPDATE tl_version SET active='' WHERE pid=?")->execute($this->intPid);
             $this->Database->prepare("UPDATE tl_version SET active=1 WHERE pid=? AND version=?")->execute($this->intPid, $intVersion);
             $this->log('Version ' . $intVersion . ' of record "' . $this->strTable . '.id=' . $this->intPid . '" has been restored' . $this->getParentEntries($this->strTable, $this->intPid), __METHOD__, TL_GENERAL);
             // Trigger the onrestore_callback
             if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_callback'])) {
                 foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_callback'] as $callback) {
                     if (is_array($callback)) {
                         $this->import($callback[0]);
                         $this->{$callback}[0]->{$callback}[1]($this->intPid, $this->strTable, $data, $intVersion);
                     } elseif (is_callable($callback)) {
                         $callback($this->intPid, $this->strTable, $data, $intVersion);
                     }
                 }
             }
         }
     }
 }
 protected function runCallbacks()
 {
     foreach ($this->arrFields as $strName => $objWidget) {
         $arrData = $this->dca['fields'][$strName];
         $varValue = $this->objActiveRecord->{$strName};
         // Set the correct empty value (see #6284, #6373)
         if ($varValue === '') {
             $varValue = \Widget::getEmptyValueByFieldType($arrData['sql']);
         }
         // Save the value if there was no error
         if (($varValue != '' || !$arrData['eval']['doNotSaveEmpty']) && ($this->objActiveRecord->{$strName} !== $varValue || $arrData['eval']['alwaysSave'])) {
             $this->objActiveRecord->{$strName} = $varValue;
         }
     }
 }
 /**
  * Update the parent field with its tl_fieldpalette item ids
  *
  * @param DataContainer $dc
  *
  * @return bool
  */
 public function updateParentField($objCurrentRecord, $intDelete = 0)
 {
     $strClass = \Model::getClassFromTable($objCurrentRecord->ptable);
     if (!class_exists($strClass)) {
         return false;
     }
     /** @var \Model $strClass */
     $objParent = $strClass::findByPk($objCurrentRecord->pid);
     if ($objParent === null) {
         return false;
     }
     $objItems = \HeimrichHannot\FieldPalette\FieldPaletteModel::findByPidAndTableAndField($objCurrentRecord->pid, $objCurrentRecord->ptable, $objCurrentRecord->pfield);
     $varValue = array();
     if ($objItems !== null) {
         $varValue = $objItems->fetchEach('id');
         // ondelete_callback support
         if ($intDelete > 0 && ($key = array_search($intDelete, $varValue)) !== false) {
             unset($varValue[$key]);
         }
     }
     if (empty($varValue)) {
         \Controller::loadDataContainer($objCurrentRecord->ptable);
         $arrData = $GLOBALS['TL_DCA'][$objCurrentRecord->ptable]['fields'][$objCurrentRecord->pfield];
         if (isset($arrData['sql'])) {
             $varValue = \Widget::getEmptyValueByFieldType($arrData['sql']);
         }
     }
     $objParent->{$objCurrentRecord->pfield} = $varValue;
     $objParent->save();
 }
 /**
  * Save the current value
  * @param mixed
  * @throws \Exception
  */
 protected function save($varValue)
 {
     if (\Input::post('FORM_SUBMIT') != $this->strTable) {
         return;
     }
     $arrField = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField];
     // table to write to: tl_formdata (base fields) or tl_formdata_details (detail fields)
     $strTargetTable = $this->strTable;
     $strTargetField = $this->strField;
     $blnDetailField = false;
     // if field is one of detail fields
     if (in_array($strTargetField, $this->arrDetailFields)) {
         $strTargetTable = $GLOBALS['TL_DCA'][$this->strTable]['config']['ctable'][0];
         $blnDetailField = true;
     }
     // Convert date formats into timestamps
     if ($varValue != '' && in_array($arrField['eval']['rgxp'], array('date', 'time', 'datim'))) {
         $objDate = new \Date($varValue, $GLOBALS['TL_CONFIG'][$arrField['eval']['rgxp'] . 'Format']);
         $varValue = $objDate->tstamp;
     }
     if (!in_array($this->strField, $this->arrOwnerFields) && !in_array($this->strField, $this->arrBaseFields)) {
         // Convert checkbox, radio, select, conditionalselect to store the values instead of keys
         if ($arrField['inputType'] == 'checkbox' && $arrField['eval']['multiple'] || in_array($arrField['inputType'], array('radio', 'select', 'conditionalselect'))) {
             $arrOpts = $arrField['options'];
             // OptGroups can not be saved so flatten grouped options array
             $arrNewOpts = array();
             foreach ($arrOpts as $strKey => $varOpt) {
                 if (is_array($varOpt) && !empty($varOpt)) {
                     foreach ($varOpt as $keyOpt => $valOpt) {
                         $arrNewOpts[$keyOpt] = $valOpt;
                     }
                 } else {
                     $arrNewOpts[$strKey] = $varOpt;
                 }
             }
             $arrOpts = $arrNewOpts;
             unset($arrNewOpts);
             $arrSel = deserialize($varValue, true);
             if (is_array($arrSel) && !empty($arrSel)) {
                 $arrSel = array_flip($arrSel);
                 // use options value or options labels
                 if ($arrField['eval']['efgStoreValues']) {
                     $arrVals = array_keys(array_intersect_key($arrOpts, $arrSel));
                 } else {
                     $arrVals = array_values(array_intersect_key($arrOpts, $arrSel));
                 }
             }
             if (is_array($arrVals) && !$arrField['eval']['multiple']) {
                 $varValue = $arrVals[0];
             } else {
                 $varValue = is_array($arrVals) && !empty($arrVals) ? $arrVals : '';
             }
         }
         if ($arrField['inputType'] == 'checkbox' && !$arrField['eval']['multiple']) {
             if (is_array($arrField['options'])) {
                 $arrVals = $arrField['eval']['efgStoreValues'] ? array_keys($arrField['options']) : array_values($arrField['options']);
             } else {
                 $arrVals = array("1");
             }
             if (strlen($varValue)) {
                 $varValue = $arrVals[0];
             } else {
                 $varValue = '';
             }
         }
     }
     // Convert fileTree IDs or UUIDs to file paths
     if ($arrField['inputType'] == 'fileTree') {
         $varValue = deserialize($varValue);
         if (is_array($varValue) && !empty($varValue)) {
             foreach ($varValue as $key => $varFile) {
                 if (\Validator::isUuid($varFile) || is_numeric($varFile)) {
                     $objFileModel = \FilesModel::findById($varFile);
                     if ($objFileModel !== null) {
                         $varValue[$key] = $objFileModel->path;
                     }
                 }
             }
             $varValue = array_values($varValue);
         } elseif (!empty($varValue)) {
             if (\Validator::isUuid($varValue) || is_numeric($varValue)) {
                 $objFileModel = \FilesModel::findById($varValue);
                 if ($objFileModel !== null) {
                     $varValue = $objFileModel->path;
                 }
             }
         }
     }
     if ($arrField['inputType'] == 'cm_alternative') {
         if (is_array($arrField['options']) && isset($arrField['options'][$varValue])) {
             $varValue = $arrField['options'][$varValue];
         }
     }
     // Make sure unique fields are unique
     if (!is_array($varValue) && strlen($varValue) && $arrField['eval']['unique']) {
         $objUnique = \Database::getInstance()->prepare("SELECT * FROM " . $this->strTable . " WHERE " . $this->strField . "=? AND id!=?")->execute($varValue, $this->intId);
         if ($objUnique->numRows) {
             throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], strlen($arrField['label'][0]) ? $arrField['label'][0] : $this->strField));
         }
     }
     if (is_array($varValue)) {
         $varValue = serialize($varValue);
     }
     // Convert arrays (see #2890)
     if ($arrField['eval']['multiple'] && isset($arrField['eval']['csv'])) {
         $varValue = implode($arrField['eval']['csv'], deserialize($varValue, true));
     }
     // Trigger the save_callback
     if (is_array($arrField['save_callback'])) {
         foreach ($arrField['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);
             }
         }
     }
     // Save the value if there was no error
     if (($varValue != '' || !$arrField['eval']['doNotSaveEmpty']) && ($this->varValue !== $varValue || $arrField['eval']['alwaysSave'])) {
         // Set the correct empty value (see #6284, #6373)
         if ($varValue === '') {
             $varValue = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->strTable]['fields'][$strTargetField]['sql']);
         }
         $arrValues = $this->values;
         $arrProcedures = $this->procedure;
         if ($blnDetailField) {
             // add condition ff_name
             $arrProcedures[] = 'ff_name=?';
             $arrValues[] = $strTargetField;
             foreach ($arrProcedures as $kP => $kV) {
                 if ($kV == 'id=?') {
                     $arrProcedures[$kP] = 'pid=?';
                 } elseif ($kV == 'form=?') {
                     $arrProcedures[$kP] = 'ff_name=?';
                     $arrValues[$kP] = $strTargetField;
                 }
             }
         }
         array_unshift($arrValues, $varValue);
         $sqlUpd = "UPDATE " . $strTargetTable . " SET " . $strTargetField . "=? WHERE " . implode(' AND ', $arrProcedures);
         if ($blnDetailField) {
             // if record does not exist insert an empty record
             $objExist = \Database::getInstance()->prepare("SELECT id FROM tl_formdata_details WHERE pid=? AND ff_name=?")->execute(array($this->intId, $strTargetField));
             if ($objExist->numRows == 0) {
                 $arrSetInsert = array('pid' => $this->intId, 'tstamp' => time(), 'ff_id' => $GLOBALS['TL_DCA'][$this->strTable]['fields'][$strTargetField]['ff_id'], 'ff_name' => $strTargetField);
                 $objInsertStmt = \Database::getInstance()->prepare("INSERT INTO " . $strTargetTable . " %s")->set($arrSetInsert)->execute();
             }
             $sqlUpd = "UPDATE " . $strTargetTable . " SET value=? WHERE " . implode(' AND ', $arrProcedures);
         }
         $objUpdateStmt = \Database::getInstance()->prepare($sqlUpd)->execute($arrValues);
         if ($objUpdateStmt->affectedRows) {
             if ($varValue != $this->varValue) {
                 if (!$arrField['eval']['submitOnChange']) {
                     $this->blnCreateNewVersion = true;
                 }
             }
             $this->varValue = deserialize($varValue);
             if (is_object($this->objActiveRecord)) {
                 $this->objActiveRecord->{$this->strField} = $this->varValue;
             }
         }
     }
 }