summaryrefslogtreecommitdiffstats
path: root/modules-available/locationinfo/api.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/locationinfo/api.inc.php')
-rw-r--r--modules-available/locationinfo/api.inc.php252
1 files changed, 247 insertions, 5 deletions
diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php
index 0d84ebce..e14fe9d7 100644
--- a/modules-available/locationinfo/api.inc.php
+++ b/modules-available/locationinfo/api.inc.php
@@ -1,7 +1,249 @@
<?php
-echo json_encode(array(
- 'key' => 'value',
- 'number' => 123,
- 'list' => array(1,2,3,4,5,6,'foo')
-));
+if (Request::get('redirect', false, 'int') !== false) {
+ // Redirect to actual panel from uuid
+ $uuid = Request::get('uuid', false, 'string');
+ if ($uuid === false) {
+ http_response_code(400);
+ die('Missing uuid parameter');
+ }
+ $row = Database::queryFirst('SELECT paneltype, panelconfig FROM locationinfo_panel WHERE paneluuid = :uuid', compact('uuid'));
+ if ($row === false) {
+ http_response_code(404);
+ die('Panel not found');
+ }
+ if ($row['paneltype'] === 'DEFAULT') {
+ Util::redirect(dirname($_SERVER['SCRIPT_NAME']) . '/modules/locationinfo/frontend/doorsign.html?uuid=' . $uuid);
+ } elseif ($row['paneltype'] === 'SUMMARY') {
+ Util::redirect(dirname($_SERVER['SCRIPT_NAME']) . '/modules/locationinfo/frontend/overview.html?uuid=' . $uuid);
+ } elseif ($row['paneltype'] === 'URL') {
+ $data = json_decode($row['panelconfig'], true);
+ if (!$data || !isset($data['url'])) {
+ http_response_code('500');
+ die('Panel config corrupted on server');
+ }
+ Util::redirect($data['url']);
+ }
+ http_response_code('500');
+ die('Panel has invalid type "' . $row['paneltype'] . '"');
+}
+
+/*
+ * vvv - API to Panel - vvv
+ */
+
+HandleParameters();
+
+/**
+ * Handles the API paramenters.
+ */
+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 = getLocationsOr404($uuid);
+ $output = array();
+ InfoPanel::appendMachineData($output, $locationIds, false);
+ $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 = getLocationsOr404($uuid);
+ $output = getPcStates($locationIds);
+ } elseif ($get === "locationtree") {
+ $locationIds = getLocationsOr404($uuid);
+ $output = getLocationTree($locationIds);
+ } elseif ($get === "calendar") {
+ $locationIds = 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';
+ }
+}
+
+/**
+ * Return list of locationids associated with given panel.
+ * @param string $paneluuid panel
+ * @return int[] locationIds
+ */
+function getLocationsOr404($paneluuid)
+{
+ $panel = Database::queryFirst('SELECT locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ compact('paneluuid'));
+ if ($panel !== false) {
+ return array_map('intval', explode(',', $panel['locationids']));
+ }
+ http_response_code(404);
+ die('Panel not found');
+}
+
+/**
+ * Get last config modification timestamp for given panel.
+ * This was planned to be smart and check the involved locations,
+ * even going up the location tree if the opening time schedule
+ * is inherited, but this would still be incomplete by design, as
+ * it wouldn't react to the linked room plan being considered
+ * for changes, or added/removed PCs etc. So rather than giving
+ * an incomplete "clever" design for detecting changes, we only
+ * consider direct editing of the panel now. 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 FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ compact('paneluuid'));
+ if ($panel === false) {
+ http_response_code(404);
+ die('Panel not found');
+ }
+ return (int)$panel['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)
+{
+ $pcStates = array();
+ foreach ($idList as $id) {
+ $pcStates[$id] = array(
+ 'id' => $id,
+ 'idle' => 0,
+ 'occupied' => 0,
+ 'off' => 0,
+ 'broken' => 0,
+ );
+ }
+
+ $locationInfoList = array();
+ InfoPanel::appendMachineData($locationInfoList, $idList);
+ foreach ($locationInfoList as $locationInfo) {
+ $id = $locationInfo['id'];
+ foreach ($locationInfo['machines'] as $pc) {
+ $key = strtolower($pc['pcState']);
+ if (isset($pcStates[$id][$key])) {
+ $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 locationid ' . $server['locationid']
+ . ': Backend type ' . $server['type'] . ' unknown. Disabling location.');
+ Database::exec("UPDATE locationinfo_locationconfig SET serverid = 0 WHERE locationid = :lid",
+ array('lid' => $server['locationid']));
+ continue;
+ }
+ $credentialsOk = $serverInstance->setCredentials($serverid, $server['credentials']);
+
+ if ($credentialsOk) {
+ $calendarFromBackend = $serverInstance->fetchSchedule($server['idlist']);
+ } else {
+ $calendarFromBackend = array();
+ }
+
+ LocationInfo::setServerError($serverid, $serverInstance->getError());
+
+ if (is_array($calendarFromBackend)) {
+ foreach ($calendarFromBackend as $key => $value) {
+ $resultArray[] = array(
+ 'id' => $key,
+ 'calendar' => $value,
+ );
+ }
+ }
+ }
+ return $resultArray;
+}
+
+// ########## </Calendar> ##########