Private/Logic/Get-CategoryHierarchy.ps1
|
# Copyright (c) 2026 Sandy Zeng. All rights reserved. # Source-available. All rights reserved. See LICENSE file. <# Get-CategoryHierarchy.ps1 — Builds full category hierarchy paths from the configurationCategories.json data. Author: Sandy Zeng Project: IntuneDiff Version History: 1.0.0 Initial release. #> function Initialize-CategoryData { <# .SYNOPSIS Loads configurationCategories.json once per session into $script:CategoriesData. #> [CmdletBinding()] param() if ($script:CategoriesData) { return } $path = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Data\configurationCategories.json' if (-not (Test-Path -LiteralPath $path)) { $script:CategoriesData = @{} return } try { $json = Get-Content -LiteralPath $path -Raw -Encoding UTF8 | ConvertFrom-Json } catch { $script:CategoriesData = @{} return } $map = @{} foreach ($cat in @($json.value)) { if ($cat.id) { $map[[string]$cat.id] = [pscustomobject]@{ Id = [string]$cat.id DisplayName = [string]$cat.displayName ParentCategoryId = [string]$cat.parentCategoryId RootCategoryId = [string]$cat.rootCategoryId } } } $script:CategoriesData = $map } function Get-CategoryHierarchy { <# .SYNOPSIS Builds the full category hierarchy path for a category id (Root > Parent > Child). #> [CmdletBinding()] [OutputType([string])] param([string]$CategoryId) if (-not $CategoryId) { return '' } Initialize-CategoryData if (-not $script:CategoriesData.ContainsKey($CategoryId)) { return '' } $parts = New-Object System.Collections.Generic.List[string] $visited = @{} $current = $CategoryId while ($current -and $script:CategoriesData.ContainsKey($current) -and -not $visited.ContainsKey($current)) { $visited[$current] = $true $cat = $script:CategoriesData[$current] if ($cat.DisplayName) { $parts.Insert(0, $cat.DisplayName) } $parentId = $cat.ParentCategoryId if (-not $parentId -or $parentId -eq '00000000-0000-0000-0000-000000000000' -or $parentId -eq $current) { break } $current = $parentId } return ($parts -join ' > ') } function Format-SettingNameWithCategory { <# .SYNOPSIS Returns a fully-qualified setting display name including special-case parent paths (LAPS, Firewall profiles) and the resolved category hierarchy. #> [CmdletBinding()] [OutputType([string])] param( [string]$SettingName, [string]$CategoryId, [string]$SettingDefId ) if ($SettingDefId) { $idLower = $SettingDefId.ToLowerInvariant() # LAPS if ($idLower.Contains('vendor_msft_laps_policies')) { if ($idLower -eq 'device_vendor_msft_laps_policies_backupdirectory') { return "LAPS > $SettingName" } return "LAPS > Backup Directory > $SettingName" } # Firewall - Domain profile if ($idLower.Contains('vendor_msft_firewall_mdmstore_domainprofile')) { if ($SettingName -like '*Enable Domain Network Firewall*') { return "Firewall > $SettingName" } return "Firewall > Enable Domain Network Firewall > $SettingName" } # Firewall - Private profile if ($idLower.Contains('vendor_msft_firewall_mdmstore_privateprofile')) { if ($SettingName -like '*Enable Private Network Firewall*') { return "Firewall > $SettingName" } return "Firewall > Enable Private Network Firewall > $SettingName" } # Firewall - Public profile if ($idLower.Contains('vendor_msft_firewall_mdmstore_publicprofile')) { if ($SettingName -like '*Enable Public Network Firewall*') { return "Firewall > $SettingName" } return "Firewall > Enable Public Network Firewall > $SettingName" } } if (-not $CategoryId) { return $SettingName } $hierarchy = Get-CategoryHierarchy -CategoryId $CategoryId if (-not $hierarchy) { return $SettingName } return "$hierarchy > $SettingName" } |