src/Private/SharePoint/SiteNav.ps1

function Get-SiteNav {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [PnP.Framework.Enums.NavigationType] $NavigationNodeLocation
    )

    $nav = New-Object System.Collections.ArrayList
    Get-PnPNavigationNode -Location $NavigationNodeLocation | ForEach-Object {
        Write-Host -NoNewline "$($_.Title)"
        Write-Verbose "Node ID: $($_.Id), Node URL: $($_.Url), Node Title: $($_.Title)"
        $ParentNode = Get-PnPNavigationNode -Id $_.Id
        $ParentNode | Add-Member NoteProperty -Name "ParentNode" -Value $null
        $ParentNode | Add-Member NoteProperty -Name "NodeLevel" -Value 1
        $nav.Add($ParentNode) | Out-Null
        Write-Host -ForegroundColor Green " .....Done!"
        $ParentNode.Children | ForEach-Object {
            Write-Host -NoNewline " $($_.Title)"
            Write-Verbose " Node ID: $($_.Id), Node URL: $($_.Url), Node Title: $($_.Title)"
            $Node = Get-PnPNavigationNode -Id $_.Id
            $Node | Add-Member NoteProperty -Name "ParentNode" -Value $ParentNode.Id    
            $Node | Add-Member NoteProperty -Name "NodeLevel" -Value 2
            $nav.Add($Node) | Out-Null
            Write-Host -ForegroundColor Green " .....Done!"
            $Node.Children | ForEach-Object {
                Write-Host -NoNewline " $($_.Title)"
                Write-Verbose " Node ID: $($_.Id), Node URL: $($_.Url), Node Title: $($_.Title)"
                $SecondNode = Get-PnPNavigationNode -Id $_.Id
                $SecondNode | Add-Member NoteProperty -Name "ParentNode" -Value $Node.Id    
                $SecondNode | Add-Member NoteProperty -Name "NodeLevel" -Value 3
                $nav.Add($SecondNode) | Out-Null
                Write-Host -ForegroundColor Green " .....Done!"
            }
        }
    }
    Write-Host ""
    return $nav  
}
    
function Add-SiteNav($newNavNodes, [PnP.Framework.Enums.NavigationType] $Location) {
    try {
        $blHasErrors = $false
        Write-Host "Starting Process to create New Nav Nodes in Target Site"
        $nodeParentMatch = @{}
        $nodeChildMatch = @{}
        $newNavNodes | ForEach-Object {
            try {
                $node = $_
                Write-Host -NoNewline "Adding navigation node (Level $($node.NodeLevel)): $($node.Title)"
                if ($node.NodeLevel -eq 1) {
                    Write-Verbose "Node ID: $($node.Id), Node URL: $($node.Url), Node Title: $($node.Title)"
                    $newNode = Add-PnPNavigationNode -Location $Location -Title $node.Title -Url $node.Url
                    $nodeParentMatch[$node.Id] = $newNode.Id
                }
                elseif ( $node.NodeLevel -eq 2) {
                    Write-Verbose "Node ID: $($node.Id), Node URL: $($node.Url), Node Title: $($node.Title), Parent Node ID: $($node.ParentNode)"
                    $parentId = $nodeParentMatch[$node.ParentNode]
                    $newNode = Add-PnPNavigationNode -Location $Location -Title $node.Title -Url $node.Url -Parent $parentId -External
                    $nodeChildMatch[$node.Id] = $newNode.Id
                }
                elseif ( $node.NodeLevel -eq 3) {
                    Write-Verbose "Node ID: $($node.Id), Node URL: $($node.Url), Node Title: $($node.Title), Parent Node ID: $($node.ParentNode)"
                    $parentId = $nodeChildMatch[$node.ParentNode]
                    $newNode = Add-PnPNavigationNode -Location $Location -Title $node.Title -Url $node.Url -Parent $parentId -External
                }
                Write-Host -ForegroundColor Green " .....Done!"
            }
            catch {
                $blHasErrors = $true
                Write-Host -ForegroundColor Red " .....Failed!"
                Write-Error "An error occurred while adding navigation node $($node.Title): $($_.Exception.Message)"
                Write-Verbose "An error occurred while adding navigation node $($node.Title): $($_.Exception.Message)"
            }
        }
        if ($blHasErrors) {
            Write-Host -ForegroundColor Yellow "Some navigation nodes failed to be added. Please check the error messages above."
        }
        else {
            Write-Host -ForegroundColor Green "All navigation nodes added successfully."
        }
    }
    catch {
        Write-error "An error occurred while adding navigation nodes: $($_.Exception.Message)"
        Write-Verbose "An error occurred while adding navigation nodes: $($_.Exception.Message)"
    }
}
    
function Clear-SiteNav([PnP.Framework.Enums.NavigationType] $Location) {
    Write-Host -NoNewline "Clearing Current Nav Nodes"
    Get-PnPNavigationNode -Location $Location | ForEach-Object {
        Remove-PnPNavigationNode $_ -Force
    }
    Write-Host -f Green " .....Done!"
}
    
# SIG # Begin signature block
# MIIHMAYJKoZIhvcNAQcCoIIHITCCBx0CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAtUu9LutmW955h
# 8rD+HMIC/25qV+vgtUjeqTjKwXUBO6CCBBwwggQYMIICgKADAgECAhBH6tQY1Crt
# r02dueiKibmNMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGU0zNjUuVG9vbGtp
# dCBDb2RlIFNpZ25pbmcwHhcNMjYwNzE2MTY1NjE0WhcNMjcwNzE2MTcwNjEzWjAk
# MSIwIAYDVQQDDBlNMzY1LlRvb2xraXQgQ29kZSBTaWduaW5nMIIBojANBgkqhkiG
# 9w0BAQEFAAOCAY8AMIIBigKCAYEAxQCBRWJ923yIy73AwGWtFvfBL/dZHvwCBO05
# dJopbkHGcCqifl9R21PXr5OIjcEFv16ObYL23cPwZaNKCiejuiU32MHwidYHU1k5
# AzFpjwW2uwjeA7Hip3cURwoeOH/LzNa/xNTBRiO70M7gunZCm+FixDcPKf66Tvb1
# iM6pbOFmJvzbGjFqKM6mQRofaCPU89SHW5y43HyZNdiWsJTN4TsWj96Rps4fKhh2
# gToexqi0GhLHhLtVQ8ZxMic6w0C9sCWhYBl3kw1OJdaa/MVBdVAXDOIL0HIG8jOa
# l1x67U1LihXEw1hdc3YabhvSYZ5ZXPV1AZ2z6+Qa0EL9XlJWqBkn0rO6sZB1IkOo
# gfeTxVuI6SjhqpW6QrAFFJzb81qd0dDWmmuVka1yoWEic7naZpDfuh3JZPOUilE1
# Wv3qhBDYN5qg1qXeh0RMosR8rMfKjE8CFvsB7LTibom+22in1x16vmIiv9ep5HNc
# eS0hRa/84+vmXQ8R6hN8x+oWbG8NAgMBAAGjRjBEMA4GA1UdDwEB/wQEAwIHgDAT
# BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUu9RWiOCtUYtlrLgwzVDsor7P
# p88wDQYJKoZIhvcNAQELBQADggGBAKJksJX6tgjdng//9wRM2ztQn8breDnY/Zki
# 8iXrC94sqCYoYg1lT0pVHZq1ZHpdUNh/xQnjP9asbIqgUt0YiCIASCONV2nM2wyK
# VjrvxaC08xefuHiO/R6Uc9sDW38mID+gDoAmswmB9JV5qm+j8b4hw3vcwuUe3nla
# 5bn3YoKXLY4/YJjHNA62TmhYNfs7iwdk2vyH/dCvD35LdBhP/y2ChmOxzI1aSp4L
# c65zCFVDPzw1IED/5q9NM48QUVDgVAX6VNuocjXZpWd7fHf7KFLRJSExXtaYQCdk
# hBSITzd5WBT2opKF02TrTyc5h1zCTr6HU+1Eqr92fvEGfqk4yYSt4plyqbm6Unnq
# gEgwDqlgm9ZNA8hzorcoxSetVVZ8z+50KB55JRTENZ/5kOJWzPtoIA+PdmFvg3wU
# jQHhO6C32rdVUk+j1hI1zL6sR8gYn5VmLPVjfs49yKf+2t3iDsaYVRNawOqHrMZj
# g59c2M2hT5D6krLsI8r3F/t3YfHbKjGCAmowggJmAgEBMDgwJDEiMCAGA1UEAwwZ
# TTM2NS5Ub29sa2l0IENvZGUgU2lnbmluZwIQR+rUGNQq7a9Nnbnoiom5jTANBglg
# hkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3
# DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV
# MC8GCSqGSIb3DQEJBDEiBCDSBZBD7LkvSXoATTonaczMeYhs6r7v8AiM3AxU25nf
# KzANBgkqhkiG9w0BAQEFAASCAYBoku6XJDSkPhWwxne1EoQrS5EGM03h1wYP7UJ3
# x8e/Zb0oFhgVHR8KbijW4VRPuhqAnHrgaRDWsfPASAJJnUq5WE56+nL33FKPChk0
# vrDdi09zRA/kJPbIy/YRWTGyDmhRVjl91jNknxUI7y0fLL7y5be9SGsmNPgXDC0I
# szgaaV8cBfq3lyt2GKuHT8MSwyqtZmVKc8WQTtOpufJtAvsuGAt7AK8LCsa+F5HY
# bz0LfTrY9fSrDNOwxHXwGPlkV62v3OsWTrp7qsq7o1xXy+lT1Y5s4AbYbPrQ3EJg
# IpSx4WEMnL8tSymlAuzRRnucN+gnidra1B24+3yLAlyTn73rjEgDawVdQoMQ9gYt
# 1R3QIDM7XztHHgoozbJL15J8U77e9sA6lzPy43rbI3i7jzf1/YHdkrf5+0yEW74y
# jJ1vUxcLEoqgtyjeBfSlNy9U2khwqv+ZJqSCIW0XozmB0h+cxiv8utGlQWF1Tacf
# 5tfsdl1IBPuvGZS949sOxK+1yUE=
# SIG # End signature block