summaryrefslogtreecommitdiffstats
path: root/modules-available/locations/inc
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/locations/inc')
-rw-r--r--modules-available/locations/inc/abstractlocationcolumn.inc.php29
-rw-r--r--modules-available/locations/inc/autolocation.inc.php2
-rw-r--r--modules-available/locations/inc/location.inc.php87
-rw-r--r--modules-available/locations/inc/locationhooks.inc.php6
-rw-r--r--modules-available/locations/inc/locationutil.inc.php32
-rw-r--r--modules-available/locations/inc/openingtimes.inc.php62
6 files changed, 149 insertions, 69 deletions
diff --git a/modules-available/locations/inc/abstractlocationcolumn.inc.php b/modules-available/locations/inc/abstractlocationcolumn.inc.php
new file mode 100644
index 00000000..65224da9
--- /dev/null
+++ b/modules-available/locations/inc/abstractlocationcolumn.inc.php
@@ -0,0 +1,29 @@
+<?php
+
+abstract class AbstractLocationColumn
+{
+
+ public abstract function getColumnHtml(int $locationId): string;
+
+ public abstract function getEditUrl(int $locationId): string;
+
+ public abstract function header(): string;
+
+ public abstract function priority(): int;
+
+ public function propagateColumn(): bool
+ {
+ return false;
+ }
+
+ public function propagationOverride(string $parent, string $data): string
+ {
+ return $data;
+ }
+
+ public function propagateDefaultHtml(): string
+ {
+ return $this->getColumnHtml(0);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/locations/inc/autolocation.inc.php b/modules-available/locations/inc/autolocation.inc.php
index 82c61251..f77cf714 100644
--- a/modules-available/locations/inc/autolocation.inc.php
+++ b/modules-available/locations/inc/autolocation.inc.php
@@ -22,7 +22,7 @@ class AutoLocation
}
$updates = array();
$nulls = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$loc = Location::mapIpToLocation($row['clientip']);
if ($loc === false) {
$nulls[] = $row['machineuuid'];
diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php
index 700edaf8..807f8577 100644
--- a/modules-available/locations/inc/location.inc.php
+++ b/modules-available/locations/inc/location.inc.php
@@ -8,7 +8,7 @@ class Location
private static $treeCache = false;
private static $subnetMapCache = false;
- public static function getTree()
+ public static function getTree(): array
{
if (self::$treeCache === false) {
self::$treeCache = self::queryLocations();
@@ -17,11 +17,11 @@ class Location
return self::$treeCache;
}
- public static function queryLocations()
+ public static function queryLocations(): array
{
$res = Database::simpleQuery("SELECT locationid, parentlocationid, locationname FROM location");
$rows = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$rows[] = $row;
}
return $rows;
@@ -29,10 +29,9 @@ class Location
/**
* Return row from location table for $locationId.
- * @param $locationId
* @return array|bool row from DB, false if not found
*/
- public static function get($locationId)
+ public static function get(int $locationId)
{
return Database::queryFirst("SELECT * FROM location WHERE locationid = :locationId", compact('locationId'));
}
@@ -42,9 +41,8 @@ class Location
* @param int $locationId id of location to get name for
* @return string|false Name of location, false if locationId doesn't exist
*/
- public static function getName($locationId)
+ public static function getName(int $locationId)
{
- $locationId = (int)$locationId;
if (self::$assocLocationCache === false) {
self::getLocationsAssoc();
}
@@ -56,15 +54,13 @@ class Location
/**
* Get all the names of the given location and its parents, up
* to the root element. Array keys will be locationids, value the names.
- * @param int $locationId
* @return array|false locations, from furthest to nearest or false if locationId doesn't exist
*/
- public static function getNameChain($locationId)
+ public static function getNameChain(int $locationId)
{
if (self::$assocLocationCache === false) {
self::getLocationsAssoc();
}
- $locationId = (int)$locationId;
if (!isset(self::$assocLocationCache[$locationId]))
return false;
$ret = array();
@@ -84,10 +80,10 @@ class Location
return self::$assocLocationCache;
}
- private static function flattenTreeAssoc($tree, $parents = array(), $depth = 0)
+ private static function flattenTreeAssoc($tree, $parents = array(), $depth = 0): array
{
if ($depth > 20) {
- Util::traceError('Recursive location definition detected at ' . print_r($tree, true));
+ ErrorHandler::traceError('Recursive location definition detected at ' . print_r($tree, true));
}
$output = array();
foreach ($tree as $node) {
@@ -121,12 +117,12 @@ class Location
/**
* @param int|int[] $selected Which locationIDs to mark as selected
- * @param int $excludeId Which locationID to explude
+ * @param int $excludeId Which locationID to exclude
* @param bool $addNoParent Add entry for "no location" at the top
* @param bool $keepArrayKeys Keep location IDs as array index
* @return array Locations
*/
- public static function getLocations($selected = 0, $excludeId = 0, $addNoParent = false, $keepArrayKeys = false)
+ public static function getLocations($selected = 0, int $excludeId = 0, bool $addNoParent = false, bool $keepArrayKeys = false): array
{
if (self::$flatLocationCache === false) {
$rows = self::getTree();
@@ -170,15 +166,15 @@ class Location
* Get nested array of all the locations and children of given locationid(s).
*
* @param int[]|int $idList List of location ids
- * @param bool $locationTree used in recursive calls, don't pass
+ * @param ?array $locationTree used in recursive calls, don't pass
* @return array list of passed locations plus their children
*/
- public static function getRecursive($idList, $locationTree = false)
+ public static function getRecursive($idList, ?array $locationTree = null): array
{
if (!is_array($idList)) {
$idList = array($idList);
}
- if ($locationTree === false) {
+ if ($locationTree === null) {
$locationTree = self::getTree();
}
$ret = array();
@@ -198,7 +194,7 @@ class Location
* @param int[]|int $idList List of location ids
* @return array list of passed locations plus their children
*/
- public static function getRecursiveFlat($idList)
+ public static function getRecursiveFlat($idList): array
{
$ret = self::getRecursive($idList);
if (!empty($ret)) {
@@ -207,7 +203,7 @@ class Location
return $ret;
}
- public static function buildTree($elements, $parentId = 0)
+ public static function buildTree(array $elements, int $parentId = 0): array
{
$branch = array();
$sort = array();
@@ -227,10 +223,10 @@ class Location
return $branch;
}
- private static function flattenTree($tree, $depth = 0)
+ private static function flattenTree(array $tree, int $depth = 0): array
{
if ($depth > 20) {
- Util::traceError('Recursive location definition detected at ' . print_r($tree, true));
+ ErrorHandler::traceError('Recursive location definition detected at ' . print_r($tree, true));
}
$output = array();
foreach ($tree as $node) {
@@ -249,16 +245,16 @@ class Location
return $output;
}
- public static function isLeaf($locationid) {
+ public static function isLeaf(int $locationid): bool
+ {
$result = Database::queryFirst('SELECT COUNT(locationid) = 0 AS isleaf '
. 'FROM location '
. 'WHERE parentlocationid = :locationid', ['locationid' => $locationid]);
$result = $result['isleaf'];
- $result = (bool)$result;
- return $result;
+ return (bool)$result;
}
- public static function extractIds($tree)
+ public static function extractIds(array $tree): array
{
$ids = array();
foreach ($tree as $node) {
@@ -272,10 +268,11 @@ class Location
/**
* Get location id for given machine (by uuid)
+ *
* @param string $uuid machine uuid
- * @return bool|int locationid, false if no match
+ * @return false|int locationid, false if no match
*/
- public static function getFromMachineUuid($uuid)
+ public static function getFromMachineUuid(string $uuid)
{
// Only if we have the statistics module which supplies the machine table
if (Module::get('statistics') === false)
@@ -292,9 +289,9 @@ class Location
*
* @param string $ip IP address of client
* @param bool $honorRoomPlanner consider a fixed location assigned manually by roomplanner
- * @return bool|int locationid, or false if no match
+ * @return false|int locationid, or false if no match
*/
- public static function getFromIp($ip, $honorRoomPlanner = false)
+ public static function getFromIp(string $ip, bool $honorRoomPlanner = false)
{
if (Module::get('statistics') !== false) {
// Shortcut - try to use subnetlocationid in machine table
@@ -323,17 +320,17 @@ class Location
* client, so if it seems too fishy, the UUID will be ignored.
*
* @param string $ip IP address of client
- * @param string $uuid System-UUID of client
- * @return int|bool location id, or false if none matches
+ * @param ?string $uuid System-UUID of client
+ * @return int|false location id, or false if none matches
*/
- public static function getFromIpAndUuid($ip, $uuid)
+ public static function getFromIpAndUuid(string $ip, ?string $uuid)
{
$locationId = false;
$ipLoc = self::getFromIp($ip);
if ($ipLoc !== false) {
// Set locationId to ipLoc for now, it will be overwritten later if another case applies.
$locationId = $ipLoc;
- if ($uuid !== false) {
+ if ($uuid !== null) {
// Machine ip maps to a location, and we have a client supplied uuid (which might not be known if the client boots for the first time)
$uuidLoc = self::getFromMachineUuid($uuid);
if (self::isFixedLocationValid($uuidLoc, $ipLoc)) {
@@ -344,7 +341,7 @@ class Location
return $locationId;
}
- public static function isFixedLocationValid($uuidLoc, $ipLoc)
+ public static function isFixedLocationValid($uuidLoc, $ipLoc): bool
{
if ($uuidLoc === false)
return false;
@@ -367,12 +364,10 @@ class Location
/**
* Get all location IDs from the given location up to the root.
*
- * @param int $locationId
* @return int[] location ids, including $locationId
*/
- public static function getLocationRootChain($locationId)
+ public static function getLocationRootChain(int $locationId): array
{
- $locationId = (int)$locationId;
if (self::$assocLocationCache === false) {
self::getLocationsAssoc();
}
@@ -386,11 +381,11 @@ class Location
/**
* @return array list of subnets as numeric array
*/
- public static function getSubnets()
+ public static function getSubnets(): array
{
$res = Database::simpleQuery("SELECT startaddr, endaddr, locationid FROM subnet");
$subnets = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
settype($row['locationid'], 'int');
$subnets[] = $row;
}
@@ -398,9 +393,9 @@ class Location
}
/**
- * @return array|bool assoc array mapping from locationid to subnets
+ * @return array assoc array mapping from locationid to subnets
*/
- public static function getSubnetsByLocation($recursive = false)
+ public static function getSubnetsByLocation($recursive = false): array
{
$locs = self::getLocationsAssoc();
$subnets = self::getSubnets();
@@ -434,9 +429,9 @@ class Location
* random one will be returned.
*
* @param string $ip IP to look up
- * @return bool|int locationid ip matches, false = no match
+ * @return false|int locationid ip matches, false = no match
*/
- public static function mapIpToLocation($ip)
+ public static function mapIpToLocation(string $ip)
{
if (self::$subnetMapCache === false) {
self::$subnetMapCache = self::getSubnetsByLocation();
@@ -465,7 +460,10 @@ class Location
return (int)$best;
}
- public static function updateMapIpToLocation($uuid, $ip)
+ /**
+ * @return false|int newly determined location
+ */
+ public static function updateMapIpToLocation(string $uuid, string $ip)
{
$loc = self::mapIpToLocation($ip);
if ($loc === false) {
@@ -473,6 +471,7 @@ class Location
} else {
Database::exec("UPDATE machine SET subnetlocationid = :loc WHERE machineuuid = :uuid", compact('loc', 'uuid'));
}
+ return $loc;
}
}
diff --git a/modules-available/locations/inc/locationhooks.inc.php b/modules-available/locations/inc/locationhooks.inc.php
index 5ce3bbfe..f6ef02da 100644
--- a/modules-available/locations/inc/locationhooks.inc.php
+++ b/modules-available/locations/inc/locationhooks.inc.php
@@ -6,7 +6,7 @@ class LocationHooks
/**
* Resolve baseconfig id to locationid -- noop in this case
*/
- public static function baseconfigLocationResolver($id)
+ public static function baseconfigLocationResolver(int $id): int
{
return $id;
}
@@ -15,13 +15,13 @@ class LocationHooks
* Hook to get inheritance tree for all config vars
* @param int $id Locationid currently being edited
*/
- public static function baseconfigInheritance($id)
+ public static function baseconfigInheritance(int $id): array
{
$locs = Location::getLocationsAssoc();
if ($locs === false || !isset($locs[$id]))
return [];
BaseConfig::prepareWithOverrides([
- 'locationid' => $locs[$id]['parentlocationid']
+ 'locationid' => $locs[$id]['parentlocationid'] ?? 0
]);
return ConfigHolder::getRecursiveConfig(true);
}
diff --git a/modules-available/locations/inc/locationutil.inc.php b/modules-available/locations/inc/locationutil.inc.php
index 708cc8a2..91117445 100644
--- a/modules-available/locations/inc/locationutil.inc.php
+++ b/modules-available/locations/inc/locationutil.inc.php
@@ -48,7 +48,7 @@ class LocationUtil
if ($overlapOther) {
$overlapOther = array();
foreach ($other as $entry) {
- if (!isset($locs[$entry['lid1']]) || !isset($locs[$entry['lid2']]))
+ if (!isset($locs[$entry['lid1']]) && !isset($locs[$entry['lid2']]))
continue;
if (in_array($entry['lid1'], $locs[$entry['lid2']]['parents']) || in_array($entry['lid2'], $locs[$entry['lid1']]['parents']))
continue;
@@ -70,12 +70,9 @@ class LocationUtil
* grouped by the location the client was assigned to via roomplanner.
* Otherwise, just return an assoc array with the requested locationid, name
* and a list of all clients that are wrongfully assigned to that room.
- * @param int $locationId
- * @return array
*/
- public static function getMachinesWithLocationMismatch($locationId = 0, $checkPerms = false)
+ public static function getMachinesWithLocationMismatch(int $locationId = 0, bool $checkPerms = false): array
{
- $locationId = (int)$locationId;
if ($checkPerms) {
if ($locationId !== 0) {
// Query details for specific location -- use assert and fake array
@@ -124,7 +121,7 @@ class LocationUtil
$res = Database::simpleQuery($query, $params);
$return = [];
$locs = false;
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if (Location::isFixedLocationValid($row['fixedlocationid'], $row['subnetlocationid']))
continue;
$lid = (int)$row['fixedlocationid'];
@@ -162,19 +159,17 @@ class LocationUtil
}
if (empty($return))
return $return;
- if ($locationId === 0) {
+ if ($locationId === 0)
return array_values($return);
- } else {
- return $return[$locationId];
- }
+ return $return[$locationId];
}
- private static function overlap($net1, $net2)
+ private static function overlap(array $net1, array $net2): bool
{
return ($net1['startaddr'] <= $net2['endaddr'] && $net1['endaddr'] >= $net2['startaddr']);
}
- public static function rangeToLongVerbose($start, $end)
+ public static function rangeToLongVerbose(string $start, string $end): ?array
{
$result = self::rangeToLong($start, $end);
list($startLong, $endLong) = $result;
@@ -185,24 +180,19 @@ class LocationUtil
Message::addWarning('main.value-invalid', 'end addr', $start);
}
if ($startLong === false || $endLong === false)
- return false;
+ return null;
if ($startLong > $endLong) {
Message::addWarning('main.value-invalid', 'range', $start . ' - ' . $end);
- return false;
+ return null;
}
return $result;
}
- public static function rangeToLong($start, $end)
+ /** @return array{0: int, 1: int} */
+ public static function rangeToLong(string $start, string $end): array
{
$startLong = ip2long($start);
$endLong = ip2long($end);
- if ($startLong !== false) {
- $startLong = sprintf("%u", $startLong);
- }
- if ($endLong !== false) {
- $endLong = sprintf("%u", $endLong);
- }
return array($startLong, $endLong);
}
diff --git a/modules-available/locations/inc/openingtimes.inc.php b/modules-available/locations/inc/openingtimes.inc.php
new file mode 100644
index 00000000..74dae7c3
--- /dev/null
+++ b/modules-available/locations/inc/openingtimes.inc.php
@@ -0,0 +1,62 @@
+<?php
+
+class OpeningTimes
+{
+
+ /**
+ * Get opening times for given location.
+ * Format is the decoded JSON from DB column, i.e. currently a list of entries:
+ * <pre>{
+ * "days": ["Monday", "Tuesday", ...],
+ * "openingtime": "8:00",
+ * "closingtime": "20:00"
+ * }</pre>
+ */
+ public static function forLocation(int $locationId): ?array
+ {
+ static $openingTimesList = false;
+ if ($openingTimesList === false) {
+ $openingTimesList = Database::queryKeyValueList("SELECT locationid, openingtime FROM location
+ WHERE openingtime IS NOT NULL");
+ }
+ $chain = Location::getLocationRootChain($locationId);
+ foreach ($chain as $lid) {
+ if (isset($openingTimesList[$lid])) {
+ if (is_string($openingTimesList[$lid])) {
+ $openingTimesList[$lid] = json_decode($openingTimesList[$lid], true);
+ }
+ return $openingTimesList[$lid];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Check whether given location is open according to openingtimes.
+ * @param int $locationId location
+ * @param int $openOffsetMin offset to apply to opening times when checking. this is subtracted from opening time
+ * @param int $closeOffsetMin offset to apply to closing times when checking. this is added to closing time
+ */
+ public static function isRoomOpen(int $locationId, int $openOffsetMin = 0, int $closeOffsetMin = 0): bool
+ {
+ $openingTimes = self::forLocation($locationId);
+ if ($openingTimes === null)
+ return true; // No opening times should mean room is always open
+ $now = time();
+ $today = date('l', $now);
+ foreach ($openingTimes as $row) {
+ foreach ($row['days'] as $day) {
+ if ($day !== $today)
+ continue; // Not today!
+ if (strtotime("today {$row['openingtime']} -$openOffsetMin minutes") > $now)
+ continue;
+ if (strtotime("today {$row['closingtime']} +$closeOffsetMin minutes") < $now)
+ continue;
+ // Bingo!
+ return true;
+ }
+ }
+ return false;
+ }
+
+} \ No newline at end of file