Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 29 additions & 42 deletions packages/web/lib/fog/fogcontroller.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -1035,42 +1035,6 @@ public function buildQuery(
$not = false,
$compare = '='
) {
/**
* Lambda function to build the where array additionals.
*
* @param string $field the field to work from
* @param mixed $value the value of the field
*/
$whereInfo = function (
&$value,
$field
) use (
&$whereArrayAnd,
&$c,
$not,
$compare
) {
if (is_array($value)) {
$whereArrayAnd[] = sprintf(
"`%s`.`%s` IN ('%s')",
$c->databaseTable,
$field,
implode("','", $value)
);
} else {
if (strpos($value, '%')) {
$compare = 'LIKE';
}
$whereArrayAnd[] = sprintf(
"`%s`.`%s` %s '%s'",
$c->databaseTable,
$c->databaseFields[$field],
$compare,
$value
);
}
unset($value, $field);
};
/**
* Lambda function to build the join of a query.
*
Expand All @@ -1084,25 +1048,48 @@ public function buildQuery(
&$join,
&$whereArrayAnd,
&$c,
$whereInfo,
$not,
$compare
) {
$className = strtolower($class);
$c = self::getClass($class);
if (!array_key_exists($className, $join)) {
// The relationship's optional 4th element is a filter on the
// joined (optional) table. It must live in the JOIN ON clause,
// not in WHERE: a WHERE condition on the right-hand table of a
// LEFT JOIN silently degrades it to an INNER JOIN, dropping the
// base row entirely when there is no matching joined row (e.g.
// a host with no primary MAC would fail to load at all).
$onExtra = '';
if (isset($fields[3]) && $fields[3]) {
foreach ((array) $fields[3] as $filterField => $filterValue) {
if (is_array($filterValue)) {
$onExtra .= sprintf(
" AND `%s`.`%s` IN ('%s')",
$c->databaseTable,
$c->databaseFields[$filterField],
implode("','", $filterValue)
);
} else {
$onExtra .= sprintf(
" AND `%s`.`%s` = '%s'",
$c->databaseTable,
$c->databaseFields[$filterField],
$filterValue
);
}
}
}
$join[$className] = sprintf(
' LEFT OUTER JOIN `%s` ON `%s`.`%s`=`%s`.`%s` ',
' LEFT OUTER JOIN `%s` ON `%s`.`%s`=`%s`.`%s`%s ',
$c->databaseTable,
$c->databaseTable,
$c->databaseFields[$fields[0]],
$this->databaseTable,
$this->databaseFields[$fields[1]]
$this->databaseFields[$fields[1]],
$onExtra
);
}
if (isset($fields[3])) {
array_walk($fields[3], $whereInfo);
}
$c->buildQuery($join, $whereArrayAnd, $c, $not, $compare);
unset($class, $fields, $c);
};
Expand Down
38 changes: 38 additions & 0 deletions packages/web/lib/fog/host.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,44 @@ public function save()
$objNeeded = false;
unset($DBPowerManagementIDs, $RemovePowerManagementIDs);
}
// Safety net: never leave the host with MAC rows but no primary MAC.
// The primac join requires hmPrimary='1', so a host with no primary
// MAC cannot be loaded and becomes un-editable via the API/GUI. If an
// update (e.g. replacing the MAC set) removed the former primary,
// promote the first remaining approved (non-pending) MAC so the host
// stays reachable.
$hostID = $this->get('id');
if ($hostID) {
$primaryMacs = self::getSubObjectIDs(
'MACAddressAssociation',
array(
'hostID' => $hostID,
'primary' => '1'
),
'mac'
);
if (count((array)$primaryMacs) < 1) {
$approvedMacs = self::getSubObjectIDs(
'MACAddressAssociation',
array(
'hostID' => $hostID,
'pending' => '0'
),
'mac'
);
if (count((array)$approvedMacs) > 0) {
self::getClass('MACAddressAssociationManager')
->update(
array(
'hostID' => $hostID,
'mac' => array_shift($approvedMacs)
),
'',
array('primary' => '1')
);
}
}
}
return $this
->assocSetter('Module')
->assocSetter('Printer')
Expand Down
Loading