Set a cookie
public static setCookie ( string $strName, mixed $varValue, integer $intExpires, string $strPath = null, string $strDomain = null, boolean $blnSecure = false, boolean $blnHttpOnly = false ) | ||
$strName | string | The cookie name |
$varValue | mixed | The cookie value |
$intExpires | integer | The expiration date |
$strPath | string | An optional path |
$strDomain | string | An optional domain name |
$blnSecure | boolean | If true, the secure flag will be set |
$blnHttpOnly | boolean | If true, the http-only flag will be set |
/** * Auto-generate a form to override all records that are currently shown * * @return string * * @throws InternalServerErrorException */ public function overrideAll() { if ($GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable']) { throw new InternalServerErrorException('Table "' . $this->strTable . '" is not editable.'); } $return = ''; $this->import('BackendUser', 'User'); /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); // Get current IDs from session $session = $objSession->all(); $ids = $session['CURRENT']['IDS']; // Save field selection in session if (\Input::post('FORM_SUBMIT') == $this->strTable . '_all' && \Input::get('fields')) { $session['CURRENT'][$this->strTable] = \Input::post('all_fields'); $objSession->replace($session); } // Add fields $fields = $session['CURRENT'][$this->strTable]; if (!empty($fields) && is_array($fields) && \Input::get('fields')) { $class = 'tl_tbox'; $formFields = array(); // Save record if (\Input::post('FORM_SUBMIT') == $this->strTable) { foreach ($ids as $id) { $this->intId = $id; $this->procedure = array('id=?'); $this->values = array($this->intId); $this->blnCreateNewVersion = false; // Get the field values $objRow = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute($this->intId); // Store the active record $this->objActiveRecord = $objRow; $objVersions = new \Versions($this->strTable, $this->intId); $objVersions->initialize(); // Store all fields foreach ($fields as $v) { // Check whether field is excluded if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['exclude']) { continue; } $this->strField = $v; $this->strInputName = $v; $this->varValue = ''; // Make sure the new value is applied $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['alwaysSave'] = true; // Store value $this->row(); } // Post processing if (!$this->noReload) { // Call the onsubmit_callback if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($this); } elseif (is_callable($callback)) { $callback($this); } } } // Create a new version if ($this->blnCreateNewVersion) { $objVersions->create(); // Call the onversion_callback if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onversion_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($this->strTable, $this->intId, $this); } elseif (is_callable($callback)) { $callback($this->strTable, $this->intId, $this); } } } $this->log('A new version of record "' . $this->strTable . '.id=' . $this->intId . '" has been created' . $this->getParentEntries($this->strTable, $this->intId), __METHOD__, TL_GENERAL); } // Set the current timestamp (-> DO NOT CHANGE ORDER version - timestamp) if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) { $this->Database->prepare("UPDATE " . $this->strTable . " SET ptable=?, tstamp=? WHERE id=?")->execute($this->ptable, time(), $this->intId); } else { $this->Database->prepare("UPDATE " . $this->strTable . " SET tstamp=? WHERE id=?")->execute(time(), $this->intId); } } } } $blnIsFirst = true; // Begin current row $return .= ' <div class="' . $class . '">'; foreach ($fields as $v) { // Check whether field is excluded if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['exclude']) { continue; } $formFields[] = $v; $this->intId = 0; $this->procedure = array('id=?'); $this->values = array($this->intId); $this->strField = $v; $this->strInputName = $v; $this->varValue = ''; // Autofocus the first field if ($blnIsFirst && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['inputType'] == 'text') { $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['autofocus'] = 'autofocus'; $blnIsFirst = false; } // Disable auto-submit $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['submitOnChange'] = false; $return .= $this->row(); } // Close box $return .= ' <input type="hidden" name="FORM_FIELDS[]" value="' . specialchars(implode(',', $formFields)) . '"> </div>'; // Submit buttons $arrButtons = array(); $arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['save'] . '</button>'; $arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">' . $GLOBALS['TL_LANG']['MSC']['saveNclose'] . '</button>'; // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['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); } } } // Add the form $return = ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="' . $this->strTable . '" class="tl_form" method="post" enctype="' . ($this->blnUploadable ? 'multipart/form-data' : 'application/x-www-form-urlencoded') . '"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="' . $this->strTable . '"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' . ($this->noReload ? ' <p class="tl_error">' . $GLOBALS['TL_LANG']['ERR']['general'] . '</p>' : '') . $return . ' </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </form>'; // Set the focus if there is an error if ($this->noReload) { $return .= ' <script> window.addEvent(\'domready\', function() { Backend.vScrollTo(($(\'' . $this->strTable . '\').getElement(\'label.error\').getPosition().y - 20)); }); </script>'; } // Reload the page to prevent _POST variables from being sent twice if (\Input::post('FORM_SUBMIT') == $this->strTable && !$this->noReload) { if (isset($_POST['saveNclose'])) { \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->redirect($this->getReferer()); } $this->reload(); } } else { $options = ''; $fields = array(); // Add fields of the current table $fields = array_merge($fields, array_keys($GLOBALS['TL_DCA'][$this->strTable]['fields'])); // Add meta fields if the current user is an administrator if ($this->User->isAdmin) { if ($this->Database->fieldExists('sorting', $this->strTable) && !in_array('sorting', $fields)) { array_unshift($fields, 'sorting'); } if ($this->Database->fieldExists('pid', $this->strTable) && !in_array('pid', $fields)) { array_unshift($fields, 'pid'); } } // Show all non-excluded fields foreach ($fields as $field) { if ($field == 'pid' || $field == 'sorting' || !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['exclude'] && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['eval']['doNotShow'] && (strlen($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['inputType']) || is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['input_field_callback']))) { $options .= ' <input type="checkbox" name="all_fields[]" id="all_' . $field . '" class="tl_checkbox" value="' . specialchars($field) . '"> <label for="all_' . $field . '" class="tl_checkbox_label">' . (($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0] ?: $GLOBALS['TL_LANG']['MSC'][$field][0]) . ' <span style="color:#b3b3b3;padding-left:3px">[' . $field . ']</span>') . '</label><br>'; } } $blnIsError = $_POST && empty($_POST['all_fields']); // Return the select menu $return .= ' <form action="' . ampersand(\Environment::get('request'), true) . '&fields=1" id="' . $this->strTable . '_all" class="tl_form" method="post"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="' . $this->strTable . '_all"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' . ($blnIsError ? ' <p class="tl_error">' . $GLOBALS['TL_LANG']['ERR']['general'] . '</p>' : '') . ' <div class="tl_tbox"> <fieldset class="tl_checkbox_container"> <legend' . ($blnIsError ? ' class="error"' : '') . '>' . $GLOBALS['TL_LANG']['MSC']['all_fields'][0] . '</legend> <input type="checkbox" id="check_all" class="tl_checkbox" onclick="Backend.toggleCheckboxes(this)"> <label for="check_all" style="color:#a6a6a6"><em>' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</em></label><br>' . $options . ' </fieldset>' . ($blnIsError ? ' <p class="tl_error">' . $GLOBALS['TL_LANG']['ERR']['all_fields'] . '</p>' : (\Config::get('showHelp') && strlen($GLOBALS['TL_LANG']['MSC']['all_fields'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['MSC']['all_fields'][1] . '</p>' : '')) . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> <button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['continue'] . '</button> </div> </div> </form>'; } // Return return ' <div id="tl_buttons"> <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div>' . $return; }
/** * Logout from phpbb */ public function logout() { if ($this->debug) { System::log("phpbb_bridge: " . __METHOD__, __METHOD__, TL_ACCESS); } $cookie_prefix = $this->getDbConfig('cookie_name'); $sid = Input::cookie($cookie_prefix . '_sid'); System::getContainer()->get('session')->remove('phpbb_user'); if ($sid) { $logoutUrl = Environment::get('url') . '/' . $this->getForumPath() . '/contao_connect/logout'; $headers = $this->initForumRequestHeaders(); $browser = $this->initForumRequest(); $browser->get($logoutUrl, $headers); // Parse cookies and send them to the client foreach ($browser->getListener()->getCookies() as $cookie) { /* @var $cookie Cookie */ // Stream cookies through to the client System::setCookie($cookie->getName(), $cookie->getValue(), strtotime($cookie->getAttribute('expires')), $cookie->getAttribute('path'), $cookie->getAttribute('domain')); } } }
/** * Return a form to choose a CSV file and import it * * @return string */ public function importRecipients() { if (\Input::get('key') != 'import') { return ''; } $this->import('BackendUser', 'User'); $class = $this->User->uploader; // See #4086 and #7046 if (!class_exists($class) || $class == 'DropZone') { $class = 'FileUpload'; } /** @var FileUpload $objUploader */ $objUploader = new $class(); // Import recipients if (\Input::post('FORM_SUBMIT') == 'tl_recipients_import') { $arrUploaded = $objUploader->uploadTo('system/tmp'); if (empty($arrUploaded)) { \Message::addError($GLOBALS['TL_LANG']['ERR']['all_fields']); $this->reload(); } $time = time(); $intTotal = 0; $intInvalid = 0; foreach ($arrUploaded as $strCsvFile) { $objFile = new \File($strCsvFile); if ($objFile->extension != 'csv') { \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['filetype'], $objFile->extension)); continue; } // Get separator switch (\Input::post('separator')) { case 'semicolon': $strSeparator = ';'; break; case 'tabulator': $strSeparator = "\t"; break; case 'linebreak': $strSeparator = "\n"; break; default: $strSeparator = ','; break; } $arrRecipients = array(); $resFile = $objFile->handle; while (($arrRow = @fgetcsv($resFile, null, $strSeparator)) !== false) { $arrRecipients = array_merge($arrRecipients, $arrRow); } $arrRecipients = array_filter(array_unique($arrRecipients)); foreach ($arrRecipients as $strRecipient) { // Skip invalid entries if (!\Validator::isEmail($strRecipient)) { $this->log('Recipient address "' . $strRecipient . '" seems to be invalid and was not imported', __METHOD__, TL_ERROR); ++$intInvalid; continue; } // Check whether the e-mail address exists $objRecipient = $this->Database->prepare("SELECT COUNT(*) AS count FROM tl_newsletter_recipients WHERE pid=? AND email=?")->execute(\Input::get('id'), $strRecipient); if ($objRecipient->count > 0) { continue; } // Check whether the e-mail address has been blacklisted $objBlacklist = $this->Database->prepare("SELECT COUNT(*) AS count FROM tl_newsletter_blacklist WHERE pid=? AND hash=?")->execute(\Input::get('id'), md5($strRecipient)); if ($objBlacklist->count > 0) { $this->log('Recipient address "' . $strRecipient . '" has been unsubscribed and was not imported', __METHOD__, TL_ERROR); continue; } $this->Database->prepare("INSERT INTO tl_newsletter_recipients SET pid=?, tstamp={$time}, email=?, active=1")->execute(\Input::get('id'), $strRecipient); ++$intTotal; } } \Message::addConfirmation(sprintf($GLOBALS['TL_LANG']['tl_newsletter_recipients']['confirm'], $intTotal)); if ($intInvalid > 0) { \Message::addInfo(sprintf($GLOBALS['TL_LANG']['tl_newsletter_recipients']['invalid'], $intInvalid)); } \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->reload(); } // Return form return ' <div id="tl_buttons"> <a href="' . ampersand(str_replace('&key=import', '', \Environment::get('request'))) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_recipients_import" class="tl_form" method="post" enctype="multipart/form-data"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="tl_recipients_import"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <input type="hidden" name="MAX_FILE_SIZE" value="' . \Config::get('maxFileSize') . '"> <div class="tl_tbox"> <h3><label for="separator">' . $GLOBALS['TL_LANG']['MSC']['separator'][0] . '</label></h3> <select name="separator" id="separator" class="tl_select" onfocus="Backend.getScrollOffset()"> <option value="comma">' . $GLOBALS['TL_LANG']['MSC']['comma'] . '</option> <option value="semicolon">' . $GLOBALS['TL_LANG']['MSC']['semicolon'] . '</option> <option value="tabulator">' . $GLOBALS['TL_LANG']['MSC']['tabulator'] . '</option> <option value="linebreak">' . $GLOBALS['TL_LANG']['MSC']['linebreak'] . '</option> </select>' . ($GLOBALS['TL_LANG']['MSC']['separator'][1] != '' ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['MSC']['separator'][1] . '</p>' : '') . ' <h3>' . $GLOBALS['TL_LANG']['MSC']['source'][0] . '</h3>' . $objUploader->generateMarkup() . (isset($GLOBALS['TL_LANG']['MSC']['source'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['MSC']['source'][1] . '</p>' : '') . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> <button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['tl_newsletter_recipients']['import'][0] . '</button> </div> </div> </form>'; }
/** * Load the source editor * * @return string * * @throws InternalServerErrorException */ public function source() { $this->isValid($this->intId); if (is_dir(TL_ROOT . '/' . $this->intId)) { throw new InternalServerErrorException('Folder "' . $this->intId . '" cannot be edited.'); } elseif (!file_exists(TL_ROOT . '/' . $this->intId)) { throw new InternalServerErrorException('File "' . $this->intId . '" does not exist.'); } $this->import('BackendUser', 'User'); // Check user permission if (!$this->User->hasAccess('f5', 'fop')) { throw new AccessDeniedException('Not enough permissions to edit the file source of file "' . $this->intId . '".'); } $objFile = new \File($this->intId); // Check whether file type is editable if (!in_array($objFile->extension, trimsplit(',', \Config::get('editableFiles')))) { throw new AccessDeniedException('File type "' . $objFile->extension . '" (' . $this->intId . ') is not allowed to be edited.'); } $objMeta = null; $objVersions = null; // Add the versioning routines if ($this->blnIsDbAssisted && \Dbafs::shouldBeSynchronized($this->intId)) { $objMeta = \FilesModel::findByPath($objFile->value); if ($objMeta === null) { $objMeta = \Dbafs::addResource($objFile->value); } $objVersions = new \Versions($this->strTable, $objMeta->id); if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu']) { // Compare versions if (\Input::get('versions')) { $objVersions->compare(); } // Restore a version if (\Input::post('FORM_SUBMIT') == 'tl_version' && \Input::post('version') != '') { $objVersions->restore(\Input::post('version')); // Purge the script cache (see #7005) if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') { $this->import('Automator'); $this->Automator->purgeScriptCache(); } $this->reload(); } } $objVersions->initialize(); } $strContent = $objFile->getContent(); if ($objFile->extension == 'svgz') { $strContent = gzdecode($strContent); } // Process the request if (\Input::post('FORM_SUBMIT') == 'tl_files') { // Restore the basic entities (see #7170) $strSource = \StringUtil::restoreBasicEntities(\Input::postRaw('source')); // Save the file if (md5($strContent) != md5($strSource)) { if ($objFile->extension == 'svgz') { $strSource = gzencode($strSource); } // Write the file $objFile->write($strSource); $objFile->close(); // Update the database if ($this->blnIsDbAssisted && $objMeta !== null) { /** @var FilesModel $objMeta */ $objMeta->hash = $objFile->hash; $objMeta->save(); $objVersions->create(); } // Purge the script cache (see #7005) if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') { $this->import('Automator'); $this->Automator->purgeScriptCache(); } } if (isset($_POST['saveNclose'])) { \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->redirect($this->getReferer()); } $this->reload(); } $codeEditor = ''; // Prepare the code editor if (\Config::get('useCE')) { /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_ace'); $objTemplate->selector = 'ctrl_source'; $objTemplate->type = $objFile->extension; $codeEditor = $objTemplate->parse(); } // Versions overview if ($GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'] && $this->blnIsDbAssisted && $objVersions !== null) { $version = $objVersions->renderDropdown(); } else { $version = ''; } // Submit buttons $arrButtons = array(); $arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['save'] . '</button>'; $arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">' . $GLOBALS['TL_LANG']['MSC']['saveNclose'] . '</button>'; // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['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); } } } // Add the form return $version . ' <div id="tl_buttons"> <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_files" class="tl_form" method="post"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="tl_files"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <div class="tl_tbox"> <h3><label for="ctrl_source">' . $GLOBALS['TL_LANG']['tl_files']['editor'][0] . '</label></h3> <textarea name="source" id="ctrl_source" class="tl_textarea monospace" rows="12" cols="80" style="height:400px" onfocus="Backend.getScrollOffset()">' . "\n" . htmlspecialchars($strContent) . '</textarea>' . (\Config::get('showHelp') && strlen($GLOBALS['TL_LANG']['tl_files']['editor'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['tl_files']['editor'][1] . '</p>' : '') . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </form>' . "\n\n" . $codeEditor; }
/** * Extract the theme files and write the data to the database * * @param array $arrFiles * @param array $arrDbFields */ protected function extractThemeFiles($arrFiles, $arrDbFields) { foreach ($arrFiles as $strZipFile) { $xml = null; // Open the archive $objArchive = new \ZipReader($strZipFile); // Extract all files while ($objArchive->next()) { // Load the XML file if ($objArchive->file_name == 'theme.xml') { $xml = new \DOMDocument(); $xml->preserveWhiteSpace = false; $xml->loadXML($objArchive->unzip()); continue; } // Limit file operations to files and the templates directory if (strncmp($objArchive->file_name, 'files/', 6) !== 0 && strncmp($objArchive->file_name, 'tl_files/', 9) !== 0 && strncmp($objArchive->file_name, 'templates/', 10) !== 0) { \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidFile'], $objArchive->file_name)); continue; } // Extract the files try { \File::putContent($this->customizeUploadPath($objArchive->file_name), $objArchive->unzip()); } catch (\Exception $e) { \Message::addError($e->getMessage()); } } // Continue if there is no XML file if (!$xml instanceof \DOMDocument) { \Message::addError(sprintf($GLOBALS['TL_LANG']['tl_theme']['missing_xml'], basename($strZipFile))); continue; } $arrMapper = array(); $tables = $xml->getElementsByTagName('table'); $arrNewFolders = array(); // Extract the folder names from the XML file for ($i = 0; $i < $tables->length; $i++) { if ($tables->item($i)->getAttribute('name') == 'tl_theme') { $fields = $tables->item($i)->childNodes->item(0)->childNodes; for ($k = 0; $k < $fields->length; $k++) { if ($fields->item($k)->getAttribute('name') == 'folders') { $arrNewFolders = \StringUtil::deserialize($fields->item($k)->nodeValue); break; } } break; } } // Sync the new folder(s) if (!empty($arrNewFolders) && is_array($arrNewFolders)) { foreach ($arrNewFolders as $strFolder) { $strCustomized = $this->customizeUploadPath($strFolder); if (\Dbafs::shouldBeSynchronized($strCustomized)) { \Dbafs::addResource($strCustomized); } } } // Lock the tables $arrLocks = array('tl_files' => 'WRITE', 'tl_theme' => 'WRITE', 'tl_style_sheet' => 'WRITE', 'tl_style' => 'WRITE', 'tl_module' => 'WRITE', 'tl_layout' => 'WRITE', 'tl_image_size' => 'WRITE', 'tl_image_size_item' => 'WRITE'); // Load the DCAs of the locked tables (see #7345) foreach (array_keys($arrLocks) as $table) { $this->loadDataContainer($table); } $this->Database->lockTables($arrLocks); // Get the current auto_increment values $tl_files = $this->Database->getNextId('tl_files'); $tl_theme = $this->Database->getNextId('tl_theme'); $tl_style_sheet = $this->Database->getNextId('tl_style_sheet'); $tl_style = $this->Database->getNextId('tl_style'); $tl_module = $this->Database->getNextId('tl_module'); $tl_layout = $this->Database->getNextId('tl_layout'); $tl_image_size = $this->Database->getNextId('tl_image_size'); $tl_image_size_item = $this->Database->getNextId('tl_image_size_item'); // Build the mapper data (see #8326) for ($i = 0; $i < $tables->length; $i++) { $rows = $tables->item($i)->childNodes; $table = $tables->item($i)->getAttribute('name'); // Skip invalid tables if (!in_array($table, array_keys($arrLocks))) { continue; } // Loop through the rows for ($j = 0; $j < $rows->length; $j++) { $fields = $rows->item($j)->childNodes; // Loop through the fields for ($k = 0; $k < $fields->length; $k++) { // Increment the ID if ($fields->item($k)->getAttribute('name') == 'id') { $arrMapper[$table][$fields->item($k)->nodeValue] = ${$table}++; break; } } } } // Loop through the tables for ($i = 0; $i < $tables->length; $i++) { $rows = $tables->item($i)->childNodes; $table = $tables->item($i)->getAttribute('name'); // Skip invalid tables if (!in_array($table, array_keys($arrLocks))) { continue; } // Get the order fields $objDcaExtractor = \DcaExtractor::getInstance($table); $arrOrder = $objDcaExtractor->getOrderFields(); // Loop through the rows for ($j = 0; $j < $rows->length; $j++) { $set = array(); $fields = $rows->item($j)->childNodes; // Loop through the fields for ($k = 0; $k < $fields->length; $k++) { $value = $fields->item($k)->nodeValue; $name = $fields->item($k)->getAttribute('name'); // Skip NULL values if ($value == 'NULL') { continue; } elseif ($name == 'id') { $value = $arrMapper[$table][$value]; } elseif ($name == 'pid') { if ($table == 'tl_style') { $value = $arrMapper['tl_style_sheet'][$value]; } elseif ($table == 'tl_image_size_item') { $value = $arrMapper['tl_image_size'][$value]; } else { $value = $arrMapper['tl_theme'][$value]; } } elseif ($name == 'fallback') { $value = ''; } elseif ($table == 'tl_layout' && $name == 'stylesheet') { $stylesheets = \StringUtil::deserialize($value); if (is_array($stylesheets)) { foreach (array_keys($stylesheets) as $key) { $stylesheets[$key] = $arrMapper['tl_style_sheet'][$stylesheets[$key]]; } $value = serialize($stylesheets); } } elseif ($table == 'tl_layout' && $name == 'modules') { $modules = \StringUtil::deserialize($value); if (is_array($modules)) { foreach ($modules as $key => $mod) { if ($mod['mod'] > 0) { $modules[$key]['mod'] = $arrMapper['tl_module'][$mod['mod']]; } } $value = serialize($modules); } } elseif (($table == 'tl_theme' || $table == 'tl_style_sheet') && $name == 'name') { $objCount = $this->Database->prepare("SELECT COUNT(*) AS count FROM " . $table . " WHERE name=?")->execute($value); if ($objCount->count > 0) { $value = preg_replace('/( |\\-)[0-9]+$/', '', $value); $value .= ($table == 'tl_style_sheet' ? '-' : ' ') . ${$table}; } } elseif (($table == 'tl_style_sheet' || $table == 'tl_style' || $table == 'tl_files' && $name == 'path') && strpos($value, 'files') !== false) { $tmp = \StringUtil::deserialize($value); if (is_array($tmp)) { foreach ($tmp as $kk => $vv) { $tmp[$kk] = $this->customizeUploadPath($vv); } $value = serialize($tmp); } else { $value = $this->customizeUploadPath($value); } } elseif ($GLOBALS['TL_DCA'][$table]['fields'][$name]['inputType'] == 'fileTree' && !$GLOBALS['TL_DCA'][$table]['fields'][$name]['eval']['multiple']) { if (!$value) { $value = null; // Contao >= 3.2 } else { // Do not use the FilesModel here – tables are locked! $objFile = $this->Database->prepare("SELECT uuid FROM tl_files WHERE path=?")->limit(1)->execute($this->customizeUploadPath($value)); $value = $objFile->uuid; } } elseif ($GLOBALS['TL_DCA'][$table]['fields'][$name]['inputType'] == 'fileTree' || in_array($name, $arrOrder)) { $tmp = \StringUtil::deserialize($value); if (is_array($tmp)) { foreach ($tmp as $kk => $vv) { // Do not use the FilesModel here – tables are locked! $objFile = $this->Database->prepare("SELECT uuid FROM tl_files WHERE path=?")->limit(1)->execute($this->customizeUploadPath($vv)); $tmp[$kk] = $objFile->uuid; } $value = serialize($tmp); } } elseif ($GLOBALS['TL_DCA'][$table]['fields'][$name]['inputType'] == 'imageSize') { $imageSizes = \StringUtil::deserialize($value, true); if (!empty($imageSizes)) { if (is_numeric($imageSizes[2])) { $imageSizes[2] = $arrMapper['tl_image_size'][$imageSizes[2]]; } } $value = serialize($imageSizes); } $set[$name] = $value; } // Skip fields that are not in the database (e.g. because of missing extensions) foreach ($set as $k => $v) { if (!in_array($k, $arrDbFields[$table])) { unset($set[$k]); } } // Create the templates folder even if it is empty (see #4793) if ($table == 'tl_theme' && isset($set['templates']) && strncmp($set['templates'], 'templates/', 10) === 0 && !is_dir(TL_ROOT . '/' . $set['templates'])) { new \Folder($set['templates']); } // Update tl_files (entries have been created by the Dbafs class) if ($table == 'tl_files') { $this->Database->prepare("UPDATE {$table} %s WHERE path=?")->set($set)->execute($set['path']); } else { $this->Database->prepare("INSERT INTO {$table} %s")->set($set)->execute(); } } } // Unlock the tables $this->Database->unlockTables(); // Update the style sheets $this->import('StyleSheets'); $this->StyleSheets->updateStyleSheets(); // Notify the user \Message::addConfirmation(sprintf($GLOBALS['TL_LANG']['tl_theme']['theme_imported'], basename($strZipFile))); // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['extractThemeFiles']) && is_array($GLOBALS['TL_HOOKS']['extractThemeFiles'])) { $intThemeId = empty($arrMapper['tl_theme']) ? null : reset($arrMapper['tl_theme']); foreach ($GLOBALS['TL_HOOKS']['extractThemeFiles'] as $callback) { \System::importStatic($callback[0])->{$callback[1]}($xml, $objArchive, $intThemeId, $arrMapper); } } unset($tl_files, $tl_theme, $tl_style_sheet, $tl_style, $tl_module, $tl_layout, $tl_image_size, $tl_image_size_item); } \System::setCookie('BE_PAGE_OFFSET', 0, 0); /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); $objSession->remove('uploaded_themes'); // Redirect $this->redirect(str_replace('&key=importTheme', '', \Environment::get('request'))); }
/** * Auto-generate a form to edit the local configuration file * * @return string */ public function edit() { $return = ''; $ajaxId = null; if (\Environment::get('isAjaxRequest')) { $ajaxId = func_get_arg(1); } // Build an array from boxes and rows $this->strPalette = $this->getPalette(); $boxes = trimsplit(';', $this->strPalette); $legends = array(); if (!empty($boxes)) { foreach ($boxes as $k => $v) { $boxes[$k] = trimsplit(',', $v); foreach ($boxes[$k] as $kk => $vv) { if (preg_match('/^\\[.*\\]$/', $vv)) { continue; } if (preg_match('/^\\{.*\\}$/', $vv)) { $legends[$k] = substr($vv, 1, -1); unset($boxes[$k][$kk]); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv]['exclude'] || !is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$vv])) { unset($boxes[$k][$kk]); } } // Unset a box if it does not contain any fields if (empty($boxes[$k])) { unset($boxes[$k]); } } /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); // Render boxes $class = 'tl_tbox'; $fs = $objSessionBag->get('fieldset_states'); $blnIsFirst = true; foreach ($boxes as $k => $v) { $strAjax = ''; $blnAjax = false; $key = ''; $cls = ''; $legend = ''; if (isset($legends[$k])) { list($key, $cls) = explode(':', $legends[$k]); $legend = "\n" . '<legend onclick="AjaxRequest.toggleFieldset(this, \'' . $key . '\', \'' . $this->strTable . '\')">' . (isset($GLOBALS['TL_LANG'][$this->strTable][$key]) ? $GLOBALS['TL_LANG'][$this->strTable][$key] : $key) . '</legend>'; } if (isset($fs[$this->strTable][$key])) { $class .= $fs[$this->strTable][$key] ? '' : ' collapsed'; } else { $class .= $cls && $legend ? ' ' . $cls : ''; } $return .= "\n\n" . '<fieldset' . ($key ? ' id="pal_' . $key . '"' : '') . ' class="' . $class . ($legend ? '' : ' nolegend') . '">' . $legend; // Build rows of the current box foreach ($v as $vv) { if ($vv == '[EOF]') { if ($blnAjax && \Environment::get('isAjaxRequest')) { return $strAjax . '<input type="hidden" name="FORM_FIELDS[]" value="' . specialchars($this->strPalette) . '">'; } $blnAjax = false; $return .= "\n " . '</div>'; continue; } if (preg_match('/^\\[.*\\]$/', $vv)) { $thisId = 'sub_' . substr($vv, 1, -1); $blnAjax = $ajaxId == $thisId && \Environment::get('isAjaxRequest') ? true : false; $return .= "\n " . '<div id="' . $thisId . '">'; continue; } $this->strField = $vv; $this->strInputName = $vv; $this->varValue = \Config::get($this->strField); // Handle entities if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['inputType'] == 'text' || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['inputType'] == 'textarea') { if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['multiple']) { $this->varValue = deserialize($this->varValue); } if (!is_array($this->varValue)) { $this->varValue = htmlspecialchars($this->varValue); } else { foreach ($this->varValue as $k => $v) { $this->varValue[$k] = htmlspecialchars($v); } } } // Autofocus the first field if ($blnIsFirst && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['inputType'] == 'text') { $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['eval']['autofocus'] = 'autofocus'; $blnIsFirst = false; } // Call load_callback if (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->varValue = $this->{$callback}[0]->{$callback}[1]($this->varValue, $this); } elseif (is_callable($callback)) { $this->varValue = $callback($this->varValue, $this); } } } // Build row $blnAjax ? $strAjax .= $this->row() : ($return .= $this->row()); } $class = 'tl_box'; $return .= "\n" . '</fieldset>'; } } $this->import('Files'); // Check whether the target file is writeable if (!$this->Files->is_writeable('system/config/localconfig.php')) { \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['notWriteable'], 'system/config/localconfig.php')); } // Submit buttons $arrButtons = array(); $arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['save'] . '</button>'; $arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">' . $GLOBALS['TL_LANG']['MSC']['saveNclose'] . '</button>'; // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['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); } } } // Add the buttons and end the form $return .= ' </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </form> <script> window.addEvent(\'domready\', function() { Theme.focusInput("' . $this->strTable . '"); }); </script>'; // Begin the form (-> DO NOT CHANGE THIS ORDER -> this way the onsubmit attribute of the form can be changed by a field) $return = ' <div id="tl_buttons"> <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="' . $this->strTable . '" class="tl_form" method="post"' . (!empty($this->onsubmit) ? ' onsubmit="' . implode(' ', $this->onsubmit) . '"' : '') . '> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="' . $this->strTable . '"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <input type="hidden" name="FORM_FIELDS[]" value="' . specialchars($this->strPalette) . '">' . ($this->noReload ? ' <p class="tl_error">' . $GLOBALS['TL_LANG']['ERR']['general'] . '</p>' : '') . $return; // Reload the page to prevent _POST variables from being sent twice if (\Input::post('FORM_SUBMIT') == $this->strTable && !$this->noReload) { // Call onsubmit_callback if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onsubmit_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $this->{$callback}[0]->{$callback}[1]($this); } elseif (is_callable($callback)) { $callback($this); } } } // Reload if (isset($_POST['saveNclose'])) { \Message::reset(); \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->redirect($this->getReferer()); } $this->reload(); } // Set the focus if there is an error if ($this->noReload) { $return .= ' <script> window.addEvent(\'domready\', function() { Backend.vScrollTo(($(\'' . $this->strTable . '\').getElement(\'label.error\').getPosition().y - 20)); }); </script>'; } return $return; }