/** * 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; } } } }
/** * 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(); }
/** * 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); } } }
/** * 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; } } } }