summaryrefslogtreecommitdiffstats
path: root/modules-available/locationinfo
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/locationinfo')
-rw-r--r--modules-available/locationinfo/api.inc.php85
-rw-r--r--modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php2
-rw-r--r--modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/Autodiscover.php2
-rw-r--r--modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php5
-rw-r--r--modules-available/locationinfo/inc/coursebackend.inc.php67
-rw-r--r--modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php20
-rw-r--r--modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php20
-rwxr-xr-xmodules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php53
-rw-r--r--modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php22
-rw-r--r--modules-available/locationinfo/inc/coursebackend/coursebackend_ical.inc.php12
-rw-r--r--modules-available/locationinfo/inc/icalcoursebackend.inc.php33
-rw-r--r--modules-available/locationinfo/inc/icalevent.inc.php444
-rw-r--r--modules-available/locationinfo/inc/icalparser.inc.php151
-rw-r--r--modules-available/locationinfo/inc/infopanel.inc.php30
-rw-r--r--modules-available/locationinfo/inc/locationinfo.inc.php116
-rw-r--r--modules-available/locationinfo/inc/locationinfohooks.inc.php27
-rw-r--r--modules-available/locationinfo/lang/de/template-tags.json6
-rw-r--r--modules-available/locationinfo/lang/en/template-tags.json6
-rw-r--r--modules-available/locationinfo/page.inc.php167
-rwxr-xr-xmodules-available/locationinfo/templates/frontend-default.html14
-rw-r--r--modules-available/locationinfo/templates/page-config-panel-url.html37
-rw-r--r--modules-available/locationinfo/templates/page-locations.html2
22 files changed, 704 insertions, 617 deletions
diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php
index d3ff9ebd..24919ba1 100644
--- a/modules-available/locationinfo/api.inc.php
+++ b/modules-available/locationinfo/api.inc.php
@@ -14,7 +14,7 @@ function HandleParameters()
$get = Request::get('get', 0, 'string');
$uuid = Request::get('uuid', false, 'string');
- $output = false;
+ $output = null;
if ($get === "timestamp") {
$output = array('ts' => getLastChangeTs($uuid));
} elseif ($get === "machines") {
@@ -24,7 +24,7 @@ function HandleParameters()
$output = array_values($output);
} elseif ($get === "config") {
$type = InfoPanel::getConfig($uuid, $output);
- if ($type === false) {
+ if ($type === null) {
http_response_code(404);
die('Panel not found');
}
@@ -36,9 +36,9 @@ function HandleParameters()
$output = getLocationTree($locationIds);
} elseif ($get === "calendar") {
$locationIds = LocationInfo::getLocationsOr404($uuid);
- $output = getCalendar($locationIds);
+ $output = LocationInfo::getCalendar($locationIds);
}
- if ($output !== false) {
+ if ($output !== null) {
Header('Content-Type: application/json; charset=utf-8');
echo json_encode($output);
} else {
@@ -59,7 +59,7 @@ function HandleParameters()
* @param string $paneluuid panels uuid
* @return int UNIX_TIMESTAMP
*/
-function getLastChangeTs($paneluuid)
+function getLastChangeTs(string $paneluuid): int
{
$panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
@@ -84,7 +84,7 @@ function getLastChangeTs($paneluuid)
* @param int[] $idList list of the location ids.
* @return array aggregated PC states
*/
-function getPcStates($idList, $paneluuid)
+function getPcStates(array $idList, string $paneluuid): array
{
$pcStates = array();
foreach ($idList as $id) {
@@ -130,18 +130,17 @@ function getPcStates($idList, $paneluuid)
* @param int[] $idList Array list of the locations.
* @return array location tree data
*/
-function getLocationTree($idList)
+function getLocationTree(array $idList): array
{
if (in_array(0, $idList)) {
return array_values(Location::getTree());
}
$locations = Location::getTree();
- $ret = findLocations($locations, $idList);
- return $ret;
+ return findLocations($locations, $idList);
}
-function findLocations($locations, $idList)
+function findLocations(array $locations, array $idList): array
{
$ret = array();
foreach ($locations as $location) {
@@ -153,69 +152,3 @@ function findLocations($locations, $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> ##########
diff --git a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php
index 6443d31d..28792929 100644
--- a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php
+++ b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/ArrayType/ArrayOfStringsType.php
@@ -32,6 +32,6 @@ class ArrayOfStringsType extends ArrayType
*/
public function __toString()
{
- return $this->String;
+ return implode(' + ', $this->String);
}
}
diff --git a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/Autodiscover.php b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/Autodiscover.php
index 8198137d..8c60a4c8 100644
--- a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/Autodiscover.php
+++ b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpEws/Autodiscover.php
@@ -891,6 +891,6 @@ class Autodiscover
protected function tryViaUrl($url, $timeout = 6)
{
$result = $this->doNTLMPost($url, $timeout);
- return ($result ? true : false);
+ return (bool)$result;
}
}
diff --git a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php
index 21c77cbf..98f23dfa 100644
--- a/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php
+++ b/modules-available/locationinfo/exchange-includes/jamesiarmes/PhpNtlm/SoapClient.php
@@ -26,6 +26,9 @@ class SoapClient extends \SoapClient
*/
protected $options;
+ protected $__last_response;
+ protected $__last_request_headers;
+
/**
* {@inheritdoc}
*
@@ -68,7 +71,7 @@ class SoapClient extends \SoapClient
/**
* {@inheritdoc}
*/
- public function __doRequest($request, $location, $action, $version, $one_way = 0)
+ public function __doRequest($request, $location, $action, $version, $oneWay = 0)
{
$headers = $this->buildHeaders($action);
$this->__last_request = $request;
diff --git a/modules-available/locationinfo/inc/coursebackend.inc.php b/modules-available/locationinfo/inc/coursebackend.inc.php
index 6e4d77ac..ea1bebac 100644
--- a/modules-available/locationinfo/inc/coursebackend.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend.inc.php
@@ -39,7 +39,7 @@ abstract class CourseBackend
$this->errors = [];
}
- protected final function addError($message, $fatal)
+ protected final function addError(string $message, bool $fatal)
{
$this->errors[] = ['time' => time(), 'message' => $message, 'fatal' => $fatal];
}
@@ -55,7 +55,7 @@ abstract class CourseBackend
self::$backendTypes = array();
foreach (glob(dirname(__FILE__) . '/coursebackend/coursebackend_*.inc.php', GLOB_NOSORT) as $file) {
require_once $file;
- preg_match('#coursebackend_([^/\.]+)\.inc\.php$#i', $file, $out);
+ preg_match('#coursebackend_([^/.]+)\.inc\.php$#i', $file, $out);
$className = 'CourseBackend_' . $out[1];
if (!class_exists($className)) {
trigger_error("Backend type source unit $file doesn't seem to define class $className", E_USER_ERROR);
@@ -71,13 +71,13 @@ abstract class CourseBackend
*
* @return array list of backends
*/
- public static function getList()
+ public static function getList(): array
{
self::loadDb();
return array_keys(self::$backendTypes);
}
- public static function exists($backendType)
+ public static function exists($backendType): bool
{
self::loadDb();
return isset(self::$backendTypes[$backendType]);
@@ -89,7 +89,7 @@ abstract class CourseBackend
* @param string $backendType name of module type
* @return \CourseBackend|false module instance
*/
- public static function getInstance($backendType)
+ public static function getInstance(string $backendType)
{
self::loadDb();
if (!isset(self::$backendTypes[$backendType])) {
@@ -106,18 +106,18 @@ abstract class CourseBackend
/**
* @return string return display name of backend
*/
- public abstract function getDisplayName();
+ public abstract function getDisplayName(): string;
/**
* @returns \BackendProperty[] list of properties that need to be set
*/
- public abstract function getCredentialDefinitions();
+ public abstract function getCredentialDefinitions(): array;
/**
* @return boolean true if the connection works, false otherwise
*/
- public abstract function checkConnection();
+ public abstract function checkConnection(): bool;
/**
* uses json to setCredentials, the json must follow the form given in
@@ -126,42 +126,39 @@ abstract class CourseBackend
* @param array $data assoc array with data required by backend
* @returns bool if the credentials were in the correct format
*/
- public abstract function setCredentialsInternal($data);
+ public abstract function setCredentialsInternal(array $data): bool;
/**
* @return int desired caching time of results, in seconds. 0 = no caching
*/
- public abstract function getCacheTime();
+ public abstract function getCacheTime(): int;
/**
* @return int age after which timetables are no longer refreshed should be
* greater then CacheTime
*/
- public abstract function getRefreshTime();
+ public abstract function getRefreshTime(): int;
/**
* Internal version of fetch, to be overridden by subclasses.
*
- * @param $roomIds array with remote IDs for wanted rooms
+ * @param $requestedRoomIds array with remote IDs for wanted rooms
* @return array a recursive array that uses the roomID as key
* and has the schedule array as value. A schedule array contains an array in this format:
* ["start"=>'JJJJ-MM-DD"T"HH:MM:SS',"end"=>'JJJJ-MM-DD"T"HH:MM:SS',"title"=>string]
*/
- protected abstract function fetchSchedulesInternal($roomId);
+ protected abstract function fetchSchedulesInternal(array $requestedRoomIds): array;
/**
* In case you want to sanitize or otherwise mangle a property for your backend,
* override this.
- * @param string $prop
- * @param $value
- * @return mixed
*/
- public function mangleProperty($prop, $value)
+ public function mangleProperty(string $prop, $value)
{
return $value;
}
- private static function fixTime(&$start, &$end)
+ private static function fixTime(string &$start, string &$end): bool
{
if (!preg_match('/^(\d{2}|\d{4})-?\d{2}-?\d{2}-?T\d{1,2}:?\d{2}:?(\d{2})?$/', $start))
return false;
@@ -178,14 +175,10 @@ abstract class CourseBackend
* Method for fetching the schedule of the given rooms on a server.
*
* @param array $requestedLocationIds array of room ID to fetch
- * @return array|bool array containing the timetables as value and roomid as key as result, or false on error
+ * @return array array containing the timetables as value and roomid as key as result, or false on error
*/
- public final function fetchSchedule($requestedLocationIds)
+ public final function fetchSchedule(array $requestedLocationIds): array
{
- if (!is_array($requestedLocationIds)) {
- $this->addError('No array of roomids was given to fetchSchedule', false);
- return false;
- }
if (empty($requestedLocationIds))
return array();
$requestedLocationIds = array_values($requestedLocationIds);
@@ -195,7 +188,7 @@ abstract class CourseBackend
array('locations' => $requestedLocationIds));
$returnValue = [];
$remoteIds = [];
- while ($row = $dbquery1->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery1 as $row) {
// Check if in cache - if lastUpdate is null then it is interpreted as 1970
if ($row['lastcalendarupdate'] + $this->getCacheTime() < $NOW) {
$remoteIds[$row['locationid']] = $row['serverlocationid'];
@@ -222,7 +215,7 @@ abstract class CourseBackend
'lastuse' => $NOW - $this->getRefreshTime(),
'minage' => $NOW - $this->getCacheTime(),
));
- while ($row = $dbquery4->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery4 as $row) {
$remoteIds[$row['locationid']] = $row['serverlocationid'];
}
}
@@ -239,9 +232,6 @@ abstract class CourseBackend
]);
}
$backendResponse = $this->fetchSchedulesInternal(array_unique($remoteIds));
- if ($backendResponse === false) {
- return false;
- }
// Fetching might have taken a while, get current time again
$NOW = time();
@@ -282,7 +272,7 @@ abstract class CourseBackend
return $returnValue;
}
- public final function setCredentials($serverId, $data)
+ public final function setCredentials(int $serverId, array $data): bool
{
foreach ($this->getCredentialDefinitions() as $prop) {
if (!isset($data[$prop->property])) {
@@ -302,18 +292,9 @@ abstract class CourseBackend
}
/**
- * @return false if there was no error string with error message if there was one
- */
- public final function getError()
- {
- trigger_error('getError() is legacy; use getErrors()');
- return $this->error;
- }
-
- /**
* @return array list of errors that occurred during processing.
*/
- public final function getErrors()
+ public final function getErrors(): array
{
return $this->errors;
}
@@ -378,7 +359,7 @@ abstract class CourseBackend
* @param string $response xml document to convert
* @return bool|array array representation of the xml if possible, false otherwise
*/
- protected function xmlStringToArray($response, &$error)
+ protected function xmlStringToArray(string $response, &$error)
{
$cleanresponse = preg_replace('/(<\/?)(\w+):([^>]*>)/', '$1$2$3', $response);
try {
@@ -390,8 +371,7 @@ abstract class CourseBackend
}
return false;
}
- $array = json_decode(json_encode((array)$xml), true);
- return $array;
+ return json_decode(json_encode((array)$xml), true);
}
}
@@ -414,7 +394,6 @@ class BackendProperty {
* Initialize additional fields of this class that are only required
* for rendering the server configuration dialog.
*
- * @param string $backendId target backend id
* @param mixed $current current value of this property.
*/
public function initForRender($current = null) {
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php
index 07c8457d..786ab459 100644
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_davinci.inc.php
@@ -11,7 +11,7 @@ class CourseBackend_Davinci extends CourseBackend
*/
private $curlHandle = false;
- public function setCredentialsInternal($data)
+ public function setCredentialsInternal(array $data): bool
{
if (empty($data['baseUrl'])) {
$this->addError("No url is given", true);
@@ -24,7 +24,7 @@ class CourseBackend_Davinci extends CourseBackend
return true;
}
- public function checkConnection()
+ public function checkConnection(): bool
{
if (empty($this->location)) {
$this->addError("Credentials are not set", true);
@@ -40,7 +40,7 @@ class CourseBackend_Davinci extends CourseBackend
return true;
}
- public function getCredentialDefinitions()
+ public function getCredentialDefinitions(): array
{
return [
new BackendProperty('baseUrl', 'string'),
@@ -49,17 +49,17 @@ class CourseBackend_Davinci extends CourseBackend
];
}
- public function getDisplayName()
+ public function getDisplayName(): string
{
return 'Davinci';
}
- public function getCacheTime()
+ public function getCacheTime(): int
{
return 30 * 60;
}
- public function getRefreshTime()
+ public function getRefreshTime(): int
{
return 0;
}
@@ -68,9 +68,9 @@ class CourseBackend_Davinci extends CourseBackend
* @param string $roomId unique name of the room, as used by davinci
* @param \DateTime $startDate start date to fetch
* @param \DateTime $endDate end date of range to fetch
- * @return array|bool if successful the arrayrepresentation of the timetable
+ * @return false|string if successful the array representation of the timetable
*/
- private function fetchRoomRaw($roomId, $startDate, $endDate)
+ private function fetchRoomRaw(string $roomId, DateTime $startDate, DateTime $endDate)
{
$url = $this->location . "content=xml&type=room&name=" . urlencode($roomId)
. "&startdate=" . $startDate->format('d.m.Y') . "&enddate=" . $endDate->format('d.m.Y');
@@ -97,7 +97,7 @@ class CourseBackend_Davinci extends CourseBackend
}
- public function fetchSchedulesInternal($requestedRoomIds)
+ public function fetchSchedulesInternal(array $requestedRoomIds): array
{
$startDate = new DateTime('last Monday 0:00');
$endDate = new DateTime('+14 days 0:00');
@@ -134,7 +134,7 @@ class CourseBackend_Davinci extends CourseBackend
$start = substr($start, 0, 2) . ':' . substr($start, 2, 2);
$end = $lesson['Finish'];
$end = substr($end, 0, 2) . ':' . substr($end, 2, 2);
- $subject = isset($lesson['Subject']) ? $lesson['Subject'] : '???';
+ $subject = $lesson['Subject'] ?? '???';
$timetable[] = array(
'title' => $subject,
'start' => $date . "T" . $start . ':00',
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
index 2cb2be18..4588bf7c 100644
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
@@ -15,9 +15,9 @@ class CourseBackend_Dummy extends CourseBackend
* @param int $serverId ID of the server
* @returns bool if the credentials were in the correct format
*/
- public function setCredentialsInternal($json)
+ public function setCredentialsInternal(array $data): bool
{
- $x = $json;
+ $x = $data;
$this->pw = $x['password'];
if ($this->pw === "mfg") {
@@ -30,7 +30,7 @@ class CourseBackend_Dummy extends CourseBackend
/**
* @return boolean true if the connection works, false otherwise
*/
- public function checkConnection()
+ public function checkConnection(): bool
{
if ($this->pw == "mfg") {
return true;
@@ -42,7 +42,7 @@ class CourseBackend_Dummy extends CourseBackend
/**
* @returns array with parameter name as key and and an array with type, help text and mask as value
*/
- public function getCredentialDefinitions()
+ public function getCredentialDefinitions(): array
{
$options = ["opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", "opt8"];
return [
@@ -58,7 +58,7 @@ class CourseBackend_Dummy extends CourseBackend
/**
* @return string return display name of backend
*/
- public function getDisplayName()
+ public function getDisplayName(): string
{
return 'Dummy with array';
}
@@ -66,7 +66,7 @@ class CourseBackend_Dummy extends CourseBackend
/**
* @return int desired caching time of results, in seconds. 0 = no caching
*/
- public function getCacheTime()
+ public function getCacheTime(): int
{
return 0;
}
@@ -75,7 +75,7 @@ class CourseBackend_Dummy extends CourseBackend
* @return int age after which timetables are no longer refreshed should be
* greater then CacheTime
*/
- public function getRefreshTime()
+ public function getRefreshTime(): int
{
return 0;
}
@@ -83,15 +83,15 @@ class CourseBackend_Dummy extends CourseBackend
/**
* Internal version of fetch, to be overridden by subclasses.
*
- * @param $roomIds array with local ID as key and serverId as value
+ * @param $requestedRoomIds array with local ID as key and serverId as value
* @return array a recursive array that uses the roomID as key
* and has the schedule array as value. A schedule array contains an array in this format:
* ["start"=>'YYYY-MM-DD<T>HH:MM:SS',"end"=>'YYYY-MM-DD<T>HH:MM:SS',"title"=>string]
*/
- public function fetchSchedulesInternal($roomId)
+ public function fetchSchedulesInternal(array $requestedRoomIds): array
{
$a = array();
- foreach ($roomId as $id) {
+ foreach ($requestedRoomIds as $id) {
if ($id == 1) {
$now = time();
return array($id => array(
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php
index 44847ce2..df33dadd 100755
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_exchange.inc.php
@@ -12,6 +12,7 @@ spl_autoload_register(function ($class) {
require_once $file;
});
+use jamesiarmes\PhpEws\ArrayType\NonEmptyArrayOfBaseFolderIdsType;
use jamesiarmes\PhpEws\Client;
use jamesiarmes\PhpEws\Enumeration\DefaultShapeNamesType;
use jamesiarmes\PhpEws\Enumeration\DistinguishedFolderIdNameType;
@@ -38,7 +39,7 @@ class CourseBackend_Exchange extends CourseBackend
/**
* @return string return display name of backend
*/
- public function getDisplayName()
+ public function getDisplayName(): string
{
return "Microsoft Exchange";
}
@@ -46,7 +47,7 @@ class CourseBackend_Exchange extends CourseBackend
/**
* @returns \BackendProperty[] list of properties that need to be set
*/
- public function getCredentialDefinitions()
+ public function getCredentialDefinitions(): array
{
$options = [
Client::VERSION_2007,
@@ -72,7 +73,7 @@ class CourseBackend_Exchange extends CourseBackend
/**
* @return boolean true if the connection works, false otherwise
*/
- public function checkConnection()
+ public function checkConnection(): bool
{
$client = $this->getClient();
$request = new ResolveNamesType();
@@ -104,7 +105,7 @@ class CourseBackend_Exchange extends CourseBackend
* @param array $data assoc array with data required by backend
* @returns bool if the credentials were in the correct format
*/
- public function setCredentialsInternal($data)
+ public function setCredentialsInternal(array $data): bool
{
foreach (['username', 'password'] as $field) {
if (empty($data[$field])) {
@@ -133,7 +134,7 @@ class CourseBackend_Exchange extends CourseBackend
/**
* @return int desired caching time of results, in seconds. 0 = no caching
*/
- public function getCacheTime()
+ public function getCacheTime(): int
{
return 15 * 60;
}
@@ -142,7 +143,7 @@ class CourseBackend_Exchange extends CourseBackend
* @return int age after which timetables are no longer refreshed. should be
* greater than CacheTime.
*/
- public function getRefreshTime()
+ public function getRefreshTime(): int
{
return 30 * 60;
}
@@ -150,12 +151,12 @@ class CourseBackend_Exchange extends CourseBackend
/**
* Internal version of fetch, to be overridden by subclasses.
*
- * @param $roomIds array with local ID as key and serverId as value
+ * @param $requestedRoomIds array with local ID as key and serverId as value
* @return array a recursive array that uses the roomID as key
* and has the schedule array as value. A schedule array contains an array in this format:
* ["start"=>'JJJJ-MM-DD HH:MM:SS',"end"=>'JJJJ-MM-DD HH:MM:SS',"title"=>string]
*/
- protected function fetchSchedulesInternal($requestedRoomIds)
+ protected function fetchSchedulesInternal(array $requestedRoomIds): array
{
$startDate = new DateTime('last Monday 0:00');
$endDate = new DateTime('+14 days 0:00');
@@ -172,8 +173,13 @@ class CourseBackend_Exchange extends CourseBackend
// Iterate over the events that were found, printing some data for each.
foreach ($items as $item) {
- $start = new DateTime($item->Start);
- $end = new DateTime($item->End);
+ try {
+ $start = new DateTime($item->Start);
+ $end = new DateTime($item->End);
+ } catch (Exception $e) {
+ $this->addError("Invalid date range: '{$item->Start}' -> '{$item->End}'", false);
+ continue;
+ }
$schedules[$roomId][] = array(
'title' => $item->Subject,
@@ -186,13 +192,9 @@ class CourseBackend_Exchange extends CourseBackend
}
/**
- * @param \jamesiarmes\PhpEws\Client $client
- * @param \DateTime $startDate
- * @param \DateTime $endDate
- * @param string $roomAddress
* @return \jamesiarmes\PhpEws\Type\CalendarItemType[]
*/
- public function findEventsForRoom($client, $startDate, $endDate, $roomAddress)
+ public function findEventsForRoom(Client $client, DateTime $startDate, DateTime $endDate, string $roomAddress): array
{
$request = new FindItemType();
$request->Traversal = ItemQueryTraversalType::SHALLOW;
@@ -206,12 +208,20 @@ class CourseBackend_Exchange extends CourseBackend
$folderId->Id = DistinguishedFolderIdNameType::CALENDAR;
$folderId->Mailbox = new EmailAddressType();
$folderId->Mailbox->EmailAddress = $roomAddress;
+ $request->ParentFolderIds = new NonEmptyArrayOfBaseFolderIdsType();
$request->ParentFolderIds->DistinguishedFolderId[] = $folderId;
- $response = $client->FindItem($request);
- $response_messages = $response->ResponseMessages->FindItemResponseMessage;
-
+ try {
+ $response = $client->FindItem($request);
+ } catch (Exception $e) {
+ $this->addError('Exception calling FindItem: ' . $e->getMessage(), true);
+ return [];
+ }
+ if (!is_object($response->ResponseMessages)) {
+ $this->addError('FindItem returned response without ResponseMessages', true);
+ return [];
+ }
$items = [];
- foreach ($response_messages as $response_message) {
+ foreach ($response->ResponseMessages->FindItemResponseMessage as $response_message) {
// Make sure the request succeeded.
if ($response_message->ResponseClass !== ResponseClassType::SUCCESS) {
$code = $response_message->ResponseCode;
@@ -224,10 +234,7 @@ class CourseBackend_Exchange extends CourseBackend
return $items;
}
- /**
- * @return \jamesiarmes\PhpEws\Client
- */
- public function getClient()
+ public function getClient(): Client
{
$client = new Client($this->serverAddress, $this->username, $this->password, $this->clientVersion);
$client->setTimezone($this->timezone);
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php
index 8bd18169..55d5ed4b 100644
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_hisinone.inc.php
@@ -3,7 +3,7 @@
class CourseBackend_HisInOne extends ICalCourseBackend
{
- public function setCredentialsInternal($data)
+ public function setCredentialsInternal(array $data): bool
{
if (empty($data['baseUrl'])) {
$this->addError("No url is given", true);
@@ -16,7 +16,7 @@ class CourseBackend_HisInOne extends ICalCourseBackend
return true;
}
- public function getCredentialDefinitions()
+ public function getCredentialDefinitions(): array
{
return [
new BackendProperty('baseUrl', 'string'),
@@ -25,7 +25,7 @@ class CourseBackend_HisInOne extends ICalCourseBackend
];
}
- public function mangleProperty($prop, $value)
+ public function mangleProperty(string $prop, $value)
{
if ($prop === 'baseUrl') {
// Update form SOAP to iCal url
@@ -43,7 +43,15 @@ class CourseBackend_HisInOne extends ICalCourseBackend
return $value;
}
- public function checkConnection()
+ protected function toTitle(ICalEvent $event): string
+ {
+ $title = parent::toTitle($event);
+ // His in one seems to prefix *some* (but *not* all) of the lectures by their ID/("Nummer")
+ // No clue what that format is supposed to be, this regex is some guesswork after observing this for a while
+ return preg_replace('#^[0-9][0-9A-ZÄÖÜ]{3,9}-[A-Za-z0-9/_ÄÖÜäöüß.-]{4,30}\s+#u', '', $title);
+ }
+
+ public function checkConnection(): bool
{
if (!$this->isOK())
return false;
@@ -57,18 +65,18 @@ class CourseBackend_HisInOne extends ICalCourseBackend
return false;
}
- public function getCacheTime()
+ public function getCacheTime(): int
{
return 30 * 60;
}
- public function getRefreshTime()
+ public function getRefreshTime(): int
{
return 60 * 60;
}
- public function getDisplayName()
+ public function getDisplayName(): string
{
return "HisInOne";
}
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_ical.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_ical.inc.php
index 98dca1cb..f1791c4e 100644
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_ical.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_ical.inc.php
@@ -6,7 +6,7 @@ class CourseBackend_ICal extends ICalCourseBackend
/** @var string room ID for testing connection */
private $testId;
- public function setCredentialsInternal($data)
+ public function setCredentialsInternal(array $data): bool
{
if (empty($data['baseUrl'])) {
$this->addError("No url is given", true);
@@ -20,7 +20,7 @@ class CourseBackend_ICal extends ICalCourseBackend
return true;
}
- public function getCredentialDefinitions()
+ public function getCredentialDefinitions(): array
{
return [
new BackendProperty('baseUrl', 'string'),
@@ -33,7 +33,7 @@ class CourseBackend_ICal extends ICalCourseBackend
];
}
- public function checkConnection()
+ public function checkConnection(): bool
{
if (!$this->isOK())
return false;
@@ -42,18 +42,18 @@ class CourseBackend_ICal extends ICalCourseBackend
return ($this->downloadIcal($this->testId) !== null);
}
- public function getCacheTime()
+ public function getCacheTime(): int
{
return 30 * 60;
}
- public function getRefreshTime()
+ public function getRefreshTime(): int
{
return 60 * 60;
}
- public function getDisplayName()
+ public function getDisplayName(): string
{
return "iCal";
}
diff --git a/modules-available/locationinfo/inc/icalcoursebackend.inc.php b/modules-available/locationinfo/inc/icalcoursebackend.inc.php
index fba0866c..838d18b7 100644
--- a/modules-available/locationinfo/inc/icalcoursebackend.inc.php
+++ b/modules-available/locationinfo/inc/icalcoursebackend.inc.php
@@ -18,18 +18,9 @@ abstract class ICalCourseBackend extends CourseBackend
/** @var bool|resource */
private $curlHandle = false;
- /**
- * Initialize values
- *
- * @param string $location
- * @param bool $verifyCert
- * @param bool $verifyHostname
- * @param string $authMethod
- * @param string $user
- * @param string $pass
- */
- protected function init($location, $verifyCert, $verifyHostname,
- $authMethod = 'NONE', $user = '', $pass = '')
+ protected function init(
+ string $location, bool $verifyCert, bool $verifyHostname,
+ string $authMethod = 'NONE', string $user = '', string $pass = '')
{
$this->verifyCert = $verifyCert;
$this->verifyHostname = $verifyHostname;
@@ -43,19 +34,26 @@ abstract class ICalCourseBackend extends CourseBackend
}
/**
- * @param int $roomId room id
+ * @param string $roomId room id
* @param callable $errorFunc
* @return ICalEvent[]|null all events for this room in the range -7 days to +7 days, or NULL on error
*/
- protected function downloadIcal($roomId)
+ protected function downloadIcal(string $roomId): ?array
{
if (!$this->isOK())
return null;
+
+ try {
+ $ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]);
+ } catch (Exception $e) {
+ $this->addError('Error instantiating ICalParser: ' . $e->getMessage(), true);
+ return null;
+ }
+
if ($this->curlHandle === false) {
$this->curlHandle = curl_init();
}
- $ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]);
$options = [
CURLOPT_WRITEFUNCTION => function ($ch, $data) use ($ical) {
$ical->feedData($data);
@@ -92,7 +90,7 @@ abstract class ICalCourseBackend extends CourseBackend
return $ical->events();
}
- public function fetchSchedulesInternal($requestedRoomIds): array
+ public function fetchSchedulesInternal(array $requestedRoomIds): array
{
if (empty($requestedRoomIds) || !$this->isOK()) {
return array();
@@ -118,9 +116,8 @@ abstract class ICalCourseBackend extends CourseBackend
/**
* Get a usable title from either SUMMARY or DESCRIPTION
- * @param ICalEvent $event
*/
- private function toTitle($event): string
+ protected function toTitle(ICalEvent $event): string
{
$title = $event->summary;
if (empty($title)) {
diff --git a/modules-available/locationinfo/inc/icalevent.inc.php b/modules-available/locationinfo/inc/icalevent.inc.php
index 1fb586ee..c5aea349 100644
--- a/modules-available/locationinfo/inc/icalevent.inc.php
+++ b/modules-available/locationinfo/inc/icalevent.inc.php
@@ -2,199 +2,253 @@
class ICalEvent
{
- // phpcs:disable Generic.Arrays.DisallowLongArraySyntax
-
- const HTML_TEMPLATE = '<p>%s: %s</p>';
-
- /**
- * https://www.kanzaki.com/docs/ical/summary.html
- *
- * @var $summary
- */
- public $summary;
-
- /**
- * https://www.kanzaki.com/docs/ical/dtstart.html
- *
- * @var $dtstart
- */
- public $dtstart;
-
- /**
- * https://www.kanzaki.com/docs/ical/dtend.html
- *
- * @var $dtend
- */
- public $dtend;
-
- /**
- * https://www.kanzaki.com/docs/ical/duration.html
- *
- * @var $duration
- */
- public $duration;
-
- /**
- * https://www.kanzaki.com/docs/ical/dtstamp.html
- *
- * @var $dtstamp
- */
- public $dtstamp;
-
- /**
- * https://www.kanzaki.com/docs/ical/uid.html
- *
- * @var $uid
- */
- public $uid;
-
- /**
- * https://www.kanzaki.com/docs/ical/created.html
- *
- * @var $created
- */
- public $created;
-
- /**
- * https://www.kanzaki.com/docs/ical/lastModified.html
- *
- * @var $lastmodified
- */
- public $lastmodified;
-
- /**
- * https://www.kanzaki.com/docs/ical/description.html
- *
- * @var $description
- */
- public $description;
-
- /**
- * https://www.kanzaki.com/docs/ical/location.html
- *
- * @var $location
- */
- public $location;
-
- /**
- * https://www.kanzaki.com/docs/ical/sequence.html
- *
- * @var $sequence
- */
- public $sequence;
-
- /**
- * https://www.kanzaki.com/docs/ical/status.html
- *
- * @var $status
- */
- public $status;
-
- /**
- * https://www.kanzaki.com/docs/ical/transp.html
- *
- * @var $transp
- */
- public $transp;
-
- /**
- * https://www.kanzaki.com/docs/ical/organizer.html
- *
- * @var $organizer
- */
- public $organizer;
-
- /**
- * https://www.kanzaki.com/docs/ical/attendee.html
- *
- * @var $attendee
- */
- public $attendee;
-
- /**
- * Creates the Event object
- *
- * @param array $data
- * @return void
- */
- public function __construct(array $data = array())
- {
- foreach ($data as $key => $value) {
- $variable = self::snakeCase($key);
- $this->{$variable} = self::prepareData($value);
- }
- }
-
- /**
- * Prepares the data for output
- *
- * @param mixed $value
- * @return mixed
- */
- protected function prepareData($value)
- {
- if (is_string($value)) {
- return stripslashes(trim(str_replace('\n', "\n", $value)));
- } elseif (is_array($value)) {
- return array_map('self::prepareData', $value);
- }
-
- return $value;
- }
-
- /**
- * Returns Event data excluding anything blank
- * within an HTML template
- *
- * @param string $html HTML template to use
- * @return string
- */
- public function printData($html = self::HTML_TEMPLATE)
- {
- $data = array(
- 'SUMMARY' => $this->summary,
- 'DTSTART' => $this->dtstart,
- 'DTEND' => $this->dtend,
- 'DURATION' => $this->duration,
- 'DTSTAMP' => $this->dtstamp,
- 'UID' => $this->uid,
- 'CREATED' => $this->created,
- 'LAST-MODIFIED' => $this->lastmodified,
- 'DESCRIPTION' => $this->description,
- 'LOCATION' => $this->location,
- 'SEQUENCE' => $this->sequence,
- 'STATUS' => $this->status,
- 'TRANSP' => $this->transp,
- 'ORGANISER' => $this->organizer,
- 'ATTENDEE(S)' => $this->attendee,
- );
-
- // Remove any blank values
- $data = array_filter($data);
-
- $output = '';
-
- foreach ($data as $key => $value) {
- $output .= sprintf($html, $key, $value);
- }
-
- return $output;
- }
-
- /**
- * Converts the given input to snake_case
- *
- * @param string $input
- * @param string $glue
- * @param string $separator
- * @return string
- */
- protected static function snakeCase($input, $glue = '_', $separator = '-')
- {
- $input = preg_split('/(?<=[a-z])(?=[A-Z])/x', $input);
- $input = implode($glue, $input);
- $input = str_replace($separator, $glue, $input);
-
- return strtolower($input);
- }
+ // phpcs:disable Generic.Arrays.DisallowLongArraySyntax
+
+ const HTML_TEMPLATE = '<p>%s: %s</p>';
+
+ /**
+ * https://www.kanzaki.com/docs/ical/summary.html
+ *
+ * @var string
+ */
+ public $summary;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/dtstart.html
+ *
+ * @var string
+ */
+ public $dtstart;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/dtend.html
+ *
+ * @var string
+ */
+ public $dtend;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/duration.html
+ *
+ * @var string
+ */
+ public $duration;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/dtstamp.html
+ *
+ * @var string
+ */
+ public $dtstamp;
+
+ /**
+ * When the event starts, represented as a timezone-adjusted string
+ *
+ * @var string
+ */
+ public $dtstart_tz;
+
+ /**
+ * When the event ends, represented as a timezone-adjusted string
+ *
+ * @var string
+ */
+ public $dtend_tz;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/uid.html
+ *
+ * @var string
+ */
+ public $uid;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/created.html
+ *
+ * @var string
+ */
+ public $created;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/lastModified.html
+ *
+ * @var string
+ */
+ public $last_modified;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/description.html
+ *
+ * @var string
+ */
+ public $description;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/location.html
+ *
+ * @var string
+ */
+ public $location;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/sequence.html
+ *
+ * @var string
+ */
+ public $sequence;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/status.html
+ *
+ * @var string
+ */
+ public $status;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/transp.html
+ *
+ * @var string
+ */
+ public $transp;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/organizer.html
+ *
+ * @var string
+ */
+ public $organizer;
+
+ /**
+ * https://www.kanzaki.com/docs/ical/attendee.html
+ *
+ * @var string
+ */
+ public $attendee;
+
+ /**
+ * Manage additional properties
+ *
+ * @var array<string, mixed>
+ */
+ private $additionalProperties = array();
+
+ /**
+ * Creates the Event object
+ *
+ * @param array $data
+ * @return void
+ */
+ public function __construct(array $data = array())
+ {
+ foreach ($data as $key => $value) {
+ $variable = self::snakeCase($key);
+ if (property_exists($this, $variable)) {
+ $this->{$variable} = $this->prepareData($value);
+ } else {
+ $this->additionalProperties[$variable] = $this->prepareData($value);
+ }
+ }
+ }
+
+ /**
+ * Magic getter method
+ *
+ * @param string $additionalPropertyName
+ * @return mixed
+ */
+ public function __get(string $additionalPropertyName)
+ {
+ if (array_key_exists($additionalPropertyName, $this->additionalProperties)) {
+ return $this->additionalProperties[$additionalPropertyName];
+ }
+
+ return null;
+ }
+
+ /**
+ * Magic isset method
+ */
+ public function __isset(string $name): bool
+ {
+ return is_null($this->$name) === false;
+ }
+
+ /**
+ * Prepares the data for output
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function prepareData($value)
+ {
+ if (is_string($value)) {
+ return stripslashes(trim(str_replace('\n', "\n", $value)));
+ }
+
+ if (is_array($value)) {
+ return array_map(function ($value) {
+ return $this->prepareData($value);
+ }, $value);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns Event data excluding anything blank
+ * within an HTML template
+ *
+ * @param string $html HTML template to use
+ * @return string
+ */
+ public function printData($html = self::HTML_TEMPLATE)
+ {
+ $data = array(
+ 'SUMMARY' => $this->summary,
+ 'DTSTART' => $this->dtstart,
+ 'DTEND' => $this->dtend,
+ 'DTSTART_TZ' => $this->dtstart_tz,
+ 'DTEND_TZ' => $this->dtend_tz,
+ 'DURATION' => $this->duration,
+ 'DTSTAMP' => $this->dtstamp,
+ 'UID' => $this->uid,
+ 'CREATED' => $this->created,
+ 'LAST-MODIFIED' => $this->last_modified,
+ 'DESCRIPTION' => $this->description,
+ 'LOCATION' => $this->location,
+ 'SEQUENCE' => $this->sequence,
+ 'STATUS' => $this->status,
+ 'TRANSP' => $this->transp,
+ 'ORGANISER' => $this->organizer,
+ 'ATTENDEE(S)' => $this->attendee,
+ );
+
+ // Remove any blank values
+ $data = array_filter($data);
+
+ $output = '';
+
+ foreach ($data as $key => $value) {
+ $output .= sprintf($html, $key, $value);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Converts the given input to snake_case
+ *
+ * @param string $input
+ * @param string $glue
+ * @param string $separator
+ * @return string
+ */
+ protected static function snakeCase($input, $glue = '_', $separator = '-')
+ {
+ $input = preg_split('/(?<=[a-z])(?=[A-Z])/x', $input);
+ $input = implode($glue, $input);
+ $input = str_replace($separator, $glue, $input);
+
+ return strtolower($input);
+ }
}
diff --git a/modules-available/locationinfo/inc/icalparser.inc.php b/modules-available/locationinfo/inc/icalparser.inc.php
index 0be8777b..eacb67b1 100644
--- a/modules-available/locationinfo/inc/icalparser.inc.php
+++ b/modules-available/locationinfo/inc/icalparser.inc.php
@@ -23,7 +23,6 @@ class ICalParser
const ICAL_DATE_TIME_TEMPLATE = 'TZID=%s:';
const ISO_8601_WEEK_START = 'MO';
const RECURRENCE_EVENT = 'Generated recurrence event';
- const TIME_FORMAT = 'His';
const TIME_ZONE_UTC = 'UTC';
const UNIX_FORMAT = 'U';
@@ -481,15 +480,12 @@ class ICalParser
/**
* Creates the ICal object
*
- * @param mixed $files
* @param array $options
* @return void
* @throws Exception
*/
public function __construct(array $options = array())
{
- ini_set('auto_detect_line_endings', '1');
-
foreach ($options as $option => $value) {
if (in_array($option, self::$configurableOptions)) {
$this->{$option} = $value;
@@ -501,10 +497,7 @@ class ICalParser
$this->defaultTimeZone = date_default_timezone_get();
}
- // Ideally you would use `PHP_INT_MIN` from PHP 7
- $php_int_min = -2147483648;
-
- $this->windowMinTimestamp = is_null($this->filterDaysBefore) ? $php_int_min : (new DateTime('now'))->sub(new DateInterval('P' . $this->filterDaysBefore . 'D'))->getTimestamp();
+ $this->windowMinTimestamp = is_null($this->filterDaysBefore) ? PHP_INT_MIN : (new DateTime('now'))->sub(new DateInterval('P' . $this->filterDaysBefore . 'D'))->getTimestamp();
$this->windowMaxTimestamp = is_null($this->filterDaysAfter) ? PHP_INT_MAX : (new DateTime('now'))->add(new DateInterval('P' . $this->filterDaysAfter . 'D'))->getTimestamp();
$this->shouldFilterByWindow = !is_null($this->filterDaysBefore) || !is_null($this->filterDaysAfter);
@@ -516,7 +509,7 @@ class ICalParser
*
* @param string $data
*/
- public function feedData($data)
+ public function feedData(string $data)
{
$this->feedBuffer .= $data;
$start = 0;
@@ -581,7 +574,7 @@ class ICalParser
*
* @return bool
*/
- public function isValid()
+ public function isValid(): bool
{
return $this->hasSeenStart;
}
@@ -591,7 +584,7 @@ class ICalParser
*
* @param string $line
*/
- protected function handleLine($line)
+ protected function handleLine(string $line)
{
$line = rtrim($line); // Trim trailing whitespace
$line = $this->removeUnprintableChars($line);
@@ -602,18 +595,18 @@ class ICalParser
$add = $this->keyValueFromString($line);
- if ($add === false) {
+ if ($add === null) {
return;
}
- $keyword = $add[0];
+ $keyword = $add[0]; // string
$values = $add[1]; // May be an array containing multiple values
if (!is_array($values)) {
if (!empty($values)) {
$values = array($values); // Make an array as not already
$blankArray = array(); // Empty placeholder array
- array_push($values, $blankArray);
+ $values[] = $blankArray;
} else {
$values = array(); // Use blank array to ignore this line
}
@@ -752,16 +745,9 @@ class ICalParser
foreach ($events as $key => $anEvent) {
if ($anEvent === null) {
unset($events[$key]);
-
- continue;
- }
-
- if ($this->doesEventStartOutsideWindow($anEvent)) {
+ } elseif ($this->doesEventStartOutsideWindow($anEvent)) {
$this->eventCount--;
-
unset($events[$key]);
-
- continue;
}
}
@@ -776,7 +762,7 @@ class ICalParser
* @param array $event
* @return boolean
*/
- protected function doesEventStartOutsideWindow(array $event)
+ protected function doesEventStartOutsideWindow(array $event): bool
{
return !isset($event['DTSTART']) || !$this->isValidDate($event['DTSTART'])
|| $this->isOutOfRange($event['DTSTART'], $this->windowMinTimestamp, $this->windowMaxTimestamp);
@@ -790,7 +776,7 @@ class ICalParser
* @param integer $maxTimestamp
* @return boolean
*/
- protected function isOutOfRange($calendarDate, $minTimestamp, $maxTimestamp)
+ protected function isOutOfRange(string $calendarDate, int $minTimestamp, int $maxTimestamp): bool
{
$timestamp = strtotime(explode('T', $calendarDate)[0]);
@@ -798,36 +784,15 @@ class ICalParser
}
/**
- * Unfolds an iCal file in preparation for parsing
- * (https://icalendar.org/iCalendar-RFC-5545/3-1-content-lines.html)
- *
- * @param array $lines
- * @return array
- */
- protected function unfold(array $lines)
- {
- $string = implode(PHP_EOL, $lines);
- $string = preg_replace('/' . PHP_EOL . '[ \t]/', '', $string);
-
- $lines = explode(PHP_EOL, $string);
-
- return $lines;
- }
-
- /**
* Add one key and value pair to the `$this->cal` array
*
* @param string $component
- * @param string|boolean $keyword
- * @param string $value
+ * @param string $keyword
+ * @param string|string[] $value
* @return void
*/
- protected function addCalendarComponentWithKeyAndValue($component, $keyword, $value)
+ protected function addCalendarComponentWithKeyAndValue(string $component, string $keyword, $value)
{
- if ($keyword == false) {
- $keyword = $this->lastKeyword;
- }
-
switch ($component) {
case 'VALARM':
$key1 = 'VEVENT';
@@ -840,7 +805,7 @@ class ICalParser
if (is_array($value)) {
// Add array of properties to the end
- array_push($this->cal[$key1][$key2][$key3]["{$keyword}_array"], $value);
+ $this->cal[$key1][$key2][$key3]["{$keyword}_array"][] = $value;
} else {
if (!isset($this->cal[$key1][$key2][$key3][$keyword])) {
$this->cal[$key1][$key2][$key3][$keyword] = $value;
@@ -862,7 +827,7 @@ class ICalParser
if (is_array($value)) {
// Add array of properties to the end
- array_push($this->cal[$key1][$key2]["{$keyword}_array"], $value);
+ $this->cal[$key1][$key2]["{$keyword}_array"][] = $value;
} else {
if (!isset($this->cal[$key1][$key2][$keyword])) {
$this->cal[$key1][$key2][$keyword] = $value;
@@ -882,7 +847,7 @@ class ICalParser
if ($keyword === 'DURATION') {
try {
$duration = new DateInterval($value);
- array_push($this->cal[$key1][$key2]["{$keyword}_array"], $duration);
+ $this->cal[$key1][$key2]["{$keyword}_array"][] = $duration;
} catch (Exception $e) {
error_log('Ignoring invalid duration ' . $value);
}
@@ -928,6 +893,7 @@ class ICalParser
break;
}
+ // Remove?
$this->lastKeyword = $keyword;
}
@@ -935,9 +901,9 @@ class ICalParser
* Gets the key value pair from an iCal string
*
* @param string $text
- * @return array|boolean
+ * @return ?array
*/
- protected function keyValueFromString($text)
+ protected function keyValueFromString(string $text): ?array
{
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
@@ -974,14 +940,14 @@ class ICalParser
}
if (count($matches) === 0) {
- return false;
+ return null;
}
- if (preg_match('/^([A-Z-]+)([;][\w\W]*)?$/', $matches[1])) {
+ if (preg_match('/^([A-Z-]+)(;[\w\W]*)?$/', $matches[1])) {
$matches = array_splice($matches, 1, 2); // Remove first match and re-align ordering
// Process properties
- if (preg_match('/([A-Z-]+)[;]([\w\W]*)/', $matches[0], $properties)) {
+ if (preg_match('/([A-Z-]+);([\w\W]*)/', $matches[0], $properties)) {
// Remove first match
array_shift($properties);
// Fix to ignore everything in keyword after a ; (e.g. Language, TZID, etc.)
@@ -1023,9 +989,8 @@ class ICalParser
}
return $matches;
- } else {
- return false; // Ignore this match
}
+ return null; // Ignore this match
}
/**
@@ -1034,7 +999,7 @@ class ICalParser
* @param string $icalDate
* @return DateTime
*/
- public function iCalDateToDateTime($icalDate)
+ public function iCalDateToDateTime(string $icalDate): DateTime
{
/**
* iCal times may be in 3 formats, (https://www.kanzaki.com/docs/ical/dateTime.html)
@@ -1091,7 +1056,7 @@ class ICalParser
* @param string $icalDate
* @return integer
*/
- public function iCalDateToUnixTimestamp($icalDate)
+ public function iCalDateToUnixTimestamp(string $icalDate): int
{
return $this->iCalDateToDateTime($icalDate)->getTimestamp();
}
@@ -1104,7 +1069,7 @@ class ICalParser
* @param string $format
* @return string|boolean
*/
- public function iCalDateWithTimeZone(array $event, $key, $format = self::DATE_TIME_FORMAT)
+ public function iCalDateWithTimeZone(array $event, string $key, string $format = self::DATE_TIME_FORMAT)
{
if (!isset($event["{$key}_array"]) || !isset($event[$key])) {
return false;
@@ -1141,7 +1106,6 @@ class ICalParser
if (empty($this->cal['VEVENT']))
return;
$events =& $this->cal['VEVENT'];
- $checks = null;
foreach ($events as $key => $anEvent) {
foreach (array('DTSTART', 'DTEND', 'RECURRENCE-ID') as $type) {
@@ -1175,23 +1139,20 @@ class ICalParser
$eventKeysToRemove = array();
foreach ($events as $key => $event) {
- $checks[] = !isset($event['RECURRENCE-ID']);
- $checks[] = isset($event['UID']);
- $checks[] = isset($event['UID']) && isset($this->alteredRecurrenceInstances[$event['UID']]);
+ $checks = !isset($event['RECURRENCE-ID'])
+ && isset($event['UID']) && isset($this->alteredRecurrenceInstances[$event['UID']]);
- if ((bool)array_product($checks)) {
+ if ($checks) {
$eventDtstartUnix = $this->iCalDateToUnixTimestamp($event['DTSTART_array'][3]);
// phpcs:ignore CustomPHPCS.ControlStructures.AssignmentInCondition
if (($alteredEventKey = array_search($eventDtstartUnix, $this->alteredRecurrenceInstances[$event['UID']])) !== false) {
$eventKeysToRemove[] = $alteredEventKey;
- $alteredEvent = array_replace_recursive($events[$key], $events[$alteredEventKey]);
+ $alteredEvent = array_replace_recursive($event, $events[$alteredEventKey]);
$this->alteredRecurrenceInstances[$event['UID']]['altered-event'] = array($key => $alteredEvent);
}
}
-
- unset($checks);
}
foreach ($eventKeysToRemove as $eventKeyToRemove) {
@@ -1568,7 +1529,7 @@ class ICalParser
* @param DateTime $initialDateTime
* @return array
*/
- protected function getDaysOfMonthMatchingByDayRRule(array $byDays, $initialDateTime)
+ protected function getDaysOfMonthMatchingByDayRRule(array $byDays, DateTime $initialDateTime): array
{
$matchingDays = array();
@@ -1628,7 +1589,7 @@ class ICalParser
* @param array $valuesList
* @return array
*/
- protected function filterValuesUsingBySetPosRRule(array $bySetPos, array $valuesList)
+ protected function filterValuesUsingBySetPosRRule(array $bySetPos, array $valuesList): array
{
$filteredMatches = array();
@@ -1688,7 +1649,7 @@ class ICalParser
*
* @return ICalEvent[]
*/
- public function events()
+ public function events(): array
{
if (empty($this->cal) || empty($this->cal['VEVENT']))
return [];
@@ -1706,9 +1667,9 @@ class ICalParser
*
* @return string
*/
- public function calendarName()
+ public function calendarName(): string
{
- return isset($this->cal['VCALENDAR']['X-WR-CALNAME']) ? $this->cal['VCALENDAR']['X-WR-CALNAME'] : '';
+ return $this->cal['VCALENDAR']['X-WR-CALNAME'] ?? '';
}
/**
@@ -1716,9 +1677,9 @@ class ICalParser
*
* @return string
*/
- public function calendarDescription()
+ public function calendarDescription(): string
{
- return isset($this->cal['VCALENDAR']['X-WR-CALDESC']) ? $this->cal['VCALENDAR']['X-WR-CALDESC'] : '';
+ return $this->cal['VCALENDAR']['X-WR-CALDESC'] ?? '';
}
/**
@@ -1727,7 +1688,7 @@ class ICalParser
* @param boolean $ignoreUtc
* @return string
*/
- public function calendarTimeZone($ignoreUtc = false)
+ public function calendarTimeZone(bool $ignoreUtc = false): ?string
{
if (isset($this->cal['VCALENDAR']['X-WR-TIMEZONE'])) {
$timeZone = $this->cal['VCALENDAR']['X-WR-TIMEZONE'];
@@ -1754,11 +1715,11 @@ class ICalParser
*
* @return array
*/
- public function freeBusyEvents()
+ public function freeBusyEvents(): array
{
$array = $this->cal;
- return isset($array['VFREEBUSY']) ? $array['VFREEBUSY'] : array();
+ return $array['VFREEBUSY'] ?? array();
}
/**
@@ -1784,7 +1745,7 @@ class ICalParser
* @return array
* @throws Exception
*/
- public function eventsFromRange($rangeStart = null, $rangeEnd = null)
+ public function eventsFromRange(string $rangeStart = null, string $rangeEnd = null): array
{
// Sort events before processing range
$events = $this->sortEventsWithOrder($this->events());
@@ -1857,7 +1818,7 @@ class ICalParser
* @param integer $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING
* @return array
*/
- public function sortEventsWithOrder(array $events, $sortOrder = SORT_ASC)
+ public function sortEventsWithOrder(array $events, int $sortOrder = SORT_ASC): array
{
$extendedEvents = array();
$timestamp = array();
@@ -1878,7 +1839,7 @@ class ICalParser
* @param string $timeZone
* @return boolean
*/
- protected function isValidTimeZoneId($timeZone)
+ protected function isValidTimeZoneId(string $timeZone): bool
{
return $this->isValidIanaTimeZoneId($timeZone) !== false
|| $this->isValidCldrTimeZoneId($timeZone) !== false
@@ -1891,7 +1852,7 @@ class ICalParser
* @param string $timeZone
* @return boolean
*/
- protected function isValidIanaTimeZoneId($timeZone)
+ protected function isValidIanaTimeZoneId(string $timeZone): bool
{
if (in_array($timeZone, $this->validIanaTimeZones)) {
return true;
@@ -1923,7 +1884,7 @@ class ICalParser
* @param string $timeZone
* @return boolean
*/
- public function isValidCldrTimeZoneId($timeZone)
+ public function isValidCldrTimeZoneId(string $timeZone): bool
{
return array_key_exists(html_entity_decode($timeZone), self::$cldrTimeZonesMap);
}
@@ -1934,7 +1895,7 @@ class ICalParser
* @param string $timeZone
* @return boolean
*/
- public function isValidWindowsTimeZoneId($timeZone)
+ public function isValidWindowsTimeZoneId(string $timeZone): bool
{
return array_key_exists(html_entity_decode($timeZone), self::$windowsTimeZonesMap);
}
@@ -1942,12 +1903,9 @@ class ICalParser
/**
* Parses a duration and applies it to a date
*
- * @param string $date
- * @param DateInterval $duration
- * @param string $format
* @return integer|DateTime
*/
- protected function parseDuration($date, $duration, $format = self::UNIX_FORMAT)
+ protected function parseDuration(string $date, DateInterval $duration, ?string $format = self::UNIX_FORMAT)
{
$dateTime = date_create($date);
$dateTime->modify("{$duration->y} year");
@@ -1974,7 +1932,7 @@ class ICalParser
* @param string $data
* @return string
*/
- protected function removeUnprintableChars($data)
+ protected function removeUnprintableChars(string $data): string
{
return preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $data);
}
@@ -1986,7 +1944,7 @@ class ICalParser
* @param string $candidateText
* @return string
*/
- protected function escapeParamText($candidateText)
+ protected function escapeParamText(string $candidateText): string
{
if (strpbrk($candidateText, ':;,') !== false) {
return '"' . $candidateText . '"';
@@ -2002,13 +1960,12 @@ class ICalParser
* @param array $event
* @return array
*/
- public function parseExdates(array $event)
+ public function parseExdates(array $event): array
{
if (empty($event['EXDATE_array'])) {
return array();
- } else {
- $exdates = $event['EXDATE_array'];
}
+ $exdates = $event['EXDATE_array'];
$output = array();
$currentTimeZone = $this->defaultTimeZone;
@@ -2046,7 +2003,7 @@ class ICalParser
* @param string $value
* @return boolean
*/
- public function isValidDate($value)
+ public function isValidDate(string $value): bool
{
if (!$value) {
return false;
@@ -2065,10 +2022,10 @@ class ICalParser
* Returns a `DateTimeZone` object based on a string containing a time zone name.
* Falls back to the default time zone if string passed not a recognised time zone.
*
- * @param string $timeZoneString
+ * @param DateTimeZone|string $timeZoneString
* @return DateTimeZone
*/
- public function timeZoneStringToDateTimeZone($timeZoneString)
+ public function timeZoneStringToDateTimeZone($timeZoneString): DateTimeZone
{
if ($timeZoneString instanceof DateTimeZone)
return $timeZoneString;
diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php
index 6deb9db5..1a0e9b67 100644
--- a/modules-available/locationinfo/inc/infopanel.inc.php
+++ b/modules-available/locationinfo/inc/infopanel.inc.php
@@ -7,16 +7,16 @@ class InfoPanel
* Gets the config of the location.
*
* @param int $locationID ID of the location
- * @param mixed $config the panel config will be returned here
- * @return string|bool paneltype, false if not exists
+ * @param ?array $config the panel config will be returned here
+ * @return ?string panel type, null if not exists
*/
- public static function getConfig($paneluuid, &$config)
+ public static function getConfig(string $paneluuid, ?array &$config): ?string
{
$panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
if ($panel === false) {
- return false;
+ return null;
}
$config = LocationInfo::defaultPanelConfig($panel['paneltype']);
@@ -87,13 +87,10 @@ class InfoPanel
* @param array $array location list to populate with machine data
* @param bool $withPosition Defines if coords should be included or not.
*/
- public static function appendMachineData(&$array, $idList = false, $withPosition = false, $withHostname = false)
+ public static function appendMachineData(array &$array, array $idList, bool $withPosition = false, bool $withHostname = false): void
{
- if (empty($array) && $idList === false)
+ if (empty($idList))
return;
- if ($idList === false) {
- $idList = array_keys($array);
- }
$ignoreList = array();
if (Module::isAvailable('runmode')) {
@@ -115,7 +112,7 @@ class InfoPanel
$dbquery = Database::simpleQuery($query, array('idlist' => $idList));
// Iterate over matching machines
- while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery as $row) {
if (isset($ignoreList[$row['machineuuid']]))
continue;
settype($row['locationid'], 'int');
@@ -165,7 +162,7 @@ class InfoPanel
* @param array $array list of locations, indexed by locationId
* @param int[] $idList list of locations
*/
- public static function appendOpeningTimes(&$array, $idList)
+ public static function appendOpeningTimes(array &$array, array $idList): void
{
// First, lets get all the parent ids for the given locations
// in case we need to get inherited opening times
@@ -175,7 +172,7 @@ class InfoPanel
$res = Database::simpleQuery("SELECT locationid, openingtime FROM location
WHERE locationid IN (:lids)", array('lids' => $allIds));
$openingTimes = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$openingTimes[(int)$row['locationid']] = $row;
}
// Now we got all the calendars for locations and parents
@@ -207,7 +204,6 @@ class InfoPanel
$currentId = $locations[$currentId]['parentlocationid'];
}
}
- return;
}
@@ -218,12 +214,12 @@ class InfoPanel
* @param int[] $idList location ids
* @return int[] more location ids
*/
- private static function getLocationsWithParents($idList)
+ private static function getLocationsWithParents(array $idList): array
{
$locations = Location::getLocationsAssoc();
$allIds = $idList;
foreach ($idList as $id) {
- if (isset($locations[$id]) && isset($locations[$id]['parents'])) {
+ if (isset($locations[$id]['parents'])) {
$allIds = array_merge($allIds, $locations[$id]['parents']);
}
}
@@ -239,9 +235,9 @@ class InfoPanel
* 'HourClose' => hh, 'MinutesClose' => mm }
*
* @param array $openingtime The opening time in the db saved format.
- * @return mixed The opening time in the frontend needed format.
+ * @return array The opening time in the frontend needed format.
*/
- private static function formatOpeningtime($openingtime)
+ private static function formatOpeningtime(array $openingtime): array
{
$result = array();
foreach ($openingtime as $entry) {
diff --git a/modules-available/locationinfo/inc/locationinfo.inc.php b/modules-available/locationinfo/inc/locationinfo.inc.php
index 6427cc1a..42829a18 100644
--- a/modules-available/locationinfo/inc/locationinfo.inc.php
+++ b/modules-available/locationinfo/inc/locationinfo.inc.php
@@ -7,14 +7,14 @@ class LocationInfo
* Gets the pc data and returns it's state.
*
* @param array $pc The pc data from the db. Array('state' => xx, 'lastseen' => xxx)
- * @return int pc state
+ * @return string pc state
*/
- public static function getPcState($pc)
+ public static function getPcState(array $pc): string
{
$lastseen = (int)$pc['lastseen'];
$NOW = time();
- if ($pc['state'] === 'OFFLINE' && $NOW - $lastseen > 21 * 86400) {
+ if ($pc['state'] === 'OFFLINE' && $NOW - $lastseen > 30 * 86400) {
return "BROKEN";
}
return $pc['state'];
@@ -22,11 +22,12 @@ class LocationInfo
/**
* Return list of locationids associated with given panel.
+ *
* @param string $paneluuid panel
* @param bool $recursive if true and paneltype == SUMMARY the result is recursive with all child room ids.
* @return int[] locationIds
*/
- public static function getLocationsOr404($paneluuid, $recursive = true)
+ public static function getLocationsOr404(string $paneluuid, bool $recursive = true): array
{
$panel = Database::queryFirst('SELECT paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
@@ -48,7 +49,7 @@ class LocationInfo
* @param int $serverId id of server
* @param string|array $message error message to set, array of error message struct, null or false clears error.
*/
- public static function setServerError($serverId, $message)
+ public static function setServerError(int $serverId, $message): void
{
if (is_array($message)) {
$fatal = false;
@@ -86,7 +87,7 @@ class LocationInfo
*
* @return array Return a default config.
*/
- public static function defaultPanelConfig($type)
+ public static function defaultPanelConfig(string $type): array
{
if ($type === 'DEFAULT') {
return array(
@@ -97,6 +98,7 @@ class LocationInfo
'prettytime' => true,
'roomplanner' => true,
'scaledaysauto' => true,
+ 'startday' => 0,
'daystoshow' => 7,
'rotation' => 0,
'scale' => 50,
@@ -127,9 +129,111 @@ class LocationInfo
'interactive' => 0,
'bookmarks' => '',
'allow-tty' => '',
+ 'url' => '',
+ 'zoom-factor' => 100,
);
}
return array();
}
+ /**
+ * Gets the calendar of the given ids.
+ *
+ * @param int[] $idList list with the location ids.
+ * @return array Calendar.
+ */
+ public static function getCalendar(array $idList, bool $forceCached = false): array
+ {
+ if (empty($idList))
+ return [];
+
+ $resultArray = array();
+
+ if ($forceCached) {
+ $res = Database::simpleQuery("SELECT locationid, calendar FROM locationinfo_locationconfig
+ WHERE Length(calendar) > 10 AND lastcalendarupdate > UNIX_TIMESTAMP() - 86400*3");
+ foreach ($res as $row) {
+ $resultArray[] = [
+ 'id' => (int)$row['locationid'],
+ 'calendar' => json_decode($row['calendar'], true),
+ ];
+ }
+ return $resultArray;
+ }
+
+ // 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();
+ foreach ($dbquery as $dbresult) {
+ if (!isset($serverList[$dbresult['serverid']])) {
+ $serverList[$dbresult['serverid']] = array(
+ 'credentials' => (array)json_decode($dbresult['credentials'], true),
+ 'type' => $dbresult['servertype'],
+ 'idlist' => array()
+ );
+ }
+ $serverList[$dbresult['serverid']]['idlist'][] = $dbresult['locationid'];
+ }
+
+ 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' => (int)$key,
+ 'calendar' => $value,
+ );
+ }
+ }
+ }
+ return $resultArray;
+ }
+
+ public static function getAllCalendars(bool $forceCached): array
+ {
+ $locations = Database::queryColumnArray("SELECT locationid FROM location");
+ $calendars = [];
+ foreach (LocationInfo::getCalendar($locations, $forceCached) as $cal) {
+ if (empty($cal['calendar']))
+ continue;
+ $calendars[$cal['id']] = $cal['calendar'];
+ }
+ return $calendars;
+ }
+
+ public static function extractCurrentEvent(array $calendar): string
+ {
+ $NOW = time();
+ foreach ($calendar as $event) {
+ $start = strtotime($event['start']);
+ $end = strtotime($event['end']) + 60;
+ if ($NOW >= $start && $NOW <= $end)
+ return $event['title'];
+ }
+ return '';
+ }
+
}
diff --git a/modules-available/locationinfo/inc/locationinfohooks.inc.php b/modules-available/locationinfo/inc/locationinfohooks.inc.php
index 8e4975e9..8ec217cc 100644
--- a/modules-available/locationinfo/inc/locationinfohooks.inc.php
+++ b/modules-available/locationinfo/inc/locationinfohooks.inc.php
@@ -5,9 +5,9 @@ class LocationInfoHooks
/**
* @param string $uuid panel uuid
- * @return bool|string panel name if exists, false otherwise
+ * @return false|string panel name if exists, false otherwise
*/
- public static function getPanelName($uuid)
+ public static function getPanelName(string $uuid)
{
$ret = Database::queryFirst('SELECT panelname FROM locationinfo_panel WHERE paneluuid = :uuid', compact('uuid'));
if ($ret === false)
@@ -18,14 +18,11 @@ class LocationInfoHooks
/**
* Hook called by runmode module where we should modify the client config according to our
* needs. Disable standby/logout timeouts, enable autologin, set URL.
- *
- * @param $machineUuid
- * @param $panelUuid
*/
- public static function configHook($machineUuid, $panelUuid)
+ public static function configHook(string $machineUuid, string $panelUuid): void
{
$type = InfoPanel::getConfig($panelUuid, $data);
- if ($type === false)
+ if ($type === null)
return; // TODO: Invalid panel - what should we do?
if ($type === 'URL') {
// Check if we should set the insecure SSL mode (accept invalid/self signed certs etc.)
@@ -51,7 +48,7 @@ class LocationInfoHooks
RunMode::updateClientFlag($machineUuid, 'locationinfo', true);
} else { // Automatic login
RunMode::updateClientFlag($machineUuid, 'locationinfo', false);
- ConfigHolder::add('SLX_AUTOLOGIN', '1', 1000);
+ ConfigHolder::add('SLX_AUTOLOGIN', 'ON', 1000);
ConfigHolder::add('SLX_ADDONS', '', 1000);
}
if (!empty($data['browser'])) {
@@ -72,13 +69,19 @@ class LocationInfoHooks
if ($data['allow-tty'] === 'yes' || $data['allow-tty'] === 'no') {
ConfigHolder::add('SLX_TTY_SWITCH', $data['allow-tty'], 1000);
}
+ if (($data['zoom-factor'] ?? 100) != 100) {
+ ConfigHolder::add('SLX_BROWSER_ZOOM', $data['zoom-factor']);
+ }
} else {
// Not URL panel
ConfigHolder::add('SLX_BROWSER_URL', 'http://' . $_SERVER['SERVER_ADDR'] . '/panel/' . $panelUuid);
- ConfigHolder::add('SLX_BROWSER_INSECURE', '1'); // TODO: Sat server might redirect to HTTPS, which in turn could have a self-signed cert - push to client
- ConfigHolder::add('SLX_AUTOLOGIN', '1', 1000);
+ ConfigHolder::add('SLX_AUTOLOGIN', 'ON', 1000);
ConfigHolder::add('SLX_ADDONS', '', 1000);
}
+ $al = ConfigHolder::get('SLX_AUTOLOGIN');
+ if (!empty($al) && $al !== 'OFF' && $al != 0) {
+ ConfigHolder::add('SLX_SHUTDOWN_TIMEOUT', '', 1000);
+ }
ConfigHolder::add('SLX_LOGOUT_TIMEOUT', '', 1000);
ConfigHolder::add('SLX_SCREEN_STANDBY_TIMEOUT', '', 1000);
ConfigHolder::add('SLX_SYSTEM_STANDBY_TIMEOUT', '', 1000);
@@ -87,10 +90,8 @@ class LocationInfoHooks
/**
* Turn multiline list into space separated list, removing any
* comments (starting with #)
- * @param string $list
- * @return string
*/
- private static function mangleList($list)
+ private static function mangleList(string $list): string
{
return preg_replace('/\s*(#[^\n]*)?(\n|$)/', ' ', $list);
}
diff --git a/modules-available/locationinfo/lang/de/template-tags.json b/modules-available/locationinfo/lang/de/template-tags.json
index 1f781721..fe6a3e53 100644
--- a/modules-available/locationinfo/lang/de/template-tags.json
+++ b/modules-available/locationinfo/lang/de/template-tags.json
@@ -50,7 +50,7 @@
"lang_ignoreSslTooltip": "Akzeptiere ung\u00fcltige, abgelaufene oder selbstsignierte SSL-Zertifikate",
"lang_insecureSsl": "Unsicheres SSL",
"lang_interactive": "Interaktiver Browser",
- "lang_interactiveTooltip": "Aktivieren, um regul\u00e4res Surfen zuzulassen",
+ "lang_interactiveTooltip": "Volles UI anzeigen (tabs, bookmarks, ...)",
"lang_language": "Sprache",
"lang_languageTooltip": "Legt die Sprache der angezeigten Oberfl\u00e4che fest",
"lang_lastCalendarUpdate": "Kalender Update",
@@ -149,5 +149,7 @@
"lang_verticalTooltip": "Legt fest, ob Kalender und Raum \u00fcbereinander angezeigt werden sollen",
"lang_wednesday": "Mittwoch",
"lang_when": "Wann",
- "lang_whitelist": "Whitelist"
+ "lang_whitelist": "Whitelist",
+ "lang_zoomFactor": "Zoom-Faktor",
+ "lang_zoomFactorTooltip": "Initialer Zoom-Faktor beim Start des Panels. Je nach gew\u00e4hltem Browser kann der Faktor vom Benutzer angepasst werden."
} \ No newline at end of file
diff --git a/modules-available/locationinfo/lang/en/template-tags.json b/modules-available/locationinfo/lang/en/template-tags.json
index ce0eac98..5f612d16 100644
--- a/modules-available/locationinfo/lang/en/template-tags.json
+++ b/modules-available/locationinfo/lang/en/template-tags.json
@@ -50,7 +50,7 @@
"lang_ignoreSslTooltip": "Accept invalid, expired or self-signed ssl certificates",
"lang_insecureSsl": "Insecure SSL",
"lang_interactive": "Interactive Browser",
- "lang_interactiveTooltip": "Activate to allow regular websurfing",
+ "lang_interactiveTooltip": "Show full browser UI (tabs, bookmarks, ...)",
"lang_language": "Language",
"lang_languageTooltip": "The language the frontend uses",
"lang_lastCalendarUpdate": "Calendar update",
@@ -149,5 +149,7 @@
"lang_verticalTooltip": "Defines whether the room and calendar are shown above each other",
"lang_wednesday": "Wednesday",
"lang_when": "When",
- "lang_whitelist": "Whitelist"
+ "lang_whitelist": "Whitelist",
+ "lang_zoomFactor": "Zoom level",
+ "lang_zoomFactorTooltip": "Initial zoom level at startup. Depending on selected browser, this can later be changed by the user."
} \ No newline at end of file
diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php
index 9e7a704e..63a02ba2 100644
--- a/modules-available/locationinfo/page.inc.php
+++ b/modules-available/locationinfo/page.inc.php
@@ -81,7 +81,7 @@ class Page_LocationInfo extends Page
$this->showLocationsTable();
break;
case 'backends':
- $this->showBackendsTable($backends);
+ $this->showBackendsTable($backends ?? []);
break;
case 'edit-panel':
$this->showPanelConfig();
@@ -100,7 +100,7 @@ class Page_LocationInfo extends Page
/**
* Deletes the server from the db.
*/
- private function deleteServer($id)
+ private function deleteServer($id): void
{
User::assertPermission('backend.edit');
if ($id === 0) {
@@ -113,7 +113,7 @@ class Page_LocationInfo extends Page
}
}
- private function deletePanel()
+ private function deletePanel(): void
{
$id = Request::post('uuid', false, 'string');
if ($id === false) {
@@ -130,25 +130,27 @@ class Page_LocationInfo extends Page
}
}
- private function getTime($str)
+ private static function getTime(string $str): ?int
{
$str = explode(':', $str);
- if (count($str) !== 2) return false;
- if ($str[0] < 0 || $str[0] > 23 || $str[1] < 0 || $str[1] > 59) return false;
+ if (count($str) !== 2)
+ return null;
+ if ($str[0] < 0 || $str[0] > 23 || $str[1] < 0 || $str[1] > 59)
+ return null;
return $str[0] * 60 + $str[1];
}
- private function writeLocationConfig()
+ private function writeLocationConfig(): void
{
// Check locations
$locationid = Request::post('locationid', false, 'int');
if ($locationid === false) {
Message::addError('main.parameter-missing', 'locationid');
- return false;
+ return;
}
if (Location::get($locationid) === false) {
Message::addError('location.invalid-location-id', $locationid);
- return false;
+ return;
}
User::assertPermission('location.edit', $locationid);
@@ -198,29 +200,23 @@ class Page_LocationInfo extends Page
));
}
}
-
- return true;
}
/**
* Get all location ids from the locationids parameter, which is comma separated, then split
- * and remove any ids that don't exist. The cleaned list will be returned
+ * and remove any ids that don't exist. The cleaned list will be returned.
+ * Will show error and redirect to main page if parameter is missing
+ *
* @param bool $failIfEmpty Show error and redirect to main page if parameter is missing or list is empty
* @return array list of locations from parameter
*/
- private function getLocationIdsFromRequest($failIfEmpty)
+ private function getLocationIdsFromRequest(): array
{
- $locationids = Request::post('locationids', false, 'string');
- if ($locationids === false) {
- if (!$failIfEmpty)
- return array();
- Message::addError('main.parameter-missing', 'locationids');
- Util::redirect('?do=locationinfo');
- }
+ $locationids = Request::post('locationids', Request::REQUIRED_EMPTY, 'string');
$locationids = explode(',', $locationids);
$all = array_map(function ($item) { return $item['locationid']; }, Location::queryLocations());
$locationids = array_filter($locationids, function ($item) use ($all) { return in_array($item, $all); });
- if ($failIfEmpty && empty($locationids)) {
+ if (empty($locationids)) {
Message::addError('main.parameter-empty', 'locationids');
Util::redirect('?do=locationinfo');
}
@@ -230,7 +226,7 @@ class Page_LocationInfo extends Page
/**
* Updated the config in the db.
*/
- private function writePanelConfig()
+ private function writePanelConfig(): void
{
// UUID - existing or new
$paneluuid = Request::post('uuid', false, 'string');
@@ -253,7 +249,7 @@ class Page_LocationInfo extends Page
}
// Permission
- $this->assertPanelPermission($paneluuid, 'panel.edit', $params['locationids']);
+ $this->assertPanelPermission($paneluuid, 'panel.edit', $params['locationids'] ?? []);
if ($paneluuid === 'new') {
$paneluuid = Util::randomUuid();
@@ -276,10 +272,13 @@ class Page_LocationInfo extends Page
Util::redirect('?do=locationinfo');
}
- private function preparePanelConfigDefault()
+ /**
+ * @return array{config: array, locationids: array}
+ */
+ private function preparePanelConfigDefault(): array
{
// Check locations
- $locationids = self::getLocationIdsFromRequest(true);
+ $locationids = self::getLocationIdsFromRequest();
if (count($locationids) > 4) {
$locationids = array_slice($locationids, 0, 4);
}
@@ -331,7 +330,10 @@ class Page_LocationInfo extends Page
return array('config' => $conf, 'locationids' => $locationids);
}
- private function preparePanelConfigUrl()
+ /**
+ * @return array{config: array, locationids: array}
+ */
+ private function preparePanelConfigUrl(): array
{
$bookmarkNames = Request::post('bookmarkNames', [], 'array');
$bookmarkUrls = Request::post('bookmarkUrls', [], 'array');
@@ -349,18 +351,22 @@ class Page_LocationInfo extends Page
'url' => Request::post('url', 'https://www.bwlehrpool.de/', 'string'),
'insecure-ssl' => Request::post('insecure-ssl', 0, 'int'),
'reload-minutes' => max(0, Request::post('reloadminutes', 0, 'int')),
- 'whitelist' => preg_replace("/[\r\n]+/ms", "\n", Request::post('whitelist', '', 'string')),
- 'blacklist' => preg_replace("/[\r\n]+/ms", "\n", Request::post('blacklist', '', 'string')),
+ 'whitelist' => preg_replace("/[\r\n]+/m", "\n", Request::post('whitelist', '', 'string')),
+ 'blacklist' => preg_replace("/[\r\n]+/m", "\n", Request::post('blacklist', '', 'string')),
'split-login' => Request::post('split-login', 0, 'bool'),
'browser' => Request::post('browser', 'slx-browser', 'string'),
'interactive' => Request::post('interactive', '0', 'bool'),
- 'bookmarks' => $bookmarkString ? $bookmarkString : '',
+ 'bookmarks' => $bookmarkString ?: '',
'allow-tty' => Request::post('allow-tty', '', 'string'),
+ 'zoom-factor' => Request::post('zoom-factor', 100, 'int'),
);
return array('config' => $conf, 'locationids' => []);
}
- private function preparePanelConfigSummary()
+ /**
+ * @return array{config: array, locationids: array}
+ */
+ private function preparePanelConfigSummary(): array
{
// Build json structure
$conf = array(
@@ -373,14 +379,14 @@ class Page_LocationInfo extends Page
$conf['panelupdate'] = 15;
}
// Check locations
- $locationids = self::getLocationIdsFromRequest(true);
+ $locationids = self::getLocationIdsFromRequest();
return array('config' => $conf, 'locationids' => $locationids);
}
/**
* Updates the server settings in the db.
*/
- private function updateServerSettings()
+ private function updateServerSettings(): void
{
User::assertPermission('backend.edit');
$serverid = Request::post('id', -1, 'int');
@@ -422,10 +428,10 @@ class Page_LocationInfo extends Page
*
* @param int $id Server id which connection should be checked.
*/
- private function checkConnection($serverid = 0)
+ private function checkConnection(int $serverid = 0): void
{
if ($serverid === 0) {
- Util::traceError('checkConnection called with no server id');
+ ErrorHandler::traceError('checkConnection called with no server id');
}
User::assertPermission('backend.check');
@@ -438,7 +444,8 @@ class Page_LocationInfo extends Page
LocationInfo::setServerError($serverid, 'Unknown backend type: ' . $dbresult['servertype']);
return;
}
- $credentialsOk = $serverInstance->setCredentials($serverid, json_decode($dbresult['credentials'], true));
+ $credentialsOk = $serverInstance->setCredentials($serverid,
+ (array)json_decode($dbresult['credentials'], true));
if ($credentialsOk) {
$serverInstance->checkConnection();
@@ -447,7 +454,7 @@ class Page_LocationInfo extends Page
LocationInfo::setServerError($serverid, $serverInstance->getErrors());
}
- private function loadBackends()
+ private function loadBackends(): array
{
// Get a list of all the backend types.
$servertypes = array();
@@ -459,7 +466,7 @@ class Page_LocationInfo extends Page
// Build list of defined backends
$serverlist = array();
$dbquery2 = Database::simpleQuery("SELECT * FROM `locationinfo_coursebackend` ORDER BY servername ASC");
- while ($row = $dbquery2->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery2 as $row) {
if (isset($servertypes[$row['servertype']])) {
$row['typename'] = $servertypes[$row['servertype']];
} else {
@@ -485,7 +492,7 @@ class Page_LocationInfo extends Page
/**
* Show the list of backends
*/
- private function showBackendsTable($serverlist)
+ private function showBackendsTable(array $serverlist): void
{
User::assertPermission('backend.*');
$data = array(
@@ -496,7 +503,7 @@ class Page_LocationInfo extends Page
Render::addTemplate('page-servers', $data);
}
- private function showBackendLog()
+ private function showBackendLog(): void
{
$id = Request::get('serverid', false, 'int');
if ($id === false) {
@@ -512,7 +519,7 @@ class Page_LocationInfo extends Page
$server['list'] = [];
$res = Database::simpleQuery('SELECT dateline, message FROM locationinfo_backendlog
WHERE serverid = :id ORDER BY logid DESC LIMIT 100', ['id' => $id]);
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$row['dateline_s'] = Util::prettyTime($row['dateline']);
$row['class'] = substr($row['message'], 0, 3) === '[F]' ? 'text-danger' : 'text-warning';
$row['message'] = Substr($row['message'], 3);
@@ -521,7 +528,7 @@ class Page_LocationInfo extends Page
Render::addTemplate('page-server-log', $server);
}
- private function showLocationsTable()
+ private function showLocationsTable(): void
{
$allowedLocations = User::getAllowedLocations('location.edit');
if (empty($allowedLocations)) {
@@ -536,7 +543,7 @@ class Page_LocationInfo extends Page
LEFT JOIN `locationinfo_coursebackend` AS cb USING (serverid)
LEFT JOIN `location` AS loc USING (locationid)");
- while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($dbquery as $row) {
$locid = (int)$row['locationid'];
if (!isset($locations[$locid]) || !in_array($locid, $allowedLocations))
continue;
@@ -547,6 +554,7 @@ class Page_LocationInfo extends Page
}
$locations[$locid] += array(
'openingGlyph' => $glyph,
+ 'strong' => $glyph === 'ok',
'backend' => $backend,
'lastCalendarUpdate' => Util::prettyTime($row['lastcalendarupdate']), // TODO
'backendMissing' => !CourseBackend::exists($row['servertype']),
@@ -575,11 +583,20 @@ class Page_LocationInfo extends Page
));
}
- private function showPanelsTable()
+ private function showPanelsTable(): void
{
$visibleLocations = User::getAllowedLocations('panel.list');
+ if (in_array(0, $visibleLocations)) {
+ $visibleLocations = true;
+ }
$editLocations = User::getAllowedLocations('panel.edit');
+ if (in_array(0, $editLocations)) {
+ $editLocations = true;
+ }
$assignLocations = USer::getAllowedLocations('panel.assign-client');
+ if (in_array(0, $assignLocations)) {
+ $assignLocations = true;
+ }
if (empty($visibleLocations)) {
Message::addError('main.no-permission');
return;
@@ -593,7 +610,7 @@ class Page_LocationInfo extends Page
}
$panels = array();
$locations = Location::getLocationsAssoc();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if ($row['paneltype'] === 'URL') {
$url = json_decode($row['panelconfig'], true)['url'];
$row['locations'] = $row['locationurl'] = $url;
@@ -602,14 +619,16 @@ class Page_LocationInfo extends Page
} else {
$lids = explode(',', $row['locationids']);
// Permissions
- if (!empty(array_diff($lids, $visibleLocations))) {
+ if ($visibleLocations !== true && !empty(array_diff($lids, $visibleLocations))) {
continue;
}
- $row['edit_disabled'] = !empty(array_diff($lids, $editLocations)) ? 'disabled' : '';
- $row['runmode_disabled'] = !empty(array_diff($lids, $assignLocations)) ? 'disabled' : '';
+ $row['edit_disabled'] = $editLocations !== true && !empty(array_diff($lids, $editLocations))
+ ? 'disabled' : '';
+ $row['runmode_disabled'] = $assignLocations !== true && !empty(array_diff($lids, $assignLocations))
+ ? 'disabled' : '';
// Locations
$locs = array_map(function ($id) use ($locations) {
- return isset($locations[$id]) ? $locations[$id]['locationname'] : $id;
+ return isset($locations[$id]) ? $locations[$id]['locationname'] : "<<deleted=$id>>";
}, $lids);
$row['locations'] = implode(', ', $locs);
}
@@ -648,7 +667,7 @@ class Page_LocationInfo extends Page
*
* @param int $id Serverid
*/
- private function ajaxServerSettings($id)
+ private function ajaxServerSettings(int $id): void
{
User::assertPermission('backend.edit');
$oldConfig = Database::queryFirst('SELECT servername, servertype, credentials
@@ -679,7 +698,7 @@ class Page_LocationInfo extends Page
} else {
$cred->initForRender();
}
- $cred->title = Dictionary::translateFile('backend-' . $s, $cred->property, true);
+ $cred->title = Dictionary::translateFile('backend-' . $s, $cred->property);
$cred->helptext = Dictionary::translateFile('backend-' . $s, $cred->property . "_helptext");
$cred->credentialsHtml = Render::parse('server-prop-' . $cred->template, (array)$cred);
}
@@ -697,7 +716,7 @@ class Page_LocationInfo extends Page
*
* @param int $id id of the location
*/
- private function ajaxConfigLocation($id)
+ private function ajaxConfigLocation(int $id): void
{
User::assertPermission('location.edit', $id);
$locConfig = Database::queryFirst("SELECT info.serverid, info.serverlocationid, loc.openingtime
@@ -721,7 +740,7 @@ class Page_LocationInfo extends Page
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)) {
+ foreach ($res as $row) {
if ($best === false || $chain[$row['locationid']] < $chain[$best['locationid']]) {
$best = $row;
}
@@ -735,7 +754,7 @@ class Page_LocationInfo extends Page
// 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)) {
+ foreach ($res as $row) {
if ($row['serverid'] == $locConfig['serverid']) {
$row['selected'] = 'selected';
}
@@ -752,12 +771,6 @@ class Page_LocationInfo extends Page
echo Render::parse('ajax-config-location', $data);
}
- private function fmtTime($time)
- {
- $t = explode(':', $time);
- return sprintf('%02d:%02d', $t[0], $t[1]);
- }
-
/**
* Checks if simple mode or expert mode is active.
* Tries to merge/compact the opening times schedule, and
@@ -766,7 +779,7 @@ class Page_LocationInfo extends Page
*
* @return array new optimized openingtimes
*/
- private function compressTimes(&$array)
+ private function compressTimes(array $array): array
{
if (empty($array))
return [];
@@ -774,9 +787,9 @@ class Page_LocationInfo extends Page
$DAYLIST = array_flip(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']);
$new = [];
foreach ($array as $row) {
- $s = $this->getTime($row['openingtime']);
- $e = $this->getTime($row['closingtime']);
- if ($s === false || $e === false || $e <= $s)
+ $s = Page_LocationInfo::getTime($row['openingtime']);
+ $e = Page_LocationInfo::getTime($row['closingtime']);
+ if ($s === null || $e === null || $e <= $s)
continue;
foreach ($row['days'] as $day) {
$day = $DAYLIST[$day] ?? -1;
@@ -811,9 +824,9 @@ class Page_LocationInfo extends Page
/**
* @param array $daysArray List of days, "Monday", "Tuesday" etc. Must not contain duplicates.
- * @return string Human readable representation of list of days
+ * @return string Human-readable representation of list of days
*/
- private function buildDaysString(array $daysArray)
+ private function buildDaysString(array $daysArray): string
{
/* Dictionary::translate('monday') Dictionary::translate('tuesday') Dictionary::translate('wednesday')
* Dictionary::translate('thursday') Dictionary::translate('friday') Dictionary::translate('saturday')
@@ -831,10 +844,10 @@ class Page_LocationInfo extends Page
// Chain
$last++;
} else {
- $string = Dictionary::translate($DAYLIST[$first], true);
+ $string = Dictionary::translate($DAYLIST[$first]);
if ($first !== $last) {
$string .= ($first + 1 === $last ? ",\xe2\x80\x89" : "\xe2\x80\x89-\xe2\x80\x89")
- . Dictionary::translate($DAYLIST[$last], true);
+ . Dictionary::translate($DAYLIST[$last]);
}
$output[] = $string;
$first = $last = $day;
@@ -870,7 +883,7 @@ class Page_LocationInfo extends Page
// $start must lie before range start, otherwise we'd have hit the case above
$e = $current[1];
unset($array[$day][$key]);
- continue;
+ //continue;
}
}
$array[$day][] = array($s, $e);
@@ -878,10 +891,8 @@ class Page_LocationInfo extends Page
/**
* Ajax the config of a panel.
- *
- * @param $id Location ID
*/
- private function showPanelConfig()
+ private function showPanelConfig(): void
{
$id = Request::get('uuid', false, 'string');
if ($id === false) {
@@ -1000,6 +1011,7 @@ class Page_LocationInfo extends Page
'uuid' => $id,
'panelname' => $panel['panelname'],
'url' => $config['url'],
+ 'zoom-factor' => $config['zoom-factor'],
'ssl_checked' => $config['insecure-ssl'] ? 'checked' : '',
'reloadminutes' => (int)$config['reload-minutes'],
'whitelist' => str_replace("\n", "\r\n", $config['whitelist']),
@@ -1025,7 +1037,7 @@ class Page_LocationInfo extends Page
}
}
- private function showPanel()
+ private function showPanel(): void
{
$uuid = Request::get('uuid', false, 'string');
if ($uuid === false) {
@@ -1033,7 +1045,7 @@ class Page_LocationInfo extends Page
die('Missing parameter uuid');
}
$type = InfoPanel::getConfig($uuid, $config);
- if ($type === false) {
+ if ($type === null) {
http_response_code(404);
die('Panel with given uuid not found');
}
@@ -1060,7 +1072,7 @@ class Page_LocationInfo extends Page
'language' => $config['language'],
);
- die(Render::parse('frontend-default', $data, $module = false, $lang = $config['language']));
+ die(Render::parse('frontend-default', $data, null, $config['language']));
}
if ($type === 'SUMMARY') {
@@ -1072,7 +1084,7 @@ class Page_LocationInfo extends Page
'language' => $config['language'],
);
- die(Render::parse('frontend-summary', $data, $module = false, $lang = $config['language']));
+ die(Render::parse('frontend-summary', $data, null, $config['language']));
}
http_response_code(500);
@@ -1081,10 +1093,9 @@ class Page_LocationInfo extends Page
/**
* @param string|array $panelOrUuid UUID of panel, or array with keys paneltype and locationds
- * @param string $permission
- * @param null|int[] $additionalLocations
+ * @param int[] $additionalLocations
*/
- private function assertPanelPermission($panelOrUuid, $permission, $additionalLocations = null)
+ private function assertPanelPermission($panelOrUuid, string $permission, array $additionalLocations = null): void
{
if (is_array($panelOrUuid)) {
$panel = $panelOrUuid;
diff --git a/modules-available/locationinfo/templates/frontend-default.html b/modules-available/locationinfo/templates/frontend-default.html
index 6e04550d..cc62075e 100755
--- a/modules-available/locationinfo/templates/frontend-default.html
+++ b/modules-available/locationinfo/templates/frontend-default.html
@@ -564,6 +564,8 @@ optional:
putInRange(config, 'rotation', 0, 3, 0);
}
+ var updateTimer = null;
+
/**
* generates the Room divs and calls the needed functions depending on the rooms mode
*/
@@ -651,7 +653,7 @@ optional:
}
mainUpdateLoop();
- setInterval(mainUpdateLoop, 10000);
+ updateTimer = setInterval(mainUpdateLoop, 10000);
setInterval(updateHeaders, globalConfig.eco ? 10000 : 1000);
}
@@ -679,7 +681,14 @@ optional:
var today = date.getDate();
if (lastDate !== false) {
if (lastDate !== today) {
- location.reload(true);
+ if (updateTimer !== null) {
+ clearInterval(updateTimer);
+ updateTimer = null;
+ }
+ // Delay by a minute, sometimes the calendar shows the previous day if we load too quickly.
+ setTimeout(function() {
+ location.reload(true);
+ }, 60000);
}
} else {
lastDate = today;
@@ -1326,7 +1335,6 @@ optional:
/========================================== Room Layout =============================================
*/
-
const picSizeX = 3.8;
const picSizeY = 3;
diff --git a/modules-available/locationinfo/templates/page-config-panel-url.html b/modules-available/locationinfo/templates/page-config-panel-url.html
index 365e15db..3aaf8620 100644
--- a/modules-available/locationinfo/templates/page-config-panel-url.html
+++ b/modules-available/locationinfo/templates/page-config-panel-url.html
@@ -188,10 +188,10 @@
</div>
<div class="col-sm-3">
<input class="form-control" name="bookmarkUrls[]" type="text" value=""
- placeholder="http://www.bwlehrpool.de/" pattern=".*://.*">
+ placeholder="https://www.bwlehrpool.de/" pattern=".*://.*">
</div>
<div class="col-sm-1">
- <button type="button" class="btn btn-danger" onclick="this.closest('.row').remove()">
+ <button type="button" class="btn btn-danger" onclick="$(this).closest('.row').remove()">
<span class="glyphicon glyphicon-minus"></span>
</button>
</div>
@@ -208,7 +208,7 @@
placeholder="http://www.bwlehrpool.de/" pattern=".*://.*" required>
</div>
<div class="col-sm-1">
- <button type="button" class="btn btn-danger" onclick="this.closest('.row').remove()">
+ <button type="button" class="btn btn-danger" onclick="$(this).closest('.row').remove()">
<span class="glyphicon glyphicon-minus"></span>
</button>
</div>
@@ -216,6 +216,24 @@
{{/bookmarks}}
</div>
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-sm-4">
+ <label for="zoom-factor">{{lang_zoomFactor}}</label>
+ </div>
+ <div class="col-sm-7 col-xs-10">
+ <input class="form-control" id="zoom-factor" type="range" min="50" max="300" step="5"
+ name="zoom-factor" value="{{zoom-factor}}">
+ </div>
+ <div class="col-sm-1 col-xs-2" id="zoom-value">
+
+ </div>
+ <div class="col-sm-12 small text-muted spacebottop">
+ {{lang_zoomFactorTooltip}}
+ </div>
+ </div>
+ </div>
+
</div>
</div>
<div class="text-right">
@@ -227,12 +245,19 @@
</div>
</form>
-<script type="text/javascript"><!--
+<script>
document.addEventListener("DOMContentLoaded", function () {
// load value to dropdown menus
- $('#browser option[value="{{browser}}"]').attr("selected", "selected");
+ $('#browser option[value="{{browser}}"]').prop("selected", true);
browserChange();
+ var $zv = $('#zoom-value');
+ var $zf = $('#zoom-factor');
+ var sliderUpdate = function() {
+ $zv.text($zf.val() + '%');
+ };
+ $zf.on('input', sliderUpdate);
+ sliderUpdate();
});
// Hide interactive-input if slx-browser is selected
@@ -257,4 +282,4 @@ function addBookmark() {
$('#bookmarks').append(rowCopy);
}
-//--></script>
+</script>
diff --git a/modules-available/locationinfo/templates/page-locations.html b/modules-available/locationinfo/templates/page-locations.html
index fa2e3a2d..c09b5336 100644
--- a/modules-available/locationinfo/templates/page-locations.html
+++ b/modules-available/locationinfo/templates/page-locations.html
@@ -35,7 +35,7 @@
{{/backend}}
</td>
<td class="text-center">
- <span class="glyphicon glyphicon-{{openingGlyph}}"></span>
+ <span class="glyphicon glyphicon-{{openingGlyph}} {{^strong}}text-muted{{/strong}}"></span>
</td>
</tr>
{{/list}}