summaryrefslogtreecommitdiffstats
path: root/modules-available/locations/inc
diff options
context:
space:
mode:
authorSimon Rettberg2016-05-25 18:11:58 +0200
committerSimon Rettberg2016-05-25 18:11:58 +0200
commit69504022a57b08774e212d741290d2b587d0230d (patch)
treea6359556265ab4b03427c17603a7c99eda31a5f6 /modules-available/locations/inc
parent[baseconfig] Add notice when editing subsection (diff)
downloadslx-admin-69504022a57b08774e212d741290d2b587d0230d.tar.gz
slx-admin-69504022a57b08774e212d741290d2b587d0230d.tar.xz
slx-admin-69504022a57b08774e212d741290d2b587d0230d.zip
[locations] Add machine count to each location
Diffstat (limited to 'modules-available/locations/inc')
-rw-r--r--modules-available/locations/inc/location.inc.php141
1 files changed, 129 insertions, 12 deletions
diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php
index 1a01ff24..4bfe9f7a 100644
--- a/modules-available/locations/inc/location.inc.php
+++ b/modules-available/locations/inc/location.inc.php
@@ -5,7 +5,17 @@ class Location
private static $flatLocationCache = false;
private static $assocLocationCache = false;
-
+ private static $treeCache = false;
+
+ private static function getTree()
+ {
+ if (self::$treeCache === false) {
+ self::$treeCache = self::queryLocations();
+ self::$treeCache = self::buildTree(self::$treeCache);
+ }
+ return self::$treeCache;
+ }
+
public static function queryLocations()
{
$res = Database::simpleQuery("SELECT locationid, parentlocationid, locationname FROM location");
@@ -24,28 +34,31 @@ class Location
return false;
return self::$assocLocationCache[$locationId]['locationname'];
}
-
+
public static function getLocationsAssoc()
{
if (self::$assocLocationCache === false) {
- $rows = self::queryLocations();
- $rows = self::buildTree($rows);
+ $rows = self::getTree();
self::$assocLocationCache = self::flattenTreeAssoc($rows);
}
return self::$assocLocationCache;
}
-
- private static function flattenTreeAssoc($tree, $depth = 0)
+
+ private static function flattenTreeAssoc($tree, $parents = array(), $depth = 0)
{
+ if ($depth > 20) {
+ Util::traceError('Recursive location definition detected at ' . print_r($tree, true));
+ }
$output = array();
foreach ($tree as $node) {
$output[(int)$node['locationid']] = array(
'parentlocationid' => (int)$node['parentlocationid'],
+ 'parents' => $parents,
'locationname' => $node['locationname'],
'depth' => $depth
);
if (!empty($node['children'])) {
- $output += self::flattenTreeAssoc($node['children'], $depth + 1);
+ $output += self::flattenTreeAssoc($node['children'], array_merge($parents, array((int)$node['locationid'])), $depth + 1);
}
}
return $output;
@@ -54,8 +67,7 @@ class Location
public static function getLocations($default = 0, $excludeId = 0, $addNoParent = false)
{
if (self::$flatLocationCache === false) {
- $rows = self::queryLocations();
- $rows = self::buildTree($rows);
+ $rows = self::getTree();
$rows = self::flattenTree($rows);
self::$flatLocationCache = $rows;
} else {
@@ -109,6 +121,9 @@ class Location
private static function flattenTree($tree, $depth = 0)
{
+ if ($depth > 20) {
+ Util::traceError('Recursive location definition detected at ' . print_r($tree, true));
+ }
$output = array();
foreach ($tree as $node) {
$output[] = array(
@@ -137,7 +152,7 @@ class Location
}
return $ids;
}
-
+
public static function getFromIp($ip)
{
$locationId = false;
@@ -147,11 +162,113 @@ class Location
while ($row = $net->fetch(PDO::FETCH_ASSOC)) {
$locations = self::getLocationsAssoc();
$id = (int)$row['locationid'];
- if (!isset($locations[$id])) continue;
- if ($locationId !== false && $locations[$id]['depth'] <= $locations[$locationId]['depth']) continue;
+ if (!isset($locations[$id]))
+ continue;
+ if ($locationId !== false && $locations[$id]['depth'] <= $locations[$locationId]['depth'])
+ continue;
$locationId = $id;
}
return $locationId;
}
+ /**
+ * @return array list of subnets as numeric array
+ */
+ public static function getSubnets()
+ {
+ $res = Database::simpleQuery("SELECT startaddr, endaddr, locationid FROM subnet");
+ $subnets = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ settype($row['locationid'], 'int');
+ $subnets[] = $row;
+ }
+ return $subnets;
+ }
+
+ /**
+ * @return array|bool assoc array mapping from locationid to subnets
+ */
+ public static function getSubnetsByLocation(&$overlapSelf, &$overlapOther)
+ {
+ $locs = self::getLocationsAssoc();
+ $subnets = self::getSubnets();
+ // Find locations having nets overlapping with themselves if array was passed
+ if ($overlapSelf === true || $overlapOther === true) {
+ self::findOverlap($locs, $subnets, $overlapSelf, $overlapOther);
+ }
+ // Accumulate - copy up subnet definitions
+ foreach ($locs as &$loc) {
+ $loc['subnets'] = array();
+ }
+ unset($loc);
+ foreach ($subnets as $subnet) {
+ $lid = $subnet['locationid'];
+ while (isset($locs[$lid])) {
+ $locs[$lid]['subnets'][] = array(
+ 'startaddr' => $subnet['startaddr'],
+ 'endaddr' => $subnet['endaddr']
+ );
+ $lid = $locs[$lid]['parentlocationid'];
+ }
+ }
+ return $locs;
+ }
+
+ private static function findOverlap($locs, $subnets, &$overlapSelf, &$overlapOther)
+ {
+ if ($overlapSelf) {
+ $self = array();
+ }
+ if ($overlapOther) {
+ $other = array();
+ }
+ $cnt = count($subnets);
+ for ($i = 0; $i < $cnt; ++$i) {
+ for ($j = $i + 1; $j < $cnt; ++$j) {
+ if ($overlapSelf && $subnets[$i]['locationid'] === $subnets[$j]['locationid']
+ && self::overlap($subnets[$i], $subnets[$j])
+ ) {
+ $self[$subnets[$i]['locationid']] = $subnets[$i]['locationid'];
+ }
+ if ($overlapOther && $subnets[$i]['locationid'] !== $subnets[$j]['locationid']
+ && self::overlap($subnets[$i], $subnets[$j])
+ ) {
+ $a = min($subnets[$i]['locationid'], $subnets[$j]['locationid']);
+ $b = max($subnets[$i]['locationid'], $subnets[$j]['locationid']);
+ $other["$a|$b"] = array('lid1' => $subnets[$i]['locationid'], 'lid2' => $subnets[$j]['locationid']);
+ }
+ }
+ }
+ if ($overlapSelf) {
+ $overlapSelf = array();
+ foreach ($self as $entry) {
+ if (!isset($locs[$entry]))
+ continue;
+ $overlapSelf[]['locationname'] = $locs[$entry['locationid']]['locationname'];
+ }
+ }
+ if ($overlapOther) {
+ $overlapOther = array();
+ foreach ($other as $entry) {
+ 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;
+ if (isset($locs[$entry['lid1']])) {
+ $entry['name1'] = $locs[$entry['lid1']]['locationname'];
+ }
+ if (isset($locs[$entry['lid2']])) {
+ $entry['name2'] = $locs[$entry['lid2']]['locationname'];
+ }
+ $overlapOther[] = $entry;
+ }
+ }
+ }
+
+ private static function overlap($net1, $net2)
+ {
+ return ($net1['startaddr'] >= $net2['startaddr'] && $net1['startaddr'] <= $net2['endaddr'])
+ || ($net1['endaddr'] >= $net2['startaddr'] && $net1['endaddr'] <= $net2['endaddr']);
+ }
+
}