Return the container object
public static getContainer ( ) : Symfony\Component\DependencyInjection\ContainerInterface | ||
Résultat | Symfony\Component\DependencyInjection\ContainerInterface | The container object |
/** * Run the controller and parse the template * * @return Response */ public function run() { /** @var \BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_preview'); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = specialchars($GLOBALS['TL_LANG']['MSC']['fePreview']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->site = \Input::get('site', true); $objTemplate->switchHref = \System::getContainer()->get('router')->generate('contao_backend_switch'); if (\Input::get('url')) { $objTemplate->url = \Environment::get('base') . \Input::get('url'); } elseif (\Input::get('page')) { $objTemplate->url = $this->redirectToFrontendPage(\Input::get('page'), \Input::get('article'), true); } else { $objTemplate->url = \System::getContainer()->get('router')->generate('contao_root', [], UrlGeneratorInterface::ABSOLUTE_URL); } // Switch to a particular member (see #6546) if (\Input::get('user') && $this->User->isAdmin) { $objUser = \MemberModel::findByUsername(\Input::get('user')); if ($objUser !== null) { $strHash = $this->getSessionHash('FE_USER_AUTH'); // Remove old sessions $this->Database->prepare("DELETE FROM tl_session WHERE tstamp<? OR hash=?")->execute(time() - \Config::get('sessionTimeout'), $strHash); // Insert the new session $this->Database->prepare("INSERT INTO tl_session (pid, tstamp, name, sessionID, ip, hash) VALUES (?, ?, ?, ?, ?, ?)")->execute($objUser->id, time(), 'FE_USER_AUTH', \System::getContainer()->get('session')->getId(), \Environment::get('ip'), $strHash); // Set the cookie $this->setCookie('FE_USER_AUTH', $strHash, time() + \Config::get('sessionTimeout'), null, null, false, true); $objTemplate->user = \Input::post('user'); } } return $objTemplate->getResponse(); }
/** * Return a response object * * The forum Page usually does not get called because the frontend listener * overrides the url for navigation for example. When called directly the layout parts * phpBB gets created und pushed to phpbb * * @see ContaoFrontendListener * * @param \PageModel $objPage * @param boolean $blnCheckRequest * * @return Response */ public function getResponse($objPage, $blnCheckRequest = false) { $this->prepare($objPage); // prepare the template contents $this->Template->main = "%%FORUM%%"; $style = $this->prepareHeadTags($this->Template->stylesheets); $mooScripts = $this->prepareHeadTags($this->Template->mooScripts); $framework = $this->prepareHeadTags($this->Template->framework); $head = $this->prepareHeadTags($this->Template->head); $this->Template->head = ""; $response = $this->Template->getResponse($blnCheckRequest); // layout sections $overall_header = ''; $overall_footer = ''; $sections = $this->generateLayoutSections($response->getContent()); // template vars will be replaced with dynamic content on each request $overall_header = '{CONTAO_LAYOUT_HEADER}'; $overall_footer = '{CONTAO_LAYOUT_FOOTER}'; // If dynamic generation is set and json format requested we can return and leave (no need to generate files) if ($this->Input->get('format') == 'json') { return new JsonResponse($sections); } // Generate files for static and generic contents $phpbbHeaders = ""; $phpbbHeaders .= $framework; $phpbbHeaders .= $style; $phpbbHeaders .= $mooScripts; $phpbbHeaders .= $head; file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_header_stylesheets_after.html', $phpbbHeaders); file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/simple_header_stylesheets_after.html', $phpbbHeaders); file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_header_body_before.html', $overall_header); file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_footer_after.html', $overall_footer); System::getContainer()->get('phpbb_bridge.connector')->updateConfig(array('contao.body_class' => $this->Template->class)); return $response; }
/** * Generate the module * * @return string */ public function run() { $arrJobs = array(); /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_purge_data'); $objTemplate->isActive = $this->isActive(); $objTemplate->message = \Message::generateUnwrapped(); // Run the jobs if (\Input::post('FORM_SUBMIT') == 'tl_purge') { $purge = \Input::post('purge'); if (!empty($purge) && is_array($purge)) { foreach ($purge as $group => $jobs) { foreach ($jobs as $job) { list($class, $method) = $GLOBALS['TL_PURGE'][$group][$job]['callback']; $this->import($class); $this->{$class}->{$method}(); } } } \Message::addConfirmation($GLOBALS['TL_LANG']['tl_maintenance']['cacheCleared']); $this->reload(); } // Tables foreach ($GLOBALS['TL_PURGE']['tables'] as $key => $config) { $arrJobs[$key] = array('id' => 'purge_' . $key, 'title' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][0], 'description' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][1], 'group' => 'tables', 'affected' => ''); // Get the current table size foreach ($config['affected'] as $table) { $objCount = $this->Database->execute("SELECT COUNT(*) AS count FROM " . $table); $arrJobs[$key]['affected'] .= '<br>' . $table . ': <span>' . sprintf($GLOBALS['TL_LANG']['MSC']['entries'], $objCount->count) . ', ' . $this->getReadableSize($this->Database->getSizeOf($table), 0) . '</span>'; } } $strCachePath = str_replace(TL_ROOT . DIRECTORY_SEPARATOR, '', \System::getContainer()->getParameter('kernel.cache_dir')); // Folders foreach ($GLOBALS['TL_PURGE']['folders'] as $key => $config) { $arrJobs[$key] = array('id' => 'purge_' . $key, 'title' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][0], 'description' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][1], 'group' => 'folders', 'affected' => ''); // Get the current folder size foreach ($config['affected'] as $folder) { $total = 0; $folder = sprintf($folder, $strCachePath); // Only check existing folders if (is_dir(TL_ROOT . '/' . $folder)) { $objFiles = Finder::create()->in(TL_ROOT . '/' . $folder)->files(); $total = iterator_count($objFiles); } $arrJobs[$key]['affected'] .= '<br>' . $folder . ': <span>' . sprintf($GLOBALS['TL_LANG']['MSC']['files'], $total) . '</span>'; } } // Custom foreach ($GLOBALS['TL_PURGE']['custom'] as $key => $job) { $arrJobs[$key] = array('id' => 'purge_' . $key, 'title' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][0], 'description' => $GLOBALS['TL_LANG']['tl_maintenance_jobs'][$key][1], 'group' => 'custom'); } $objTemplate->jobs = $arrJobs; $objTemplate->action = ampersand(\Environment::get('request')); $objTemplate->headline = $GLOBALS['TL_LANG']['tl_maintenance']['clearCache']; $objTemplate->job = $GLOBALS['TL_LANG']['tl_maintenance']['job']; $objTemplate->description = $GLOBALS['TL_LANG']['tl_maintenance']['description']; $objTemplate->submit = \StringUtil::specialchars($GLOBALS['TL_LANG']['tl_maintenance']['clearCache']); $objTemplate->help = \Config::get('showHelp') && $GLOBALS['TL_LANG']['tl_maintenance']['cacheTables'][1] != '' ? $GLOBALS['TL_LANG']['tl_maintenance']['cacheTables'][1] : ''; return $objTemplate->parse(); }
/** * Overwrite for Automator::purgePageCache * Makes sure the forum layout is regenerated */ public function purgePageCache() { $automator = new Automator(); $automator->purgePageCache(); System::getContainer()->get('phpbb_bridge.connector')->generateForumLayoutFiles(); $this->log('Purged the phpbb forum cache', __METHOD__, TL_CRON); }
/** * Get the session data */ protected function __construct() { if (PHP_SAPI == 'cli') { $this->session = new SymfonySession(new MockArraySessionStorage()); } else { $this->session = \System::getContainer()->get('session'); } $this->sessionBag = $this->session->getBag($this->getSessionBagKey()); }
/** * Generate the widget and return it as string * * @return string */ public function generate() { $arrOptions = array(); if (!$this->multiple && count($this->arrOptions) > 1) { $this->arrOptions = array($this->arrOptions[0]); } // The "required" attribute only makes sense for single checkboxes if ($this->mandatory && !$this->multiple) { $this->arrAttributes['required'] = 'required'; } /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $state = $objSessionBag->get('checkbox_groups'); // Toggle the checkbox group if (\Input::get('cbc')) { $state[\Input::get('cbc')] = isset($state[\Input::get('cbc')]) && $state[\Input::get('cbc')] == 1 ? 0 : 1; $objSessionBag->set('checkbox_groups', $state); $this->redirect(preg_replace('/(&(amp;)?|\\?)cbc=[^& ]*/i', '', \Environment::get('request'))); } $blnFirst = true; $blnCheckAll = true; foreach ($this->arrOptions as $i => $arrOption) { // Single dimension array if (is_numeric($i)) { $arrOptions[] = $this->generateCheckbox($arrOption, $i); continue; } $id = 'cbc_' . $this->strId . '_' . \StringUtil::standardize($i); $img = 'folPlus.svg'; $display = 'none'; if (!isset($state[$id]) || !empty($state[$id])) { $img = 'folMinus.svg'; $display = 'block'; } $arrOptions[] = '<div class="checkbox_toggler' . ($blnFirst ? '_first' : '') . '"><a href="' . $this->addToUrl('cbc=' . $id) . '" onclick="AjaxRequest.toggleCheckboxGroup(this,\'' . $id . '\');Backend.getScrollOffset();return false">' . \Image::getHtml($img) . '</a>' . $i . '</div><fieldset id="' . $id . '" class="tl_checkbox_container checkbox_options" style="display:' . $display . '"><input type="checkbox" id="check_all_' . $id . '" class="tl_checkbox" onclick="Backend.toggleCheckboxGroup(this, \'' . $id . '\')"> <label for="check_all_' . $id . '" style="color:#a6a6a6"><em>' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</em></label>'; // Multidimensional array foreach ($arrOption as $k => $v) { $arrOptions[] = $this->generateCheckbox($v, standardize($i) . '_' . $k); } $arrOptions[] = '</fieldset>'; $blnFirst = false; $blnCheckAll = false; } // Add a "no entries found" message if there are no options if (empty($arrOptions)) { $arrOptions[] = '<p class="tl_noopt">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>'; $blnCheckAll = false; } if ($this->multiple) { return sprintf('<fieldset id="ctrl_%s" class="tl_checkbox_container%s"><legend>%s%s%s%s</legend><input type="hidden" name="%s" value="">%s%s</fieldset>%s', $this->strId, $this->strClass != '' ? ' ' . $this->strClass : '', $this->mandatory ? '<span class="invisible">' . $GLOBALS['TL_LANG']['MSC']['mandatory'] . ' </span>' : '', $this->strLabel, $this->mandatory ? '<span class="mandatory">*</span>' : '', $this->xlabel, $this->strName, $blnCheckAll ? '<input type="checkbox" id="check_all_' . $this->strId . '" class="tl_checkbox" onclick="Backend.toggleCheckboxGroup(this,\'ctrl_' . $this->strId . '\')' . ($this->onclick ? ';' . $this->onclick : '') . '"> <label for="check_all_' . $this->strId . '" style="color:#a6a6a6"><em>' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</em></label><br>' : '', str_replace('<br></fieldset><br>', '</fieldset>', implode('<br>', $arrOptions)), $this->wizard); } else { return sprintf('<div id="ctrl_%s" class="tl_checkbox_single_container%s"><input type="hidden" name="%s" value="">%s</div>%s', $this->strId, $this->strClass != '' ? ' ' . $this->strClass : '', $this->strName, str_replace('<br></div><br>', '</div>', implode('<br>', $arrOptions)), $this->wizard); } }
protected function execute(InputInterface $input, OutputInterface $output) { $this->getFramework()->initialize(); $output->writeln('Clearing Forum Cache'); System::getContainer()->get('phpbb_bridge.connector')->clearForumCache(); // Generate the layout if not explicitly asked for cache only if (!$input->getOption('cache-only')) { $output->writeln('Generating Layout Files'); System::getContainer()->get('phpbb_bridge.connector')->generateForumLayoutFiles(); } return 0; }
/** * Establish the database connection * * @param array $arrConfig The configuration array * * @throws \Exception If a connection cannot be established */ protected function __construct(array $arrConfig) { // Deprecated since Contao 4.0, to be removed in Contao 5.0 if (!empty($arrConfig)) { @trigger_error('Passing a custom configuration to Database::__construct() has been deprecated and will no longer work in Contao 5.0.', E_USER_DEPRECATED); $arrParams = array('driver' => \System::getContainer()->getParameter('database_driver'), 'host' => $arrConfig['dbHost'], 'port' => $arrConfig['dbPort'], 'user' => $arrConfig['dbUser'], 'password' => $arrConfig['dbPass'], 'dbname' => $arrConfig['dbDatabase']); $this->resConnection = DriverManager::getConnection($arrParams); } else { $this->resConnection = \System::getContainer()->get('database_connection'); } if (!is_object($this->resConnection)) { throw new \Exception(sprintf('Could not connect to database (%s)', $this->error)); } }
/** * Initialize the object */ public function __construct() { // Load the user object before calling the parent constructor $this->import('FrontendUser', 'User'); parent::__construct(); // Check whether a user is logged in define('BE_USER_LOGGED_IN', $this->getLoginStatus('BE_USER_AUTH')); define('FE_USER_LOGGED_IN', $this->getLoginStatus('FE_USER_AUTH')); // No back end user logged in if (!$_SESSION['DISABLE_CACHE']) { // Maintenance mode (see #4561 and #6353) if (\Config::get('maintenanceMode') && !\System::getContainer()->get('kernel')->isDebug()) { throw new ServiceUnavailableException('This site is currently down for maintenance. Please come back later.'); } } }
/** * Validate a token * * @param string $strToken The request token * * @return boolean True if the token matches the stored one */ public static function validate($strToken) { // The feature has been disabled if (\Config::get('disableRefererCheck') || defined('BYPASS_TOKEN_CHECK')) { return true; } // Check against the whitelist (thanks to Tristan Lins) (see #3164) if (\Config::get('requestTokenWhitelist')) { $strHostname = gethostbyaddr($_SERVER['REMOTE_ADDR']); foreach (\Config::get('requestTokenWhitelist') as $strDomain) { if ($strDomain == $strHostname || preg_match('/\\.' . preg_quote($strDomain, '/') . '$/', $strHostname)) { return true; } } } $container = \System::getContainer(); return $container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($container->getParameter('contao.csrf_token_name'), $strToken)); }
/** * Return a response object * * The forum Page usually does not get called because the frontend listener * overrides the url for navigation for example. When called directly the layout parts * phpBB gets created und pushed to phpbb * * @see ContaoFrontendListener * * @param \PageModel $objPage * @param boolean $blnCheckRequest * * @return Response */ public function getResponse($objPage, $blnCheckRequest = false) { $this->prepare($objPage); //dump($this->Template); $this->Template->main = "%%FORUM%%"; $headTags = $this->Template->head; $this->Template->head = ""; $response = $this->Template->getResponse($blnCheckRequest); $style = preg_replace('/href\\=\\"(?!http|\\/)/', 'href="/', $this->Template->replaceDynamicScriptTags($this->Template->stylesheets)); $headTags = preg_replace('/href\\=\\"(?!http|\\/)/', 'href="/', $this->Template->replaceDynamicScriptTags($headTags)); $headTags = preg_replace('/src\\=\\"(?!http|\\/)/', 'href="/', $headTags); // @todo Add framework, mooscripts etc? $phpbbHeaders = ""; $phpbbHeaders .= $style; $phpbbHeaders .= $headTags; file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_header_stylesheets_after.html', $phpbbHeaders); //dump($phpbbHeaders); //dump($this->Template->class); $html = $response->getContent(); // Ajust link paths $html = preg_replace('/href\\=\\"(?!http|\\/)/', 'href="/', $html); // Ajust src paths $html = preg_replace('/src\\=\\"(?!http|\\/)/', 'src="/', $html); $html = preg_replace('/content\\=\\"(?!http|\\/)/', 'content="/', $html); $parts = explode("%%FORUM%%", $html); $overall_header = $parts[0]; $overall_footer = $parts[1]; $overall_header = preg_replace('/<\\!DOC.*/i', '', $overall_header); $overall_header = preg_replace('/<html.*/i', '', $overall_header); $overall_header = preg_replace('/<body.*/i', '', $overall_header); $overall_header = preg_replace('/<head>.*<\\/head>/s', '', $overall_header); $overall_footer = preg_replace('/<\\/body.*/i', '', $overall_footer); $overall_footer = preg_replace('/<\\/html.*/i', '', $overall_footer); //dump($overall_footer); //dump($this->Template); //dump($html); file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_header_body_before.html', $overall_header); file_put_contents(__DIR__ . '/../Resources/phpBB/ctsmedia/contaophpbbbridge/styles/all/template/event/overall_footer_after.html', $overall_footer); System::getContainer()->get('phpbb_bridge.connector')->updateConfig(array('contao.body_class' => $this->Template->class)); return $response; }
/** * Set the new password */ protected function setNewPassword() { $objMember = \MemberModel::findOneByActivation(\Input::get('token')); if ($objMember === null || $objMember->login == '') { $this->strTemplate = 'mod_message'; /** @var FrontendTemplate|object $objTemplate */ $objTemplate = new \FrontendTemplate($this->strTemplate); $this->Template = $objTemplate; $this->Template->type = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['MSC']['accountError']; return; } $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(); // Define the form field $arrField = $GLOBALS['TL_DCA']['tl_member']['fields']['password']; /** @var Widget $strClass */ $strClass = $GLOBALS['TL_FFL']['password']; // Fallback to default if the class is not defined if (!class_exists($strClass)) { $strClass = 'FormPassword'; } /** @var Widget $objWidget */ $objWidget = new $strClass($strClass::getAttributesFromDca($arrField, 'password')); // Set row classes $objWidget->rowClass = 'row_0 row_first even'; $objWidget->rowClassConfirm = 'row_1 odd'; $this->Template->rowLast = 'row_2 row_last even'; /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); // Validate the field if (strlen(\Input::post('FORM_SUBMIT')) && \Input::post('FORM_SUBMIT') == $objSession->get('setPasswordToken')) { $objWidget->validate(); // Set the new password and redirect if (!$objWidget->hasErrors()) { $objSession->set('setPasswordToken', ''); $objMember->tstamp = time(); $objMember->activation = ''; $objMember->password = $objWidget->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, $objWidget->value, $this); } } // Redirect to the jumpTo page if (($objTarget = $this->objModel->getRelated('reg_jumpTo')) instanceof PageModel) { /** @var PageModel $objTarget */ $this->redirect($objTarget->getFrontendUrl()); } // Confirm $this->strTemplate = 'mod_message'; /** @var FrontendTemplate|object $objTemplate */ $objTemplate = new \FrontendTemplate($this->strTemplate); $this->Template = $objTemplate; $this->Template->type = 'confirm'; $this->Template->message = $GLOBALS['TL_LANG']['MSC']['newPasswordSet']; return; } } $strToken = md5(uniqid(mt_rand(), true)); $objSession->set('setPasswordToken', $strToken); $this->Template->formId = $strToken; $this->Template->fields = $objWidget->parse(); $this->Template->action = \Environment::get('indexFreeRequest'); $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['setNewPassword']); }
/** * Generate the navigation menu and return it as array * * @param boolean $blnShowAll * * @return array */ public function navigation($blnShowAll = false) { /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $arrModules = array(); $session = $objSessionBag->all(); // Toggle nodes if (\Input::get('mtg')) { $session['backend_modules'][\Input::get('mtg')] = isset($session['backend_modules'][\Input::get('mtg')]) && $session['backend_modules'][\Input::get('mtg')] == 0 ? 1 : 0; $objSessionBag->replace($session); \Controller::redirect(preg_replace('/(&(amp;)?|\\?)mtg=[^& ]*/i', '', \Environment::get('request'))); } foreach ($GLOBALS['BE_MOD'] as $strGroupName => $arrGroupModules) { if (!empty($arrGroupModules) && ($strGroupName == 'system' || $this->hasAccess(array_keys($arrGroupModules), 'modules'))) { $arrModules[$strGroupName]['icon'] = 'modMinus.gif'; $arrModules[$strGroupName]['title'] = specialchars($GLOBALS['TL_LANG']['MSC']['collapseNode']); $arrModules[$strGroupName]['label'] = ($label = is_array($GLOBALS['TL_LANG']['MOD'][$strGroupName]) ? $GLOBALS['TL_LANG']['MOD'][$strGroupName][0] : $GLOBALS['TL_LANG']['MOD'][$strGroupName]) != false ? $label : $strGroupName; $arrModules[$strGroupName]['href'] = \Controller::addToUrl('mtg=' . $strGroupName); // Do not show the modules if the group is closed if (!$blnShowAll && isset($session['backend_modules'][$strGroupName]) && $session['backend_modules'][$strGroupName] < 1) { $arrModules[$strGroupName]['modules'] = false; $arrModules[$strGroupName]['icon'] = 'modPlus.gif'; $arrModules[$strGroupName]['title'] = specialchars($GLOBALS['TL_LANG']['MSC']['expandNode']); } else { foreach ($arrGroupModules as $strModuleName => $arrModuleConfig) { // Check access if ($strModuleName == 'undo' || $this->hasAccess($strModuleName, 'modules')) { $arrModules[$strGroupName]['modules'][$strModuleName] = $arrModuleConfig; $arrModules[$strGroupName]['modules'][$strModuleName]['title'] = specialchars($GLOBALS['TL_LANG']['MOD'][$strModuleName][1]); $arrModules[$strGroupName]['modules'][$strModuleName]['label'] = ($label = is_array($GLOBALS['TL_LANG']['MOD'][$strModuleName]) ? $GLOBALS['TL_LANG']['MOD'][$strModuleName][0] : $GLOBALS['TL_LANG']['MOD'][$strModuleName]) != false ? $label : $strModuleName; $arrModules[$strGroupName]['modules'][$strModuleName]['icon'] = !empty($arrModuleConfig['icon']) ? sprintf(' style="background-image:url(\'%s%s\')"', TL_ASSETS_URL, $arrModuleConfig['icon']) : ''; $arrModules[$strGroupName]['modules'][$strModuleName]['class'] = 'navigation ' . $strModuleName; $arrModules[$strGroupName]['modules'][$strModuleName]['href'] = TL_SCRIPT . '?do=' . $strModuleName . '&ref=' . TL_REFERER_ID; // Mark the active module and its group if (\Input::get('do') == $strModuleName) { $arrModules[$strGroupName]['class'] = ' trail'; $arrModules[$strGroupName]['modules'][$strModuleName]['class'] .= ' active'; } } } } } } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getUserNavigation']) && is_array($GLOBALS['TL_HOOKS']['getUserNavigation'])) { foreach ($GLOBALS['TL_HOOKS']['getUserNavigation'] as $callback) { $this->import($callback[0]); $arrModules = $this->{$callback[0]}->{$callback[1]}($arrModules, $blnShowAll); } } return $arrModules; }
/** * Generate the internal cache */ public function generateInternalCache() { $container = \System::getContainer(); $command = new ContaoCacheWarmer($container->get('filesystem'), $container->get('contao.resource_finder'), $container->get('contao.resource_locator'), $container->getParameter('kernel.root_dir'), $container->get('database_connection'), $container->get('contao.framework')); $command->warmUp(\System::getContainer()->getParameter('kernel.cache_dir')); // Add a log entry $this->log('Generated the internal cache', __METHOD__, TL_CRON); }
/** * Generate an absolute URL depending on the current rewriteURL setting * * @param string $strParams An optional string of URL parameters * * @return string An absolute URL that can be used in the front end */ public function getAbsoluteUrl($strParams = null) { $this->loadDetails(); $objUrlGenerator = \System::getContainer()->get('contao.routing.url_generator'); $strUrl = $objUrlGenerator->generate(($this->alias ?: $this->id) . $strParams, array('_locale' => $this->rootLanguage, '_domain' => $this->domain, '_ssl' => (bool) $this->rootUseSSL), UrlGeneratorInterface::ABSOLUTE_URL); $strUrl = $this->applyLegacyLogic($strUrl, $strParams); return $strUrl; }
/** * Return a route relative to the base URL * * @param string $strName The route name * @param array $arrParams The route parameters * * @return string The route */ public function route($strName, $arrParams = array()) { $strUrl = \System::getContainer()->get('router')->generate($strName, $arrParams); $strUrl = substr($strUrl, strlen(\Environment::get('path')) + 1); return ampersand($strUrl); }
/** * Return a pagination menu to browse results * * @return string */ protected function paginationMenu() { /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $filter = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4 ? $this->strTable . '_' . CURRENT_ID : $this->strTable; list($offset, $limit) = explode(',', $this->limit); // Set the limit filter based on the page number if (isset($_GET['lp'])) { $lp = intval(\Input::get('lp')) - 1; if ($lp >= 0 && $lp < ceil($this->total / $limit)) { $session['filter'][$filter]['limit'] = $lp * $limit . ',' . $limit; $objSessionBag->replace($session); } $this->redirect(preg_replace('/&(amp;)?lp=[^&]+/i', '', \Environment::get('request'))); } if ($limit) { \Input::setGet('lp', $offset / $limit + 1); } $objPagination = new \Pagination($this->total, $limit, 7, 'lp', new \BackendTemplate('be_pagination'), true); return $objPagination->generate(); }
/** * Generate the module */ protected function compile() { // Show logout form if (FE_USER_LOGGED_IN) { $this->import('FrontendUser', 'User'); $this->Template->logout = true; $this->Template->formId = 'tl_logout_' . $this->id; $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['logout']); $this->Template->loggedInAs = sprintf($GLOBALS['TL_LANG']['MSC']['loggedInAs'], $this->User->username); $this->Template->action = ampersand(\Environment::get('indexFreeRequest')); if ($this->User->lastLogin > 0) { /** @var PageModel $objPage */ global $objPage; $this->Template->lastLogin = sprintf($GLOBALS['TL_LANG']['MSC']['lastLogin'][1], \Date::parse($objPage->datimFormat, $this->User->lastLogin)); } return; } $flashBag = \System::getContainer()->get('session')->getFlashBag(); if ($flashBag->has($this->strFlashType)) { $this->Template->hasError = true; $this->Template->message = $flashBag->get($this->strFlashType)[0]; } $this->Template->username = $GLOBALS['TL_LANG']['MSC']['username']; $this->Template->password = $GLOBALS['TL_LANG']['MSC']['password'][0]; $this->Template->action = ampersand(\Environment::get('indexFreeRequest')); $this->Template->slabel = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['login']); $this->Template->value = \StringUtil::specialchars(\Input::post('username')); $this->Template->formId = 'tl_login_' . $this->id; $this->Template->autologin = $this->autologin && \Config::get('autologin') > 0; $this->Template->autoLabel = $GLOBALS['TL_LANG']['MSC']['autologin']; }
/** * Parse simple tokens * * @param string $strString The string to be parsed * @param array $arrData The replacement data * * @return string The converted string * * @throws \Exception If $strString cannot be parsed * @throws \InvalidArgumentException If there are incorrectly formatted if-tags */ public static function parseSimpleTokens($strString, $arrData) { $strReturn = ''; $replaceTokens = function ($strSubject) use($arrData) { // Replace tokens return preg_replace_callback('/##([^=!<>\\s]+?)##/', function (array $matches) use($arrData) { if (!array_key_exists($matches[1], $arrData)) { \System::getContainer()->get('monolog.logger.contao')->log(LogLevel::INFO, sprintf('Tried to parse unknown simple token "%s".', $matches[1])); return '##' . $matches[1] . '##'; } return $arrData[$matches[1]]; }, $strSubject); }; $evaluateExpression = function ($strExpression) use($arrData) { if (!preg_match('/^([^=!<>\\s]+)([=!<>]+)(.+)$/is', $strExpression, $arrMatches)) { return false; } $strToken = $arrMatches[1]; $strOperator = $arrMatches[2]; $strValue = $arrMatches[3]; if (!array_key_exists($strToken, $arrData)) { \System::getContainer()->get('monolog.logger.contao')->log(LogLevel::INFO, sprintf('Tried to evaluate unknown simple token "%s".', $strToken)); return false; } $varTokenValue = $arrData[$strToken]; if (is_numeric($strValue)) { if (strpos($strValue, '.') === false) { $varValue = intval($strValue); } else { $varValue = floatval($strValue); } } elseif (strtolower($strValue) === 'true') { $varValue = true; } elseif (strtolower($strValue) === 'false') { $varValue = false; } elseif (strtolower($strValue) === 'null') { $varValue = null; } elseif (substr($strValue, 0, 1) === '"' && substr($strValue, -1) === '"') { $varValue = str_replace('\\"', '"', substr($strValue, 1, -1)); } elseif (substr($strValue, 0, 1) === "'" && substr($strValue, -1) === "'") { $varValue = str_replace("\\'", "'", substr($strValue, 1, -1)); } else { throw new \InvalidArgumentException(sprintf('Unknown data type of comparison value "%s".', $strValue)); } switch ($strOperator) { case '==': return $varTokenValue == $varValue; case '!=': return $varTokenValue != $varValue; case '===': return $varTokenValue === $varValue; case '!==': return $varTokenValue !== $varValue; case '<': return $varTokenValue < $varValue; case '>': return $varTokenValue > $varValue; case '<=': return $varTokenValue <= $varValue; case '>=': return $varTokenValue >= $varValue; default: throw new \InvalidArgumentException(sprintf('Unknown simple token comparison operator "%s".', $strOperator)); } }; // Parsing stack used to keep track of the nesting level // The last item is true if it is inside a matching if-tag $arrStack = [true]; // Tokenize the string into tag and text blocks $arrTags = preg_split('/({[^{}]+})\\n?/', $strString, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); // Parse the tokens foreach ($arrTags as $strTag) { // true if it is inside a matching if-tag $blnCurrent = $arrStack[count($arrStack) - 1]; if (strncmp($strTag, '{if', 3) === 0) { $arrStack[] = $blnCurrent && $evaluateExpression(substr($strTag, 4, -1)); } elseif (strncmp($strTag, '{elseif', 7) === 0) { array_pop($arrStack); $arrStack[] = !$blnCurrent && $arrStack[count($arrStack) - 1] && $evaluateExpression(substr($strTag, 8, -1)); } elseif (strncmp($strTag, '{else}', 6) === 0) { array_pop($arrStack); $arrStack[] = !$blnCurrent && $arrStack[count($arrStack) - 1]; } elseif (strncmp($strTag, '{endif}', 7) === 0) { array_pop($arrStack); } elseif ($blnCurrent) { $strReturn .= $replaceTokens($strTag); } } // Throw an exception if there is an error if (count($arrStack) !== 1) { throw new \Exception('Error parsing simple tokens'); } return $strReturn; }
/** * 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'); }
/** * @return array */ protected function listDataContainerArrayFiles() { $arrFiles = array(); $arrActiveModules = System::getContainer()->get('kernel.bundles')->getActive(); // Parse all active modules foreach ($arrActiveModules as $strModule) { $strDir = 'system/modules/' . $strModule . '/dca'; if (!is_dir(TL_ROOT . '/' . $strDir)) { continue; } foreach (scan(TL_ROOT . '/' . $strDir) as $strFile) { // Ignore non PHP files and files which have been included before if (strncmp($strFile, '.', 1) === 0 || substr($strFile, -4) != '.php' || in_array($strFile, $arrFiles)) { continue; } $arrFiles[] = substr($strFile, 0, -4); } } return $arrFiles; }
/** * Send the activation mail * * @param array $arrData */ protected function sendActivationMail($arrData) { // Prepare the simple token data $arrTokenData = $arrData; $arrTokenData['domain'] = \Idna::decode(\Environment::get('host')); $arrTokenData['link'] = \Idna::decode(\Environment::get('base')) . \Environment::get('request') . (strpos(\Environment::get('request'), '?') !== false ? '&' : '?') . 'token=' . $arrData['activation']; $arrTokenData['channels'] = ''; $bundles = \System::getContainer()->getParameter('kernel.bundles'); if (isset($bundles['ContaoNewsletterBundle'])) { // Make sure newsletter is an array if (!is_array($arrData['newsletter'])) { if ($arrData['newsletter'] != '') { $arrData['newsletter'] = array($arrData['newsletter']); } else { $arrData['newsletter'] = array(); } } // Replace the wildcard if (!empty($arrData['newsletter'])) { $objChannels = \NewsletterChannelModel::findByIds($arrData['newsletter']); if ($objChannels !== null) { $arrTokenData['channels'] = implode("\n", $objChannels->fetchEach('title')); } } } // Deprecated since Contao 4.0, to be removed in Contao 5.0 $arrTokenData['channel'] = $arrTokenData['channels']; $objEmail = new \Email(); $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL']; $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME']; $objEmail->subject = sprintf($GLOBALS['TL_LANG']['MSC']['emailSubject'], \Idna::decode(\Environment::get('host'))); $objEmail->text = \StringUtil::parseSimpleTokens($this->reg_text, $arrTokenData); $objEmail->sendTo($arrData['email']); }
/** * Run the controller and parse the template * * @return Response */ public function run() { /** @var SessionInterface $objSession */ $objSession = \System::getContainer()->get('session'); /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_picker'); $objTemplate->main = ''; // Ajax request if ($_POST && \Environment::get('isAjaxRequest')) { $this->objAjax = new \Ajax(\Input::post('action')); $this->objAjax->executePreActions(); } $strTable = \Input::get('table'); $strField = \Input::get('field'); // Define the current ID define('CURRENT_ID', \Input::get('table') ? $objSession->get('CURRENT_ID') : \Input::get('id')); $this->loadDataContainer($strTable); $strDriver = 'DC_' . $GLOBALS['TL_DCA'][$strTable]['config']['dataContainer']; $objDca = new $strDriver($strTable); $objDca->field = $strField; // Set the active record if ($this->Database->tableExists($strTable)) { /** @var Model $strModel */ $strModel = \Model::getClassFromTable($strTable); if (class_exists($strModel)) { $objModel = $strModel::findByPk(\Input::get('id')); if ($objModel !== null) { $objDca->activeRecord = $objModel; } } } // AJAX request if ($_POST && \Environment::get('isAjaxRequest')) { $this->objAjax->executePostActions($objDca); } $objSession->set('filePickerRef', \Environment::get('request')); $arrValues = array_filter(explode(',', \Input::get('value'))); // Convert UUIDs to binary foreach ($arrValues as $k => $v) { // Can be a UUID or a path if (\Validator::isStringUuid($v)) { $arrValues[$k] = \StringUtil::uuidToBin($v); } } // Call the load_callback if (is_array($GLOBALS['TL_DCA'][$strTable]['fields'][$strField]['load_callback'])) { foreach ($GLOBALS['TL_DCA'][$strTable]['fields'][$strField]['load_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $arrValues = $this->{$callback[0]}->{$callback[1]}($arrValues, $objDca); } elseif (is_callable($callback)) { $arrValues = $callback($arrValues, $objDca); } } } /** @var FileSelector $strClass */ $strClass = $GLOBALS['BE_FFL']['fileSelector']; /** @var FileSelector $objFileTree */ $objFileTree = new $strClass($strClass::getAttributesFromDca($GLOBALS['TL_DCA'][$strTable]['fields'][$strField], $strField, $arrValues, $strField, $strTable, $objDca)); /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = $objSession->getBag('contao_backend'); $objTemplate->main = $objFileTree->generate(); $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = specialchars($GLOBALS['TL_LANG']['MSC']['filepicker']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->addSearch = true; $objTemplate->search = $GLOBALS['TL_LANG']['MSC']['search']; $objTemplate->searchExclude = $GLOBALS['TL_LANG']['MSC']['searchExclude']; $objTemplate->action = ampersand(\Environment::get('request')); $objTemplate->value = $objSessionBag->get('file_selector_search'); $objTemplate->manager = $GLOBALS['TL_LANG']['MSC']['fileManager']; $objTemplate->managerHref = 'contao/main.php?do=files&popup=1'; $objTemplate->breadcrumb = $GLOBALS['TL_DCA']['tl_files']['list']['sorting']['breadcrumb']; if (\Input::get('switch')) { $objTemplate->switch = $GLOBALS['TL_LANG']['MSC']['pagePicker']; $objTemplate->switchHref = str_replace('contao/file?', 'contao/page?', ampersand(\Environment::get('request'))); } return $objTemplate->getResponse(); }
/** * Add the template output to the cache and add the cache headers */ protected function addToCache() { /** @var PageModel $objPage */ global $objPage; $intCache = 0; // Decide whether the page shall be cached if (!isset($_GET['file']) && !isset($_GET['token']) && empty($_POST) && !BE_USER_LOGGED_IN && !FE_USER_LOGGED_IN && !$_SESSION['DISABLE_CACHE'] && !isset($_SESSION['LOGIN_ERROR']) && !\Message::hasMessages() && intval($objPage->cache) > 0 && !$objPage->protected) { $intCache = time() + intval($objPage->cache); } // Server-side cache if ($intCache > 0 && (\Config::get('cacheMode') == 'both' || \Config::get('cacheMode') == 'server')) { // If the request string is empty, use a special cache tag which considers the page language if (\Environment::get('relativeRequest') == '') { $strCacheKey = \Environment::get('host') . '/empty.' . $objPage->language; } 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) { $this->import($callback[0]); $strCacheKey = $this->{$callback[0]}->{$callback[1]}($strCacheKey); } } // Add a suffix if there is a mobile layout (see #7826) if ($objPage->mobileLayout > 0) { if (\Input::cookie('TL_VIEW') == 'mobile' || \Environment::get('agent')->mobile && \Input::cookie('TL_VIEW') != 'desktop') { $strCacheKey .= '.mobile'; } else { $strCacheKey .= '.desktop'; } } // Replace insert tags for caching $strBuffer = $this->replaceInsertTags($this->strBuffer); $strBuffer = $this->replaceDynamicScriptTags($strBuffer); // see #4203 // Add the cache file header $strHeader = sprintf("<?php /* %s */ \$expire = %d; \$content = %s; \$type = %s; \$files = %s; \$assets = %s; ?>\n", $strCacheKey, (int) $intCache, var_export($this->strContentType, true), var_export($objPage->type, true), var_export(TL_FILES_URL, true), var_export(TL_ASSETS_URL, true)); $strCachePath = str_replace(TL_ROOT . '/', '', \System::getContainer()->getParameter('kernel.cache_dir')); // Create the cache file $strMd5CacheKey = md5($strCacheKey); $objFile = new \File($strCachePath . '/contao/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'); $objFile->write($strHeader); $objFile->append($this->minifyHtml($strBuffer), ''); $objFile->close(); } // Client-side cache if (!headers_sent()) { if ($intCache > 0 && (\Config::get('cacheMode') == 'both' || \Config::get('cacheMode') == 'browser')) { header('Cache-Control: private, max-age=' . ($intCache - time())); header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT'); header('Expires: ' . gmdate('D, d M Y H:i:s', $intCache) . ' GMT'); } else { header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); header('Expires: Fri, 06 Jun 1975 15:10:00 GMT'); } } }
/** * Recursively render the filetree * * @param string $path * @param integer $intMargin * @param boolean $mount * @param boolean $blnProtected * @param array $arrFound * * @return string */ protected function renderFiletree($path, $intMargin, $mount = false, $blnProtected = true, $arrFound = array()) { // Invalid path if (!is_dir($path)) { return ''; } // Make sure that $this->varValue is an array (see #3369) if (!is_array($this->varValue)) { $this->varValue = array($this->varValue); } static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $flag = substr($this->strField, 0, 2); $node = 'tree_' . $this->strTable . '_' . $this->strField; $xtnode = 'tree_' . $this->strTable . '_' . $this->strName; // Get session data and toggle nodes if (\Input::get($flag . 'tg')) { $session[$node][\Input::get($flag . 'tg')] = isset($session[$node][\Input::get($flag . 'tg')]) && $session[$node][\Input::get($flag . 'tg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)' . $flag . 'tg=[^& ]*/i', '', \Environment::get('request'))); } $return = ''; $intSpacing = 20; $files = array(); $folders = array(); $level = $intMargin / $intSpacing + 1; // Mount folder if ($mount) { $folders = array($path); } else { foreach (scan($path) as $v) { if (strncmp($v, '.', 1) === 0) { continue; } if (is_dir($path . '/' . $v)) { $folders[] = $path . '/' . $v; } else { $files[] = $path . '/' . $v; } } } natcasesort($folders); $folders = array_values($folders); natcasesort($files); $files = array_values($files); // Sort descending (see #4072) if ($this->sort == 'desc') { $folders = array_reverse($folders); $files = array_reverse($files); } $folderClass = $this->files || $this->filesOnly ? 'tl_folder' : 'tl_file'; // Process folders for ($f = 0, $c = count($folders); $f < $c; $f++) { $content = scan($folders[$f]); $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $countFiles = count($content); // Check whether there are subfolders or files foreach ($content as $file) { if (strncmp($file, '.', 1) === 0) { --$countFiles; } elseif (!$this->files && !$this->filesOnly && is_file($folders[$f] . '/' . $file)) { --$countFiles; } elseif (!empty($arrFound) && !in_array($currentFolder . '/' . $file, $arrFound) && !preg_grep('/^' . preg_quote($currentFolder . '/' . $file, '/') . '\\//', $arrFound)) { --$countFiles; } } if (!empty($arrFound) && $countFiles < 1 && !in_array($currentFolder, $arrFound)) { continue; } $tid = md5($folders[$f]); $folderAttribute = 'style="margin-left:20px"'; $session[$node][$tid] = is_numeric($session[$node][$tid]) ? $session[$node][$tid] : 0; $currentFolder = str_replace(TL_ROOT . '/', '', $folders[$f]); $blnIsOpen = !empty($arrFound) || $session[$node][$tid] == 1 || count(preg_grep('/^' . preg_quote($currentFolder, '/') . '\\//', $this->varValue)) > 0; $return .= "\n " . '<li class="' . $folderClass . ' toggle_select hover-div"><div class="tl_left" style="padding-left:' . $intMargin . 'px">'; // Add a toggle button if there are childs if ($countFiles > 0) { $folderAttribute = ''; $img = $blnIsOpen ? 'folMinus.svg' : 'folPlus.svg'; $alt = $blnIsOpen ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . \Backend::addToUrl($flag . 'tg=' . $tid) . '" title="' . \StringUtil::specialchars($alt) . '" onclick="return AjaxRequest.toggleFiletree(this,\'' . $xtnode . '_' . $tid . '\',\'' . $currentFolder . '\',\'' . $this->strField . '\',\'' . $this->strName . '\',' . $level . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } $protected = $blnProtected; // Check whether the folder is public if ($protected === true && array_search('.public', $content) !== false) { $protected = false; } $folderImg = $protected ? 'folderCP.svg' : 'folderC.svg'; $folderLabel = $this->files || $this->filesOnly ? '<strong>' . \StringUtil::specialchars(basename($currentFolder)) . '</strong>' : \StringUtil::specialchars(basename($currentFolder)); // Add the current folder $return .= \Image::getHtml($folderImg, '', $folderAttribute) . ' <a href="' . \Backend::addToUrl('fn=' . $this->urlEncode($currentFolder)) . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $folderLabel . '</a></div> <div class="tl_right">'; // Add a checkbox or radio button if (!$this->filesOnly) { switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_checkbox" value="' . \StringUtil::specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFolder) . '" class="tl_tree_radio" value="' . \StringUtil::specialchars($currentFolder) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFolder, $this->varValue) . '>'; break; } } $return .= '</div><div style="clear:both"></div></li>'; // Call the next node if ($blnIsOpen) { $return .= '<li class="parent" id="' . $xtnode . '_' . $tid . '"><ul class="level_' . $level . '">'; $return .= $this->renderFiletree($folders[$f], $intMargin + $intSpacing, false, $protected, $arrFound); $return .= '</ul></li>'; } } // Process files if ($this->files || $this->filesOnly) { for ($h = 0, $c = count($files); $h < $c; $h++) { $thumbnail = ''; $currentFile = str_replace(TL_ROOT . '/', '', $files[$h]); $currentEncoded = $this->urlEncode($currentFile); $objFile = new \File($currentFile); if (!empty($this->arrValidFileTypes) && !in_array($objFile->extension, $this->arrValidFileTypes)) { continue; } // Ignore files not matching the search criteria if (!empty($arrFound) && !in_array($currentFile, $arrFound)) { continue; } $return .= "\n " . '<li class="tl_file toggle_select hover-div"><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; $thumbnail .= ' <span class="tl_gray">(' . $this->getReadableSize($objFile->filesize); if ($objFile->width && $objFile->height) { $thumbnail .= ', ' . $objFile->width . 'x' . $objFile->height . ' px'; } $thumbnail .= ')</span>'; // Generate thumbnail if ($objFile->isImage && $objFile->viewHeight > 0 && \Config::get('thumbnails') && ($objFile->isSvgImage || $objFile->height <= \Config::get('gdMaxImgHeight') && $objFile->width <= \Config::get('gdMaxImgWidth'))) { $imageObj = \Image::create($currentEncoded, array(400, $objFile->height && $objFile->height < 50 ? $objFile->height : 50, 'box')); $importantPart = $imageObj->getImportantPart(); $thumbnail .= '<br>' . \Image::getHtml($imageObj->executeResize()->getResizedPath(), '', 'style="margin:0 0 2px -19px"'); if ($importantPart['x'] > 0 || $importantPart['y'] > 0 || $importantPart['width'] < $objFile->width || $importantPart['height'] < $objFile->height) { $thumbnail .= ' ' . \Image::getHtml($imageObj->setZoomLevel(100)->setTargetWidth(320)->setTargetHeight($objFile->height && $objFile->height < 40 ? $objFile->height : 40)->executeResize()->getResizedPath(), '', 'style="margin:0 0 2px 0;vertical-align:bottom"'); } } $return .= \Image::getHtml($objFile->icon, $objFile->mime) . ' ' . \StringUtil::convertEncoding(\StringUtil::specialchars(basename($currentFile)), \Config::get('characterSet')) . $thumbnail . '</div> <div class="tl_right">'; // Add checkbox or radio button switch ($this->fieldType) { case 'checkbox': $return .= '<input type="checkbox" name="' . $this->strName . '[]" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_checkbox" value="' . \StringUtil::specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; case 'radio': $return .= '<input type="radio" name="' . $this->strName . '" id="' . $this->strName . '_' . md5($currentFile) . '" class="tl_tree_radio" value="' . \StringUtil::specialchars($currentFile) . '" onfocus="Backend.getScrollOffset()"' . $this->optionChecked($currentFile, $this->varValue) . '>'; break; } $return .= '</div><div style="clear:both"></div></li>'; } } return $return; }
/** * Generate the module */ protected function compile() { /** @var PageModel $objPage */ global $objPage; $this->Template->event = ''; $this->Template->referer = 'javascript:history.go(-1)'; $this->Template->back = $GLOBALS['TL_LANG']['MSC']['goBack']; // Get the current event $objEvent = \CalendarEventsModel::findPublishedByParentAndIdOrAlias(\Input::get('events'), $this->cal_calendar); if (null === $objEvent) { throw new PageNotFoundException('Page not found: ' . \Environment::get('uri')); } // Overwrite the page title (see #2853 and #4955) if ($objEvent->title != '') { $objPage->pageTitle = strip_tags(\StringUtil::stripInsertTags($objEvent->title)); } // Overwrite the page description if ($objEvent->teaser != '') { $objPage->description = $this->prepareMetaDescription($objEvent->teaser); } $intStartTime = $objEvent->startTime; $intEndTime = $objEvent->endTime; $span = \Calendar::calculateSpan($intStartTime, $intEndTime); // Do not show dates in the past if the event is recurring (see #923) if ($objEvent->recurring) { $arrRange = \StringUtil::deserialize($objEvent->repeatEach); if (is_array($arrRange) && isset($arrRange['unit']) && isset($arrRange['value'])) { while ($intStartTime < time() && $intEndTime < $objEvent->repeatEnd) { $intStartTime = strtotime('+' . $arrRange['value'] . ' ' . $arrRange['unit'], $intStartTime); $intEndTime = strtotime('+' . $arrRange['value'] . ' ' . $arrRange['unit'], $intEndTime); } } } $strDate = \Date::parse($objPage->dateFormat, $intStartTime); if ($span > 0) { $strDate = \Date::parse($objPage->dateFormat, $intStartTime) . ' – ' . \Date::parse($objPage->dateFormat, $intEndTime); } $strTime = ''; if ($objEvent->addTime) { if ($span > 0) { $strDate = \Date::parse($objPage->datimFormat, $intStartTime) . ' – ' . \Date::parse($objPage->datimFormat, $intEndTime); } elseif ($intStartTime == $intEndTime) { $strTime = \Date::parse($objPage->timeFormat, $intStartTime); } else { $strTime = \Date::parse($objPage->timeFormat, $intStartTime) . ' – ' . \Date::parse($objPage->timeFormat, $intEndTime); } } $until = ''; $recurring = ''; // Recurring event if ($objEvent->recurring) { $arrRange = \StringUtil::deserialize($objEvent->repeatEach); if (is_array($arrRange) && isset($arrRange['unit']) && isset($arrRange['value'])) { $strKey = 'cal_' . $arrRange['unit']; $recurring = sprintf($GLOBALS['TL_LANG']['MSC'][$strKey], $arrRange['value']); if ($objEvent->recurrences > 0) { $until = sprintf($GLOBALS['TL_LANG']['MSC']['cal_until'], \Date::parse($objPage->dateFormat, $objEvent->repeatEnd)); } } } /** @var FrontendTemplate|object $objTemplate */ $objTemplate = new \FrontendTemplate($this->cal_template); $objTemplate->setData($objEvent->row()); $objTemplate->date = $strDate; $objTemplate->time = $strTime; $objTemplate->datetime = $objEvent->addTime ? date('Y-m-d\\TH:i:sP', $intStartTime) : date('Y-m-d', $intStartTime); $objTemplate->begin = $intStartTime; $objTemplate->end = $intEndTime; $objTemplate->class = $objEvent->cssClass != '' ? ' ' . $objEvent->cssClass : ''; $objTemplate->recurring = $recurring; $objTemplate->until = $until; $objTemplate->locationLabel = $GLOBALS['TL_LANG']['MSC']['location']; $objTemplate->details = ''; $objTemplate->hasDetails = false; $objTemplate->hasTeaser = false; // Clean the RTE output if ($objEvent->teaser != '') { $objTemplate->hasTeaser = true; $objTemplate->teaser = \StringUtil::toHtml5($objEvent->teaser); $objTemplate->teaser = \StringUtil::encodeEmail($objTemplate->teaser); } // Display the "read more" button for external/article links if ($objEvent->source != 'default') { $objTemplate->details = true; $objTemplate->hasDetails = true; } else { $id = $objEvent->id; $objTemplate->details = function () use($id) { $strDetails = ''; $objElement = \ContentModel::findPublishedByPidAndTable($id, 'tl_calendar_events'); if ($objElement !== null) { while ($objElement->next()) { $strDetails .= $this->getContentElement($objElement->current()); } } return $strDetails; }; $objTemplate->hasDetails = function () use($id) { return \ContentModel::countPublishedByPidAndTable($id, 'tl_calendar_events') > 0; }; } $objTemplate->addImage = false; // Add an image if ($objEvent->addImage && $objEvent->singleSRC != '') { $objModel = \FilesModel::findByUuid($objEvent->singleSRC); if ($objModel !== null && is_file(TL_ROOT . '/' . $objModel->path)) { // Do not override the field now that we have a model registry (see #6303) $arrEvent = $objEvent->row(); // Override the default image size if ($this->imgSize != '') { $size = \StringUtil::deserialize($this->imgSize); if ($size[0] > 0 || $size[1] > 0 || is_numeric($size[2])) { $arrEvent['size'] = $this->imgSize; } } $arrEvent['singleSRC'] = $objModel->path; $this->addImageToTemplate($objTemplate, $arrEvent); } } $objTemplate->enclosure = array(); // Add enclosures if ($objEvent->addEnclosure) { $this->addEnclosuresToTemplate($objTemplate, $objEvent->row()); } $this->Template->event = $objTemplate->parse(); $bundles = \System::getContainer()->getParameter('kernel.bundles'); // HOOK: comments extension required if ($objEvent->noComments || !isset($bundles['ContaoCommentsBundle'])) { $this->Template->allowComments = false; return; } /** @var CalendarModel $objCalendar */ $objCalendar = $objEvent->getRelated('pid'); $this->Template->allowComments = $objCalendar->allowComments; // Comments are not allowed if (!$objCalendar->allowComments) { return; } // Adjust the comments headline level $intHl = min(intval(str_replace('h', '', $this->hl)), 5); $this->Template->hlc = 'h' . ($intHl + 1); $this->import('Comments'); $arrNotifies = array(); // Notify the system administrator if ($objCalendar->notify != 'notify_author') { $arrNotifies[] = $GLOBALS['TL_ADMIN_EMAIL']; } // Notify the author if ($objCalendar->notify != 'notify_admin') { /** @var UserModel $objAuthor */ if (($objAuthor = $objEvent->getRelated('author')) instanceof UserModel && $objAuthor->email != '') { $arrNotifies[] = $objAuthor->email; } } $objConfig = new \stdClass(); $objConfig->perPage = $objCalendar->perPage; $objConfig->order = $objCalendar->sortOrder; $objConfig->template = $this->com_template; $objConfig->requireLogin = $objCalendar->requireLogin; $objConfig->disableCaptcha = $objCalendar->disableCaptcha; $objConfig->bbcode = $objCalendar->bbcode; $objConfig->moderate = $objCalendar->moderate; $this->Comments->addCommentsToTemplate($this->Template, $objConfig, 'tl_calendar_events', $objEvent->id, $arrNotifies); }
/** * Add a breadcrumb menu to the file tree * * @param string $strKey * * @throws AccessDeniedException * @throws \RuntimeException */ public static function addFilesBreadcrumb($strKey = 'tl_files_node') { /** @var AttributeBagInterface $objSession */ $objSession = \System::getContainer()->get('session')->getBag('contao_backend'); // Set a new node if (isset($_GET['fn'])) { // Check the path (thanks to Arnaud Buchoux) if (\Validator::isInsecurePath(\Input::get('fn', true))) { throw new \RuntimeException('Insecure path ' . \Input::get('fn', true)); } $objSession->set($strKey, \Input::get('fn', true)); \Controller::redirect(preg_replace('/(&|\\?)fn=[^&]*/', '', \Environment::get('request'))); } $strNode = $objSession->get($strKey); if ($strNode == '') { return; } // Check the path (thanks to Arnaud Buchoux) if (\Validator::isInsecurePath($strNode)) { throw new \RuntimeException('Insecure path ' . $strNode); } // Currently selected folder does not exist if (!is_dir(TL_ROOT . '/' . $strNode)) { $objSession->set($strKey, ''); return; } $objUser = \BackendUser::getInstance(); $strPath = \Config::get('uploadPath'); $arrNodes = explode('/', preg_replace('/^' . preg_quote(\Config::get('uploadPath'), '/') . '\\//', '', $strNode)); $arrLinks = array(); // Add root link $arrLinks[] = \Image::getHtml('filemounts.svg') . ' <a href="' . \Backend::addToUrl('fn=') . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectAllNodes']) . '">' . $GLOBALS['TL_LANG']['MSC']['filterAll'] . '</a>'; // Generate breadcrumb trail foreach ($arrNodes as $strFolder) { $strPath .= '/' . $strFolder; // Do not show pages which are not mounted if (!$objUser->hasAccess($strPath, 'filemounts')) { continue; } // No link for the active folder if ($strPath == $strNode) { $arrLinks[] = \Image::getHtml('folderC.svg') . ' ' . $strFolder; } else { $arrLinks[] = \Image::getHtml('folderC.svg') . ' <a href="' . \Backend::addToUrl('fn=' . $strPath) . '" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['selectNode']) . '">' . $strFolder . '</a>'; } } // Check whether the node is mounted if (!$objUser->hasAccess($strNode, 'filemounts')) { $objSession->set($strKey, ''); throw new AccessDeniedException('Folder ID "' . $strNode . '" is not mounted'); } // Limit tree $GLOBALS['TL_DCA']['tl_files']['list']['sorting']['root'] = array($strNode); // Insert breadcrumb menu $GLOBALS['TL_DCA']['tl_files']['list']['sorting']['breadcrumb'] .= ' <ul id="tl_breadcrumb"> <li>' . implode(' > </li><li>', $arrLinks) . '</li> </ul>'; }
/** * Disable the profile */ private function disableProfiler() { $container = \System::getContainer(); if ($container->has('profiler')) { $container->get('profiler')->disable(); } }
/** * Compiles the command required to update the database. */ private function compileCommands() { $return = ['CREATE' => [], 'ALTER_CHANGE' => [], 'ALTER_ADD' => [], 'DROP' => [], 'ALTER_DROP' => []]; $fromSchema = $this->connection->getSchemaManager()->createSchema(); $toSchema = System::getContainer()->get('contao.doctrine.schema_provider')->createSchema(); $diff = $fromSchema->getMigrateToSql($toSchema, $this->connection->getDatabasePlatform()); foreach ($diff as $sql) { switch (true) { case 0 === strpos($sql, 'CREATE TABLE '): $return['CREATE'][md5($sql)] = $sql; break; case 0 === strpos($sql, 'DROP TABLE '): $return['DROP'][md5($sql)] = $sql; break; case 0 === strpos($sql, 'CREATE INDEX '): case 0 === strpos($sql, 'CREATE UNIQUE INDEX '): case 0 === strpos($sql, 'CREATE FULLTEXT INDEX '): $return['ALTER_ADD'][md5($sql)] = $sql; break; case 0 === strpos($sql, 'DROP INDEX'): $return['ALTER_CHANGE'][md5($sql)] = $sql; break; case preg_match('/^(ALTER TABLE [^ ]+) /', $sql, $matches): $prefix = $matches[1]; $sql = substr($sql, strlen($prefix)); $parts = array_map('trim', explode(',', $sql)); foreach ($parts as $part) { $command = $prefix . ' ' . $part; switch (true) { case 0 === strpos($part, 'DROP '): $return['ALTER_DROP'][md5($command)] = $command; break; case 0 === strpos($part, 'ADD '): $return['ALTER_ADD'][md5($command)] = $command; break; case 0 === strpos($part, 'CHANGE '): case 0 === strpos($part, 'RENAME '): $return['ALTER_CHANGE'][md5($command)] = $command; break; default: throw new \RuntimeException(sprintf('Unsupported SQL schema diff: %s', $command)); } } break; default: throw new \RuntimeException(sprintf('Unsupported SQL schema diff: %s', $sql)); } } $this->commands = array_filter($return); }
/** * Ajax actions that do not require a data container object */ public function executePreActions() { /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); switch ($this->strAction) { // Toggle navigation menu case 'toggleNavigation': $bemod = $objSessionBag->get('backend_modules'); $bemod[\Input::post('id')] = intval(\Input::post('state')); $objSessionBag->set('backend_modules', $bemod); throw new NoContentResponseException(); // Load a navigation menu group // Load a navigation menu group case 'loadNavigation': $bemod = $objSessionBag->get('backend_modules'); $bemod[\Input::post('id')] = intval(\Input::post('state')); $objSessionBag->set('backend_modules', $bemod); $this->import('BackendUser', 'User'); /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_navigation'); $navigation = $this->User->navigation(); $objTemplate->modules = $navigation[\Input::post('id')]['modules']; throw new ResponseException($objTemplate->getResponse()); // Toggle nodes of the file or page tree // Toggle nodes of the file or page tree case 'toggleStructure': case 'toggleFileManager': case 'togglePagetree': case 'toggleFiletree': $this->strAjaxId = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', \Input::post('id')); $this->strAjaxKey = str_replace('_' . $this->strAjaxId, '', \Input::post('id')); if (\Input::get('act') == 'editAll') { $this->strAjaxKey = preg_replace('/(.*)_[0-9a-zA-Z]+$/', '$1', $this->strAjaxKey); $this->strAjaxName = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', \Input::post('name')); } $nodes = $objSessionBag->get($this->strAjaxKey); $nodes[$this->strAjaxId] = intval(\Input::post('state')); $objSessionBag->set($this->strAjaxKey, $nodes); throw new NoContentResponseException(); // Load nodes of the file or page tree // Load nodes of the file or page tree case 'loadStructure': case 'loadFileManager': case 'loadPagetree': case 'loadFiletree': $this->strAjaxId = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', \Input::post('id')); $this->strAjaxKey = str_replace('_' . $this->strAjaxId, '', \Input::post('id')); if (\Input::get('act') == 'editAll') { $this->strAjaxKey = preg_replace('/(.*)_[0-9a-zA-Z]+$/', '$1', $this->strAjaxKey); $this->strAjaxName = preg_replace('/.*_([0-9a-zA-Z]+)$/', '$1', \Input::post('name')); } $nodes = $objSessionBag->get($this->strAjaxKey); $nodes[$this->strAjaxId] = intval(\Input::post('state')); $objSessionBag->set($this->strAjaxKey, $nodes); break; // Toggle the visibility of a fieldset // Toggle the visibility of a fieldset case 'toggleFieldset': $fs = $objSessionBag->get('fieldset_states'); $fs[\Input::post('table')][\Input::post('id')] = intval(\Input::post('state')); $objSessionBag->set('fieldset_states', $fs); throw new NoContentResponseException(); // Toggle checkbox groups // Toggle checkbox groups case 'toggleCheckboxGroup': $state = $objSessionBag->get('checkbox_groups'); $state[\Input::post('id')] = intval(\Input::post('state')); $objSessionBag->set('checkbox_groups', $state); break; // HOOK: pass unknown actions to callback functions // HOOK: pass unknown actions to callback functions default: if (isset($GLOBALS['TL_HOOKS']['executePreActions']) && is_array($GLOBALS['TL_HOOKS']['executePreActions'])) { foreach ($GLOBALS['TL_HOOKS']['executePreActions'] as $callback) { $this->import($callback[0]); $this->{$callback[0]}->{$callback[1]}($this->strAction); } } break; } }