Page.psm1
#!/usr/bin/env pwsh $ErrorActionPreference = "Stop" function New-Page { <# .SYNOPSIS Add a confluence page .DESCRIPTION This function is unaware of the publishing status of ancestors and assumes that ancestral hierarchy is maintained through the manifest's item order. If a page's metadata does not include a reference, it will be treated as a publishing failure and therefore not output the original metadata. .OUTPUTS When no $Title is provided and the $Manifest array only contains 1 page metadata, the ``Count`` attribute is faulty. Why? Don't know. .EXAMPLE Add-ConfluencePage ` -Host 'confluence.contoso.com' ` -Space 'TIARA' ` -Title 'Testitest' ` -Content @{} #> Param( # confluence instance hostname [Parameter(Mandatory)] [string]$Host, # name of the Confluence space to publish to [Parameter(Mandatory)] [string]$Space, # title of page to be published [Parameter()] [string]$Title, # pages manifest [Parameter(Mandatory,ValueFromPipeline)] [PSCustomObject[]]$Manifest, # pages manifest index, mandatory for ancestor lookup [Parameter(Mandatory)] [Collections.Hashtable]$Index, # flag on whether to fail hard, or just continue [Parameter()] [Switch]$Strict ) Begin { $pat = Get-PersonalAccessToken $Host } Process { If ($Title -And $Manifest[$Index.$Title]) { $Manifest = @( $Manifest[$Index.$Title] ) } ForEach($pageMeta in $Manifest) { If ($Title -And $pageMeta.Title -ne $Title) {continue} ElseIf (-Not $pageMeta.Ref) { $errMsg = ("``$($pageMeta.Title)``: no reference to local " + 'content for page .') If ($Strict) {throw $errMsg} Write-Host $errMsg continue } ElseIf ($pageMeta.Id) { Write-Debug ( "New-Page: ``$($pageMeta.Title)``: skipping, already " + "published ($($pageMeta.Id))" ) $pageMeta continue } Else { Write-Host "New-Page: ``$($pageMeta.Title)``: creating" Try { $content = Get-Content -Path $pageMeta.Ref | Out-String } Catch { $errMsg = "``New-Page: $($PageMeta.Title)``: $_" If ($Strict) {throw $errMsg} Write-Host $errMsg continue } $contentHash = (Get-StringHash $content).Hash $transportBody = @{ 'type' = 'page' 'title' = $pageMeta.Title 'space' = @{ 'key' = $Space } 'body' = @{ 'storage' = @{ 'value' = $content 'representation' = 'storage' } } } If ($pageMeta.AncestorTitle) { $ancestorPageMeta = $Manifest[ $Index."$($pageMeta.AncestorTitle)" ] If (-Not $ancestorPageMeta) { Throw ( "ancestor (``$($ancestorPageMeta.Title)``) of " + "``$($pageMeta.Title)`` does not have an id. " + "This indicates, that the ancestor has not been " + "published and therefore the pages manifest may " + "not be in the correct order." ) } $transportBody.ancestors = @( @{'id' = $ancestorPageMeta.Id} ) } $rawTransportBody = ( $transportBody | ConvertTo-JSON ` -WarningAction 'SilentlyContinue' ) Try { Invoke-WebRequest ` -Uri "https://${Host}/rest/api/content" ` -Method 'Post' ` -Headers @{ 'Authorization' = "Bearer $pat" } ` -ContentType "application/json" ` -Body $rawTransportBody ` -OutVariable rawResponse | Out-Null } Catch { $errMsg = "skipping ``$($pageMeta.Title)``: $($_)" If ($Strict) { $_ throw $errMsg } Write-Host $errMsg continue } $response = ($rawResponse.Content | ConvertFrom-JSON) $pageMeta | Add-Member ` -NotePropertyName 'Id' ` -NotePropertyValue $response.id ` -Force $pageMeta | Add-Member ` -NotePropertyName 'Version' ` -NotePropertyValue "1" ` -Force $pageMeta | Add-Member ` -NotePropertyName 'Hash' ` -NotePropertyValue $contentHash ` -Force If ( ($Title -And $pageMeta.Title -eq $Title) -Or $Manifest.Count -eq 1 ) { # TODO: further research mechanism of expanding single item # array pipelines. For now we have to apply the unary # operator, otherwise we get a wrong count on the output ,@($pageMeta) break } Else { $pageMeta } } } } } function Update-Page { <# .SYNOPSIS Update an existing Confluence page .DESCRIPTION This function is unaware of the publishing status of ancestors and assumes that ancestral hierarchy is maintained through the manifest's item order, therefore an index must be supplied. If a page's metadata does not include a reference, it will be treated as a publishing failure and therefore not output the original metadata. .OUTPUTS When no $Title is provided and the $Manifest array only contains 1 page metadata, the ``Count`` attribute is faulty. Why? Don't know. .EXAMPLE Add-ConfluencePage ` -Host 'confluence.contoso.com' ` -Space 'TIARA' ` -Title 'Testitest' ` -Content @{} #> Param( # confluence instance hostname [Parameter(Mandatory)] [string]$Host, # name of the Confluence space to publish to [Parameter(Mandatory)] [string]$Space, # title of page to be published [Parameter()] [string]$Title, # pages manifest [Parameter(Mandatory, ValueFromPipeline)] [PSCustomObject[]]$Manifest, # pages manifest index, mandatory for ancestor lookup [Parameter(Mandatory)] [Collections.Hashtable]$Index, # flag on whether to fail hard, or just continue [Parameter()] [Switch]$Strict, # flag on whether to force update of page, regardless of content [Parameter()] [Switch]$Force ) Begin { $pat = Get-PersonalAccessToken $Host } Process { If ($Title -And $Manifest[$Index.$Title]) { $Manifest = @( $Manifest[$Index.$Title] ) } ForEach($pageMeta in $Manifest) { If ($Title -And $pageMeta.Title -ne $Title) {continue} ElseIf (-Not $pageMeta.Ref) { $errMsg = "no reference to local content for page ``$Title``." If ($Strict) {throw $errMsg} Write-Host $errMsg continue } ElseIf (-Not $pageMeta.Id) { $errMsg = ( "Update-Page: ``$($pageMeta.Title)``: unknown page id." ) If ($Strict) {throw $errMsg} Write-Host "$errMsg Skipping." $pageMeta continue } ElseIf (-Not $pageMeta.Version) { Write-Host ( "Update-Page: ``$($pageMeta.Title)``: unknown (current) " + "version. Skipping." ) $pageMeta continue } Else { Try { $content = Get-Content -Path $pageMeta.Ref | Out-String } Catch { $errMsg = "``$Title``: $_" If ($Strict) {throw $errMsg} Write-Host $errMsg continue } $version = [Int]$pageMeta.Version + 1 $contentHash = (Get-StringHash $content).Hash If ( $pageMeta.Hash -And $pageMeta.Hash -eq $contentHash -And -Not $Force ) { Write-Debug ( "Update-Page: ``$($pageMeta.Title)``: skipping, no " + "content changes" ) $pageMeta continue } Else { Write-Host ( "Update-Page: ``$($pageMeta.Title)``: updating" ) } # status needs to be set as to restore the page, if it is # trashed $transportBody = @{ 'id' = $PageMeta.Id 'type' = 'page' 'title' = $pageMeta.Title 'space' = @{ 'key' = $Space } 'body' = @{ 'storage' = @{ 'value' = $content 'representation' = 'storage' } } 'status' = 'current' 'version' = @{ 'number' = $version } } If ($pageMeta.AncestorTitle) { $ancestorPageMeta = $Manifest[ $Index."$($pageMeta.AncestorTitle)" ] If (-Not $ancestorPageMeta) { Throw ( "ancestor (``$($ancestorPageMeta.Title)``) of " + "``$($pageMeta.Title)`` does not have an id. " + "This indicates, that the ancestor has not been " + "published and therefore the pages manifest may " + "not be in the correct order." ) } $transportBody.ancestors = @( @{'id' = $ancestorPageMeta.Id} ) } $rawTransportBody = ( $transportBody | ConvertTo-JSON ` -WarningAction 'SilentlyContinue' ) Try { Invoke-WebRequest ` -Uri ("https://${Host}/rest/api/content/" + $PageMeta.Id) ` -Method 'Put' ` -Headers @{ 'Authorization' = "Bearer $pat" } ` -ContentType "application/json" ` -Body $rawTransportBody ` -OutVariable rawResponse | Out-Null } Catch { $errMsg = "skipping ``$($pageMeta.Title)``: $_" If ($Strict) { $_ throw $errMsg } Write-Host $errMsg continue } # response isn't needed since no field will be updated by the # Confluence instance itself #$response = ($rawResponse.Content | ConvertFrom-JSON) $pageMeta | Add-Member ` -NotePropertyName 'Version' ` -NotePropertyValue $version ` -Force $pageMeta | Add-Member ` -NotePropertyName 'Hash' ` -NotePropertyValue $contentHash ` -Force If ( ($Title -And $pageMeta.Title -eq $Title) -Or $Manifest.Count -eq 1 ) { # TODO: further research mechanism of expanding single item # array pipelines. For now we have to apply the unary # operator, otherwise we get a wrong count on the output ,@($pageMeta) break } Else { $pageMeta } } } } } function Publish-Page { Param( # confluence instance hostname [Parameter(Mandatory)] [string]$Host, # name of the Confluence space to publish to [Parameter(Mandatory)] [string]$Space, # title of page to be published [Parameter()] [string]$Title, # pages manifest [Parameter(Mandatory)] [PSCustomObject[]]$Manifest, # pages manifest index, mandatory for ancestor lookup [Parameter(Mandatory)] [Collections.Hashtable]$Index, # flag on whether to fail hard, or just continue [Parameter()] [Switch]$Strict, # flag on whether to force update of page, regardless of content [Parameter()] [Switch]$Force ) Process { $result = Update-Page ` -Host $Host ` -Space $Space ` -Manifest $Manifest ` -Index $Index ` -Strict:$Strict ` -Force:$Force $result = New-Page ` -Host $Host ` -Space $Space ` -Manifest $result ` -Index $Index ` -Strict:$Strict } End { $result } } |