/** * @return array */ public function getCurrencies() { $return = array(); $arrAux = array(); \Contao\System::loadLanguageFile('currencies'); $this->loadCurrencies(); if (is_array($this->arrCurrencies)) { foreach ($this->arrCurrencies as $strKey => $strName) { $arrAux[$strKey] = isset($GLOBALS['TL_LANG']['CUR'][$strKey]) ? Utf8::toAscii($GLOBALS['TL_LANG']['CUR'][$strKey]) : $strName; } } asort($arrAux); if (is_array($arrAux)) { foreach (array_keys($arrAux) as $strKey) { $return[$strKey] = isset($GLOBALS['TL_LANG']['CUR'][$strKey]) ? $GLOBALS['TL_LANG']['CUR'][$strKey] : $this->arrCurrencies[$strKey]; } } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getCurrencies']) && is_array($GLOBALS['TL_HOOKS']['getCurrencies'])) { foreach ($GLOBALS['TL_HOOKS']['getCurrencies'] as $callback) { $return = static::importStatic($callback[0])->{$callback}[1]($return, $this->arrCurrencies); } } return $return; }
/** * Initialize the controller * * 1. Import the user * 2. Call the parent constructor * 3. Authenticate the user * 4. Load the language files * DO NOT CHANGE THIS ORDER! */ public function __construct() { $this->import('BackendUser', 'User'); parent::__construct(); $this->User->authenticate(); \System::loadLanguageFile('default'); }
/** * Get buttons. * * @param $articleId * * @return string */ protected function getButtons($articleId) { global $container; System::loadLanguageFile('tl_article'); $translator = $container['translator']; $buttons = self::getModalEditButton($articleId, $translator); $buttons .= self::getModalShowButton($articleId, $translator); return $buttons; }
/** * Initialize the controller */ public function __construct() { $this->import('Config'); $this->import('Session'); \Config::set('showHelp', false); $this->setStaticUrls(); \System::loadLanguageFile('default'); \System::loadLanguageFile('tl_install'); }
/** * Initialize the controller * * 1. Import the user * 2. Call the parent constructor * 3. Authenticate the user * 4. Load the language files * DO NOT CHANGE THIS ORDER! */ public function __construct() { $this->import('BackendUser', 'User'); parent::__construct(); $this->User->authenticate(); \System::loadLanguageFile('default'); $strFile = \Input::get('src', true); $strFile = base64_decode($strFile); $strFile = preg_replace('@^/+@', '', rawurldecode($strFile)); $this->strFile = $strFile; }
/** * Generate the purge cache field * * @return string */ public function generatePurgeField() { System::loadLanguageFile('tl_maintenance'); $template = new BackendTemplate('be_vimeo_rebuilder_user'); $template->elementsCount = count(Rebuilder::getContentElements()); if (($stats = Rebuilder::generateStats()) !== null) { foreach ($stats as $k => $v) { $template->{$k} = $v; } } return $template->parse(); }
/** * @param $strField */ protected function addTranslationContentToField($strField) { if ($this->Config->get($strField) === null) { $arrValues = array(); System::loadLanguageFile('tl_email', 'de', true); $arrValues['de'] = $GLOBALS['TL_LANG']['tl_email']['defaultContents'][$strField]; System::loadLanguageFile('tl_email', 'en', true); $arrValues['en'] = $GLOBALS['TL_LANG']['tl_email']['defaultContents'][$strField]; // Load translation file by current language System::loadLanguageFile('tl_email', null, true); $this->Config->persist($strField, TranslationFieldsModel::saveValuesAndReturnFid($arrValues)); } }
/** * Initialize the controller * * 1. Import the user * 2. Call the parent constructor * 3. Login the user * 4. Load the language files * DO NOT CHANGE THIS ORDER! */ public function __construct() { $this->import('BackendUser', 'User'); parent::__construct(); // Login if ($this->User->login()) { $strUrl = 'contao/main.php'; // Redirect to the last page visited if (\Input::get('referer', true) != '') { $strUrl = base64_decode(\Input::get('referer', true)); } $this->redirect($strUrl); } elseif (!empty($_POST['username']) && !empty($_POST['password'])) { $this->reload(); } elseif ($this->User->logout()) { $this->reload(); } \System::loadLanguageFile('default'); \System::loadLanguageFile('tl_user'); }
/** * 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'); // Old password widget $arrFields['oldPassword'] = array('name' => 'oldpassword', 'label' => &$GLOBALS['TL_LANG']['MSC']['oldPassword'], 'inputType' => 'text', 'eval' => array('mandatory' => true, 'preserveTags' => true, 'hideInput' => true)); // New password widget $arrFields['newPassword'] = $GLOBALS['TL_DCA']['tl_member']['fields']['password']; $arrFields['newPassword']['name'] = 'password'; $arrFields['newPassword']['label'] =& $GLOBALS['TL_LANG']['MSC']['newPassword']; $row = 0; $strFields = ''; $doNotSubmit = false; $objMember = \MemberModel::findByPk($this->User->id); $strFormId = 'tl_change_password_' . $this->id; $flashBag = \System::getContainer()->get('session')->getFlashBag(); $strTable = $objMember->getTable(); // Initialize the versioning (see #8301) $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(); /** @var FormTextField $objOldPassword */ $objOldPassword = null; /** @var FormPassword $objNewPassword */ $objNewPassword = null; // Initialize the widgets foreach ($arrFields as $strKey => $arrField) { /** @var Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrField['inputType']]; // Continue if the class is not defined if (!class_exists($strClass)) { continue; } $arrField['eval']['required'] = $arrField['eval']['mandatory']; /** @var Widget $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($arrField, $arrField['name'])); $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) { $objWidget->rowClassConfirm = 'row_' . ++$row . ($row % 2 == 0 ? ' even' : ' odd'); } ++$row; // Store the widget objects $strVar = 'obj' . ucfirst($strKey); ${$strVar} = $objWidget; // Validate the widget if (\Input::post('FORM_SUBMIT') == $strFormId) { $objWidget->validate(); // Validate the old password if ($strKey == 'oldPassword') { if (\Encryption::test($objMember->password)) { $blnAuthenticated = \Encryption::verify($objWidget->value, $objMember->password); } else { list($strPassword, $strSalt) = explode(':', $objMember->password); $blnAuthenticated = $strSalt == '' ? $strPassword === sha1($objWidget->value) : $strPassword === sha1($strSalt . $objWidget->value); } if (!$blnAuthenticated) { $objWidget->value = ''; $objWidget->addError($GLOBALS['TL_LANG']['MSC']['oldPasswordWrong']); sleep(2); // Wait 2 seconds while brute forcing :) } } if ($objWidget->hasErrors()) { $doNotSubmit = true; } } $strFields .= $objWidget->parse(); } $this->Template->fields = $strFields; $this->Template->hasError = $doNotSubmit; // Store the new password if (\Input::post('FORM_SUBMIT') == $strFormId && !$doNotSubmit) { $objMember->tstamp = time(); $objMember->password = $objNewPassword->value; $objMember->save(); // Create a new version if ($GLOBALS['TL_DCA'][$strTable]['config']['enableVersioning']) { $objVersions->create(); } // HOOK: set new password callback if (isset($GLOBALS['TL_HOOKS']['setNewPassword']) && is_array($GLOBALS['TL_HOOKS']['setNewPassword'])) { foreach ($GLOBALS['TL_HOOKS']['setNewPassword'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($objMember, $objNewPassword->value, $this); } } // Check whether there is a jumpTo page if (($objJumpTo = $this->objModel->getRelated('jumpTo')) instanceof PageModel) { $this->jumpToOrReload($objJumpTo->row()); } $flashBag->set('mod_change_password_confirm', $GLOBALS['TL_LANG']['MSC']['newPasswordSet']); $this->reload(); } // Confirmation message if ($flashBag->has('mod_change_password_confirm')) { $arrMessages = $flashBag->get('mod_change_password_confirm'); $this->Template->message = $arrMessages[0]; } $this->Template->formId = $strFormId; $this->Template->action = \Environment::get('indexFreeRequest'); $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['changePassword']); $this->Template->rowLast = 'row_' . $row . ' row_last' . ($row % 2 == 0 ? ' even' : ' odd'); }
/** * 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']; }
/** * Create the extract from the DCA or the database.sql files */ protected function createExtract() { // Load the default language file (see #7202) if (empty($GLOBALS['TL_LANG']['MSC'])) { System::loadLanguageFile('default'); } // Load the data container if (!isset($GLOBALS['loadDataContainer'][$this->strTable])) { $this->loadDataContainer($this->strTable); } // Return if the DC type is "File" if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dataContainer'] == 'File') { return; } $blnFromFile = false; $arrRelations = array(); // Check whether there are fields (see #4826) if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $field => $config) { // Check whether all fields have an SQL definition if (!isset($config['sql']) && isset($config['inputType'])) { $blnFromFile = true; } // Check whether there is a relation (see #6524) if (isset($config['relation'])) { $table = substr($config['foreignKey'], 0, strrpos($config['foreignKey'], '.')); $arrRelations[$field] = array_merge(array('table' => $table, 'field' => 'id'), $config['relation']); // Table name and field name are mandatory if (empty($arrRelations[$field]['table']) || empty($arrRelations[$field]['field'])) { throw new \Exception('Incomplete relation defined for ' . $this->strTable . '.' . $field); } } } } $sql = $GLOBALS['TL_DCA'][$this->strTable]['config']['sql'] ?: array(); $fields = $GLOBALS['TL_DCA'][$this->strTable]['fields'] ?: array(); // Deprecated since Contao 4.0, to be removed in Contao 5.0 if ($blnFromFile) { trigger_error('Using database.sql files has been deprecated and will no longer work in Contao 5.0. Use a DCA file instead.', E_USER_DEPRECATED); if (!isset(static::$arrSql[$this->strTable])) { try { /** @var SplFileInfo[] $files */ $files = \System::getContainer()->get('contao.resource_locator')->locate('config/database.sql', null, false); } catch (\InvalidArgumentException $e) { return array(); } $arrSql = array(); foreach ($files as $file) { $arrSql = array_merge_recursive($arrSql, \SqlFileParser::parse($file)); } static::$arrSql = $arrSql; } $arrTable = static::$arrSql[$this->strTable]; list($engine, , $charset) = explode(' ', trim($arrTable['TABLE_OPTIONS'])); if ($engine != '') { $sql['engine'] = str_replace('ENGINE=', '', $engine); } if ($charset != '') { $sql['charset'] = str_replace('CHARSET=', '', $charset); } // Fields if (isset($arrTable['TABLE_FIELDS'])) { foreach ($arrTable['TABLE_FIELDS'] as $k => $v) { $fields[$k]['sql'] = str_replace('`' . $k . '` ', '', $v); } } // Keys if (isset($arrTable['TABLE_CREATE_DEFINITIONS'])) { foreach ($arrTable['TABLE_CREATE_DEFINITIONS'] as $strKey) { if (preg_match('/^([A-Z]+ )?KEY .+\\(([^)]+)\\)$/', $strKey, $arrMatches) && preg_match_all('/`([^`]+)`/', $arrMatches[2], $arrFields)) { $type = trim($arrMatches[1]); $field = implode(',', $arrFields[1]); $sql['keys'][$field] = $type != '' ? strtolower($type) : 'index'; } } } } // Not a database table or no field information if (empty($sql) || empty($fields)) { return; } // Add the default engine and charset if none is given if (empty($sql['engine'])) { $sql['engine'] = 'MyISAM'; } if (empty($sql['charset'])) { $sql['charset'] = \Config::get('dbCharset'); } // Meta $this->arrMeta = array('engine' => $sql['engine'], 'charset' => $sql['charset']); // Fields if (!empty($fields)) { $this->arrFields = array(); $this->arrOrderFields = array(); foreach ($fields as $field => $config) { if (isset($config['sql'])) { $this->arrFields[$field] = $config['sql']; } // Only add order fields of binary fields (see #7785) if (isset($config['inputType']) && $config['inputType'] == 'fileTree' && isset($config['eval']['orderField'])) { $this->arrOrderFields[] = $config['eval']['orderField']; } if (isset($config['eval']['unique']) && $config['eval']['unique']) { $this->arrUniqueFields[] = $field; } } } // Keys if (!empty($sql['keys']) && is_array($sql['keys'])) { $this->arrKeys = array(); foreach ($sql['keys'] as $field => $type) { $this->arrKeys[$field] = $type; if ($type == 'unique') { $this->arrUniqueFields[] = $field; } } } // Relations if (!empty($arrRelations)) { $this->arrRelations = array(); foreach ($arrRelations as $field => $config) { $this->arrRelations[$field] = array(); foreach ($config as $k => $v) { $this->arrRelations[$field][$k] = $v; } } } $this->arrUniqueFields = array_unique($this->arrUniqueFields); $this->blnIsDbTable = true; }
/** * Prepare buttons. * * @param $newsId * * @return string */ protected function prepareButtons($newsId) { global $container; System::loadLanguageFile('tl_calendar_events'); $translator = $container['translator']; $buttons = self::getModalEditButton($newsId, $translator); $buttons .= self::getModalShowButton($newsId, $translator); return $buttons; }
/** * Run the controller and parse the template * * @return Response */ public function run() { $table = \Input::get('table'); $field = \Input::get('field'); \System::loadLanguageFile($table); $this->loadDataContainer($table); /** @var \BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_help'); $objTemplate->rows = array(); $objTemplate->explanation = ''; $arrData = $GLOBALS['TL_DCA'][$table]['fields'][$field]; // Back end modules if ($table == 'tl_user_group' && $field == 'modules') { $rows = array(); foreach (array_keys($GLOBALS['BE_MOD']) as $group) { $rows[] = array('headspan', $arrData['reference'][$group]); foreach ($GLOBALS['BE_MOD'][$group] as $module => $class) { $rows[] = $arrData['reference'][$module]; } } $objTemplate->rows = $rows; } elseif ($table == 'tl_module' && $field == 'type') { $rows = array(); foreach (array_keys($GLOBALS['FE_MOD']) as $group) { $rows[] = array('headspan', $arrData['reference'][$group]); foreach ($GLOBALS['FE_MOD'][$group] as $module => $class) { $rows[] = $arrData['reference'][$module]; } } $objTemplate->rows = $rows; } elseif ($table == 'tl_content' && $field == 'type') { $rows = array(); foreach (array_keys($GLOBALS['TL_CTE']) as $group) { $rows[] = array('headspan', $arrData['reference'][$group]); foreach ($GLOBALS['TL_CTE'][$group] as $element => $class) { $rows[] = $arrData['reference'][$element]; } } $objTemplate->rows = $rows; } elseif (!empty($arrData['reference'])) { $rows = array(); $options = is_array($arrData['options']) ? $arrData['options'] : array_keys($arrData['reference']); // Unset the predefined image sizes unset($options['image_sizes']); foreach ($options as $key => $option) { if (is_array($option)) { if (is_array($arrData['reference'][$key])) { $rows[] = array('headspan', $arrData['reference'][$key][0]); } else { $rows[] = array('headspan', $arrData['reference'][$key]); } foreach ($option as $opt) { $rows[] = $arrData['reference'][$opt]; } } else { if (!is_array($arrData['reference'][$option])) { $rows[] = array('headspan', $arrData['reference'][$option]); } else { $rows[] = $arrData['reference'][$option]; } } } $objTemplate->rows = $rows; } // Add an explanation if (isset($arrData['explanation'])) { \System::loadLanguageFile('explain'); $key = $arrData['explanation']; if (!is_array($GLOBALS['TL_LANG']['XPL'][$key])) { $objTemplate->explanation = trim($GLOBALS['TL_LANG']['XPL'][$key]); } else { $objTemplate->rows = $GLOBALS['TL_LANG']['XPL'][$key]; } } $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = specialchars($GLOBALS['TL_LANG']['MSC']['helpWizardTitle']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->headline = $arrData['label'][0] ?: $field; $objTemplate->helpWizard = $GLOBALS['TL_LANG']['MSC']['helpWizard']; return $objTemplate->getResponse(); }
/** * Generate the module */ protected function compile() { \System::loadLanguageFile($this->list_table); $this->loadDataContainer($this->list_table); // List a single record if (\Input::get('show')) { $this->listSingleRecord(\Input::get('show')); return; } /** * Add the search menu */ $strWhere = ''; $varKeyword = ''; $strOptions = ''; $this->Template->searchable = false; $arrSearchFields = \StringUtil::trimsplit(',', $this->list_search); if (!empty($arrSearchFields) && is_array($arrSearchFields)) { $this->Template->searchable = true; if (\Input::get('search') && \Input::get('for')) { $varKeyword = '%' . \Input::get('for') . '%'; $strWhere = (!$this->list_where ? " WHERE " : " AND ") . \Input::get('search') . " LIKE ?"; } foreach ($arrSearchFields as $field) { $strOptions .= ' <option value="' . $field . '"' . ($field == \Input::get('search') ? ' selected="selected"' : '') . '>' . (strlen($label = $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['label'][0]) ? $label : $field) . '</option>' . "\n"; } } $this->Template->search_fields = $strOptions; /** * Get the total number of records */ $strQuery = "SELECT COUNT(*) AS count FROM " . $this->list_table; if ($this->list_where) { $strQuery .= " WHERE (" . $this->list_where . ")"; } $strQuery .= $strWhere; $objTotal = $this->Database->prepare($strQuery)->execute($varKeyword); /** * Validate the page count */ $id = 'page_l' . $this->id; $page = \Input::get($id) !== null ? \Input::get($id) : 1; $per_page = \Input::get('per_page') ?: $this->perPage; // Thanks to Hagen Klemp (see #4485) if ($per_page > 0 && ($page < 1 || $page > max(ceil($objTotal->count / $per_page), 1))) { throw new PageNotFoundException('Page not found: ' . \Environment::get('uri')); } /** * Get the selected records */ $strQuery = "SELECT " . $this->strPk . "," . $this->list_fields; if ($this->list_info_where) { $strQuery .= ", (SELECT COUNT(*) FROM " . $this->list_table . " t2 WHERE t2." . $this->strPk . "=t1." . $this->strPk . " AND " . $this->list_info_where . ") AS _details"; } $strQuery .= " FROM " . $this->list_table . " t1"; if ($this->list_where) { $strQuery .= " WHERE (" . $this->list_where . ")"; } $strQuery .= $strWhere; // Cast date fields to int (see #5609) $isInt = function ($field) { return $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'date' || $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'time' || $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'datim'; }; // Order by if (\Input::get('order_by')) { if ($isInt(\Input::get('order_by'))) { $strQuery .= " ORDER BY CAST(" . \Input::get('order_by') . " AS SIGNED) " . \Input::get('sort'); } else { $strQuery .= " ORDER BY " . \Input::get('order_by') . ' ' . \Input::get('sort'); } } elseif ($this->list_sort) { if ($isInt($this->list_sort)) { $strQuery .= " ORDER BY CAST(" . $this->list_sort . " AS SIGNED)"; } else { $strQuery .= " ORDER BY " . $this->list_sort; } } $objDataStmt = $this->Database->prepare($strQuery); // Limit if (\Input::get('per_page')) { $objDataStmt->limit(\Input::get('per_page'), ($page - 1) * $per_page); } elseif ($this->perPage) { $objDataStmt->limit($this->perPage, ($page - 1) * $per_page); } $objData = $objDataStmt->execute($varKeyword); /** * Prepare the URL */ $strUrl = preg_replace('/\\?.*$/', '', \Environment::get('request')); $blnQuery = false; foreach (preg_split('/&(amp;)?/', \Environment::get('queryString')) as $fragment) { if ($fragment != '' && strncasecmp($fragment, 'order_by', 8) !== 0 && strncasecmp($fragment, 'sort', 4) !== 0 && strncasecmp($fragment, $id, strlen($id)) !== 0) { $strUrl .= (!$blnQuery ? '?' : '&') . $fragment; $blnQuery = true; } } $this->Template->url = $strUrl; $strVarConnector = $blnQuery ? '&' : '?'; /** * Prepare the data arrays */ $arrTh = array(); $arrTd = array(); $arrFields = \StringUtil::trimsplit(',', $this->list_fields); // THEAD for ($i = 0, $c = count($arrFields); $i < $c; $i++) { // Never show passwords if ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$arrFields[$i]]['inputType'] == 'password') { continue; } $class = ''; $sort = 'asc'; $strField = strlen($label = $GLOBALS['TL_DCA'][$this->list_table]['fields'][$arrFields[$i]]['label'][0]) ? $label : $arrFields[$i]; // Add a CSS class to the order_by column if (\Input::get('order_by') == $arrFields[$i]) { $sort = \Input::get('sort') == 'asc' ? 'desc' : 'asc'; $class = ' sorted ' . \Input::get('sort'); } $arrTh[] = array('link' => $strField, 'href' => ampersand($strUrl) . $strVarConnector . 'order_by=' . $arrFields[$i] . '&sort=' . $sort, 'title' => \StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['list_orderBy'], $strField)), 'class' => $class . ($i == 0 ? ' col_first' : '')); } $j = 0; $arrRows = $objData->fetchAllAssoc(); // TBODY for ($i = 0, $c = count($arrRows); $i < $c; $i++) { $j = 0; $class = 'row_' . $i . ($i == 0 ? ' row_first' : '') . ($i + 1 == count($arrRows) ? ' row_last' : '') . ($i % 2 == 0 ? ' even' : ' odd'); foreach ($arrRows[$i] as $k => $v) { // Skip the primary key if ($k == $this->strPk && !in_array($this->strPk, $arrFields)) { continue; } if ($k == '_details') { continue; } // Never show passwords if ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['inputType'] == 'password') { continue; } $value = $this->formatValue($k, $v); $arrTd[$class][$k] = array('raw' => $v, 'content' => $value ? $value : ' ', 'class' => 'col_' . $j . ($j++ == 0 ? ' col_first' : '') . ($this->list_info ? '' : ($j >= count($arrRows[$i]) - 1 ? ' col_last' : '')), 'id' => $arrRows[$i][$this->strPk], 'field' => $k, 'url' => $strUrl . $strVarConnector . 'show=' . $arrRows[$i][$this->strPk], 'details' => isset($arrRows[$i]['_details']) ? $arrRows[$i]['_details'] : 1); } } $this->Template->thead = $arrTh; $this->Template->tbody = $arrTd; /** * Pagination */ $objPagination = new \Pagination($objTotal->count, $per_page, \Config::get('maxPaginationLinks'), $id); $this->Template->pagination = $objPagination->generate("\n "); $this->Template->per_page = $per_page; $this->Template->total = $objTotal->count; /** * Template variables */ $this->Template->action = \Environment::get('indexFreeRequest'); $this->Template->details = $this->list_info != '' ? true : false; $this->Template->search_label = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['search']); $this->Template->per_page_label = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['list_perPage']); $this->Template->fields_label = $GLOBALS['TL_LANG']['MSC']['all_fields'][0]; $this->Template->keywords_label = $GLOBALS['TL_LANG']['MSC']['keywords']; $this->Template->search = \Input::get('search'); $this->Template->for = \Input::get('for'); $this->Template->order_by = \Input::get('order_by'); $this->Template->sort = \Input::get('sort'); $this->Template->col_last = 'col_' . $j; }
/** * 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'); }
/** * Loads the language strings. * * @return array|null The language strings or null */ private function loadLanguageStrings() { $this->framework->initialize(); System::loadLanguageFile('exception'); if (!isset($GLOBALS['TL_LANG']['XPT'])) { return null; } return $GLOBALS['TL_LANG']['XPT']; }
/** * Add the welcome screen * * @return string */ protected function welcomeScreen() { \System::loadLanguageFile('explain'); /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_welcome'); $objTemplate->messages = \Message::generateUnwrapped() . \Backend::getSystemMessages(); $objTemplate->loginMsg = $GLOBALS['TL_LANG']['MSC']['firstLogin']; // Add the login message if ($this->User->lastLogin > 0) { $formatter = new DateTimeFormatter(\System::getContainer()->get('translator')); $diff = $formatter->formatDiff(new \DateTime(date('Y-m-d H:i:s', $this->User->lastLogin)), new \DateTime()); $objTemplate->loginMsg = sprintf($GLOBALS['TL_LANG']['MSC']['lastLogin'][1], '<time title="' . \Date::parse(\Config::get('datimFormat'), $this->User->lastLogin) . '">' . $diff . '</time>'); } // Add the versions overview \Versions::addToTemplate($objTemplate); $objTemplate->welcome = sprintf($GLOBALS['TL_LANG']['MSC']['welcomeTo'], \Config::get('websiteTitle')); $objTemplate->showDifferences = \StringUtil::specialchars(str_replace("'", "\\'", $GLOBALS['TL_LANG']['MSC']['showDifferences'])); $objTemplate->recordOfTable = \StringUtil::specialchars(str_replace("'", "\\'", $GLOBALS['TL_LANG']['MSC']['recordOfTable'])); $objTemplate->systemMessages = $GLOBALS['TL_LANG']['MSC']['systemMessages']; $objTemplate->shortcuts = $GLOBALS['TL_LANG']['MSC']['shortcuts'][0]; $objTemplate->shortcutsLink = $GLOBALS['TL_LANG']['MSC']['shortcuts'][1]; $objTemplate->editElement = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['editElement']); return $objTemplate->parse(); }
/** * Run the controller and parse the template * * @return Response */ public function run() { $table = \Input::get('table'); $field = \Input::get('field'); \System::loadLanguageFile($table); $this->loadDataContainer($table); /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_help'); $objTemplate->rows = array(); $objTemplate->explanation = ''; $arrData = $GLOBALS['TL_DCA'][$table]['fields'][$field]; // Add the reference if (!empty($arrData['reference'])) { $rows = array(); if (is_array($arrData['options'])) { $options = $arrData['options']; } elseif (is_array($arrData['options_callback'])) { $this->import($arrData['options_callback'][0]); $options = $this->{$arrData['options_callback'][0]}->{$arrData['options_callback'][1]}(new \DC_Table($table)); } elseif (is_callable($arrData['options_callback'])) { $options = $arrData['options_callback'](); } else { $options = array_keys($arrData['reference']); } // Unset the predefined image sizes unset($options['image_sizes']); foreach ($options as $key => $option) { if (is_array($option)) { if (is_array($arrData['reference'][$key])) { $rows[] = array('headspan', $arrData['reference'][$key][0]); } else { $rows[] = array('headspan', $arrData['reference'][$key]); } foreach ($option as $opt) { $rows[] = $arrData['reference'][$opt]; } } else { if (isset($arrData['reference'][$key])) { $rows[] = $arrData['reference'][$key]; } elseif (is_array($arrData['reference'][$option])) { $rows[] = $arrData['reference'][$option]; } else { $rows[] = array('headspan', $arrData['reference'][$option]); } } } $objTemplate->rows = $rows; } // Add an explanation if (isset($arrData['explanation'])) { \System::loadLanguageFile('explain'); $key = $arrData['explanation']; if (!is_array($GLOBALS['TL_LANG']['XPL'][$key])) { $objTemplate->explanation = trim($GLOBALS['TL_LANG']['XPL'][$key]); } else { $objTemplate->rows = $GLOBALS['TL_LANG']['XPL'][$key]; } } $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['helpWizardTitle']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->headline = $arrData['label'][0] ?: $field; $objTemplate->helpWizard = $GLOBALS['TL_LANG']['MSC']['helpWizard']; return $objTemplate->getResponse(); }
/** * Return the languages for the TinyMCE spellchecker * * @return string The TinyMCE spellchecker language string */ protected function getSpellcheckerString() { \System::loadLanguageFile('languages'); $return = array(); $langs = scan(__DIR__ . '/../../languages'); array_unshift($langs, $GLOBALS['TL_LANGUAGE']); foreach ($langs as $lang) { $lang = substr($lang, 0, 2); if (isset($GLOBALS['TL_LANG']['LNG'][$lang])) { $return[$lang] = $GLOBALS['TL_LANG']['LNG'][$lang] . '=' . $lang; } } return '+' . implode(',', array_unique($return)); }
/** * Run the controller * * @return Response */ public function run() { /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); // Redirect to the back end home page if (\Input::post('FORM_SUBMIT') == 'invalid_token_url') { list($strUrl) = explode('?', $objSession->get('INVALID_TOKEN_URL')); $this->redirect($strUrl); } /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_confirm'); // Prepare the URL $url = preg_replace('/(\\?|&)rt=[^&]*/', '', $objSession->get('INVALID_TOKEN_URL')); $objTemplate->href = ampersand($url . (strpos($url, '?') !== false ? '&rt=' : '?rt=') . REQUEST_TOKEN); $vars = array(); list(, $request) = explode('?', $url, 2); // Extract the arguments foreach (explode('&', $request) as $arg) { list($key, $value) = explode('=', $arg, 2); $vars[$key] = $value; } $arrInfo = array(); // Provide more information about the link (see #4007) foreach ($vars as $k => $v) { switch ($k) { default: $arrInfo[$k] = $v; break; case 'do': $arrInfo['do'] = $GLOBALS['TL_LANG']['MOD'][$v][0]; break; case 'id': $arrInfo['id'] = 'ID ' . $v; break; } } // Use the first table if none is given if (!isset($arrInfo['table'])) { foreach ($GLOBALS['BE_MOD'] as $category => $modules) { if (isset($GLOBALS['BE_MOD'][$category][$vars['do']])) { $arrInfo['table'] = $GLOBALS['BE_MOD'][$category][$vars['do']]['tables'][0]; break; } } } \System::loadLanguageFile($arrInfo['table']); // Override the action label if (isset($arrInfo['clipboard'])) { $arrInfo['act'] = $GLOBALS['TL_LANG']['MSC']['clearClipboard']; } elseif (isset($arrInfo['mode']) && !isset($arrInfo['act'])) { if ($arrInfo['mode'] == 'create') { $arrInfo['act'] = $GLOBALS['TL_LANG'][$arrInfo['table']]['new'][0]; } elseif ($arrInfo['mode'] == 'cut' || $arrInfo['mode'] == 'copy') { $arrInfo['act'] = $GLOBALS['TL_LANG'][$arrInfo['table']][$arrInfo['mode']][0]; } } else { $arrInfo['act'] = $GLOBALS['TL_LANG'][$arrInfo['table']][$arrInfo['act']][0]; } unset($arrInfo['pid']); unset($arrInfo['clipboard']); unset($arrInfo['ref']); unset($arrInfo['mode']); // Template variables $objTemplate->confirm = true; $objTemplate->link = \StringUtil::specialchars($url); $objTemplate->info = $arrInfo; $objTemplate->labels = $GLOBALS['TL_LANG']['CONFIRM']; $objTemplate->explain = $GLOBALS['TL_LANG']['ERR']['invalidTokenUrl']; $objTemplate->cancel = $GLOBALS['TL_LANG']['MSC']['cancelBT']; $objTemplate->continue = $GLOBALS['TL_LANG']['MSC']['continue']; $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['invalidTokenUrl']); $objTemplate->charset = \Config::get('characterSet'); return $objTemplate->getResponse(); }
/** * Loads the language strings. * * @return array|null The language strings or null */ private function loadLanguageStrings() { if (!class_exists('Contao\\System')) { return null; } System::loadLanguageFile('exception'); if (!isset($GLOBALS['TL_LANG']['XPT'])) { return null; } return $GLOBALS['TL_LANG']['XPT']; }
/** * Add the welcome screen * * @return string */ protected function welcomeScreen() { \System::loadLanguageFile('explain'); /** @var \BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_welcome'); $objTemplate->messages = \Message::generateUnwrapped(); // HOOK: add custom messages if (isset($GLOBALS['TL_HOOKS']['getSystemMessages']) && is_array($GLOBALS['TL_HOOKS']['getSystemMessages'])) { $arrMessages = array(); foreach ($GLOBALS['TL_HOOKS']['getSystemMessages'] as $callback) { $this->import($callback[0]); $strBuffer = $this->{$callback}[0]->{$callback}[1](); if ($strBuffer != '') { $arrMessages[] = $strBuffer; } } if (!empty($arrMessages)) { $objTemplate->messages .= "\n" . implode("\n", $arrMessages); } } // Add the versions overview \Versions::addToTemplate($objTemplate); $objTemplate->welcome = sprintf($GLOBALS['TL_LANG']['MSC']['welcomeTo'], \Config::get('websiteTitle')); $objTemplate->showDifferences = specialchars(str_replace("'", "\\'", $GLOBALS['TL_LANG']['MSC']['showDifferences'])); $objTemplate->systemMessages = $GLOBALS['TL_LANG']['MSC']['systemMessages']; $objTemplate->shortcuts = $GLOBALS['TL_LANG']['MSC']['shortcuts'][0]; $objTemplate->shortcutsLink = $GLOBALS['TL_LANG']['MSC']['shortcuts'][1]; $objTemplate->editElement = specialchars($GLOBALS['TL_LANG']['MSC']['editElement']); return $objTemplate->parse(); }
/** * Open a back end module and return it as HTML * * @param string $module * * @return string * * @throws AccessDeniedException */ protected function getBackendModule($module) { $arrModule = array(); foreach ($GLOBALS['BE_MOD'] as &$arrGroup) { if (isset($arrGroup[$module])) { $arrModule =& $arrGroup[$module]; break; } } $this->import('BackendUser', 'User'); // Dynamically add the "personal data" module (see #4193) if (\Input::get('do') == 'login') { $arrModule = array('tables' => array('tl_user'), 'callback' => 'ModuleUser'); } elseif ($module != 'undo' && !$this->User->hasAccess($module, 'modules')) { throw new AccessDeniedException('Back end module "' . $module . '" is not allowed for user "' . $this->User->username . '".'); } /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); $arrTables = (array) $arrModule['tables']; $strTable = \Input::get('table') ?: $arrTables[0]; $id = !\Input::get('act') && \Input::get('id') ? \Input::get('id') : $objSession->get('CURRENT_ID'); // Store the current ID in the current session if ($id != $objSession->get('CURRENT_ID')) { $objSession->set('CURRENT_ID', $id); } define('CURRENT_ID', \Input::get('table') ? $id : \Input::get('id')); $this->Template->headline = $GLOBALS['TL_LANG']['MOD'][$module][0]; // Add the module style sheet if (isset($arrModule['stylesheet'])) { foreach ((array) $arrModule['stylesheet'] as $stylesheet) { $GLOBALS['TL_CSS'][] = $stylesheet; } } // Add module javascript if (isset($arrModule['javascript'])) { foreach ((array) $arrModule['javascript'] as $javascript) { $GLOBALS['TL_JAVASCRIPT'][] = $javascript; } } $dc = null; // Create the data container object if ($strTable != '') { if (!in_array($strTable, $arrTables)) { throw new AccessDeniedException('Table "' . $strTable . '" is not allowed in module "' . $module . '".'); } // Load the language and DCA file \System::loadLanguageFile($strTable); $this->loadDataContainer($strTable); // Include all excluded fields which are allowed for the current user if ($GLOBALS['TL_DCA'][$strTable]['fields']) { foreach ($GLOBALS['TL_DCA'][$strTable]['fields'] as $k => $v) { if ($v['exclude']) { if ($this->User->hasAccess($strTable . '::' . $k, 'alexf')) { if ($strTable == 'tl_user_group') { $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['orig_exclude'] = $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['exclude']; } $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['exclude'] = false; } } } } // Fabricate a new data container object if ($GLOBALS['TL_DCA'][$strTable]['config']['dataContainer'] == '') { $this->log('Missing data container for table "' . $strTable . '"', __METHOD__, TL_ERROR); trigger_error('Could not create a data container object', E_USER_ERROR); } $dataContainer = 'DC_' . $GLOBALS['TL_DCA'][$strTable]['config']['dataContainer']; /** @var DataContainer $dc */ $dc = new $dataContainer($strTable, $arrModule); } // AJAX request if ($_POST && \Environment::get('isAjaxRequest')) { $this->objAjax->executePostActions($dc); } elseif (class_exists($arrModule['callback'])) { /** @var Module $objCallback */ $objCallback = new $arrModule['callback']($dc); $this->Template->main .= $objCallback->generate(); } elseif (\Input::get('key') && isset($arrModule[\Input::get('key')])) { $objCallback = \System::importStatic($arrModule[\Input::get('key')][0]); $this->Template->main .= $objCallback->{$arrModule[\Input::get('key')][1]}($dc); // Add the name of the parent element if (isset($_GET['table']) && in_array(\Input::get('table'), $arrTables) && \Input::get('table') != $arrTables[0]) { if ($GLOBALS['TL_DCA'][$strTable]['config']['ptable'] != '') { $objRow = $this->Database->prepare("SELECT * FROM " . $GLOBALS['TL_DCA'][$strTable]['config']['ptable'] . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } } // Add the name of the submodule $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][\Input::get('key')][1], \Input::get('id')); } elseif (is_object($dc)) { $act = \Input::get('act'); if ($act == '' || $act == 'paste' || $act == 'select') { $act = $dc instanceof \listable ? 'showAll' : 'edit'; } switch ($act) { case 'delete': case 'show': case 'showAll': case 'undo': if (!$dc instanceof \listable) { $this->log('Data container ' . $strTable . ' is not listable', __METHOD__, TL_ERROR); trigger_error('The current data container is not listable', E_USER_ERROR); } break; case 'create': case 'cut': case 'cutAll': case 'copy': case 'copyAll': case 'move': case 'edit': if (!$dc instanceof \editable) { $this->log('Data container ' . $strTable . ' is not editable', __METHOD__, TL_ERROR); trigger_error('The current data container is not editable', E_USER_ERROR); } break; } $strFirst = null; $strSecond = null; // Handle child child tables (e.g. tl_style) if (isset($GLOBALS['TL_DCA'][$strTable]['config']['ptable'])) { $ptable = $GLOBALS['TL_DCA'][$strTable]['config']['ptable']; if (in_array($ptable, $arrTables)) { $this->loadDataContainer($ptable); if (isset($GLOBALS['TL_DCA'][$ptable]['config']['ptable'])) { $ftable = $GLOBALS['TL_DCA'][$ptable]['config']['ptable']; if (in_array($ftable, $arrTables)) { $strFirst = $ftable; $strSecond = $ptable; } } } } // Build the breadcrumb trail if ($strFirst !== null && $strSecond !== null) { if (!isset($_GET['act']) || \Input::get('act') == 'paste' && \Input::get('mode') == 'create' || \Input::get('act') == 'select' || \Input::get('act') == 'editAll' || \Input::get('act') == 'overrideAll') { if ($strTable == $strSecond) { $strQuery = "SELECT * FROM {$strFirst} WHERE id=?"; } else { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=?)"; } } else { if ($strTable == $strSecond) { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=?)"; } else { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=(SELECT pid FROM {$strTable} WHERE id=?))"; } } // Add the first level name $objRow = $this->Database->prepare($strQuery)->limit(1)->execute($dc->id); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } if (isset($GLOBALS['TL_LANG']['MOD'][$strSecond])) { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MOD'][$strSecond]; } // Add the second level name $objRow = $this->Database->prepare("SELECT * FROM {$strSecond} WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } else { // Add the name of the parent element if ($strTable && in_array($strTable, $arrTables) && $strTable != $arrTables[0]) { if ($GLOBALS['TL_DCA'][$strTable]['config']['ptable'] != '') { $objRow = $this->Database->prepare("SELECT * FROM " . $GLOBALS['TL_DCA'][$strTable]['config']['ptable'] . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } } // Add the name of the submodule if ($strTable && isset($GLOBALS['TL_LANG']['MOD'][$strTable])) { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MOD'][$strTable]; } } // Add the current action if (\Input::get('act') == 'editAll') { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MSC']['all'][0]; } elseif (\Input::get('act') == 'overrideAll') { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MSC']['all_override'][0]; } else { if (\Input::get('id')) { if (\Input::get('do') == 'files' || \Input::get('do') == 'tpl_editor') { // Handle new folders (see #7980) if (strpos(\Input::get('id'), '__new__') !== false) { $this->Template->headline .= ' » ' . dirname(\Input::get('id')) . ' » ' . $GLOBALS['TL_LANG'][$strTable]['new'][1]; } else { $this->Template->headline .= ' » ' . \Input::get('id'); } } elseif (is_array($GLOBALS['TL_LANG'][$strTable][$act])) { $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][$act][1], \Input::get('id')); } } elseif (\Input::get('pid')) { if (\Input::get('do') == 'files' || \Input::get('do') == 'tpl_editor') { $this->Template->headline .= ' » ' . \Input::get('pid'); } elseif (is_array($GLOBALS['TL_LANG'][$strTable][$act])) { $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][$act][1], \Input::get('pid')); } } } return $dc->{$act}(); } return null; }
/** * Check whether there is a cached version of the page and return a response object * * @return Response|null */ public static function getResponseFromCache() { // Build the page if a user is (potentially) logged in or there is POST data if (!empty($_POST) || \Input::cookie('BE_USER_AUTH') || \Input::cookie('FE_USER_AUTH') || \Input::cookie('FE_AUTO_LOGIN') || $_SESSION['DISABLE_CACHE'] || isset($_SESSION['LOGIN_ERROR']) || \Message::hasMessages() || \Config::get('debugMode')) { return null; } $strCacheDir = \System::getContainer()->getParameter('kernel.cache_dir'); // Try to map the empty request if (\Environment::get('relativeRequest') == '') { // Return if the language is added to the URL and the empty domain will be redirected if (\Config::get('addLanguageToUrl') && !\Config::get('doNotRedirectEmpty')) { return null; } $strCacheKey = null; $arrLanguage = \Environment::get('httpAcceptLanguage'); $strMappingFile = $strCacheDir . '/contao/config/mapping.php'; // Try to get the cache key from the mapper array if (file_exists($strMappingFile)) { $arrMapper = (include $strMappingFile); $arrPaths = array(\Environment::get('host'), '*'); // Try the language specific keys foreach ($arrLanguage as $strLanguage) { foreach ($arrPaths as $strPath) { $strKey = $strPath . '/empty.' . $strLanguage; if (isset($arrMapper[$strKey])) { $strCacheKey = $arrMapper[$strKey]; break; } } } // Try the fallback key if ($strCacheKey === null) { foreach ($arrPaths as $strPath) { $strKey = $strPath . '/empty.fallback'; if (isset($arrMapper[$strKey])) { $strCacheKey = $arrMapper[$strKey]; break; } } } } // Fall back to the first accepted language if ($strCacheKey === null) { $strCacheKey = \Environment::get('host') . '/empty.' . $arrLanguage[0]; } } else { $strCacheKey = \Environment::get('host') . '/' . \Environment::get('relativeRequest'); } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getCacheKey']) && is_array($GLOBALS['TL_HOOKS']['getCacheKey'])) { foreach ($GLOBALS['TL_HOOKS']['getCacheKey'] as $callback) { $strCacheKey = \System::importStatic($callback[0])->{$callback[1]}($strCacheKey); } } $blnFound = false; $strCacheFile = null; // Check for a mobile layout if (\Input::cookie('TL_VIEW') == 'mobile' || \Environment::get('agent')->mobile && \Input::cookie('TL_VIEW') != 'desktop') { $strMd5CacheKey = md5($strCacheKey . '.mobile'); $strCacheFile = $strCacheDir . '/contao/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'; if (file_exists($strCacheFile)) { $blnFound = true; } } else { $strMd5CacheKey = md5($strCacheKey . '.desktop'); $strCacheFile = $strCacheDir . '/contao/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'; if (file_exists($strCacheFile)) { $blnFound = true; } } // Check for a regular layout if (!$blnFound) { $strMd5CacheKey = md5($strCacheKey); $strCacheFile = $strCacheDir . '/contao/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'; if (file_exists($strCacheFile)) { $blnFound = true; } } // Return if the file does not exist if (!$blnFound) { return null; } $expire = null; $content = null; $type = null; $files = null; $assets = null; // Include the file ob_start(); require_once $strCacheFile; // The file has expired if ($expire < time()) { ob_end_clean(); return null; } // Define the static URL constants (see #7914) define('TL_FILES_URL', $files); define('TL_ASSETS_URL', $assets); // Read the buffer $strBuffer = ob_get_clean(); /** @var AttributeBagInterface $session */ $session = \System::getContainer()->get('session')->getBag('contao_frontend'); // Session required to determine the referer $data = $session->all(); // Set the new referer if (!isset($_GET['pdf']) && !isset($_GET['file']) && !isset($_GET['id']) && $data['referer']['current'] != \Environment::get('requestUri')) { $data['referer']['last'] = $data['referer']['current']; $data['referer']['current'] = substr(\Environment::get('requestUri'), strlen(\Environment::get('path')) + 1); } // Store the session data $session->replace($data); // Load the default language file (see #2644) \System::loadLanguageFile('default'); // Replace the insert tags and then re-replace the request_token tag in case a form element has been loaded via insert tag $strBuffer = \Controller::replaceInsertTags($strBuffer, false); $strBuffer = str_replace(array('{{request_token}}', '[{]', '[}]'), array(REQUEST_TOKEN, '{{', '}}'), $strBuffer); // HOOK: allow to modify the compiled markup (see #4291 and #7457) if (isset($GLOBALS['TL_HOOKS']['modifyFrontendPage']) && is_array($GLOBALS['TL_HOOKS']['modifyFrontendPage'])) { foreach ($GLOBALS['TL_HOOKS']['modifyFrontendPage'] as $callback) { $strBuffer = \System::importStatic($callback[0])->{$callback[1]}($strBuffer, null); } } // Content type if (!$content) { $content = 'text/html'; } $response = new Response($strBuffer); // Send the status header (see #6585) if ($type == 'error_403') { $response->setStatusCode(Response::HTTP_FORBIDDEN); } elseif ($type == 'error_404') { $response->setStatusCode(Response::HTTP_NOT_FOUND); } $response->headers->set('Vary', 'User-Agent', false); $response->headers->set('Content-Type', $content . '; charset=' . \Config::get('characterSet')); // Send the cache headers if ($expire !== null && (\Config::get('cacheMode') == 'both' || \Config::get('cacheMode') == 'browser')) { $response->headers->set('Cache-Control', 'public, max-age=' . ($expire - time())); $response->headers->set('Pragma', 'public'); $response->headers->set('Last-Modified', gmdate('D, d M Y H:i:s', time()) . ' GMT'); $response->headers->set('Expires', gmdate('D, d M Y H:i:s', $expire) . ' GMT'); } else { $response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); $response->headers->set('Pragma', 'no-cache'); $response->headers->set('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); $response->headers->set('Expires', 'Fri, 06 Jun 1975 15:10:00 GMT'); } return $response; }
/** * Compare versions */ public function compare() { $strBuffer = ''; $arrVersions = array(); $intTo = 0; $intFrom = 0; $objVersions = $this->Database->prepare("SELECT * FROM tl_version WHERE pid=? AND fromTable=? ORDER BY version DESC")->execute($this->intPid, $this->strTable); if ($objVersions->numRows < 2) { $strBuffer = '<p>There are no versions of ' . $this->strTable . '.id=' . $this->intPid . '</p>'; } else { $intIndex = 0; $from = array(); // Store the versions and mark the active one while ($objVersions->next()) { if ($objVersions->active) { $intIndex = $objVersions->version; } $arrVersions[$objVersions->version] = $objVersions->row(); $arrVersions[$objVersions->version]['info'] = $GLOBALS['TL_LANG']['MSC']['version'] . ' ' . $objVersions->version . ' (' . \Date::parse(\Config::get('datimFormat'), $objVersions->tstamp) . ') ' . $objVersions->username; } // To if (\Input::post('to') && isset($arrVersions[\Input::post('to')])) { $intTo = \Input::post('to'); $to = \StringUtil::deserialize($arrVersions[\Input::post('to')]['data']); } elseif (\Input::get('to') && isset($arrVersions[\Input::get('to')])) { $intTo = \Input::get('to'); $to = \StringUtil::deserialize($arrVersions[\Input::get('to')]['data']); } else { $intTo = $intIndex; $to = \StringUtil::deserialize($arrVersions[$intTo]['data']); } // From if (\Input::post('from') && isset($arrVersions[\Input::post('from')])) { $intFrom = \Input::post('from'); $from = \StringUtil::deserialize($arrVersions[\Input::post('from')]['data']); } elseif (\Input::get('from') && isset($arrVersions[\Input::get('from')])) { $intFrom = \Input::get('from'); $from = \StringUtil::deserialize($arrVersions[\Input::get('from')]['data']); } elseif ($intIndex > 1) { $intFrom = $intIndex - 1; $from = \StringUtil::deserialize($arrVersions[$intFrom]['data']); } // Only continue if both version numbers are set if ($intTo > 0 && $intFrom > 0) { \System::loadLanguageFile($this->strTable); $this->loadDataContainer($this->strTable); // Get the order fields $objDcaExtractor = \DcaExtractor::getInstance($this->strTable); $arrOrder = $objDcaExtractor->getOrderFields(); // Find the changed fields and highlight the changes foreach ($to as $k => $v) { if ($from[$k] != $to[$k]) { if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['doNotShow'] || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['hideInput']) { continue; } $blnIsBinary = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['inputType'] == 'fileTree' || in_array($k, $arrOrder); // Decrypt the values if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['encrypt']) { $to[$k] = \Encryption::decrypt($to[$k]); $from[$k] = \Encryption::decrypt($from[$k]); } // Convert serialized arrays into strings if (is_array($tmp = \StringUtil::deserialize($to[$k])) && !is_array($to[$k])) { $to[$k] = $this->implodeRecursive($tmp, $blnIsBinary); } if (is_array($tmp = \StringUtil::deserialize($from[$k])) && !is_array($from[$k])) { $from[$k] = $this->implodeRecursive($tmp, $blnIsBinary); } unset($tmp); // Convert binary UUIDs to their hex equivalents (see #6365) if ($blnIsBinary && \Validator::isBinaryUuid($to[$k])) { $to[$k] = \StringUtil::binToUuid($to[$k]); } if ($blnIsBinary && \Validator::isBinaryUuid($from[$k])) { $to[$k] = \StringUtil::binToUuid($from[$k]); } // Convert date fields if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['rgxp'] == 'date') { $to[$k] = \Date::parse(\Config::get('dateFormat'), $to[$k] ?: ''); $from[$k] = \Date::parse(\Config::get('dateFormat'), $from[$k] ?: ''); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['rgxp'] == 'time') { $to[$k] = \Date::parse(\Config::get('timeFormat'), $to[$k] ?: ''); $from[$k] = \Date::parse(\Config::get('timeFormat'), $from[$k] ?: ''); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['eval']['rgxp'] == 'datim' || $k == 'tstamp') { $to[$k] = \Date::parse(\Config::get('datimFormat'), $to[$k] ?: ''); $from[$k] = \Date::parse(\Config::get('datimFormat'), $from[$k] ?: ''); } // Convert strings into arrays if (!is_array($to[$k])) { $to[$k] = explode("\n", $to[$k]); } if (!is_array($from[$k])) { $from[$k] = explode("\n", $from[$k]); } $objDiff = new \Diff($from[$k], $to[$k]); $strBuffer .= $objDiff->render(new DiffRenderer(array('field' => $GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['label'][0] ?: (isset($GLOBALS['TL_LANG']['MSC'][$k]) ? is_array($GLOBALS['TL_LANG']['MSC'][$k]) ? $GLOBALS['TL_LANG']['MSC'][$k][0] : $GLOBALS['TL_LANG']['MSC'][$k] : $k)))); } } } } // Identical versions if ($strBuffer == '') { $strBuffer = '<p>' . $GLOBALS['TL_LANG']['MSC']['identicalVersions'] . '</p>'; } /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_diff'); // Template variables $objTemplate->content = $strBuffer; $objTemplate->versions = $arrVersions; $objTemplate->to = $intTo; $objTemplate->from = $intFrom; $objTemplate->showLabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['showDifferences']); $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['showDifferences']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->action = ampersand(\Environment::get('request')); throw new ResponseException($objTemplate->getResponse()); }
/** * Try to login the current user * * @return boolean True if the user could be logged in */ public function login() { \System::loadLanguageFile('default'); // Do not continue if username or password are missing if (empty($_POST['username']) || empty($_POST['password'])) { return false; } // Load the user object if ($this->findBy('username', \Input::post('username', true)) == false) { $blnLoaded = false; // HOOK: pass credentials to callback functions if (isset($GLOBALS['TL_HOOKS']['importUser']) && is_array($GLOBALS['TL_HOOKS']['importUser'])) { foreach ($GLOBALS['TL_HOOKS']['importUser'] as $callback) { $this->import($callback[0], 'objImport', true); $blnLoaded = $this->objImport->{$callback[1]}(\Input::post('username', true), \Input::postUnsafeRaw('password'), $this->strTable); // Load successfull if ($blnLoaded === true) { break; } } } // Return if the user still cannot be loaded if (!$blnLoaded || $this->findBy('username', \Input::post('username', true)) == false) { \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Could not find user "' . \Input::post('username', true) . '"', __METHOD__, TL_ACCESS); return false; } } $time = time(); // Set the user language if (\Input::post('language')) { $this->language = \Input::post('language'); } // Lock the account if there are too many login attempts if ($this->loginCount < 1) { $this->locked = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Add a log entry and the error message, because checkAccountStatus() will not be called (see #4444) $this->log('User "' . $this->username . '" has been locked for ' . ceil(\Config::get('lockPeriod') / 60) . ' minutes', __METHOD__, TL_ACCESS); \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['accountLocked'], ceil(($this->locked + \Config::get('lockPeriod') - $time) / 60))); // Send admin notification if (\Config::get('adminEmail') != '') { $objEmail = new \Email(); $objEmail->subject = $GLOBALS['TL_LANG']['MSC']['lockedAccount'][0]; $objEmail->text = sprintf($GLOBALS['TL_LANG']['MSC']['lockedAccount'][1], $this->username, TL_MODE == 'FE' ? $this->firstname . " " . $this->lastname : $this->name, \Idna::decode(\Environment::get('base')), ceil(\Config::get('lockPeriod') / 60)); $objEmail->sendTo(\Config::get('adminEmail')); } return false; } // Check the account status if ($this->checkAccountStatus() == false) { return false; } // The password has been generated with crypt() if (\Encryption::test($this->password)) { $blnAuthenticated = \Encryption::verify(\Input::postUnsafeRaw('password'), $this->password); } else { list($strPassword, $strSalt) = explode(':', $this->password); $blnAuthenticated = $strSalt == '' ? $strPassword === sha1(\Input::postUnsafeRaw('password')) : $strPassword === sha1($strSalt . \Input::postUnsafeRaw('password')); // Store a SHA-512 encrpyted version of the password if ($blnAuthenticated) { $this->password = \Encryption::hash(\Input::postUnsafeRaw('password')); } } // HOOK: pass credentials to callback functions if (!$blnAuthenticated && isset($GLOBALS['TL_HOOKS']['checkCredentials']) && is_array($GLOBALS['TL_HOOKS']['checkCredentials'])) { foreach ($GLOBALS['TL_HOOKS']['checkCredentials'] as $callback) { $this->import($callback[0], 'objAuth', true); $blnAuthenticated = $this->objAuth->{$callback[1]}(\Input::post('username', true), \Input::postUnsafeRaw('password'), $this); // Authentication successfull if ($blnAuthenticated === true) { break; } } } // Redirect if the user could not be authenticated if (!$blnAuthenticated) { --$this->loginCount; $this->save(); \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Invalid password submitted for username "' . $this->username . '"', __METHOD__, TL_ACCESS); return false; } $this->setUserFromDb(); // Update the record $this->lastLogin = $this->currentLogin; $this->currentLogin = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Generate the session $this->regenerateSessionId(); $this->generateSession(); $this->log('User "' . $this->username . '" has logged in', __METHOD__, TL_ACCESS); // HOOK: post login callback if (isset($GLOBALS['TL_HOOKS']['postLogin']) && is_array($GLOBALS['TL_HOOKS']['postLogin'])) { foreach ($GLOBALS['TL_HOOKS']['postLogin'] as $callback) { $this->import($callback[0], 'objLogin', true); $this->objLogin->{$callback[1]}($this); } } return true; }
/** * Generate the module */ protected function compile() { /** @var PageModel $objPage */ global $objPage; $GLOBALS['TL_LANGUAGE'] = $objPage->language; \System::loadLanguageFile('tl_member'); $this->loadDataContainer('tl_member'); // Set new password if (strlen(\Input::get('token'))) { $this->setNewPassword(); return; } // Username widget if (!$this->reg_skipName) { $arrFields['username'] = $GLOBALS['TL_DCA']['tl_member']['fields']['username']; $arrFields['username']['name'] = 'username'; } // E-mail widget $arrFields['email'] = $GLOBALS['TL_DCA']['tl_member']['fields']['email']; $arrFields['email']['name'] = 'email'; // Captcha widget if (!$this->disableCaptcha) { $arrFields['captcha'] = array('name' => 'lost_password', 'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'inputType' => 'captcha', 'eval' => array('mandatory' => true)); } $row = 0; $strFields = ''; $doNotSubmit = false; $strFormId = 'tl_lost_password_' . $this->id; // Initialize the widgets foreach ($arrFields as $arrField) { /** @var Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrField['inputType']]; // Continue if the class is not defined if (!class_exists($strClass)) { continue; } $arrField['eval']['required'] = $arrField['eval']['mandatory']; /** @var Widget $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($arrField, $arrField['name'])); $objWidget->storeValues = true; $objWidget->rowClass = 'row_' . $row . ($row == 0 ? ' row_first' : '') . ($row % 2 == 0 ? ' even' : ' odd'); ++$row; // Validate the widget if (\Input::post('FORM_SUBMIT') == $strFormId) { $objWidget->validate(); if ($objWidget->hasErrors()) { $doNotSubmit = true; } } $strFields .= $objWidget->parse(); } $this->Template->fields = $strFields; $this->Template->hasError = $doNotSubmit; // Look for an account and send the password link if (\Input::post('FORM_SUBMIT') == $strFormId && !$doNotSubmit) { if ($this->reg_skipName) { $objMember = \MemberModel::findActiveByEmailAndUsername(\Input::post('email', true), null); } else { $objMember = \MemberModel::findActiveByEmailAndUsername(\Input::post('email', true), \Input::post('username')); } if ($objMember === null) { sleep(2); // Wait 2 seconds while brute forcing :) $this->Template->error = $GLOBALS['TL_LANG']['MSC']['accountNotFound']; } else { $this->sendPasswordLink($objMember); } } $this->Template->formId = $strFormId; $this->Template->username = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['username']); $this->Template->email = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['emailAddress']); $this->Template->action = \Environment::get('indexFreeRequest'); $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['requestPassword']); $this->Template->rowLast = 'row_' . $row . ' row_last' . ($row % 2 == 0 ? ' even' : ' odd'); }
/** * Generate a regular page * * @param \PageModel $objPage * * @internal */ protected function prepare($objPage) { $GLOBALS['TL_KEYWORDS'] = ''; $GLOBALS['TL_LANGUAGE'] = $objPage->language; $locale = str_replace('-', '_', $objPage->language); \System::getContainer()->get('request_stack')->getCurrentRequest()->setLocale($locale); \System::getContainer()->get('translator')->setLocale($locale); \System::loadLanguageFile('default'); // Static URLs $this->setStaticUrls(); // Get the page layout $objLayout = $this->getPageLayout($objPage); // HOOK: modify the page or layout object (see #4736) if (isset($GLOBALS['TL_HOOKS']['getPageLayout']) && is_array($GLOBALS['TL_HOOKS']['getPageLayout'])) { foreach ($GLOBALS['TL_HOOKS']['getPageLayout'] as $callback) { $this->import($callback[0]); $this->{$callback}[0]->{$callback}[1]($objPage, $objLayout, $this); } } /** @var \ThemeModel $objTheme */ $objTheme = $objLayout->getRelated('pid'); // Set the layout template and template group $objPage->template = $objLayout->template ?: 'fe_page'; $objPage->templateGroup = $objTheme->templates; // Store the output format list($strFormat, $strVariant) = explode('_', $objLayout->doctype); $objPage->outputFormat = $strFormat; $objPage->outputVariant = $strVariant; // Initialize the template $this->createTemplate($objPage, $objLayout); // Initialize modules and sections $arrCustomSections = array(); $arrSections = array('header', 'left', 'right', 'main', 'footer'); $arrModules = deserialize($objLayout->modules); $arrModuleIds = array(); // Filter the disabled modules foreach ($arrModules as $module) { if ($module['enable']) { $arrModuleIds[] = $module['mod']; } } // Get all modules in a single DB query $objModules = \ModuleModel::findMultipleByIds($arrModuleIds); if ($objModules !== null || $arrModules[0]['mod'] == 0) { $arrMapper = array(); // Create a mapper array in case a module is included more than once (see #4849) if ($objModules !== null) { while ($objModules->next()) { $arrMapper[$objModules->id] = $objModules->current(); } } foreach ($arrModules as $arrModule) { // Disabled module if (!$arrModule['enable']) { continue; } // Replace the module ID with the module model if ($arrModule['mod'] > 0 && isset($arrMapper[$arrModule['mod']])) { $arrModule['mod'] = $arrMapper[$arrModule['mod']]; } // Generate the modules if (in_array($arrModule['col'], $arrSections)) { // Filter active sections (see #3273) if ($arrModule['col'] == 'header' && $objLayout->rows != '2rwh' && $objLayout->rows != '3rw') { continue; } if ($arrModule['col'] == 'left' && $objLayout->cols != '2cll' && $objLayout->cols != '3cl') { continue; } if ($arrModule['col'] == 'right' && $objLayout->cols != '2clr' && $objLayout->cols != '3cl') { continue; } if ($arrModule['col'] == 'footer' && $objLayout->rows != '2rwf' && $objLayout->rows != '3rw') { continue; } $this->Template->{$arrModule}['col'] .= $this->getFrontendModule($arrModule['mod'], $arrModule['col']); } else { $arrCustomSections[$arrModule['col']] .= $this->getFrontendModule($arrModule['mod'], $arrModule['col']); } } } $this->Template->sections = $arrCustomSections; // Mark RTL languages (see #7171) if ($GLOBALS['TL_LANG']['MSC']['textDirection'] == 'rtl') { $this->Template->isRTL = true; } // HOOK: modify the page or layout object if (isset($GLOBALS['TL_HOOKS']['generatePage']) && is_array($GLOBALS['TL_HOOKS']['generatePage'])) { foreach ($GLOBALS['TL_HOOKS']['generatePage'] as $callback) { $this->import($callback[0]); $this->{$callback}[0]->{$callback}[1]($objPage, $objLayout, $this); } } // Set the page title and description AFTER the modules have been generated $this->Template->mainTitle = $objPage->rootPageTitle; $this->Template->pageTitle = $objPage->pageTitle ?: $objPage->title; // Meta robots tag $this->Template->robots = $objPage->robots ?: 'index,follow'; // Remove shy-entities (see #2709) $this->Template->mainTitle = str_replace('[-]', '', $this->Template->mainTitle); $this->Template->pageTitle = str_replace('[-]', '', $this->Template->pageTitle); // Fall back to the default title tag if ($objLayout->titleTag == '') { $objLayout->titleTag = '{{page::pageTitle}} - {{page::rootPageTitle}}'; } // Assign the title and description $this->Template->title = strip_insert_tags($this->replaceInsertTags($objLayout->titleTag)); // see #7097 $this->Template->description = str_replace(array("\n", "\r", '"'), array(' ', '', ''), $objPage->description); // Body onload and body classes $this->Template->onload = trim($objLayout->onload); $this->Template->class = trim($objLayout->cssClass . ' ' . $objPage->cssClass); // Execute AFTER the modules have been generated and create footer scripts first $this->createFooterScripts($objLayout); $this->createHeaderScripts($objPage, $objLayout); }
/** * Show header of the parent table and list all records of the current table * * @return string */ protected function parentView() { /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); $blnClipboard = false; $arrClipboard = $objSession->get('CLIPBOARD'); $table = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $this->ptable : $this->strTable; $blnHasSorting = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'][0] == 'sorting'; $blnMultiboard = false; // Check clipboard if (!empty($arrClipboard[$table])) { $blnClipboard = true; $arrClipboard = $arrClipboard[$table]; if (is_array($arrClipboard['id'])) { $blnMultiboard = true; } } // Load the fonts to display the paste hint \Config::set('loadGoogleFonts', $blnClipboard); // Load the language file and data container array of the parent table \System::loadLanguageFile($this->ptable); $this->loadDataContainer($this->ptable); $return = ' <div id="tl_buttons">' . (\Input::get('nb') ? ' ' : ($this->ptable ? ' <a href="' . $this->getReferer(true, $this->ptable) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>' : (isset($GLOBALS['TL_DCA'][$this->strTable]['config']['backlink']) ? ' <a href="contao/main.php?' . $GLOBALS['TL_DCA'][$this->strTable]['config']['backlink'] . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>' : ''))) . ' ' . (\Input::get('act') != 'select' && !$blnClipboard && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl($blnHasSorting ? 'act=paste&mode=create' : 'act=create&mode=2&pid=' . $this->intId) . '" class="header_new" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]) . '" accesskey="n" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG'][$this->strTable]['new'][0] . '</a> ' : '') . ($blnClipboard ? ' <a href="' . $this->addToUrl('clipboard=1') . '" class="header_clipboard" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']) . '" accesskey="x">' . $GLOBALS['TL_LANG']['MSC']['clearClipboard'] . '</a> ' : $this->generateGlobalButtons()) . ' </div>' . \Message::generate(true); // Get all details of the parent record $objParent = $this->Database->prepare("SELECT * FROM " . $this->ptable . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objParent->numRows < 1) { return $return; } $return .= (\Input::get('act') == 'select' ? ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_select" class="tl_form' . (\Input::get('act') == 'select' ? ' unselectable' : '') . '" method="post" novalidate> <div class="tl_formbody"> <input type="hidden" name="FORM_SUBMIT" value="tl_select"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' : '') . ($blnClipboard ? ' <div id="paste_hint"> <p>' . $GLOBALS['TL_LANG']['MSC']['selectNewPosition'] . '</p> </div>' : '') . ' <div class="tl_listing_container parent_view"> <div class="tl_header click2edit toggle_select hover-div">'; // List all records of the child table if (!\Input::get('act') || \Input::get('act') == 'paste' || \Input::get('act') == 'select') { $this->import('BackendUser', 'User'); // Header $imagePasteNew = \Image::getHtml('new.gif', $GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]); $imagePasteAfter = \Image::getHtml('pasteafter.gif', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]); $imageEditHeader = \Image::getHtml('header.gif', $GLOBALS['TL_LANG'][$this->strTable]['editheader'][0]); $return .= ' <div class="tl_content_right">' . (\Input::get('act') == 'select' ? ' <label for="tl_select_trigger" class="tl_select_label">' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox">' : ($blnClipboard ? ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $objParent->id . (!$blnMultiboard ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a>' : (!$GLOBALS['TL_DCA'][$this->ptable]['config']['notEditable'] && $this->User->canEditFieldsOf($this->ptable) ? ' <a href="' . preg_replace('/&(amp;)?table=[^& ]*/i', $this->ptable != '' ? '&table=' . $this->ptable : '', $this->addToUrl('act=edit')) . '" class="edit" title="' . specialchars(isset($GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1]) ? $GLOBALS['TL_LANG'][$this->ptable]['editmeta'][1] : $GLOBALS['TL_LANG'][$this->strTable]['editheader'][1]) . '">' . $imageEditHeader . '</a>' : '') . ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl('act=create&mode=2&pid=' . $objParent->id . '&id=' . $this->intId) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]) . '">' . $imagePasteNew . '</a>' : ''))) . ' </div>'; // Format header fields $add = array(); $headerFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['headerFields']; foreach ($headerFields as $v) { $_v = deserialize($objParent->{$v}); // Translate UUIDs to paths if ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'fileTree') { $objFiles = \FilesModel::findMultipleByUuids((array) $_v); if ($objFiles !== null) { $_v = $objFiles->fetchEach('path'); } } if (is_array($_v)) { $_v = implode(', ', $_v); } elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['multiple']) { $_v = $_v != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'date') { $_v = $_v ? \Date::parse(\Config::get('dateFormat'), $_v) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'time') { $_v = $_v ? \Date::parse(\Config::get('timeFormat'), $_v) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['rgxp'] == 'datim') { $_v = $_v ? \Date::parse(\Config::get('datimFormat'), $_v) : '-'; } elseif ($v == 'tstamp') { if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) { $ptable = $GLOBALS['TL_DCA'][$this->strTable]['config']['ptable']; $cond = $ptable == 'tl_article' ? "(ptable=? OR ptable='')" : "ptable=?"; $objMaxTstamp = $this->Database->prepare("SELECT MAX(tstamp) AS tstamp FROM " . $this->strTable . " WHERE pid=? AND {$cond}")->execute($objParent->id, $ptable); } else { $objMaxTstamp = $this->Database->prepare("SELECT MAX(tstamp) AS tstamp FROM " . $this->strTable . " WHERE pid=?")->execute($objParent->id); } if (!$objMaxTstamp->tstamp) { $objMaxTstamp->tstamp = $objParent->tstamp; } $_v = \Date::parse(\Config::get('datimFormat'), max($objParent->tstamp, $objMaxTstamp->tstamp)); } elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey'])) { $arrForeignKey = explode('.', $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['foreignKey'], 2); $objLabel = $this->Database->prepare("SELECT " . $arrForeignKey[1] . " AS value FROM " . $arrForeignKey[0] . " WHERE id=?")->limit(1)->execute($_v); if ($objLabel->numRows) { $_v = $objLabel->value; } } elseif (is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v])) { $_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v][0]; } elseif (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v])) { $_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['reference'][$_v]; } elseif ($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options'])) { $_v = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options'][$_v]; } elseif (is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'][1]; $this->import($strClass); $options_callback = $this->{$strClass}->{$strMethod}($this); $_v = $options_callback[$_v]; } elseif (is_callable($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback'])) { $options_callback = $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['options_callback']($this); $_v = $options_callback[$_v]; } // Add the sorting field if ($_v != '') { if (isset($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'])) { $key = is_array($GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']) ? $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label'][0] : $GLOBALS['TL_DCA'][$this->ptable]['fields'][$v]['label']; } else { $key = isset($GLOBALS['TL_LANG'][$this->ptable][$v][0]) ? $GLOBALS['TL_LANG'][$this->ptable][$v][0] : $v; } $add[$key] = $_v; } } // Trigger the header_callback (see #3417) if (is_array($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'])) { $strClass = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'][1]; $this->import($strClass); $add = $this->{$strClass}->{$strMethod}($add, $this); } elseif (is_callable($GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback'])) { $add = $GLOBALS['TL_DCA'][$table]['list']['sorting']['header_callback']($add, $this); } // Output the header data $return .= ' <table class="tl_header_table">'; foreach ($add as $k => $v) { if (is_array($v)) { $v = $v[0]; } $return .= ' <tr> <td><span class="tl_label">' . $k . ':</span> </td> <td>' . $v . '</td> </tr>'; } $return .= ' </table> </div>'; $orderBy = array(); $firstOrderBy = array(); // Add all records of the current table $query = "SELECT * FROM " . $this->strTable; if (is_array($this->orderBy) && strlen($this->orderBy[0])) { $orderBy = $this->orderBy; $firstOrderBy = preg_replace('/\\s+.*$/', '', $orderBy[0]); // Order by the foreign key if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'])) { $key = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'], 2); $query = "SELECT *, (SELECT " . $key[1] . " FROM " . $key[0] . " WHERE " . $this->strTable . "." . $firstOrderBy . "=" . $key[0] . ".id) AS foreignKey FROM " . $this->strTable; $orderBy[0] = 'foreignKey'; } } elseif (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'])) { $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']; $firstOrderBy = preg_replace('/\\s+.*$/', '', $orderBy[0]); } $arrProcedure = $this->procedure; $arrValues = $this->values; // Support empty ptable fields if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) { $arrProcedure[] = $this->ptable == 'tl_article' ? "(ptable=? OR ptable='')" : "ptable=?"; $arrValues[] = $this->ptable; } // WHERE if (!empty($arrProcedure)) { $query .= " WHERE " . implode(' AND ', $arrProcedure); } if (!empty($this->root) && is_array($this->root)) { $query .= (!empty($arrProcedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('intval', $this->root)) . ")"; } // ORDER BY if (!empty($orderBy) && is_array($orderBy)) { $query .= " ORDER BY " . implode(', ', $orderBy); } $objOrderByStmt = $this->Database->prepare($query); // LIMIT if (strlen($this->limit)) { $arrLimit = explode(',', $this->limit); $objOrderByStmt->limit($arrLimit[1], $arrLimit[0]); } $objOrderBy = $objOrderByStmt->execute($arrValues); if ($objOrderBy->numRows < 1) { return $return . ' <p class="tl_empty_parent_view">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p> </div>'; } // Call the child_record_callback if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']) || is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'])) { $strGroup = ''; $blnIndent = false; $intWrapLevel = 0; $row = $objOrderBy->fetchAllAssoc(); // Make items sortable if ($blnHasSorting) { $return .= ' <ul id="ul_' . CURRENT_ID . '">'; } for ($i = 0, $c = count($row); $i < $c; $i++) { $this->current[] = $row[$i]['id']; $imagePasteAfter = \Image::getHtml('pasteafter.gif', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])); $imagePasteNew = \Image::getHtml('new.gif', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id'])); // Decrypt encrypted value foreach ($row[$i] as $k => $v) { if ($GLOBALS['TL_DCA'][$table]['fields'][$k]['eval']['encrypt']) { $row[$i][$k] = \Encryption::decrypt(deserialize($v)); } } // Make items sortable if ($blnHasSorting) { $return .= ' <li id="li_' . $row[$i]['id'] . '">'; } // Add the group header if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && $firstOrderBy != 'sorting') { $sortingMode = count($orderBy) == 1 && $firstOrderBy == $orderBy[0] && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] != '' && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'] == '' ? $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag']; $remoteNew = $this->formatCurrentValue($firstOrderBy, $row[$i][$firstOrderBy], $sortingMode); $group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row); if ($group != $strGroup) { $return .= "\n\n" . '<div class="tl_content_header">' . $group . '</div>'; $strGroup = $group; } } $blnWrapperStart = in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['start']); $blnWrapperSeparator = in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['separator']); $blnWrapperStop = in_array($row[$i]['type'], $GLOBALS['TL_WRAPPERS']['stop']); // Closing wrappers if ($blnWrapperStop) { if (--$intWrapLevel < 1) { $blnIndent = false; } } $return .= ' <div class="tl_content' . ($blnWrapperStart ? ' wrapper_start' : '') . ($blnWrapperSeparator ? ' wrapper_separator' : '') . ($blnWrapperStop ? ' wrapper_stop' : '') . ($blnIndent ? ' indent indent_' . $intWrapLevel : '') . ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] != '' ? ' ' . $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_class'] : '') . ($i % 2 == 0 ? ' even' : ' odd') . ' click2edit toggle_select hover-div"> <div class="tl_content_right">'; // Opening wrappers if ($blnWrapperStart) { if (++$intWrapLevel > 0) { $blnIndent = true; } } // Edit multiple if (\Input::get('act') == 'select') { $return .= '<input type="checkbox" name="IDS[]" id="ids_' . $row[$i]['id'] . '" class="tl_tree_checkbox" value="' . $row[$i]['id'] . '">'; } else { $return .= $this->generateButtons($row[$i], $this->strTable, $this->root, false, null, $row[$i - 1]['id'], $row[$i + 1]['id']); // Sortable table if ($blnHasSorting) { // Create new button if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable']) { $return .= ' <a href="' . $this->addToUrl('act=create&mode=1&pid=' . $row[$i]['id'] . '&id=' . $objParent->id) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][1], $row[$i]['id'])) . '">' . $imagePasteNew . '</a>'; } // Prevent circular references if ($blnClipboard && $arrClipboard['mode'] == 'cut' && $row[$i]['id'] == $arrClipboard['id'] || $blnMultiboard && $arrClipboard['mode'] == 'cutAll' && in_array($row[$i]['id'], $arrClipboard['id'])) { $return .= ' ' . \Image::getHtml('pasteafter_.gif'); } elseif ($blnMultiboard) { $return .= ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $row[$i]['id']) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a>'; } elseif ($blnClipboard) { $return .= ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $row[$i]['id'] . '&id=' . $arrClipboard['id']) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $row[$i]['id'])) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a>'; } // Drag handle if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable']) { $return .= ' ' . \Image::getHtml('drag.gif', '', 'class="drag-handle" title="' . sprintf($GLOBALS['TL_LANG'][$this->strTable]['cut'][1], $row[$i]['id']) . '"'); } } } if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'][1]; $this->import($strClass); $return .= '</div>' . $this->{$strClass}->{$strMethod}($row[$i]) . '</div>'; } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback'])) { $return .= '</div>' . $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['child_record_callback']($row[$i]) . '</div>'; } // Make items sortable if ($blnHasSorting) { $return .= ' </li>'; } } } } // Make items sortable if ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable'] && \Input::get('act') != 'select') { $return .= ' </ul> <script> Backend.makeParentViewSortable("ul_' . CURRENT_ID . '"); </script>'; } $return .= ' </div>'; // Close form if (\Input::get('act') == 'select') { // Submit buttons $arrButtons = array(); if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable']) { $arrButtons['delete'] = '<button type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $GLOBALS['TL_LANG']['MSC']['delAllConfirm'] . '\')">' . $GLOBALS['TL_LANG']['MSC']['deleteSelected'] . '</button>'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable']) { $arrButtons['cut'] = '<button type="submit" name="cut" id="cut" class="tl_submit" accesskey="x">' . $GLOBALS['TL_LANG']['MSC']['moveSelected'] . '</button>'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable']) { $arrButtons['copy'] = '<button type="submit" name="copy" id="copy" class="tl_submit" accesskey="c">' . $GLOBALS['TL_LANG']['MSC']['copySelected'] . '</button>'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable']) { $arrButtons['override'] = '<button type="submit" name="override" id="override" class="tl_submit" accesskey="v">' . $GLOBALS['TL_LANG']['MSC']['overrideSelected'] . '</button>'; $arrButtons['edit'] = '<button type="submit" name="edit" id="edit" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['editSelected'] . '</button>'; } // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $arrButtons = $this->{$callback[0]}->{$callback[1]}($arrButtons, $this); } elseif (is_callable($callback)) { $arrButtons = $callback($arrButtons, $this); } } } $return .= ' <div class="tl_formbody_submit" style="text-align:right"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </div> </form>'; } return $return; }
/** * Run the tests on a table * * @param string $table * @param Result $records * * @return array */ protected function runTests($table, Result $records) { System::loadLanguageFile('seo_serp_tests'); $result = ['errors' => 0, 'warnings' => 0]; /** @var TestInterface $test */ foreach (TestsManager::getAll() as $test) { // Skip the unsupported tests if (!$test->supports($table)) { continue; } while ($records->next()) { try { $test->run($records->row(), $table); } catch (ErrorException $e) { $result['errors']++; } catch (WarningException $e) { $result['warnings']++; } } $records->reset(); } return $result; }