/** * 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(); // Password change required if ($this->User->pwChange) { /** @var SessionInterface $session */ $session = \System::getContainer()->get('session'); $objSession = $this->Database->prepare("SELECT su FROM tl_session WHERE sessionID=? AND pid=?")->execute($session->getId(), $this->User->id); if (!$objSession->su) { $this->redirect('contao/password.php'); } } // Front end redirect if (\Input::get('do') == 'feRedirect') { $this->redirectToFrontendPage(\Input::get('page'), \Input::get('article')); } // Convenience functions if ($this->User->isAdmin) { // Maintenance mode off if (\Input::get('mmo')) { \Config::persist('maintenanceMode', false); $this->redirect($this->getReferer()); } // Build internal cache if (\Input::get('bic')) { $this->import('Automator'); $this->Automator->generateInternalCache(); $this->redirect($this->getReferer()); } } \System::loadLanguageFile('default'); \System::loadLanguageFile('modules'); }
/** * Set the property * * @param string $key * @param int $value * * @throws \InvalidArgumentException */ public static function set($key, $value) { if (!in_array($key, static::getAllowedKeys(), true)) { throw new \InvalidArgumentException(sprintf('The key "%s" is not allowed', $key)); } $data = static::getData(); $data[$key] = (int) $value; Config::set(static::$configKey, serialize($data)); Config::persist(static::$configKey, serialize($data)); }
/** * Check for new \Contao versions */ public function checkForUpdates() { if (!is_numeric(BUILD)) { return; } // HOOK: proxy module if (Config::get('useProxy')) { $objRequest = new \ProxyRequest(); } else { $objRequest = new \Request(); } $objRequest->send(\Config::get('liveUpdateBase') . (LONG_TERM_SUPPORT ? 'lts-version.txt' : 'version.txt')); if (!$objRequest->hasError()) { \Config::set('latestVersion', $objRequest->response); \Config::persist('latestVersion', $objRequest->response); } // Add a log entry $this->log('Checked for Contao updates', __METHOD__, TL_CRON); }
/** * Ajax actions that do require a data container object * * @param DataContainer $dc * * @throws NoContentResponseException * @throws ResponseException * @throws BadRequestHttpException */ public function executePostActions(DataContainer $dc) { header('Content-Type: text/html; charset=' . \Config::get('characterSet')); // Bypass any core logic for non-core drivers (see #5957) if (!$dc instanceof DC_File && !$dc instanceof DC_Folder && !$dc instanceof DC_Table) { $this->executePostActionsHook($dc); throw new NoContentResponseException(); } switch ($this->strAction) { // Load nodes of the page structure tree case 'loadStructure': throw new ResponseException($this->convertToResponse($dc->ajaxTreeView($this->strAjaxId, intval(\Input::post('level'))))); // Load nodes of the file manager tree // Load nodes of the file manager tree case 'loadFileManager': throw new ResponseException($this->convertToResponse($dc->ajaxTreeView(\Input::post('folder', true), intval(\Input::post('level'))))); // Load nodes of the page tree // Load nodes of the page tree case 'loadPagetree': $varValue = null; $strField = $dc->field = \Input::post('name'); // Call the load_callback if (is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'])) { foreach ($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, $dc); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $dc); } } } /** @var PageSelector $strClass */ $strClass = $GLOBALS['BE_FFL']['pageSelector']; /** @var PageSelector $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField], $dc->field, $varValue, $strField, $dc->table, $dc)); throw new ResponseException($this->convertToResponse($objWidget->generateAjax($this->strAjaxId, \Input::post('field'), intval(\Input::post('level'))))); // Load nodes of the file tree // Load nodes of the file tree case 'loadFiletree': $varValue = null; $strField = $dc->field = \Input::post('name'); // Call the load_callback if (is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'])) { foreach ($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, $dc); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $dc); } } } /** @var FileSelector $strClass */ $strClass = $GLOBALS['BE_FFL']['fileSelector']; /** @var FileSelector $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField], $dc->field, $varValue, $strField, $dc->table, $dc)); // Load a particular node if (\Input::post('folder', true) != '') { throw new ResponseException($this->convertToResponse($objWidget->generateAjax(\Input::post('folder', true), \Input::post('field'), intval(\Input::post('level'))))); } throw new ResponseException($this->convertToResponse($objWidget->generate())); // Reload the page/file picker // Reload the page/file picker case 'reloadPagetree': case 'reloadFiletree': $intId = \Input::get('id'); $strField = $dc->inputName = \Input::post('name'); // Handle the keys in "edit multiple" mode if (\Input::get('act') == 'editAll') { $intId = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', $strField); $strField = preg_replace('/(.*)_[0-9a-zA-Z]+$/', '$1', $strField); } $dc->field = $strField; // The field does not exist if (!isset($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField])) { $this->log('Field "' . $strField . '" does not exist in DCA "' . $dc->table . '"', __METHOD__, TL_ERROR); throw new BadRequestHttpException('Bad request'); } $objRow = null; $varValue = null; // Load the value if (\Input::get('act') != 'overrideAll') { if ($GLOBALS['TL_DCA'][$dc->table]['config']['dataContainer'] == 'File') { $varValue = \Config::get($strField); } elseif ($intId > 0 && $this->Database->tableExists($dc->table)) { $objRow = $this->Database->prepare("SELECT * FROM " . $dc->table . " WHERE id=?")->execute($intId); // The record does not exist if ($objRow->numRows < 1) { $this->log('A record with the ID "' . $intId . '" does not exist in table "' . $dc->table . '"', __METHOD__, TL_ERROR); throw new BadRequestHttpException('Bad request'); } $varValue = $objRow->{$strField}; $dc->activeRecord = $objRow; } } // Call the load_callback if (is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'])) { foreach ($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField]['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($varValue, $dc); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $dc); } } } // Set the new value $varValue = \Input::post('value', true); $strKey = $this->strAction == 'reloadPagetree' ? 'pageTree' : 'fileTree'; // Convert the selected values if ($varValue != '') { $varValue = \StringUtil::trimsplit("\t", $varValue); // Automatically add resources to the DBAFS if ($strKey == 'fileTree') { foreach ($varValue as $k => $v) { if (\Dbafs::shouldBeSynchronized($v)) { $objFile = \FilesModel::findByPath($v); if ($objFile === null) { $objFile = \Dbafs::addResource($v); } $varValue[$k] = $objFile->uuid; } } } $varValue = serialize($varValue); } /** @var FileTree|PageTree $strClass */ $strClass = $GLOBALS['BE_FFL'][$strKey]; /** @var FileTree|PageTree $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($GLOBALS['TL_DCA'][$dc->table]['fields'][$strField], $dc->inputName, $varValue, $strField, $dc->table, $dc)); throw new ResponseException($this->convertToResponse($objWidget->generate())); // Feature/unfeature an element // Feature/unfeature an element case 'toggleFeatured': if (class_exists($dc->table, false)) { $dca = new $dc->table(); if (method_exists($dca, 'toggleFeatured')) { $dca->toggleFeatured(\Input::post('id'), \Input::post('state') == 1 ? true : false); } } throw new NoContentResponseException(); // Toggle subpalettes // Toggle subpalettes case 'toggleSubpalette': $this->import('BackendUser', 'User'); // Check whether the field is a selector field and allowed for regular users (thanks to Fabian Mihailowitsch) (see #4427) if (!is_array($GLOBALS['TL_DCA'][$dc->table]['palettes']['__selector__']) || !in_array(\Input::post('field'), $GLOBALS['TL_DCA'][$dc->table]['palettes']['__selector__']) || $GLOBALS['TL_DCA'][$dc->table]['fields'][\Input::post('field')]['exclude'] && !$this->User->hasAccess($dc->table . '::' . \Input::post('field'), 'alexf')) { $this->log('Field "' . \Input::post('field') . '" is not an allowed selector field (possible SQL injection attempt)', __METHOD__, TL_ERROR); throw new BadRequestHttpException('Bad request'); } if ($dc instanceof DC_Table) { if (\Input::get('act') == 'editAll') { $this->strAjaxId = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', \Input::post('id')); $this->Database->prepare("UPDATE " . $dc->table . " SET " . \Input::post('field') . "='" . (intval(\Input::post('state') == 1) ? 1 : '') . "' WHERE id=?")->execute($this->strAjaxId); if (\Input::post('load')) { echo $dc->editAll($this->strAjaxId, \Input::post('id')); } } else { $this->Database->prepare("UPDATE " . $dc->table . " SET " . \Input::post('field') . "='" . (intval(\Input::post('state') == 1) ? 1 : '') . "' WHERE id=?")->execute($dc->id); if (\Input::post('load')) { throw new ResponseException($this->convertToResponse($dc->edit(false, \Input::post('id')))); } } } elseif ($dc instanceof DC_File) { $val = intval(\Input::post('state') == 1) ? true : false; \Config::persist(\Input::post('field'), $val); if (\Input::post('load')) { \Config::set(\Input::post('field'), $val); throw new ResponseException($this->convertToResponse($dc->edit(false, \Input::post('id')))); } } throw new NoContentResponseException(); // DropZone file upload // DropZone file upload case 'fileupload': $dc->move(); throw new NoContentResponseException(); // HOOK: pass unknown actions to callback functions // HOOK: pass unknown actions to callback functions default: $this->executePostActionsHook($dc); throw new NoContentResponseException(); } }
/** * Save the current value * * @param mixed $varValue */ protected function save($varValue) { if (\Input::post('FORM_SUBMIT') != $this->strTable) { return; } $arrData = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]; // Make sure that checkbox values are boolean if ($arrData['inputType'] == 'checkbox' && !$arrData['eval']['multiple']) { $varValue = $varValue ? true : false; } if ($varValue != '') { // Convert binary UUIDs (see #6893) if ($arrData['inputType'] == 'fileTree') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::binToUuid($varValue); } else { $varValue = serialize(array_map('StringUtil::binToUuid', $varValue)); } } // Convert date formats into timestamps if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp'])); $varValue = $objDate->tstamp; } // Handle entities if ($arrData['inputType'] == 'text' || $arrData['inputType'] == 'textarea') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::restoreBasicEntities($varValue); } else { $varValue = serialize(array_map('StringUtil::restoreBasicEntities', $varValue)); } } } // Trigger the save_callback if (is_array($arrData['save_callback'])) { foreach ($arrData['save_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback}[0]->{$callback}[1]($varValue, $this); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $this); } } } $strCurrent = $this->varValue; // Handle arrays and strings if (is_array($strCurrent)) { $strCurrent = serialize($strCurrent); } elseif (is_string($strCurrent)) { $strCurrent = html_entity_decode($this->varValue, ENT_QUOTES, \Config::get('characterSet')); } // Save the value if there was no error if ((strlen($varValue) || !$arrData['eval']['doNotSaveEmpty']) && $strCurrent != $varValue) { \Config::persist($this->strField, $varValue); $deserialize = deserialize($varValue); $prior = is_bool(\Config::get($this->strField)) ? \Config::get($this->strField) ? 'true' : 'false' : \Config::get($this->strField); // Add a log entry if (!is_array(deserialize($prior)) && !is_array($deserialize)) { if ($arrData['inputType'] == 'password' || $arrData['inputType'] == 'textStore') { $this->log('The global configuration variable "' . $this->strField . '" has been changed', __METHOD__, TL_CONFIGURATION); } else { $this->log('The global configuration variable "' . $this->strField . '" has been changed from "' . $prior . '" to "' . $varValue . '"', __METHOD__, TL_CONFIGURATION); } } // Set the new value so the input field can show it $this->varValue = $deserialize; \Config::set($this->strField, $deserialize); } }
/** * Rebuild the cache */ public function rebuildCache() { Config::persist($this->cacheKey, $this->getStatus()); }
/** * Permanently sets a configuration value. * * @param string $key The short key or full variable name * @param mixed $value The configuration value */ public function persist($key, $value) { Config::persist($key, $value); }
/** * Version 3.0.0 update */ protected function update300() { // Step 1: database structure if (!$this->Database->tableExists('tl_files')) { $this->enableMaintenanceMode(); if (\Input::post('FORM_SUBMIT') == 'tl_30update') { $this->import('Database\\Updater', 'Updater'); $this->Updater->run300Update(); $this->reload(); } // Disable the tasks extension (see #4907) if (is_dir(TL_ROOT . '/system/modules/tasks')) { \System::disableModule('tasks'); } // Reset the upload path if it has been changed already (see #5560 and #5870) if (\Config::get('uploadPath') == 'files' && is_dir(TL_ROOT . '/tl_files')) { \Config::set('uploadPath', 'tl_files'); \Config::persist('uploadPath', 'tl_files'); } // Show a warning if the upload folder does not exist (see #4626) if (!is_dir(TL_ROOT . '/' . \Config::get('uploadPath'))) { $this->Template->filesWarning = sprintf($GLOBALS['TL_LANG']['tl_install']['filesWarning'], '<a href="https://gist.github.com/3304014" target="_blank">https://gist.github.com/3304014</a>'); } $this->Template->step = 1; $this->Template->is30Update = true; $this->outputAndExit(); } $objRow = $this->Database->query("SELECT COUNT(*) AS count FROM tl_files"); // Step 2: scan the upload folder if it is not empty (see #6061) if ($objRow->count < 1 && count(scan(TL_ROOT . '/' . \Config::get('uploadPath'))) > 0) { $this->enableMaintenanceMode(); if (\Input::post('FORM_SUBMIT') == 'tl_30update') { $this->import('Database\\Updater', 'Updater'); $this->Updater->scanUploadFolder(); \Config::persist('checkFileTree', true); $this->reload(); } $this->Template->step = 2; $this->Template->is30Update = true; $this->outputAndExit(); } elseif (\Config::get('checkFileTree')) { $this->enableMaintenanceMode(); if (\Input::post('FORM_SUBMIT') == 'tl_30update') { $this->import('Database\\Updater', 'Updater'); $this->Updater->updateFileTreeFields(); \Config::persist('checkFileTree', false); $this->reload(); } $this->Template->step = 3; $this->Template->is30Update = true; $this->outputAndExit(); } }