Valo.ps1
<#
.SYNOPSIS Sanitize the Language script webparts in the Genesis Language root XML configuration. .DESCRIPTION Sanitize the Language script webparts in the Genesis Language root XML configuration. The leftover elements are then purged from the file. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function global:Update-ValoMultilingualRoot { Param( [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_})] [string]$LanguagesConfigFilePath, [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_})] [ValidatePattern("genesis-languageroot\.[\D]+\.xml")] [string]$GenesisLanguageRootFilePath, [Parameter(Mandatory = $true)] [ValidatePattern("https\:\/\/[\D\d]*\.sharepoint\.com|de")] [string]$O365Tenant ) # Load the Multilingual XML configuration file [xml]$languagesConfigXml = Get-Content $LanguagesConfigFilePath # Load the Genesis Language root file to be sanitized [xml]$xml = Get-Content $GenesisLanguageRootFilePath # Obtain the ScriptWebParts tag to modify $webParts = $xml.Tenant.SiteCollection.Pages.Page.ScriptWebParts.ScriptWebPart | Where-Object {$_.Zone -like "WebPartZoneWide*"} # Replacing the original ScriptWebPArt CDATA section by updating the Node InnerText string value $webPartPattern = '<language-selection url="{0}" title="{1}"/>' $webPartIndex = 0 $languagesConfigXml.Languages.Language | ForEach-Object { $siteCollectionUrl = "$O365Tenant/sites$($_.SiteCollectionRelativeUrl)" $newTagInfo = [string]::Format($webPartPattern, $siteCollectionUrl, $_.Title) $updated = $xml.CreateCDataSection($newTagInfo) $webParts[$webPartIndex].'#cdata-section' = $updated.Value $webPartIndex++ } # Select all ScriptWebPart nodes within the file that haven't been modified. The idea is to sanitize the xml file and keep the minimum nodes # to ensure having only the minimum webparts deployed and configured within the root landing page in a Valo multilingual scenario. $parentNode = $xml | Select-Xml -XPath '//*[local-name() = ''ScriptWebParts'']' $childsToRemove = $parentNode.Node.ChildNodes | Where-Object {$_.Zone -like "WebpartZoneWide*" -and $_.InnerText -like '*url=""*'} $childsToRemove | ForEach-Object { $parentNode.Node.RemoveChild($_) } $xml.Save($GenesisLanguageRootFilePath) } <# .SYNOPSIS Activate the Language script in the Genesis Language ressources xml configuration. .DESCRIPTION Uncommenting xml elements used by the multilingual mode. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function global:Enable-ScriptForMultilingualSiteCollection { param( [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_})] [string]$GenesisRessourceFilePath ) $regEx = "(<!--(.*((.*)\W*((?i)valo-riot-language-webparts.js(.*)(?-i))\W)(.*))-->)" $scriptName = "valo-riot-language-webparts.js" #Obtains the xml file. $xml = (Get-Content -Path $GenesisRessourceFilePath) #Look if the xml file contains the call to valo-riot-language-webparts.js script. $xml | Where-Object {$_ -match $scriptName} if ($Matches.ContainsValue($scriptName)) { #Uncomment each call refering to the script. $xml -replace $regEx,'$2' | Set-Content -Path $GenesisRessourceFilePath Write-host "The $GenesisRessourceFilePath have been properly modified !" -ForegroundColor Green } else { Write-Host " The analysed file does not contains the script name : $scriptName " -ForegroundColor Red } } <# .SYNOPSIS Adds the language reusable content to all the sites listed in the configuration file. .DESCRIPTION Adds the language reusable content to all the sites listed in the configuration file. Must already be logged to a Sharepoint account. Returns all the added list items. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function global:Add-ValoLanguageReusableContent { Param ( [Parameter(Mandatory=$true)] [ValidateScript({Test-Path $_})] [string]$ConfigFilePath, [Parameter(Mandatory=$true)] [ValidatePattern("https\:\/\/[\D\d]*\.sharepoint\.com|de")] [string]$O365Tenant, [Parameter(Mandatory=$true)] [pscredential]$Credentials ) $config = Get-Content $ConfigFilePath -Raw | ConvertFrom-Json $listItems = @() ForEach ($rc in $config.ReusableContents) { $site = Get-PnPTenantSite | Where-Object {$_.Url.EndsWith($rc.RelativeUrl)} Connect-PnPOnline -Url $site.Url -Credentials $Credentials $reusableContent = @() for ($i = 0; $i -lt $config.UrlTemplates.Count; $i++){ $reusableContent += ,[string]::Format($config.UrlTemplates[$i], $rc.Labels[$i], $O365Tenant) } $listItems += Add-PnPListItem -ContentType "Item" -List "Reusable Content" -Values @{"Title" = "Languages"; "AutomaticUpdate" = $true; "ReusableHtml" = ($reusableContent -join ",")} } return $listItems } <# .SYNOPSIS Creates and properly copy a valid Valo deployment folder with integrated customisation .DESCRIPTION This method acted as a controller to coordinate all methods to create a Valo Intranet from the information contained in client repository. .LINK Nexus Innovations : http://www.nexusinno.com #> function global:Initialize-DeploymentFolder { Param ( [Parameter(Mandatory=$true)] [hashtable]$ClientConfig, [string]$DeploymentFolderName = [string]::Format("Valo-Deployment-{0}", (Get-Date).ToShortDateString().Replace('/','-')) ) if(-not (Test-Path($DeploymentFolderName))) { Write-Verbose "Creating the deployment folder -> $DeploymentFolderName" $deploymentFolder = New-Item -Path $DeploymentFolderName -ItemType Directory # Login to Azure and select the subscription containing Login-AzureRmAccount Select-AzureRmSubscription -SubscriptionId $ClientConfig.AzureSubscriptionId # Fetch Valo starter pack from the Blob Storage Write-Verbose "Connection established to Azure, downloading the Valo partner pack" $valoFolderPath = Get-ValoStarterPackFromAzureStorage ` -ValoVersion $ClientConfig.ValoVersion ` -ResourceGroupName $ClientConfig.AzureResourceGroup ` -StorageAccountName $ClientConfig.AzureStorageAccount ` -DestinationPath $deploymentFolder.FullName # Unzip the Valo partner pack and content import $valoPartnerPackFolderPath = Expand-ValoPartnerPack ` -ValoFolderPath $valoFolderPath[1].ToString() ` -DestinationPath $deploymentFolder.FullName ` -ClientConfig $clientConfig } # Copy all client specific files to the Extracted valo folder Get-ChildItem -Directory -Exclude $deploymentFolder.Name | ForEach-Object { Write-Verbose "Copying $($_.FullName) to $valoPartnerPackFolderPath" Copy-Item $_.FullName -Recurse -Destination $valoPartnerPackFolderPath -Force } Write-Verbose "Deployment folder is ready!" return $valoPartnerPackFolderPath } <# .SYNOPSIS This method is used to read the client information contains in his configuration file. .DESCRIPTION This method return a hash table with all useful informations from the client xml file. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function global:Read-ClientConfigurationProject { Param ( [Parameter(Mandatory=$true)] [ValidateScript({Test-Path $_})] [string]$FilePath ) [xml]$xml = (Get-Content($FilePath)) $clientConfig = @{ ValoProjectName = $xml.Project.Name ; ValoVersion = $xml.Project.Valo.Version ; ValoEnvironment = $xml.Project.Valo.Environment; ValoLanguages = $xml.Project.Valo.Languages; AzureSubscriptionID = $xml.Project.Azure.SubscriptionID; AzureResourceGroup = $xml.Project.Azure.ResourceGroupName; AzureStorageAccount = $xml.Project.Azure.StorageAccountName; } $clientConfig.Keys | ForEach-Object { if ([string]::IsNullOrEmpty($clientConfig.Item($_))) { throw [string]::Format("The {0} element is empty!", $_) } } return $clientConfig } <# .SYNOPSIS This method return the file path of where the folder has been downloaded. .DESCRIPTION From the Azure storage account and the resource group name and the valo version, this method retrieve the original partner pack from the blob storage and download it. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function script:Get-ValoStarterPackFromAzureStorage { Param( [Parameter(Mandatory=$true)] [string]$ValoVersion, [Parameter(Mandatory=$true)] [string]$ResourceGroupName, [Parameter(Mandatory=$true)] [string]$StorageAccountName, [Parameter(Mandatory=$false)] [ValidateScript({Test-Path $_})] [string]$DestinationPath = (Get-Location) ) # Obtain storage account context $storageKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceGroupName -Name $StorageAccountName $storageContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $storageKeys[0].Value # Obtain reference to blob partner pack based on the desired version of Valo $container = Get-AzureStorageContainer -Context $storageContext $blob = Get-AzureStorageBlob -Container $container.Name -Context $storageContext | Where-Object {$_.Name -like "*$ValoVersion*"} if($blob -eq $null) { throw "Valo version not found!" } # Download the partner pack localy Get-AzureStorageBlobContent -Blob $blob.Name -Container $container.Name -Context $storageContext -Destination $DestinationPath $valoFilePath = Join-Path $DestinationPath $blob.Name return $valoFilePath } <# .SYNOPSIS This method create, by unziping, the valo partner pack and return is folder path. .DESCRIPTION From the downloaded zip valo package and the client configuration, this method generate a folder ready to launch the genesis valo generator. .LINK Nexus Innovations : http://www.nexusinno.com -------------------------------------------------------------------------------------- Module 'Nexus.PSToolkit' by: Nexus Innovations. -------------------------------------------------------------------------------------- #> function script:Expand-ValoPartnerPack { Param ( [Parameter(Mandatory=$true)] [ValidateScript({Test-Path $_})] [string]$ValoFolderPath, [Parameter(Mandatory=$true)] [hashtable]$ClientConfig, [ValidateScript({Test-Path $_})] [string]$DestinationPath = (Get-Location) ) try { # Unzip the valo package Expand-Archive -Path $ValoFolderPath -DestinationPath $DestinationPath -Force # Move inside the unzipped Valo folder Push-Location -Path $ValoFolderPath.TrimEnd('.zip') # Retrieve the Installation packages path $partnerPackName = [string]::Format("PartnerPack-release{0}-{1}.zip", $ClientConfig.ValoEnvironment, $ClientConfig.ValoVersion) $partnerPackPath = (Get-ChildItem -Recurse -Filter $partnerPackName).FullName if (-not ([string]::IsNullOrEmpty($partnerPackPath))) { Set-Location -Path $DestinationPath # Unzip the PartnerPack Expand-Archive -Path $partnerPackPath -DestinationPath $DestinationPath -Force # Unzip Content Importation folder inside the PartnerPack $contentValoPath = (Get-ChildItem -Recurse -Filter "Example-Content-Valo-demo.zip").FullName $destination = (Get-ChildItem | Where-Object { $_.Name -match $clientConfig.ValoEnvironment}).FullName Expand-Archive -Path $contentValoPath -DestinationPath $destination -Force return $destination } else { throw " An error occurred, the valo environment or the valo version is wrong " } } finally { Pop-Location } } |