summaryrefslogblamecommitdiffstats
path: root/modules-available/sysconfig/addmodule.inc.php
blob: 32752c03e6763f5db47516ce7d44b60c068a7f37 (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                         
                                                              

                              

                                         


                                                                                     

                             
           
                               
 
           
           
                                                                          
                                                                                   
           
                                                                              
         


                                                                                                           
                 
                                              



                                                                 
                                                                           
                                                           
                                                                                          
                                                                                                                                  
                                                                                                 

                                                                                    
         
 

                                    
                                                            
                                                
         
 






                                                          
                                                                                  
                 
                                                             
                                                



                                                               
                                                                 


                                                            
                                               




                       
                             
           
                                           


                       
        







                                         
                                           
         
                                                
                                                                         
                 
                                                      

         
                                       
         
                                                
                                                                         
                 
                                                                                                          
                                                                                             
                 
                                                  
         



                                                
                                                                         


                                                


 




                                                 
 

                                           
         
                                          
                                                
                                            

                                                        
                 
                                                                           
                                                                                                                                    
         
 
 
 








                                               


                                                                     







                                                                             
                                                          
                                                
                                                                                              

                                                                     





                                                                                                                                 
                         


                                                                                                                                    
 
                                                                       
                                                           
                                                                                                                                                 


                                                                


                                                                    

                         
                                                                     




                                           
                                                           

                                                                     

                                                        
                                                                                                                  
                                                                     




                                                                                                                                  






                                                                                  

                                                                                    


                                                                                                       









                                                                                 

                                                  
                                                     




                                                                                                      



                                                                                 
                                                                              





                                                      
                                                                             




                                                     

                                                                              


                                                            

                                                               


                                    
<?php

/**
 * Addmodule subpage base - makes sure
 * we have the two required methods preprocess and render
 */
abstract class AddModule_Base
{

	/**
	 * Holds the instance for the currently executing step
	 *
	 * @var AddModule_Base
	 */
	private static $instance = false;
	
	/**
	 * Instance of ConfigModule we're editing. False if not editing but creating.
	 *
	 * @var ?ConfigModule
	 */
	protected $edit = null;

	/**
	 * 
	 * @param string $step name of class representing the current step
	 * @param int $editId (optional) overwrite for the request parameter 'edit'
	 */
	public static function setStep(string $step, int $editId = null): void
	{
		if (empty($step) || !class_exists($step) || get_parent_class($step) !== 'AddModule_Base') {
			Message::addError('invalid-action', $step);
			Util::redirect('?do=SysConfig');
		}
		self::$instance = new $step();
		if ($editId === null) {
			$editId = Request::any('edit', 0, 'int');
		}
		if ($editId !== 0) {
			self::$instance->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;
	}
}