/** * Open a back end module and return it as HTML * * @param string $module * * @return string */ protected function getBackendModule($module) { $arrModule = array(); foreach ($GLOBALS['BE_MOD'] as &$arrGroup) { if (isset($arrGroup[$module])) { $arrModule =& $arrGroup[$module]; break; } } $arrInactiveModules = \ModuleLoader::getDisabled(); // Check whether the module is active if (is_array($arrInactiveModules) && in_array($module, $arrInactiveModules)) { $this->log('Attempt to access the inactive back end module "' . $module . '"', __METHOD__, TL_ACCESS); $this->redirect('contao/main.php?act=error'); } $this->import('BackendUser', 'User'); // Dynamically add the "personal data" module (see #4193) if (\Input::get('do') == 'login') { $arrModule = array('tables' => array('tl_user'), 'callback' => 'ModuleUser'); } elseif ($module != 'undo' && !$this->User->hasAccess($module, 'modules')) { $this->log('Back end module "' . $module . '" was not allowed for user "' . $this->User->username . '"', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } $arrTables = (array) $arrModule['tables']; $strTable = \Input::get('table') ?: $arrTables[0]; $id = !\Input::get('act') && \Input::get('id') ? \Input::get('id') : $this->Session->get('CURRENT_ID'); // Store the current ID in the current session if ($id != $this->Session->get('CURRENT_ID')) { $this->Session->set('CURRENT_ID', $id); } define('CURRENT_ID', \Input::get('table') ? $id : \Input::get('id')); $this->Template->headline = $GLOBALS['TL_LANG']['MOD'][$module][0]; // Add the module style sheet if (isset($arrModule['stylesheet'])) { foreach ((array) $arrModule['stylesheet'] as $stylesheet) { $GLOBALS['TL_CSS'][] = $stylesheet; } } // Add module javascript if (isset($arrModule['javascript'])) { foreach ((array) $arrModule['javascript'] as $javascript) { $GLOBALS['TL_JAVASCRIPT'][] = $javascript; } } $dc = null; // Redirect if the current table does not belong to the current module if ($strTable != '') { if (!in_array($strTable, $arrTables)) { $this->log('Table "' . $strTable . '" is not allowed in module "' . $module . '"', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } // Load the language and DCA file \System::loadLanguageFile($strTable); $this->loadDataContainer($strTable); // Include all excluded fields which are allowed for the current user if ($GLOBALS['TL_DCA'][$strTable]['fields']) { foreach ($GLOBALS['TL_DCA'][$strTable]['fields'] as $k => $v) { if ($v['exclude']) { if ($this->User->hasAccess($strTable . '::' . $k, 'alexf')) { if ($strTable == 'tl_user_group') { $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['orig_exclude'] = $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['exclude']; } $GLOBALS['TL_DCA'][$strTable]['fields'][$k]['exclude'] = false; } } } } // Fabricate a new data container object if ($GLOBALS['TL_DCA'][$strTable]['config']['dataContainer'] == '') { $this->log('Missing data container for table "' . $strTable . '"', __METHOD__, TL_ERROR); trigger_error('Could not create a data container object', E_USER_ERROR); } $dataContainer = 'DC_' . $GLOBALS['TL_DCA'][$strTable]['config']['dataContainer']; /** @var \DataContainer $dc */ $dc = new $dataContainer($strTable, $arrModule); } // AJAX request if ($_POST && \Environment::get('isAjaxRequest')) { $this->objAjax->executePostActions($dc); } elseif (class_exists($arrModule['callback'])) { /** @var \Module $objCallback */ $objCallback = new $arrModule['callback']($dc); $this->Template->main .= $objCallback->generate(); } elseif (\Input::get('key') && isset($arrModule[\Input::get('key')])) { $objCallback = new $arrModule[\Input::get('key')][0](); $this->Template->main .= $objCallback->{$arrModule[\Input::get('key')][1]}($dc); // Add the name of the parent element if (isset($_GET['table']) && in_array(\Input::get('table'), $arrTables) && \Input::get('table') != $arrTables[0]) { if ($GLOBALS['TL_DCA'][$strTable]['config']['ptable'] != '') { $objRow = $this->Database->prepare("SELECT * FROM " . $GLOBALS['TL_DCA'][$strTable]['config']['ptable'] . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } } // Add the name of the submodule $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][\Input::get('key')][1], \Input::get('id')); } elseif (is_object($dc)) { $act = \Input::get('act'); if ($act == '' || $act == 'paste' || $act == 'select') { $act = $dc instanceof \listable ? 'showAll' : 'edit'; } switch ($act) { case 'delete': case 'show': case 'showAll': case 'undo': if (!$dc instanceof \listable) { $this->log('Data container ' . $strTable . ' is not listable', __METHOD__, TL_ERROR); trigger_error('The current data container is not listable', E_USER_ERROR); } break; case 'create': case 'cut': case 'cutAll': case 'copy': case 'copyAll': case 'move': case 'edit': if (!$dc instanceof \editable) { $this->log('Data container ' . $strTable . ' is not editable', __METHOD__, TL_ERROR); trigger_error('The current data container is not editable', E_USER_ERROR); } break; } $strFirst = null; $strSecond = null; // Handle child child tables (e.g. tl_style) if (isset($GLOBALS['TL_DCA'][$strTable]['config']['ptable'])) { $ptable = $GLOBALS['TL_DCA'][$strTable]['config']['ptable']; if (in_array($ptable, $arrTables)) { $this->loadDataContainer($ptable); if (isset($GLOBALS['TL_DCA'][$ptable]['config']['ptable'])) { $ftable = $GLOBALS['TL_DCA'][$ptable]['config']['ptable']; if (in_array($ftable, $arrTables)) { $strFirst = $ftable; $strSecond = $ptable; } } } } // Build the breadcrumb trail if ($strFirst !== null && $strSecond !== null) { if (!isset($_GET['act']) || \Input::get('act') == 'paste' && \Input::get('mode') == 'create' || \Input::get('act') == 'select' || \Input::get('act') == 'editAll' || \Input::get('act') == 'overrideAll') { if ($strTable == $strSecond) { $strQuery = "SELECT * FROM {$strFirst} WHERE id=?"; } else { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=?)"; } } else { if ($strTable == $strSecond) { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=?)"; } else { $strQuery = "SELECT * FROM {$strFirst} WHERE id=(SELECT pid FROM {$strSecond} WHERE id=(SELECT pid FROM {$strTable} WHERE id=?))"; } } // Add the first level name $objRow = $this->Database->prepare($strQuery)->limit(1)->execute($dc->id); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } if (isset($GLOBALS['TL_LANG']['MOD'][$strSecond])) { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MOD'][$strSecond]; } // Add the second level name $objRow = $this->Database->prepare("SELECT * FROM {$strSecond} WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } else { // Add the name of the parent element if ($strTable && in_array($strTable, $arrTables) && $strTable != $arrTables[0]) { if ($GLOBALS['TL_DCA'][$strTable]['config']['ptable'] != '') { $objRow = $this->Database->prepare("SELECT * FROM " . $GLOBALS['TL_DCA'][$strTable]['config']['ptable'] . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objRow->title != '') { $this->Template->headline .= ' » ' . $objRow->title; } elseif ($objRow->name != '') { $this->Template->headline .= ' » ' . $objRow->name; } } } // Add the name of the submodule if ($strTable && isset($GLOBALS['TL_LANG']['MOD'][$strTable])) { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MOD'][$strTable]; } } // Add the current action if (\Input::get('act') == 'editAll') { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MSC']['all'][0]; } elseif (\Input::get('act') == 'overrideAll') { $this->Template->headline .= ' » ' . $GLOBALS['TL_LANG']['MSC']['all_override'][0]; } else { if (\Input::get('id')) { if (\Input::get('do') == 'files' || \Input::get('do') == 'tpl_editor') { // Handle new folders (see #7980) if (strpos(\Input::get('id'), '__new__') !== false) { $this->Template->headline .= ' » ' . dirname(\Input::get('id')) . ' » ' . $GLOBALS['TL_LANG'][$strTable]['new'][1]; } else { $this->Template->headline .= ' » ' . \Input::get('id'); } } elseif (is_array($GLOBALS['TL_LANG'][$strTable][$act])) { $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][$act][1], \Input::get('id')); } } elseif (\Input::get('pid')) { if (\Input::get('do') == 'files' || \Input::get('do') == 'tpl_editor') { $this->Template->headline .= ' » ' . \Input::get('pid'); } elseif (is_array($GLOBALS['TL_LANG'][$strTable][$act])) { $this->Template->headline .= ' » ' . sprintf($GLOBALS['TL_LANG'][$strTable][$act][1], \Input::get('pid')); } } } return $dc->{$act}(); } return null; }
/** * Generate the navigation menu and return it as array * * @param boolean $blnShowAll * * @return array */ public function navigation($blnShowAll = false) { $arrModules = array(); $session = $this->Session->getData(); // 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; $this->Session->setData($session); \Controller::redirect(preg_replace('/(&(amp;)?|\\?)mtg=[^& ]*/i', '', \Environment::get('request'))); } $arrInactiveModules = \ModuleLoader::getDisabled(); $blnCheckInactiveModules = is_array($arrInactiveModules); 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) { // Exclude inactive modules if ($blnCheckInactiveModules && in_array($strModuleName, $arrInactiveModules)) { continue; } // 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; }
/** * Create the config cache files */ public function generateConfigCache() { // Generate the class/template laoder cache file $objCacheFile = new \File('system/cache/config/autoload.php', true); $objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error foreach (\ModuleLoader::getActive() as $strModule) { $strFile = 'system/modules/' . $strModule . '/config/autoload.php'; if (file_exists(TL_ROOT . '/' . $strFile)) { $objCacheFile->append(static::readPhpFileWithoutTags($strFile)); } } // Close the file (moves it to its final destination) $objCacheFile->close(); // Generate the module loader cache file $objCacheFile = new \File('system/cache/config/modules.php', true); $objCacheFile->write("<?php\n\n"); $objCacheFile->append(sprintf("static::\$active = %s;\n", var_export(\ModuleLoader::getActive(), true))); $objCacheFile->append(sprintf("static::\$disabled = %s;", var_export(\ModuleLoader::getDisabled(), true))); // Close the file (moves it to its final destination) $objCacheFile->close(); // Generate the config cache file $objCacheFile = new \File('system/cache/config/config.php', true); $objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error foreach (\ModuleLoader::getActive() as $strModule) { $strFile = 'system/modules/' . $strModule . '/config/config.php'; if (file_exists(TL_ROOT . '/' . $strFile)) { $objCacheFile->append(static::readPhpFileWithoutTags($strFile)); } } // Close the file (moves it to its final destination) $objCacheFile->close(); // Generate the page mapping array $arrMapper = array(); $objPages = \PageModel::findPublishedRootPages(); if ($objPages !== null) { while ($objPages->next()) { $strBase = $objPages->dns ?: '*'; if ($objPages->fallback) { $arrMapper[$strBase . '/empty.fallback'] = $strBase . '/empty.' . $objPages->language; } $arrMapper[$strBase . '/empty.' . $objPages->language] = $strBase . '/empty.' . $objPages->language; } } // Generate the page mapper file $objCacheFile = new \File('system/cache/config/mapping.php', true); $objCacheFile->write(sprintf("<?php\n\nreturn %s;\n", var_export($arrMapper, true))); $objCacheFile->close(); // Add a log entry $this->log('Generated the config cache', __METHOD__, TL_CRON); }
/** * check module access * * @param $module * * @return bool */ protected function hasAccess($module) { $arrModule = array(); foreach ($GLOBALS['BE_MOD'] as &$arrGroup) { if (isset($arrGroup[$module])) { $arrModule =& $arrGroup[$module]; break; } } $arrInactiveModules = \ModuleLoader::getDisabled(); // Check whether the module is active if (is_array($arrInactiveModules) && in_array($module, $arrInactiveModules)) { return false; } $this->import('BackendUser', 'User'); // Check whether the current user has access to the current module if (!$this->User->hasAccess($module, 'modules')) { return false; } return true; }
/** * Create the config cache files */ public function generateConfigCache() { // Generate the class/template laoder cache file $objCacheFile = new \File('system/cache/config/autoload.php', true); $objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error foreach (\ModuleLoader::getActive() as $strModule) { $strFile = 'system/modules/' . $strModule . '/config/autoload.php'; if (file_exists(TL_ROOT . '/' . $strFile)) { $objCacheFile->append(static::readPhpFileWithoutTags($strFile)); } } // Close the file (moves it to its final destination) $objCacheFile->close(); // Generate the module loader cache file $objCacheFile = new \File('system/cache/config/modules.php', true); $objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error $strContent = "\n\n"; $strContent .= "/**\n * Active modules\n */\n"; $strContent .= "static::\$active = array\n"; $strContent .= "(\n"; foreach (\ModuleLoader::getActive() as $strModule) { $strContent .= "\t'{$strModule}',\n"; } $strContent .= ");\n\n"; $strContent .= "/**\n * Disabled modules\n */\n"; $strContent .= "static::\$disabled = array\n"; $strContent .= "(\n"; foreach (\ModuleLoader::getDisabled() as $strModule) { $strContent .= "\t'{$strModule}',\n"; } $strContent .= ");"; $objCacheFile->append($strContent); // Close the file (moves it to its final destination) $objCacheFile->close(); // Generate the config cache file $objCacheFile = new \File('system/cache/config/config.php', true); $objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error foreach (\ModuleLoader::getActive() as $strModule) { $strFile = 'system/modules/' . $strModule . '/config/config.php'; if (file_exists(TL_ROOT . '/' . $strFile)) { $objCacheFile->append(static::readPhpFileWithoutTags($strFile)); } } // Close the file (moves it to its final destination) $objCacheFile->close(); // Add a log entry $this->log('Generated the autoload cache', __METHOD__, TL_CRON); }