internal/functions/ConvertTo-SchemaLdifPhase.ps1
function ConvertTo-SchemaLdifPhase { <# .SYNOPSIS Converts ldif files into a phased state index. .DESCRIPTION Converts ldif files into a phased state index. For each phase/file for each object it calculates the resulting state after ALL commands in the file have been executed. This allows stepping through the individual ldif files in the order they are to be applied and figure out the last applied deployment state. .PARAMETER LdifData The set of Ldif file definitions as returned by Get-FMSchemaLdif .EXAMPLE PS C:\> $ldifPhases = ConvertTo-SchemaLdifPhase -LdifData (Get-FMSchemaLdif) Returns the hashtable containing the different phases of all registered ldif files. #> [OutputType([Hashtable])] [CmdletBinding()] param ( $LdifData ) #region Utility Functions function Add-Node { [CmdletBinding()] param ( [string] $DistinguishedName, [string] $LdifName, [Hashtable] $MappingTable ) if (-not $MappingTable.ContainsKey($DistinguishedName)) { $MappingTable[$DistinguishedName] = @{ } } if (-not $MappingTable[$DistinguishedName][$LdifName]) { $MappingTable[$DistinguishedName][$LdifName] = @{ State = @{ } Add = @{ } Replace = @{ } } } } function Write-Change { [CmdletBinding()] param ( [string] $DistinguishedName, [string] $LdifName, $Change, [Hashtable] $MappingTable ) Add-Node -DistinguishedName $DistinguishedName -LdifName $LdifName -MappingTable $MappingTable $datasheet = $MappingTable[$DistinguishedName][$LdifName] switch -regex ($Change.changetype) { 'add' { $datasheet.State = @{ } foreach ($propertyName in $Change.PSObject.Properties.Name) { if ($propertyName -in 'changeType', 'FM_OrderCount') { continue } $datasheet.State[$propertyName] = $Change.$propertyName } } 'modify' { #region We already have a defined state if ($datasheet.State.Count -gt 0) { if ($Change.add) { if ($datasheet.State.$($Change.add)) { $datasheet.State.$($Change.add) = @($datasheet.State.$($Change.add)) + @($Change.$($Change.add)) } else { $datasheet.State[$Change.add] = $Change.$($Change.add) } } elseif ($Change.replace) { $datasheet.State[$Change.replace] = $Change.$($Change.replace) } else { foreach ($propertyName in $Change.PSObject.Properties.Name) { if ($propertyName -in 'DistinguishedName','changetype','FM_OrderCount') { continue } $datasheet.State[$propertyName] = $Change.$propertyName } } } #endregion We already have a defined state #region Undefined state else { if ($Change.add) { if ($datasheet.Add.$($Change.add)) { $datasheet.Add.$($Change.add) = @($datasheet.Add.$($Change.add)) + @($Change.$($Change.add)) } else { $datasheet.Add[$Change.add] = $Change.$($Change.add) } } elseif ($Change.replace) { $datasheet.Replace[$Change.replace] = $Change.$($Change.replace) } else { foreach ($propertyName in $Change.PSObject.Properties.Name) { if ($propertyName -in 'DistinguishedName','changetype','FM_OrderCount') { continue } $datasheet.Replace[$propertyName] = $Change.$propertyName } } } #endregion Undefined state } } } function Copy-State { [CmdletBinding()] param ( [Hashtable] $MappingTable, [string] $OldLdif, [string] $NewLdif ) foreach ($name in $MappingTable.Keys) { Add-Node -DistinguishedName $name -LdifName $NewLdif -MappingTable $MappingTable foreach ($key in $MappingTable[$name][$OldLdif].State.Keys) { $MappingTable[$name][$NewLdif].State[$key] = $MappingTable[$name][$OldLdif].State[$key] | Write-Output } foreach ($key in $MappingTable[$name][$OldLdif].Add.Keys) { $MappingTable[$name][$NewLdif].Add[$key] = $MappingTable[$name][$OldLdif].Add[$key] | Write-Output } foreach ($key in $MappingTable[$name][$OldLdif].Replace.Keys) { $MappingTable[$name][$NewLdif].Replace[$key] = $MappingTable[$name][$OldLdif].Replace[$key] | Write-Output } } } function Remove-NoOp { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( $LdifData, [Hashtable] $MappingTable ) $identities = $MappingTable.Keys | Write-Output foreach ($identity in $identities) { foreach ($ldifFile in $LdifData) { if (-not $MappingTable[$identity][$ldifFile.Name]) { continue } if ($ldifFile.Settings.DistinguishedName -contains $identity) { continue } $MappingTable[$identity].Remove($ldifFile.Name) } } } #endregion Utility Functions $mappingTable = @{ } $sortedLdif = $ldifData | Sort-Object Weight $previousLdif = '' foreach ($ldifItem in $sortedLdif) { if ($previousLdif) { Copy-State -MappingTable $mappingTable -OldLdif $previousLdif -NewLdif $ldifItem.Name } foreach ($setting in ($ldifItem.Settings | Sort-Object FM_OrderCount)) { Write-Change -DistinguishedName $setting.DistinguishedName -LdifName $ldifItem.Name -Change $setting -MappingTable $mappingTable } $previousLdif = $ldifItem.Name } Remove-NoOp -LdifData $sortedLdif -MappingTable $mappingTable $mappingTable } |