edit = ConfigModule::get($editId); if (self::$instance->edit === null) ErrorHandler::traceError('Invalid module id for editing'); if ($step !== 'AddModule_Assign' && !preg_match('/^' . self::$instance->edit->moduleType() . '_/', $step)) ErrorHandler::traceError('Module to edit is of different type!'); Util::addRedirectParam('edit', self::$instance->edit->id()); } } protected function tmError() { Message::addError('main.taskmanager-error'); Util::redirect('?do=SysConfig'); } protected function taskError($status) { if (isset($status['data']['error'])) { $error = $status['data']['error']; } elseif (isset($status['statusCode'])) { $error = $status['statusCode']; } else { $error = Dictionary::translate('lang_unknwonTaskManager'); } Message::addError('main.task-error', $error); Util::redirect('?do=SysConfig'); } /** * Called before any HTML rendering happens, so you can * prepare stuff, validate input, and optionally redirect * early if something is wrong, or you received post * data etc. */ protected function preprocessInternal() { // void } /** * Do page rendering. */ protected function renderInternal() { // void } /** * Handle ajax stuff */ protected function ajaxInternal() { // void } public static function preprocess() { if (self::$instance === false) { ErrorHandler::traceError('No step instance yet'); } self::$instance->preprocessInternal(); } public static function render() { if (self::$instance === false) { ErrorHandler::traceError('No step instance yet'); } if (get_class(self::$instance) !== 'AddModule_Assign' && self::$instance->edit !== null) { Message::addInfo('replacing-module', self::$instance->edit->title()); } self::$instance->renderInternal(); } public static function ajax() { if (self::$instance === false) { ErrorHandler::traceError('No step instance yet'); } self::$instance->ajaxInternal(); } } /** * Start dialog for adding module. Here the user * selects which kind of module they want to add. */ class AddModule_Start extends AddModule_Base { protected function renderInternal() { $title = $order = array(); $mods = ConfigModule::getList(); foreach ($mods as $module) { $title[] = $module['title']; $order[] = $module['sortOrder']; } array_multisort($order, SORT_ASC, $title, SORT_ASC, $mods); Render::addDialog(Dictionary::translate('lang_moduleAdd'), false, 'start', array('modules' => array_values($mods))); } } /** * End dialog for adding module. Here the user * can assign the module to configs. */ class AddModule_Assign extends AddModule_Base { protected function preprocessInternal() { if (!User::hasPermission('config.edit')) Util::redirect('?do=SysConfig', false, true); $assign = Request::any('assign', false, 'boolean'); if ($assign) { $configIds = Request::any('configs', [], 'array'); $moduleId = $this->edit->id(); $moduleType = $this->edit->moduleType(); if (ConfigModule::getList()[$moduleType]['unique']) { // Is a unique type module $moduleIds = []; foreach (ConfigModule::getAll($moduleType) ?? [] as $module) { $moduleIds[] = $module->id(); } // First, delete all modules of given type from all involved configs Database::exec("DELETE FROM configtgz_x_module WHERE configid IN (:configids) AND moduleid IN (:moduleids) AND moduleid <> :moduleid", ['configids' => $configIds, 'moduleids' => $moduleIds, 'moduleid' => $moduleId]); } // Not delete module from all configs that are not selected Database::exec("DELETE FROM configtgz_x_module WHERE moduleid = :moduleid AND configid NOT IN (:configids)", ['configids' => $configIds, 'moduleid' => $moduleId]); // Finally, (re)insert for all configs selected foreach ($configIds as $configId) { Database::exec("INSERT IGNORE INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array( 'configid' => $configId, 'moduleid' => $moduleId )); $config = ConfigTgz::get($configId); $config->markOutdated(); $config->generate(); } Util::redirect('?do=SysConfig', false, true); } } protected function renderInternal() { $data = ['configs' => SysConfig::getAll()]; if (count($data['configs']) === 0) // Nothing to do Util::redirect('?do=SysConfig', false, true); $moduleType = $this->edit->moduleType(); // If this is a module of type unique, mark all configs that already contain a module of that type if (ConfigModule::getList()[$moduleType]['unique']) { $modules = Database::queryAll("SELECT cm.moduleid as moduleid, cm.title as title, cxm.configid as configid FROM configtgz_module cm INNER JOIN configtgz_x_module cxm ON (cm.moduleid = cxm.moduleid) WHERE cm.moduletype = :moduletype AND cxm.moduleid <> :moduleid", ['moduletype' => $moduleType, 'moduleid' => $this->edit->id()]); $modulesByConfigId = []; foreach ($modules as $module) { $modulesByConfigId[$module['configid']] = $module; } foreach ($data['configs'] as &$config) { if (!isset($modulesByConfigId[$config['configid']])) continue; $config['replaces'] = $modulesByConfigId[$config['configid']]['title']; } } // Pre-check those that are already included $tgzs = []; foreach (ConfigTgz::getAllForModule($this->edit->id()) as $tgz) { $tgzs[$tgz->id()] = 1; } foreach ($data['configs'] as &$config) { if (!isset($tgzs[$config['configid']])) continue; $config['checked'] = 'checked'; } $data['edit'] = $this->edit->id(); $data['name'] = $this->edit->title(); Render::addDialog(Dictionary::translate('lang_moduleAssign'), false, 'assign', $data); } } /* * Helper functions to set/get a batch of vars from/to post variables or a module */ function moduleToArray(ConfigModule $module, array &$array, array $keys): void { foreach ($keys as $key) { $array[$key] = $module->getData($key); } } function arrayToModule(ConfigModule $module, array $array, array $keys): void { foreach ($keys as $key) { $module->setData($key, $array[$key]); } } function postToArray(array &$array, array $keys, $ignoreMissing = false): void { foreach ($keys as $key) { $val = Request::post($key, '--not-in-post'); if ($ignoreMissing && $val === '--not-in-post') continue; $array[$key] = $val; } }