protected function reduceNodeVariantsByWorkspacesAndDimensions(array $nodes, array $workspaces, array $dimensions)
{
$foundNodes = [];
$minimalDimensionPositionsByIdentifier = [];
foreach ($nodes as $node) {
/** @var NodeData $node */
$nodeDimensions = $node->getDimensionValues();
// Find the position of the workspace, a smaller value means more priority
$workspaceNames = array_map(function (Workspace $workspace) {
return $workspace->getName();
}, $workspaces);
$workspacePosition = array_search($node->getWorkspace()->getName(), $workspaceNames);
if ($workspacePosition === false) {
throw new Exception\NodeException(sprintf('Node workspace "%s" not found in allowed workspaces (%s), this could result from a detached workspace entity in the context.', $node->getWorkspace()->getName(), implode($workspaceNames, ', ')), 1413902143);
}
// Find positions in dimensions, add workspace in front for highest priority
$dimensionPositions = [];
// Special case for no dimensions
if ($dimensions === []) {
// We can just decide if the given node has no dimensions.
$dimensionPositions[] = $nodeDimensions === [] ? 0 : 1;
}
foreach ($dimensions as $dimensionName => $dimensionValues) {
if (isset($nodeDimensions[$dimensionName])) {
foreach ($nodeDimensions[$dimensionName] as $nodeDimensionValue) {
$position = array_search($nodeDimensionValue, $dimensionValues);
$dimensionPositions[$dimensionName] = isset($dimensionPositions[$dimensionName]) ? min($dimensionPositions[$dimensionName], $position) : $position;
}
} else {
$dimensionPositions[$dimensionName] = isset($dimensionPositions[$dimensionName]) ? min($dimensionPositions[$dimensionName], PHP_INT_MAX) : PHP_INT_MAX;
}
}
$dimensionPositions[] = $workspacePosition;
$identifier = $node->getIdentifier();
// Yes, it seems to work comparing arrays that way!
if (!isset($minimalDimensionPositionsByIdentifier[$identifier]) || $dimensionPositions < $minimalDimensionPositionsByIdentifier[$identifier]) {
$foundNodes[$identifier] = $node;
$minimalDimensionPositionsByIdentifier[$identifier] = $dimensionPositions;
}
}
return $foundNodes;
}