summaryrefslogblamecommitdiffstats
path: root/modules-available/locationinfo/api.inc.php
blob: c44ec72d43a0cc877fcc10c6b57c521a7c8afadc (plain) (tree)
1
2
3
4
5
6
7
8
9

     



                           

                   
   
                              
   

                           
 

                                                      
                        


                                                                
                                                                      
                                  
                                                                          
                                                
                                      




                                                             
                                        
                                                                      
                                                           
                                            
                                                                      

                                                        
                                                                      
                                                    

                                
                                                                        
                                          


                                          


         
   
                                                          




                                                          
                                                     
  

                                       


                                    
                                                                                                                            




                                        








                                                                                                                    


   

                                             
                                                 
                                     
   
                                         
 
                            


                                       

                                        
                                       
                                      
                                       
                  
         

                                    





                                                                                                                           

                                                      

                                                            
                                                          
                                                             





                                                                                 

                         
         

                                       

 
   
                                                 
  
                                                    
                                   
   
                                 
 


                                                         
                                         
 
                                                  
                    

 
                                           
 




                                                                 
                                                                                                
                 
         
                    


                                    


                                      
                                                   
                          
   

                             

                           
 

                                                                                                  

                                                                                                       
                                                               
                                                           
                                                                                           
 







                                                                                             
                 
                                                                                         

         
                               

                                                                              
                                                
                                                                                                                         
                                                                                                         

                                                                                                                           
                                 
                 
                                                                                                    
 

                                                                                                 
                        
                                                       
                 
 
                                                                                      
 

                                                                          



                                                             
                         

                 
                            


                                    
<?php

/*
 * vvv - API to Panel - vvv
 */

HandleParameters();

/**
 * Handles the API parameters.
 */
function HandleParameters()
{

	$get = Request::get('get', 0, 'string');
	$uuid = Request::get('uuid', false, 'string');
	$output = false;
	if ($get === "timestamp") {
		$output = array('ts' => getLastChangeTs($uuid));
	} elseif ($get === "machines") {
		$locationIds = LocationInfo::getLocationsOr404($uuid);
		$output = array();
		InfoPanel::appendMachineData($output, $locationIds, true);
		$output = array_values($output);
	} elseif ($get === "config") {
		$type = InfoPanel::getConfig($uuid, $output);
		if ($type === false) {
			http_response_code(404);
			die('Panel not found');
		}
	} elseif ($get === "pcstates") {
		$locationIds = LocationInfo::getLocationsOr404($uuid);
		$output = getPcStates($locationIds, $uuid);
	} elseif ($get === "locationtree") {
		$locationIds = LocationInfo::getLocationsOr404($uuid);
		$output = getLocationTree($locationIds);
	} elseif ($get === "calendar") {
		$locationIds = LocationInfo::getLocationsOr404($uuid);
		$output = getCalendar($locationIds);
	}
	if ($output !== false) {
		Header('Content-Type: application/json; charset=utf-8');
		echo json_encode($output);
	} else {
		http_response_code(404);
		echo 'Unknown get option';
	}
}

/**
 * Get last config modification timestamp for given panel.
 * This is incomplete however, as it wouldn't react to the
 * linked room plan being edited, or added/removed PCs
 * etc. So the advice would simply be "if you want the
 * panel to reload automatically, hit the edit button
 * and click save". Might even add a shortcut
 * reload-button to the list of panels at some point.
 *
 * @param string $paneluuid panels uuid
 * @return int UNIX_TIMESTAMP
 */
function getLastChangeTs($paneluuid)
{
	$panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
		compact('paneluuid'));
	if ($panel === false) {
		http_response_code(404);
		die('Panel not found');
	}
	$lastChange = array((int)$panel['lastchange']);
	if (!empty($panel['locationids'])) {
		$res = Database::simpleQuery('SELECT lastchange FROM locationinfo_locationconfig
				WHERE locationid IN (:locs)', array('locs' => explode(',', $panel['locationids'])));
		while (($lc = $res->fetchColumn()) !== false) {
			$lastChange[] = (int)$lc;
		}
	}
	return max($lastChange);
}

/**
 * Gets the pc states of the given locations.
 *
 * @param int[] $idList list of the location ids.
 * @return array aggregated PC states
 */
function getPcStates($idList, $paneluuid)
{
	$pcStates = array();
	foreach ($idList as $id) {
		$pcStates[$id] = array(
			'id' => $id,
			'idle' => 0,
			'occupied' => 0,
			'offline' => 0,
			'broken' => 0,
			'standby' => 0,
		);
	}

	$locationInfoList = array();
	InfoPanel::appendMachineData($locationInfoList, $idList, true);

	$panel = Database::queryFirst('SELECT paneluuid, panelconfig FROM locationinfo_panel WHERE paneluuid = :paneluuid',
		compact('paneluuid'));
	$config = json_decode($panel['panelconfig'], true);

	foreach ($locationInfoList as $locationInfo) {
		$id = $locationInfo['id'];
		foreach ($locationInfo['machines'] as $pc) {
			$key = strtolower($pc['pcState']);
			if (isset($pcStates[$id][$key])) {
				if ($config['roomplanner']) {
					if (isset($pc['x']) && isset($pc['y'])) {
						$pcStates[$id][$key]++;
					}
				} else {
					$pcStates[$id][$key]++;
				}
			}
		}
	}

	return array_values($pcStates);
}

/**
 * Gets the location tree of the given locations.
 *
 * @param int[] $idList Array list of the locations.
 * @return array location tree data
 */
function getLocationTree($idList)
{
	if (in_array(0, $idList)) {
		return array_values(Location::getTree());
	}
	$locations = Location::getTree();

	$ret = findLocations($locations, $idList);
	return $ret;
}

function findLocations($locations, $idList)
{
	$ret = array();
	foreach ($locations as $location) {
		if (in_array($location['locationid'], $idList)) {
			$ret[] = $location;
		} elseif (!empty($location['children'])) {
			$ret = array_merge($ret, findLocations($location['children'], $idList));
		}
	}
	return $ret;
}

// ########## <Calendar> ###########
/**
 * Gets the calendar of the given ids.
 *
 * @param int[] $idList list with the location ids.
 * @return array Calendar.
 */
function getCalendar($idList)
{
	if (empty($idList))
		return [];

	// Build SQL query for multiple ids.
	$query = "SELECT l.locationid, l.serverid, l.serverlocationid, s.servertype, s.credentials
				FROM `locationinfo_locationconfig` AS l
				INNER JOIN locationinfo_coursebackend AS s ON (s.serverid = l.serverid)
				WHERE l.locationid IN (:idlist)
				ORDER BY s.servertype ASC";
	$dbquery = Database::simpleQuery($query, array('idlist' => array_values($idList)));

	$serverList = array();
	while ($dbresult = $dbquery->fetch(PDO::FETCH_ASSOC)) {
		if (!isset($serverList[$dbresult['serverid']])) {
			$serverList[$dbresult['serverid']] = array(
				'credentials' => json_decode($dbresult['credentials'], true),
				'type' => $dbresult['servertype'],
				'idlist' => array()
			);
		}
		$serverList[$dbresult['serverid']]['idlist'][] = $dbresult['locationid'];
	}

	$resultArray = array();
	foreach ($serverList as $serverid => $server) {
		$serverInstance = CourseBackend::getInstance($server['type']);
		if ($serverInstance === false) {
			EventLog::warning('Cannot fetch schedule for location (' . implode(', ', $server['idlist']) . ')'
				. ': Backend type ' . $server['type'] . ' unknown. Disabling location.');
			Database::exec("UPDATE locationinfo_locationconfig SET serverid = NULL WHERE locationid IN (:lid)",
				array('lid' => $server['idlist']));
			continue;
		}
		$credentialsOk = $serverInstance->setCredentials($serverid, $server['credentials']);

		if ($credentialsOk) {
			$calendarFromBackend = $serverInstance->fetchSchedule($server['idlist']);
		} else {
			$calendarFromBackend = array();
		}

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

		if (is_array($calendarFromBackend)) {
			foreach ($calendarFromBackend as $key => $value) {
				$resultArray[] = array(
					'id' => $key,
					'calendar' => $value,
				);
			}
		}
	}
	return $resultArray;
}

// ########## </Calendar> ##########