Return a numeric format string depending on the regular expression name
public static getFormatFromRgxp ( string $strRgxp ) : string | ||
$strRgxp | string | The regular expression name |
return | string | The numeric format string |
/** * Obtain the correct date/time string. * * @return string */ private function determineDateFormat() { if ($format = trim($this->get('dateformat'))) { return $format; } return Date::getFormatFromRgxp($this->get('timetype')); }
public function addTypeIcon($row, $label, DataContainer $dc, $args = null) { $args[0] = \Image::getHtml(\Image::get('system/modules/mail_to/assets/mail-open-image.png', 16, 16)); $objFile = FilesModel::findByUuid($row['folder']); $args[2] = $objFile !== null ? $objFile->path : '-'; $args[5] = Date::parse(Date::getFormatFromRgxp('datim'), $row['lastrun']); return $args; }
/** * 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 = \Widget::getEmptyStringOrNullByFieldType($arrData['sql']); } 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; } } } }
/** * Extract the Widget attributes from a Data Container array * * @param array $arrData The field configuration array * @param string $strName The field name in the form * @param mixed $varValue The field value * @param string $strField The field name in the database * @param string $strTable The table name in the database * @param DataContainer|null $objDca An optional DataContainer object * * @return array An attributes array that can be passed to a widget */ public static function getAttributesFromDca($arrData, $strName, $varValue = null, $strField = '', $strTable = '', $objDca = null) { $arrAttributes = $arrData['eval']; $arrAttributes['id'] = $strName; $arrAttributes['name'] = $strName; $arrAttributes['strField'] = $strField; $arrAttributes['strTable'] = $strTable; $arrAttributes['label'] = ($label = is_array($arrData['label']) ? $arrData['label'][0] : $arrData['label']) != false ? $label : $strField; $arrAttributes['description'] = $arrData['label'][1]; $arrAttributes['type'] = $arrData['inputType']; $arrAttributes['dataContainer'] = $objDca; // Internet Explorer does not support onchange for checkboxes and radio buttons if ($arrData['eval']['submitOnChange']) { if ($arrData['inputType'] == 'checkbox' || $arrData['inputType'] == 'checkboxWizard' || $arrData['inputType'] == 'radio' || $arrData['inputType'] == 'radioTable') { $arrAttributes['onclick'] = trim($arrAttributes['onclick'] . " Backend.autoSubmit('" . $strTable . "')"); } else { $arrAttributes['onchange'] = trim($arrAttributes['onchange'] . " Backend.autoSubmit('" . $strTable . "')"); } } $arrAttributes['allowHtml'] = $arrData['eval']['allowHtml'] || strlen($arrData['eval']['rte']) || $arrData['eval']['preserveTags'] ? true : false; // Decode entities if HTML is allowed if ($arrAttributes['allowHtml'] || $arrData['inputType'] == 'fileTree') { $arrAttributes['decodeEntities'] = true; } // Add Ajax event if ($arrData['inputType'] == 'checkbox' && is_array($GLOBALS['TL_DCA'][$strTable]['subpalettes']) && in_array($strField, array_keys($GLOBALS['TL_DCA'][$strTable]['subpalettes'])) && $arrData['eval']['submitOnChange']) { $arrAttributes['onclick'] = "AjaxRequest.toggleSubpalette(this, 'sub_" . $strName . "', '" . $strField . "')"; } // Options callback if (is_array($arrData['options_callback'])) { $arrCallback = $arrData['options_callback']; $arrData['options'] = static::importStatic($arrCallback[0])->{$arrCallback[1]}($objDca); } elseif (is_callable($arrData['options_callback'])) { $arrData['options'] = $arrData['options_callback']($objDca); } elseif (isset($arrData['foreignKey'])) { $arrKey = explode('.', $arrData['foreignKey'], 2); $objOptions = \Database::getInstance()->query("SELECT id, " . $arrKey[1] . " AS value FROM " . $arrKey[0] . " WHERE tstamp>0 ORDER BY value"); $arrData['options'] = array(); while ($objOptions->next()) { $arrData['options'][$objOptions->id] = $objOptions->value; } } // Add default option to single checkbox if ($arrData['inputType'] == 'checkbox' && !isset($arrData['options']) && !isset($arrData['options_callback']) && !isset($arrData['foreignKey'])) { if (TL_MODE == 'FE' && isset($arrAttributes['description'])) { $arrAttributes['options'][] = array('value' => 1, 'label' => $arrAttributes['description']); } else { $arrAttributes['options'][] = array('value' => 1, 'label' => $arrAttributes['label']); } } // Add options if (is_array($arrData['options'])) { $blnIsAssociative = $arrData['eval']['isAssociative'] || array_is_assoc($arrData['options']); $blnUseReference = isset($arrData['reference']); if ($arrData['eval']['includeBlankOption'] && !$arrData['eval']['multiple']) { $strLabel = isset($arrData['eval']['blankOptionLabel']) ? $arrData['eval']['blankOptionLabel'] : '-'; $arrAttributes['options'][] = array('value' => '', 'label' => $strLabel); } foreach ($arrData['options'] as $k => $v) { if (!is_array($v)) { $arrAttributes['options'][] = array('value' => $blnIsAssociative ? $k : $v, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$v]) ? $arrData['reference'][$v][0] : $arrData['reference'][$v]) != false ? $ref : $v : $v); continue; } $key = $blnUseReference ? ($ref = is_array($arrData['reference'][$k]) ? $arrData['reference'][$k][0] : $arrData['reference'][$k]) != false ? $ref : $k : $k; $blnIsAssoc = array_is_assoc($v); foreach ($v as $kk => $vv) { $arrAttributes['options'][$key][] = array('value' => $blnIsAssoc ? $kk : $vv, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$vv]) ? $arrData['reference'][$vv][0] : $arrData['reference'][$vv]) != false ? $ref : $vv : $vv); } } } $arrAttributes['value'] = \StringUtil::deserialize($varValue); // Convert timestamps if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp'])); $arrAttributes['value'] = $objDate->{$arrData['eval']['rgxp']}; } // Add the "rootNodes" array as attribute (see #3563) if (isset($arrData['rootNodes']) && !isset($arrData['eval']['rootNodes'])) { $arrAttributes['rootNodes'] = $arrData['rootNodes']; } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getAttributesFromDca']) && is_array($GLOBALS['TL_HOOKS']['getAttributesFromDca'])) { foreach ($GLOBALS['TL_HOOKS']['getAttributesFromDca'] as $callback) { $arrAttributes = static::importStatic($callback[0])->{$callback[1]}($arrAttributes, $objDca); } } return $arrAttributes; }
/** * Generate the module */ protected function compile() { /** @var PageModel $objPage */ global $objPage; $GLOBALS['TL_LANGUAGE'] = $objPage->language; \System::loadLanguageFile('tl_member'); $this->loadDataContainer('tl_member'); // Call onload_callback (e.g. to check permissions) if (is_array($GLOBALS['TL_DCA']['tl_member']['config']['onload_callback'])) { foreach ($GLOBALS['TL_DCA']['tl_member']['config']['onload_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}(); } elseif (is_callable($callback)) { $callback(); } } } // Activate account if (\Input::get('token') != '') { $this->activateAcount(); return; } if ($this->memberTpl != '') { /** @var FrontendTemplate|object $objTemplate */ $objTemplate = new \FrontendTemplate($this->memberTpl); $this->Template = $objTemplate; $this->Template->setData($this->arrData); } $this->Template->fields = ''; $objCaptcha = null; $doNotSubmit = false; $strFormId = 'tl_registration_' . $this->id; // Predefine the group order (other groups will be appended automatically) $arrGroups = array('personal' => array(), 'address' => array(), 'contact' => array(), 'login' => array(), 'profile' => array()); // Captcha if (!$this->disableCaptcha) { $arrCaptcha = array('id' => 'registration', 'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'type' => 'captcha', 'mandatory' => true, 'required' => true); /** @var FormCaptcha $strClass */ $strClass = $GLOBALS['TL_FFL']['captcha']; // Fallback to default if the class is not defined if (!class_exists($strClass)) { $strClass = 'FormCaptcha'; } /** @var FormCaptcha $objCaptcha */ $objCaptcha = new $strClass($arrCaptcha); if (\Input::post('FORM_SUBMIT') == $strFormId) { $objCaptcha->validate(); if ($objCaptcha->hasErrors()) { $doNotSubmit = true; } } } $objMember = null; // Check for a follow-up registration (see #7992) if (\Input::post('email', true) != '' && ($objMember = \MemberModel::findUnactivatedByEmail(\Input::post('email', true))) !== null) { $this->resendActivationMail($objMember); return; } $arrUser = array(); $arrFields = array(); $hasUpload = false; $i = 0; // Build form foreach ($this->editable as $field) { $arrData = $GLOBALS['TL_DCA']['tl_member']['fields'][$field]; // Map checkboxWizards to regular checkbox widgets if ($arrData['inputType'] == 'checkboxWizard') { $arrData['inputType'] = 'checkbox'; } // Map fileTrees to upload widgets (see #8091) if ($arrData['inputType'] == 'fileTree') { $arrData['inputType'] = 'upload'; } /** @var Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrData['inputType']]; // Continue if the class is not defined if (!class_exists($strClass)) { continue; } $arrData['eval']['required'] = $arrData['eval']['mandatory']; // Unset the unique field check upon follow-up registrations if ($objMember !== null && $arrData['eval']['unique'] && \Input::post($field) == $objMember->{$field}) { $arrData['eval']['unique'] = false; } $objWidget = new $strClass($strClass::getAttributesFromDca($arrData, $field, $arrData['default'], '', '', $this)); $objWidget->storeValues = true; $objWidget->rowClass = 'row_' . $i . ($i == 0 ? ' row_first' : '') . ($i % 2 == 0 ? ' even' : ' odd'); // Increase the row count if its a password field if ($objWidget instanceof FormPassword) { $objWidget->rowClassConfirm = 'row_' . ++$i . ($i % 2 == 0 ? ' even' : ' odd'); } // Validate input if (\Input::post('FORM_SUBMIT') == $strFormId) { $objWidget->validate(); $varValue = $objWidget->value; // Check whether the password matches the username if ($objWidget instanceof FormPassword && \Encryption::verify(\Input::post('username'), $varValue)) { $objWidget->addError($GLOBALS['TL_LANG']['ERR']['passwordName']); } $rgxp = $arrData['eval']['rgxp']; // Convert date formats into timestamps (check the eval setting first -> #3063) if ($varValue != '' && in_array($rgxp, array('date', 'time', 'datim'))) { try { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($rgxp)); $varValue = $objDate->tstamp; } catch (\OutOfBoundsException $e) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varValue)); } } // Make sure that unique fields are unique (check the eval setting first -> #3063) if ($arrData['eval']['unique'] && $varValue != '' && !$this->Database->isUniqueValue('tl_member', $field, $varValue)) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrData['label'][0] ?: $field)); } // Save callback if ($objWidget->submitInput() && !$objWidget->hasErrors() && is_array($arrData['save_callback'])) { foreach ($arrData['save_callback'] as $callback) { try { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, null); } elseif (is_callable($callback)) { $varValue = $callback($varValue, null); } } catch (\Exception $e) { $objWidget->class = 'error'; $objWidget->addError($e->getMessage()); } } } // Store the current value if ($objWidget->hasErrors()) { $doNotSubmit = true; } elseif ($objWidget->submitInput()) { // Set the correct empty value (see #6284, #6373) if ($varValue === '') { $varValue = $objWidget->getEmptyValue(); } // Encrypt the value (see #7815) if ($arrData['eval']['encrypt']) { $varValue = \Encryption::encrypt($varValue); } // Set the new value $arrUser[$field] = $varValue; } } if ($objWidget instanceof \uploadable) { $hasUpload = true; } $temp = $objWidget->parse(); $this->Template->fields .= $temp; $arrFields[$arrData['eval']['feGroup']][$field] .= $temp; ++$i; } // Captcha if (!$this->disableCaptcha) { $objCaptcha->rowClass = 'row_' . $i . ($i == 0 ? ' row_first' : '') . ($i % 2 == 0 ? ' even' : ' odd'); $strCaptcha = $objCaptcha->parse(); $this->Template->fields .= $strCaptcha; $arrFields['captcha']['captcha'] .= $strCaptcha; } $this->Template->rowLast = 'row_' . ++$i . ($i % 2 == 0 ? ' even' : ' odd'); $this->Template->enctype = $hasUpload ? 'multipart/form-data' : 'application/x-www-form-urlencoded'; $this->Template->hasError = $doNotSubmit; // Create new user if there are no errors if (\Input::post('FORM_SUBMIT') == $strFormId && !$doNotSubmit) { $this->createNewUser($arrUser); } $this->Template->loginDetails = $GLOBALS['TL_LANG']['tl_member']['loginDetails']; $this->Template->addressDetails = $GLOBALS['TL_LANG']['tl_member']['addressDetails']; $this->Template->contactDetails = $GLOBALS['TL_LANG']['tl_member']['contactDetails']; $this->Template->personalData = $GLOBALS['TL_LANG']['tl_member']['personalData']; $this->Template->captchaDetails = $GLOBALS['TL_LANG']['MSC']['securityQuestion']; // Add the groups foreach ($arrFields as $k => $v) { // Deprecated since Contao 4.0, to be removed in Contao 5.0 $this->Template->{$k} = $v; $key = $k . ($k == 'personal' ? 'Data' : 'Details'); $arrGroups[$GLOBALS['TL_LANG']['tl_member'][$key]] = $v; } $this->Template->categories = $arrGroups; $this->Template->formId = $strFormId; $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['register']); $this->Template->action = \Environment::get('indexFreeRequest'); // Deprecated since Contao 4.0, to be removed in Contao 5.0 $this->Template->captcha = $arrFields['captcha']['captcha']; }
/** * 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::toAscii($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 . '/' . \System::getContainer()->getParameter('contao.image.target_path') . '/*/' . $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); } // Update the symlinks if (is_link(TL_ROOT . '/web/' . $this->strPath . '/' . $this->varValue . $this->strExtension)) { $this->Files->delete('web/' . $this->strPath . '/' . $this->varValue . $this->strExtension); SymlinkUtil::symlink($this->strPath . '/' . $varValue . $this->strExtension, 'web/' . $this->strPath . '/' . $varValue . $this->strExtension, TL_ROOT); } // Set the new value so the input field can show it if (\Input::get('act') == 'editAll') { /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); $session = $objSession->all(); if (($index = array_search($this->strPath . '/' . $this->varValue . $this->strExtension, $session['CURRENT']['IDS'])) !== false) { $session['CURRENT']['IDS'][$index] = $this->strPath . '/' . $varValue . $this->strExtension; $objSession->replace($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); } } }
/** * Save the current value * * @param mixed $varValue */ protected function save($varValue) { if (\Input::post('FORM_SUBMIT') != $this->strTable) { return; } $arrData = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]; // Make sure that checkbox values are boolean if ($arrData['inputType'] == 'checkbox' && !$arrData['eval']['multiple']) { $varValue = $varValue ? true : false; } if ($varValue != '') { // Convert binary UUIDs (see #6893) if ($arrData['inputType'] == 'fileTree') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::binToUuid($varValue); } else { $varValue = serialize(array_map('StringUtil::binToUuid', $varValue)); } } // 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; } // Handle entities if ($arrData['inputType'] == 'text' || $arrData['inputType'] == 'textarea') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::restoreBasicEntities($varValue); } else { $varValue = serialize(array_map('StringUtil::restoreBasicEntities', $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); } } } $strCurrent = $this->varValue; // Handle arrays and strings if (is_array($strCurrent)) { $strCurrent = serialize($strCurrent); } elseif (is_string($strCurrent)) { $strCurrent = html_entity_decode($this->varValue, ENT_QUOTES, \Config::get('characterSet')); } // Save the value if there was no error if ((strlen($varValue) || !$arrData['eval']['doNotSaveEmpty']) && $strCurrent != $varValue) { \Config::persist($this->strField, $varValue); $deserialize = deserialize($varValue); $prior = is_bool(\Config::get($this->strField)) ? \Config::get($this->strField) ? 'true' : 'false' : \Config::get($this->strField); // Add a log entry if (!is_array(deserialize($prior)) && !is_array($deserialize)) { if ($arrData['inputType'] == 'password' || $arrData['inputType'] == 'textStore') { $this->log('The global configuration variable "' . $this->strField . '" has been changed', __METHOD__, TL_CONFIGURATION); } else { $this->log('The global configuration variable "' . $this->strField . '" has been changed from "' . $prior . '" to "' . $varValue . '"', __METHOD__, TL_CONFIGURATION); } } // Set the new value so the input field can show it $this->varValue = $deserialize; \Config::set($this->strField, $deserialize); } }
/** * 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 = \StringUtil::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')) instanceof PageModel) { $this->jumpToOrReload($objJumpTo->row()); } $this->reload(); }
/** * Generate the module */ protected function compile() { /** @var PageModel $objPage */ global $objPage; $this->import('FrontendUser', 'User'); $GLOBALS['TL_LANGUAGE'] = $objPage->language; \System::loadLanguageFile('tl_member'); $this->loadDataContainer('tl_member'); // Call onload_callback (e.g. to check permissions) if (is_array($GLOBALS['TL_DCA']['tl_member']['config']['onload_callback'])) { foreach ($GLOBALS['TL_DCA']['tl_member']['config']['onload_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}(); } elseif (is_callable($callback)) { $callback(); } } } $this->Template->fields = ''; $arrFields = array(); $doNotSubmit = false; $hasUpload = false; $row = 0; // Predefine the group order (other groups will be appended automatically) $arrGroups = array('personal' => array(), 'address' => array(), 'contact' => array(), 'login' => array(), 'profile' => array()); $blnModified = false; $objMember = \MemberModel::findByPk($this->User->id); $strTable = $objMember->getTable(); $strFormId = 'tl_member_' . $this->id; $flashBag = \System::getContainer()->get('session')->getFlashBag(); // Initialize the versioning (see #7415) $objVersions = new \Versions($strTable, $objMember->id); $objVersions->setUsername($objMember->username); $objVersions->setUserId(0); $objVersions->setEditUrl('contao/main.php?do=member&act=edit&id=%s&rt=1'); $objVersions->initialize(); // Build the form foreach ($this->editable as $field) { $arrData =& $GLOBALS['TL_DCA']['tl_member']['fields'][$field]; // Map checkboxWizards to regular checkbox widgets if ($arrData['inputType'] == 'checkboxWizard') { $arrData['inputType'] = 'checkbox'; } // Map fileTrees to upload widgets (see #8091) if ($arrData['inputType'] == 'fileTree') { $arrData['inputType'] = 'upload'; } /** @var Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrData['inputType']]; // Continue if the class does not exist if (!$arrData['eval']['feEditable'] || !class_exists($strClass)) { continue; } $strGroup = $arrData['eval']['feGroup']; $arrData['eval']['required'] = false; // Use strlen() here (see #3277) if ($arrData['eval']['mandatory']) { if (is_array($this->User->{$field})) { if (empty($this->User->{$field})) { $arrData['eval']['required'] = true; } } else { if (!strlen($this->User->{$field})) { $arrData['eval']['required'] = true; } } } $varValue = $this->User->{$field}; // Call the load_callback if (isset($arrData['load_callback']) && is_array($arrData['load_callback'])) { foreach ($arrData['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, $this->User, $this); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $this->User, $this); } } } /** @var Widget $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($arrData, $field, $varValue, '', '', $this)); $objWidget->storeValues = true; $objWidget->rowClass = 'row_' . $row . ($row == 0 ? ' row_first' : '') . ($row % 2 == 0 ? ' even' : ' odd'); // Increase the row count if it is a password field if ($objWidget instanceof FormPassword) { if ($objMember->password != '') { $objWidget->mandatory = false; } $objWidget->rowClassConfirm = 'row_' . ++$row . ($row % 2 == 0 ? ' even' : ' odd'); } // Validate the form data if (\Input::post('FORM_SUBMIT') == $strFormId) { $objWidget->validate(); $varValue = $objWidget->value; $rgxp = $arrData['eval']['rgxp']; // Convert date formats into timestamps (check the eval setting first -> #3063) if ($varValue != '' && in_array($rgxp, array('date', 'time', 'datim'))) { try { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($rgxp)); $varValue = $objDate->tstamp; } catch (\OutOfBoundsException $e) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varValue)); } } // Make sure that unique fields are unique (check the eval setting first -> #3063) if ($arrData['eval']['unique'] && $varValue != '' && !$this->Database->isUniqueValue('tl_member', $field, $varValue, $this->User->id)) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['unique'], $arrData['label'][0] ?: $field)); } // Trigger the save_callback (see #5247) if ($objWidget->submitInput() && !$objWidget->hasErrors() && is_array($arrData['save_callback'])) { foreach ($arrData['save_callback'] as $callback) { try { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, $this->User, $this); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $this->User, $this); } } catch (\Exception $e) { $objWidget->class = 'error'; $objWidget->addError($e->getMessage()); } } } // Do not submit the field if there are errors if ($objWidget->hasErrors()) { $doNotSubmit = true; } elseif ($objWidget->submitInput()) { // Store the form data $_SESSION['FORM_DATA'][$field] = $varValue; // Set the correct empty value (see #6284, #6373) if ($varValue === '') { $varValue = $objWidget->getEmptyValue(); } // Encrypt the value (see #7815) if ($arrData['eval']['encrypt']) { $varValue = \Encryption::encrypt($varValue); } // Set the new value if ($varValue !== $this->User->{$field}) { $this->User->{$field} = $varValue; // Set the new field in the member model $blnModified = true; $objMember->{$field} = $varValue; } } } if ($objWidget instanceof \uploadable) { $hasUpload = true; } $temp = $objWidget->parse(); $this->Template->fields .= $temp; $arrFields[$strGroup][$field] .= $temp; ++$row; } // Save the model if ($blnModified) { $objMember->tstamp = time(); $objMember->save(); // Create a new version if ($GLOBALS['TL_DCA'][$strTable]['config']['enableVersioning']) { $objVersions->create(); $this->log('A new version of record "' . $strTable . '.id=' . $objMember->id . '" has been created' . $this->getParentEntries($strTable, $objMember->id), __METHOD__, TL_GENERAL); } } $this->Template->hasError = $doNotSubmit; // Redirect or reload if there was no error if (\Input::post('FORM_SUBMIT') == $strFormId && !$doNotSubmit) { // HOOK: updated personal data if (isset($GLOBALS['TL_HOOKS']['updatePersonalData']) && is_array($GLOBALS['TL_HOOKS']['updatePersonalData'])) { foreach ($GLOBALS['TL_HOOKS']['updatePersonalData'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($this->User, $_SESSION['FORM_DATA'], $this); } } // Call the onsubmit_callback if (is_array($GLOBALS['TL_DCA']['tl_member']['config']['onsubmit_callback'])) { foreach ($GLOBALS['TL_DCA']['tl_member']['config']['onsubmit_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($this->User, $this); } elseif (is_callable($callback)) { $callback($this->User, $this); } } } // Check whether there is a jumpTo page if (($objJumpTo = $this->objModel->getRelated('jumpTo')) !== null) { $this->jumpToOrReload($objJumpTo->row()); } $flashBag->set('mod_personal_data_confirm', $GLOBALS['TL_LANG']['MSC']['savedData']); $this->reload(); } $this->Template->loginDetails = $GLOBALS['TL_LANG']['tl_member']['loginDetails']; $this->Template->addressDetails = $GLOBALS['TL_LANG']['tl_member']['addressDetails']; $this->Template->contactDetails = $GLOBALS['TL_LANG']['tl_member']['contactDetails']; $this->Template->personalData = $GLOBALS['TL_LANG']['tl_member']['personalData']; // Add the groups foreach ($arrFields as $k => $v) { // Deprecated since Contao 4.0, to be removed in Contao 5.0 $this->Template->{$k} = $v; $key = $k . ($k == 'personal' ? 'Data' : 'Details'); $arrGroups[$GLOBALS['TL_LANG']['tl_member'][$key]] = $v; } // Confirmation message if ($flashBag->has('mod_personal_data_confirm')) { $arrMessages = $flashBag->get('mod_personal_data_confirm'); $this->Template->message = $arrMessages[0]; } $this->Template->categories = $arrGroups; $this->Template->formId = $strFormId; $this->Template->slabel = specialchars($GLOBALS['TL_LANG']['MSC']['saveData']); $this->Template->action = \Environment::get('indexFreeRequest'); $this->Template->enctype = $hasUpload ? 'multipart/form-data' : 'application/x-www-form-urlencoded'; $this->Template->rowLast = 'row_' . $row . ($row % 2 == 0 ? ' even' : ' odd'); }