<?php
class SubPage
{
public static function doPreprocess($action): bool
{
if ($action === 'addlocations') {
self::addLocations();
return true;
}
return false;
}
public static function doRender($getAction): bool
{
if ($getAction === false) {
if (User::hasPermission('location.view')) {
// OK
} elseif (User::hasPermission('subnets.edit')) {
// Fallback to something else?
Util::redirect('?do=locations&page=subnets');
} else {
// Trigger permission denied by asserting non-existent permission
User::assertPermission('location.view');
}
}
if ($getAction === false) {
self::showLocationList();
return true;
}
return false;
}
public static function doAjax($action): bool
{
return false;
}
private static function addLocations()
{
$names = Request::post('newlocation', false);
$parents = Request::post('newparent', []);
if (!is_array($names) || !is_array($parents)) {
Message::addError('main.empty-field');
Util::redirect('?do=Locations');
}
$locs = Location::getLocations();
$count = 0;
foreach ($names as $idx => $name) {
$name = trim($name);
if (empty($name))
continue;
$parent = isset($parents[$idx]) ? (int)$parents[$idx] : 0;
if (!User::hasPermission("location.add", $parent)) {
Message::addError('no-permission-location', isset($locs[$parent]) ? $locs[$parent]['locationname'] : $parent);
continue;
}
if ($parent !== 0) {
$ok = false;
foreach ($locs as $loc) {
if ($loc['locationid'] == $parent) {
$ok = true;
}
}
if (!$ok) {
Message::addWarning('main.value-invalid', 'parentlocationid', $parent);
continue;
}
}
Database::exec("INSERT INTO location (parentlocationid, locationname)"
. " VALUES (:parent, :name)", array(
'parent' => $parent,
'name' => $name
));
$count++;
}
Message::addSuccess('added-x-entries', $count);
Util::redirect('?do=Locations');
}
public static function showLocationList()
{
// Warn admin about overlapping subnet definitions
$overlapSelf = $overlapOther = true;
LocationUtil::getOverlappingSubnets($overlapSelf, $overlapOther);
// Find machines assigned to a room with a UUID mismatch
$mismatchMachines = LocationUtil::getMachinesWithLocationMismatch(0, true);
$locationList = Location::getLocationsAssoc();
unset($locationList[0]);
// Statistics: Count machines for each subnet
$unassigned = false;
$unassignedIdle = $unassignedLoad = $unassignedOverrides = 0;
$allowedLocationIds = User::getAllowedLocations("location.view");
$plugins = [];
foreach (Hook::load('locations-column') as $hook) {
$c = @include($hook->file);
if ($c instanceof AbstractLocationColumn) {
$plugins[sprintf('%04d.%s', $c->priority(), $hook->moduleId)] = $c;
} elseif (is_array($c)) {
foreach ($c as $i => $cc) {
if ($cc instanceof AbstractLocationColumn) {
$plugins[sprintf('%04d.%d.%s', $cc->priority(), $i, $hook->moduleId)] = $cc;
}
}
}
}
ksort($plugins);
foreach ($locationList as $lid => &$loc) {
$loc['plugins'] = [];
foreach ($plugins as $pk => $plugin) {
$loc['plugins'][$pk] = [
'url' => $plugin->getEditUrl($lid),
'html' => $plugin->getColumnHtml($lid),
];
}
if (!in_array($lid, $allowedLocationIds)) {
$locationList[$lid]['show-only'] = true;
}
}
unset($loc);
foreach ($plugins as $pk => $plugin) {
if ($plugin->propagateColumn()) {
self::propagateFields($locationList, $plugin, $pk);
}
}
foreach ($locationList as &$loc) {
$loc['plugins'] = array_values($loc['plugins']);
}
unset($loc);
$addAllowedLocs = User::getAllowedLocations("location.add");
$addAllowedList = Location::getLocations(0, 0, true);
foreach ($addAllowedList as &$loc) {
if (!in_array($loc["locationid"], $addAllowedLocs)) {
$loc["disabled"] = "disabled";
}
}
unset($loc);
// Output
$data = [
'colspan' => (2 + count($plugins)),
'plugins' => array_values($plugins),
'list' => array_values($locationList),
'overlapSelf' => $overlapSelf,
'overlapOther' => $overlapOther,
'mismatchMachines' => $mismatchMachines,
'addAllowedList' => array_values($addAllowedList),
];
Permission::addGlobalTags($data['perms'], NULL, ['subnets.edit', 'location.add']);
Render::addTemplate('locations', $data);
Module::isAvailable('js_ip'); // For CIDR magic
}
private static function propagateFields(array &$locationList, AbstractLocationColumn $plugin, string $pluginKey)
{
$depth = array();
foreach ($locationList as &$loc) {
$d = $loc['depth'];
if (empty($loc['plugins'][$pluginKey]['html'])) {
// Has no explicit config assignment
$loc['plugins'][$pluginKey]['html'] = $depth[$d - 1] ?? $plugin->propagateDefaultHtml();
$loc['plugins'][$pluginKey]['class'] = 'gray';
} elseif (empty($loc['plugins'][$pluginKey]['class'])) {
$loc['plugins'][$pluginKey]['class'] = 'slx-bold';
$loc['plugins'][$pluginKey]['html'] =
$plugin->propagationOverride($depth[$d - 1] ?? $plugin->propagateDefaultHtml(),
$loc['plugins'][$pluginKey]['html']);
}
$depth[$d] = $loc['plugins'][$pluginKey]['html'];
unset($depth[$d + 1]);
}
}
}