summaryrefslogblamecommitdiffstats
path: root/modules-available/locationinfo/page.inc.php
blob: 333e5c48d399a981cc5474b182c9516738f91f2a (plain) (tree)
1
2
3
4
5
6
7




                                    

                        





                                                                                         



                                                                      
 
                                                           
                                                        




                                                                    

                                                             
                                                                
                                                                                    

                                                                     



                                                                                   



                                                                   
                 






                                                                                        













                                                                               

         
           

                                          

                                       




                                                                
                                                                                                                  

         
                                      
         




                                                                                             
 








                                                                                 
                                                                                       
                                     
                 

                                                                
                                         
                 
                                                                                    
 








                                                                               







































                                                                                                                                                   

                                                                                                                                                                         
                                                                                                          
                                            
                                                            
                                                
                                                        
                                                                
                                                         
                   

















                                                                                                                               


































































                                                                                                                         
 

                                                    

         


                                                 

                                               

                                                                         
                                                                  
                                                                   





                                                                                
                                                                     

                                           
                                                  
                                                                                                     
                 
                                
                                              



                                                                      
                                                                                                                      
                                                                                       
                                                                         
                        
                                                  
                                                                           
                                                                                                              

                                                                        
                 

         
           



                                                                       
                                                       
         

                                                                                     
                 
 
                                                                                
                                                                 
                                                                                             
 

                                                                                      
                                                                                                                    

                               
                                                                                                                         
 


                                                                           
 
                                                                                     

         


                                                                                          
                                              
         
                                                       
                                       

                                                   
                                                                       
                                                                           
                 
 
                                                                                 
                                      
                                                                                                
                                                                   





                                                                                    







                                                                                         
                                 
                                                                                                             
                         
                                             

                 
                                                           
                                                          
                                                    


                   




                                                                       


                                                                                                                                                              


                                                                  




                                                                                                     
                                                    

                                                         



                                                                                           















                                                                                                       




                                                            
           

               






                                                 
                                                   

                                                       
                                                         
                                                       


                 


                                    
                                  
           

                                                
                                                                                             
                                                                                                             
 
                                     




                                                                                       




                                                       
                                                                          








                                                                                                      
                                        
                                                               
                                 


                                                                                                                            
                         
                                                     
                 
                                                                           

                                                                     

                                                                 

         




                                        
                                                
         


                                                                                                                                                                                  

                                                                                         
                 
                                                                        

                                                
 


















                                                                                                                                  





                                                                                                                                    
                         
                                             
                 










                                                                                                  

         
           



                                                                 
          

                                                                 
           
                                              
         

                                    

























                                                                                      
                 





























































                                                                                                                                             
         
 




                                         
                                          
         
                                                                 
                                          




                                                                                         

                 
                                                                                                                                   
 




                                                                  
                 
 
                                                               
                                    











                                                                                             
                   
         
 
 
<?php

class Page_LocationInfo extends Page
{

	private $action;

	/**
	 * Called before any page rendering happens - early hook to check parameters etc.
	 */
	protected function doPreprocess()
	{
		User::load();
		if (!User::isLoggedIn()) {
			Message::addError('main.no-permission');
			Util::redirect('?do=Main'); // does not return
		}

		$show = Request::any('show', '', 'string');
		$this->action = Request::post('action');
		if ($this->action === 'writePanelConfig') {
			$this->writePanelConfig();
		} elseif ($this->action === 'writeLocationConfig') {
			$this->writeLocationConfig();
			$show = 'locations';
		} elseif ($this->action === 'deleteServer') {
			$this->deleteServer();
		} elseif ($this->action === 'checkConnection') {
			$this->checkConnection(Request::post('serverid', 0, 'int'));
		} elseif ($this->action === 'updateServerSettings') {
			$this->updateServerSettings();
		} elseif (Request::isPost()) {
			Messages::addWarning('main.invalid-action', $this->action);
		}
		if (Request::isPost()) {
			if (!empty($show)) {
				$show = '&show=' . $show;
			}
			Util::redirect('?do=locationinfo' . $show);
		}
	}

	/**
	 * Menu etc. has already been generated, now it's time to generate page content.
	 */
	protected function doRender()
	{
		$show = Request::get('show', '', 'string');
		switch ($show) {
		case 'locations':
			$this->showLocationsTable();
			break;
		case 'edit-panel':
			$this->showConfigPanel();
			break;
		case '':
			$this->showInfoScreenTable();
			break;
		default:
			Message::addError('main.value-invalid', 'show', $show);
		}
	}

	/**
	 * Deletes the server from the db.
	 */
	private function deleteServer()
	{
		$id = Request::post('serverid', false, 'int');
		if ($id === false) {
			Messages::addError('server-id-missing');
			return;
		}
		Database::exec("DELETE FROM `locationinfo_coursebackend` WHERE serverid=:id", array('id' => $id));
	}

	private function getTime($str)
	{
		$str = explode(':', $str);
		if (count($str) !== 2) return false;
		if ($str[0] < 0 || $str[0] > 23 || $str[1] < 0 || $str[1] > 59) return false;
		return $str[0] * 60 + $str[1];
	}

	private function writeLocationConfig()
	{
		// Check locations
		$locationid = Request::post('locationid', false, 'int');
		if ($locationid === false) {
			Message::addError('main.paramter-missing', 'locationid');
			return false;
		}
		if (Location::get($locationid) === false) {
			Message::addError('location.invalid-location-id', $locationid);
			return false;
		}
		$serverid = Request::post('serverid', 0, 'int');
		if ($serverid === 0) {
			$serverid = null;
		}
		$serverlocationid = Request::post('serverlocationid', '', 'string');

		$recursive = (Request::post('recursive', '', 'string') !== '');
		if (empty($serverlocationid) && !$recursive) {
			$insertServerId = null;
			$ignoreServer = 1;
		} else {
			$insertServerId = $serverid;
			$ignoreServer = 0;
		}

		// Opening times
		$openingtimes = Request::post('openingtimes', '', 'string');
		if ($openingtimes !== '') {
			$openingtimes = json_decode($openingtimes, true);
			if (!is_array($openingtimes)) {
				$openingtimes = '';
			} else {
				$mangled = array();
				foreach (array_keys($openingtimes) as $key) {
					$entry = $openingtimes[$key];
					if (!isset($entry['days']) || !is_array($entry['days']) || empty($entry['days'])) {
						Message::addError('ignored-line-no-days');
						continue;
					}
					$s = $this->getTime($entry['openingtime']);
					$e = $this->getTime($entry['closingtime']);
					if ($s === false) {
						Message::addError('ignored-invalid-start', $entry['openingtime']);
						continue;
					}
					if ($e === false) {
						Message::addError('ignored-invalid-end', $entry['closingtime']);
						continue;
					}
					if ($e <= $s) {
						Message::addError('ignored-invalid-range', $entry['openingtime'], $entry['closingtime']);
						continue;
					}
					unset($entry['tag']);
					$mangled[] = $entry;
				}
				if (empty($mangled)) {
					$openingtimes = '';
				} else {
					$openingtimes = json_encode($mangled);
				}
			}
		}

		Database::exec("INSERT INTO `locationinfo_locationconfig` (locationid, serverid, serverlocationid, openingtime, lastcalendarupdate)
				VALUES (:id, :insertserverid, :serverlocationid, :openingtimes, 0)
				ON DUPLICATE KEY UPDATE serverid = IF(:ignore_server AND serverid IS NULL, NULL, :serverid), serverlocationid = VALUES(serverlocationid),
					openingtime = VALUES(openingtime), lastcalendarupdate = 0", array(
			'id' => $locationid,
			'insertserverid' => $insertServerId,
			'serverid' => $serverid,
			'openingtimes' => $openingtimes,
			'serverlocationid' => $serverlocationid,
			'ignore_server' => $ignoreServer,
		));

		if (!$recursive)
			return true;

		// Recursive overwriting of serverid
		$children = Location::getRecursiveFlat($locationid);
		$array = array();
		foreach ($children as $loc) {
			$array[] = $loc['locationid'];
		}
		if (!empty($array)) {
			Database::exec("UPDATE locationinfo_locationconfig
				SET serverid = :serverid, lastcalendarupdate = IF(serverid <> :serverid, 0, lastcalendarupdate)
				WHERE locationid IN (:locations)", array(
					'serverid' => $serverid,
					'locations' => $array,
			));
		}
		return true;
	}

	/**
	 * Updated the config in the db.
	 */
	private function writePanelConfig()
	{
		// UUID - existing or new
		$paneluuid = Request::post('paneluuid', false, 'string');
		if (($paneluuid === false || strlen($paneluuid) !== 36) && $paneluuid !== 'new') {
			Message::addError('invalid-panel-id', $paneluuid);
			Util::redirect('?do=locationinfo');
		}
		// Check locations
		$locationids = Request::post('locationids', false, 'array');
		if ($locationids === false) {
			Message::addError('main.paramter-missing', 'locationids');
			Util::redirect('?do=locationinfo');
		}
		$all = array_map(function ($item) { return $item['locationid']; }, Location::queryLocations());
		$locationids = array_filter($locationids, function ($item) use ($all) { return in_array($item, $all); });
		if (empty($locationids)) {
			Message::addError('main.paramter-empty', 'locationids');
			Util::redirect('?do=locationinfo');
		}
		if (count($locationids) > 4) {
			$locationids = array_slice($locationids, 0, 4);
		}
		// Build json struct
		$conf = array(
			'ts' => time(),
			'language' => Request::post('language', 'en', 'string'),
			'mode' => Request::post('mode', 1, 'int'),
			'vertical' => Request::post('vertical', false, 'bool'),
			'eco' => Request::post('eco', false, 'bool'),
			'scaledaysauto' => Request::post('scaledaysauto', false, 'bool'),
			'daystoshow' => Request::post('daystoshow', 7, 'int'),
			'rotation' => Request::post('rotation', 0, 'int'),
			'scale' => Request::post('scale', 50, 'int'),
			'switchtime' => Request::post('switchtime', 20, 'int'),
			'calupdate' => Request::post('calupdate', 120, 'int'),
			'roomupdate' => Request::post('roomupdate', 30, 'int'),
			'configupdate' => Request::post('configupdate', 180, 'int'),
		);
		if ($conf['roomupdate'] < 30) {
			$conf['roomupdate'] = 30;
		}
		if ($conf['calupdate'] < 120) {
			$conf['calupdate'] = 120;
		}

		if ($paneluuid === 'new') {
			$paneluuid = Util::randomUuid();
			$query = "INSERT INTO `locationinfo_panel` (paneluuid, locationids, paneltype, panelconfig)
				VALUES (:id, :locationids, :type, :config)";
		} else {
			$query = "UPDATE `locationinfo_panel`
				SET locationids = :locationids, paneltype = :type, panelconfig = :config
				WHERE paneluuid = :id";
		}
		Database::exec($query, array(
			'id' => $paneluuid,
			'locationids' => implode(',', $locationids),
			'type' => 'DEFAULT', // TODO
			'config' => json_encode($conf),
		));

		Message::addSuccess('config-saved');
		Util::redirect('?do=locationinfo');
	}

	/**
	 * Updates the server settings in the db.
	 */
	private function updateServerSettings()
	{
		$serverid = Request::post('id', -1, 'int');
		$servername = Request::post('name', 'unnamed', 'string');
		$servertype = Request::post('type', '', 'string');
		$backend = CourseBackend::getInstance($servertype);

		if ($backend === false) {
			Messages::addError('invalid-backend-type', $servertype);
			Util::redirect('?do=locationinfo');
		}

		$tmptypeArray = $backend->getCredentialDefinitions();

		$credentialsJson = array();
		foreach ($tmptypeArray as $cred) {
			$credentialsJson[$cred->property] = Request::post('prop-' . $cred->property);
		}
		$params = array(
			'name' => $servername,
			'type' => $servertype,
			'credentials' => json_encode($credentialsJson)
		);
		if ($serverid === 0) {
			Database::exec('INSERT INTO `locationinfo_coursebackend` (servername, servertype, credentials)
					VALUES (:name, :type, :credentials)', $params);
			$this->checkConnection(Database::lastInsertId());
		} else {
			$params['id'] = $serverid;
			Database::exec('UPDATE `locationinfo_coursebackend`
					SET servername = :name, servertype = :type, credentials = :credentials
					WHERE serverid = :id', $params);
			$this->checkConnection($serverid);
		}
	}

	/**
	 * Checks if the server connection to a backend is valid.
	 *
	 * @param int $id Server id which connection should be checked.
	 */
	private function checkConnection($serverid = 0)
	{
		if ($serverid === 0) {
			Util::traceError('checkConnection called with no server id');
		}

		$dbresult = Database::queryFirst("SELECT servertype, credentials
				FROM `locationinfo_coursebackend`
				WHERE serverid = :serverid", array('serverid' => $serverid));

		$serverInstance = CourseBackend::getInstance($dbresult['servertype']);
		if ($serverInstance === false) {
			LocationInfo::setServerError($serverid, 'Unknown backend type: ' . $dbresult['servertype']);
			return;
		}
		$credentialsOk = $serverInstance->setCredentials($serverid, json_decode($dbresult['credentials'], true));

		if ($credentialsOk) {
			$connectionOk = $serverInstance->checkConnection();
		}

		LocationInfo::setServerError($serverid, $serverInstance->getError());
	}

	/**
	 * Loads the Infoscreen page in the admin-panel and passes all needed information.
	 */
	private function showInfoScreenTable()
	{
		// Get a list of all the backend types.
		$servertypes = array();
		$s_list = CourseBackend::getList();
		foreach ($s_list as $s) {
			$typeInstance = CourseBackend::getInstance($s);
			$servertypes[$s] = $typeInstance->getDisplayName();
		}

		// Get the Serverlist from the DB and make it mustache accessable
		$serverlist = array();
		$dbquery2 = Database::simpleQuery("SELECT * FROM `locationinfo_coursebackend`");
		while ($row = $dbquery2->fetch(PDO::FETCH_ASSOC)) {
			if (isset($servertypes[$row['servertype']])) {
				$row['typename'] = $servertypes[$row['servertype']];
			} else {
				$row['typename'] = '[' . $row['servertype'] . ']';
				$row['disabled'] = 'disabled';
			}

			if (!empty($row['error'])) {
				$row['autherror'] = true;
				$error = json_decode($row['error'], true);
				if (isset($error['timestamp'])) {
					$time = date('Y/m/d H:i:s', $error['timestamp']);
				} else {
					$time = '???';
				}
				Message::addError('auth-failed', $row['servername'], $time, $error['error']);
			}
			$serverlist[] = $row;
		}

		// Pass the data to the html and render it.
		Render::addTemplate('page-servers', array(
			'serverlist' => $serverlist,
		));
	}

	private function showLocationsTable()
	{
		$locations = Location::getLocations(0, 0, false, true);

		// Get hidden state of all locations
		$dbquery = Database::simpleQuery("SELECT li.locationid, li.serverid, li.serverlocationid, li.openingtime, li.lastcalendarupdate, cb.servername
			FROM `locationinfo_locationconfig` AS li
			LEFT JOIN `locationinfo_coursebackend` AS cb USING (serverid)");

		while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) {
			$locid = (int)$row['locationid'];
			$glyph = !empty($row['openingtime']) ? 'ok' : '';
			$backend = '';
			if (!empty($row['serverid']) && !empty($row['serverlocationid'])) {
				$backend = $row['servername'] . '(' . $row['serverlocationid'] . ')';
			}
			$locations[$locid] += array(
				'openingGlyph' => $glyph,
				'backend' => $backend,
				'lastCalendarUpdate' => $row['lastcalendarupdate'], // TODO
			);
		}

		$stack = array();
		$depth = -1;
		foreach ($locations as &$location) {
			while ($location['depth'] <= $depth) {
				array_pop($stack);
				$depth--;
			}
			while ($location['depth'] > $depth) {
				$depth++;
				array_push($stack, empty($location['openingGlyph']) ? '' : 'arrow-up');
			}
			if ($depth > 0 && empty($location['openingGlyph'])) {
				$location['openingGlyph'] = $stack[$depth - 1];
			}
		}

		Render::addTemplate('page-locations', array(
			'list' => array_values($locations),
		));
	}

	/**
	 * AJAX
	 */
	protected function doAjax()
	{
		User::load();
		if (!User::isLoggedIn()) {
			die('Unauthorized');
		}
		$action = Request::any('action');
		$id = Request::any('id', 0, 'int');
		if ($action === 'config-location') {
			$this->ajaxConfigLocation($id);
		} elseif ($action === 'serverSettings') {
			$this->ajaxServerSettings($id);
		}
	}

	/**
	 * Ajax the server settings.
	 *
	 * @param int $id Serverid
	 */
	private function ajaxServerSettings($id)
	{
		$oldConfig = Database::queryFirst('SELECT servername, servertype, credentials
				FROM `locationinfo_coursebackend` WHERE serverid = :id', array('id' => $id));

		// Credentials stuff.
		if ($oldConfig !== false) {
			$oldCredentials = json_decode($oldConfig['credentials'], true);
		} else {
			$oldCredentials = array();
		}

		// Get a list of all the backend types.
		$serverBackends = array();
		$s_list = CourseBackend::getList();
		foreach ($s_list as $s) {
			$backendInstance = CourseBackend::getInstance($s);
			$backend = array(
				'backendtype' => $s,
				'display' => $backendInstance->getDisplayName(),
				'active' => ($oldConfig !== false && $s === $oldConfig['servertype']),
			);
			$backend['credentials'] = $backendInstance->getCredentialDefinitions();
			foreach ($backend['credentials'] as $cred) {
				if ($backend['active'] && isset($oldCredentials[$cred->property])) {
					$cred->initForRender($oldCredentials[$cred->property]);
				} else {
					$cred->initForRender();
				}
				$cred->title = Dictionary::translateFile('backend-' . $s, $cred->property, true);
				$cred->helptext = Dictionary::translateFile('backend-' . $s, $cred->property . "_helptext");
				$cred->credentialsHtml = Render::parse('server-prop-' . $cred->template, (array)$cred);
			}
			$serverBackends[] = $backend;
		}
		echo Render::parse('ajax-config-server', array('id' => $id,
			'name' => $oldConfig['servername'],
			'currentbackend' => $oldConfig['servertype'],
			'backendList' => $serverBackends,
			'defaultBlank' => $oldConfig === false));
	}

	/**
	 * Ajax the time table
	 *
	 * @param $id id of the location
	 */
	private function ajaxConfigLocation($id)
	{
		$locConfig = Database::queryFirst("SELECT serverid, serverlocationid, openingtime FROM `locationinfo_locationconfig` WHERE locationid = :id", array('id' => $id));
		if ($locConfig !== false) {
			$openingtimes = json_decode($locConfig['openingtime'], true);
		} else {
			$locConfig = array('serverid' => null, 'serverlocationid' => '');
		}
		if (!isset($openingtimes) || !is_array($openingtimes)) {
			$openingtimes = array();
		}

		// Preset serverid from parent if none is set
		if (is_null($locConfig['serverid'])) {
			$chain = Location::getLocationRootChain($id);
			if (!empty($chain)) {
				$res = Database::simpleQuery("SELECT serverid, locationid FROM locationinfo_locationconfig
					WHERE locationid IN (:locations) AND serverid IS NOT NULL", array('locations' => $chain));
				$chain = array_flip($chain);
				$best = false;
				while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
					if ($best === false || $chain[$row['locationid']] < $chain[$best['locationid']]) {
						$best = $row;
					}
				}
				if ($best !== false) {
					$locConfig['serverid'] = $best['serverid'];
				}
			}
		}

		// get Server / ID list
		$res = Database::simpleQuery("SELECT serverid, servername FROM locationinfo_coursebackend ORDER BY servername ASC");
		$serverList = array();
		while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
			if ($row['serverid'] == $locConfig['serverid']) {
				$row['selected'] = 'selected';
			}
			$serverList[] = $row;
		}

		$data = array(
			'id' => $id,
			'serverlist' => $serverList,
			'serverlocationid' => $locConfig['serverlocationid'],
		);
		$data['expertMode'] = !$this->isSimpleMode($openingtimes);
		// !! isSimpleMode might have changed $openingtimes, so order is important here...
		$data['schedule_data'] = json_encode($openingtimes);

		echo Render::parse('ajax-config-location', $data);
	}

	/**
	 * Checks if simple mode or expert mode is active.
	 * Tries to merge/compact the opening times schedule, and
	 * will actually modify the passed array iff it can be
	 * transformed into easy opening times.
	 *
	 * @param array $array of the saved openingtimes.
	 * @return bool True if simple mode, false if expert mode
	 */
	private function isSimpleMode(&$array)
	{
		if (empty($array))
			return true;
		// Decompose by day
		$new = array();
		foreach ($array as $row) {
			$s = $this->getTime($row['openingtime']);
			$e = $this->getTime($row['closingtime']);
			if ($s === false || $e === false || $e <= $s)
				continue;
			foreach ($row['days'] as $day) {
				$this->addDay($new, $day, $s, $e);
			}
		}
		// Merge by timespan, but always keep saturday and sunday separate
		$merged = array();
		foreach ($new as $day => $ranges) {
			foreach ($ranges as $range) {
				if ($day === 'Saturday' || $day === 'Sunday') {
					$add = $day;
				} else {
					$add = '';
				}
				$key = '#' . $range[0] . '#' . $range[1] . '#' . $add;
				if (!isset($merged[$key])) {
					$merged[$key] = array();
				}
				$merged[$key][$day] = true;
			}
		}
		// Check if it passes as simple mode
		if (count($merged) > 3)
			return false;
		foreach ($merged as $days) {
			if (count($days) === 5) {
				$res = array_keys($days);
				$res = array_intersect($res, array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday"));
				if (count($res) !== 5)
					return false;
			} elseif (count($days) === 1) {
				if (!isset($days['Saturday']) && !isset($days['Sunday'])) {
					return false;
				}
			} else {
				return false;
			}
		}
		// Valid simple mode, finally transform back to what we know
		$new = array();
		foreach ($merged as $span => $days) {
			preg_match('/^#(\d+)#(\d+)#/', $span, $out);
			$new[] = array(
				'days' => array_keys($days),
				'openingtime' => floor($out[1] / 60) . ':' . ($out[1] % 60),
				'closingtime' => floor($out[2] / 60) . ':' . ($out[2] % 60),
			);
		}
		$array = $new;
		return true;
	}

	private function addDay(&$array, $day, $s, $e)
	{
		if (!isset($array[$day])) {
			$array[$day] = array(array($s, $e));
			return;
		}
		foreach (array_keys($array[$day]) as $key) {
			$current = $array[$day][$key];
			if ($s <= $current[0] && $e >= $current[1]) {
				// Fully dominated
				unset($array[$day][$key]);
				continue; // Might partially overlap with additional ranges, keep going
			}
			if ($current[0] <= $s && $current[1] >= $s) {
				// $start lies within existing range
				if ($current[0] <= $e && $current[1] >= $e)
					return; // Fully in existing range, do nothing
				// $end seems to extend range we're checking against but $start lies within this range, update and keep going
				$s = $current[0];
				unset($array[$day][$key]);
				continue;
			}
			// Last possibility: $start is before range, $end within range
			if ($current[0] <= $e && $current[1] >= $e) {
				// $start must lie before range start, otherwise we'd have hit the case above
				$e = $current[1];
				unset($array[$day][$key]);
				continue;
			}
		}
		$array[$day][] = array($s, $e);
	}

	/**
	 * Ajax the config of a location.
	 *
	 * @param $id Location ID
	 */
	private function showConfigPanel()
	{
		$id = Request::get('paneluuid', false, 'string');
		// Get Config data from db
		$panel = Database::queryFirst("SELECT locationids, paneltype, panelconfig
			FROM locationinfo_panel
			WHERE paneluuid = :id", array('id' => $id));
		if ($panel === false) {
			die("Invalid panel id: $id");
		}

		$config = json_decode($panel['panelconfig'], true); // TODO: Validate we got an array, fill with defaults otherwise

		$langs = Dictionary::getLanguages(true);
		foreach ($langs as &$lang) {
			if ($lang['cc'] === $config['language']) {
				$lang['selected'] = 'selected';
			}
		}

		Render::addTemplate('page-config-panel', array(
			'id' => $id,
			'languages' => $langs,
			'mode' => $config['mode'],
			'vertical_checked' => $config['vertical'] ? 'checked' : '',
			'eco_checked' => $config['eco'] ? 'checked' : '',
			'scaledaysauto_checked' => $config['scaledaysauto'] ? 'checked' : '',
			'daystoshow' => $config['daystoshow'],
			'rotation' => $config['rotation'],
			'scale' => $config['scale'],
			'switchtime' => $config['switchtime'],
			'calupdate' => $config['calupdate'],
			'roomupdate' => $config['roomupdate'],
			'configupdate' => $config['configupdate'],
		));
	}

}