Skip to content

Instantly share code, notes, and snippets.

@AdamNaj
Last active April 10, 2017 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AdamNaj/30fecc6dad6b2a4a85ba855c43a10135 to your computer and use it in GitHub Desktop.
Save AdamNaj/30fecc6dad6b2a4a85ba855c43a10135 to your computer and use it in GitHub Desktop.
SXA Folder Synchronizer
<#
.SYNOPSIS
Synchronize local folder (with subfolders) with Media Library (matching structure) on a remote Sitecore instance
.DESCRIPTION
The script allows you to work with SXA Themes in a more comfortable way.
You can need specify the instance hostname, a folder to watch and the location of your Theme in Media Library
in the variables directly below and run the script that will monitor and upload your changes.
The script requires that SPE Remoting is deployed and enabled on the Sitecore Server.
The script requires that SPE Remoting PowerShell Module is installed on your local machine.
The following endpoints must be enabled:
- remoting
- mediaUpload
.NOTES
Author PowerShell: Adam Najmanowicz
Version: 1.0.0 29.March.2017
#>
$ThemeFolder = 'C:\Projects\Showcase'
$MediaLibaryPath = "Project/Showcase/Themes/Showcase"
$protocolHost = "http://sxa"
$userName = "sitecore\admin"
$password = "b"
$global:skippedpaths = @(".sass-cache*","*optimized*", "Styles.css","node_modules*", "Showcase.zip", "Scripts\concat.js");
function global:ShouldSkip([string] $path){
$skipped = $false;
$global:skippedpaths | % {
if($path -like $_){
return $true;
}
}
return $false;
}
function global:GetRelativePath{
Param(
[string] $fullPath,
[string] $ThemeFolder
)
[System.Uri]$fileUri = [System.IO.Path]::GetDirectoryName($fullPath);
[System.Uri]$themeUri = "$ThemeFolder\"
[string]$relativePath = $themeUri.MakeRelativeUri($fileUri);
return $relativePath
}
Import-Module SPE
$filter = '*.*'
#$logfile = "C:\Projects\Showcase.log\outlog.$([DateTime]::Now.ToString('yyMMdd_HHmm')).txt"
$session = New-ScriptSession -Username $userName -Password $password -ConnectionUri $protocolHost
$MessageData = New-Object PSObject -Property @{MediaLibaryPath = $MediaLibaryPath.Trim("/"); logfile = $logfile; session = $session; ThemeFolder = $ThemeFolder.Trim("\")}
$fsw = New-Object IO.FileSystemWatcher $ThemeFolder, $filter -Property @{IncludeSubdirectories = $true; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
Write-Host "Watching '$ThemeFolder'" -fore green
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -MessageData $MessageData -Action {
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$extension = [System.IO.Path]::GetExtension($fullPath).Replace(".", "");
if(global:ShouldSkip $name){
return;
}
Write-Host "[$timeStamp] [$extension] [$changeType] : '$name'" -fore DarkGreen
#Out-File -FilePath $Event.MessageData.logfile -Append -InputObject "The file '$name' was $changeType at $timeStamp"
} | Out-Null
Register-ObjectEvent $fsw Renamed -SourceIdentifier FileRenamed -MessageData $MessageData -Action {
$name = $Event.SourceEventArgs.Name;
$changeType = $Event.SourceEventArgs.ChangeType;
$timeStamp = $Event.TimeGenerated;
$fullPath = $Event.SourceEventArgs.FullPath;
$session = $Event.MessageData.session;
$MediaLibaryPath = $Event.MessageData.MediaLibaryPath;
$newFilenameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fullPath);
$filenameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($Event.SourceEventArgs.OldName);
$extension = [System.IO.Path]::GetExtension($fullPath).Replace(".", "");
$ThemeFolder = $Event.MessageData.ThemeFolder;
if(global:ShouldSkip $name){
return;
}
[string]$relativePath = global:GetRelativePath $fullPath $ThemeFolder
$mediaPath = "master:/media library/$MediaLibaryPath/$relativePath/$filenameWithoutExtension"
Write-Host "[$timeStamp] [$extension] [$changeType] : '$name'" -fore DarkCyan
#Write-Host "'$name' $changeType at $timeStamp. Renaming in Media Library..." -fore Cyan
Invoke-RemoteScript -Session $session -ScriptBlock {
if(Test-Path $using:mediaPath) {
Rename-Item -Path $using:mediaPath -NewName $using:newFilenameWithoutExtension
}
}
Write-Host "[$timeStamp] [$extension] [SERVER:$changeType] : '$mediaPath'" -fore Cyan
#Write-Host "'$mediaPath' was renamed to 'master:\media library\$MediaLibaryPath\$relativePath\$newFilenameWithoutExtension'" -fore Cyan
} | Out-Null
Register-ObjectEvent $fsw Deleted -SourceIdentifier FileDeleted -MessageData $MessageData -Action {
$name = $Event.SourceEventArgs.Name;
$changeType = $Event.SourceEventArgs.ChangeType;
$timeStamp = $Event.TimeGenerated;
$fullPath = $Event.SourceEventArgs.FullPath;
$session = $Event.MessageData.session;
$MediaLibaryPath = $Event.MessageData.MediaLibaryPath;
$filenameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fullPath);
$extension = [System.IO.Path]::GetExtension($fullPath).Replace(".", "");
$ThemeFolder = $Event.MessageData.ThemeFolder;
[string]$relativePath = global:GetRelativePath $fullPath $ThemeFolder
if(global:ShouldSkip $name){
return;
}
$mediaPath = "master:/media library/$MediaLibaryPath/$relativePath/$filenameWithoutExtension"
#Write-Host "'$name' $changeType at $timeStamp. Removing from Media Library..." -fore Red
Write-Host "[$timeStamp] [$extension] [$changeType] : '$name'" -fore DarkRed
Invoke-RemoteScript -Session $session -ScriptBlock {
if(Test-Path $using:mediaPath) {
Remove-Item -Path $using:mediaPath -Force
}
}
Write-Host "[$timeStamp] [$extension] [SERVER:$changeType] : '$mediaPath'" -fore Red
#Write-Host "'$mediaPath' was deleted" -fore Red
#Out-File -FilePath $Event.MessageData.logfile -Append -InputObject "The file '$name' was $changeType at $timeStamp"
} | Out-Null
Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -MessageData $MessageData -Action {
$name = $Event.SourceEventArgs.Name;
$changeType = $Event.SourceEventArgs.ChangeType;
$timeStamp = $Event.TimeGenerated;
$fullPath = $Event.SourceEventArgs.FullPath;
$session = $Event.MessageData.session;
$MediaLibaryPath = $Event.MessageData.MediaLibaryPath;
$filenameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($fullPath);
$extension = [System.IO.Path]::GetExtension($fullPath).Replace(".", "");
$ThemeFolder = $Event.MessageData.ThemeFolder;
if(global:ShouldSkip $name){
return;
}
if((Get-Item $fullPath) -is [System.IO.DirectoryInfo]){
Write-Host "'$name' is a folder - skipping upload." -fore White
return;
}
[string]$relativePath = global:GetRelativePath $fullPath $ThemeFolder
Write-Host "[$timeStamp] [$extension] [$changeType] : '$name'" -fore DarkYellow
#Write-Host "'$name' $changeType at $timeStamp. Uploading..." -fore Yellow
Get-Item -Path $fullPath | Send-RemoteItem -Session $session -RootPath Media -Destination "$MediaLibaryPath/$relativePath"
$mediaPath = "master:/media library/$MediaLibaryPath/$relativePath/$filenameWithoutExtension"
Write-Host "[$timeStamp] [$extension] [SERVER:$changeType] : '$mediaPath'" -fore Yellow
#Write-Host "'$mediaPath' was uploaded" -fore Yellow
#Out-File -FilePath $Event.MessageData.logfile -Append -InputObject "The file '$name' was $changeType at $timeStamp"
} | Out-Null
Write-Host "Uploaded to '$protocolHost/-/media/$MediaLibaryPath'" -fore green
Write-Host "Watcher started." -fore green
while($true) { Start-Sleep -Seconds 1 }
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<remoting enabled="false" requireSecureConnection="false">
<patch:attribute name="enabled">true</patch:attribute>
<authorization>
<add Permission="Allow" IdentityType="User" Identity="sitecore\admin" />
</authorization>
</remoting>
<mediaDownload enabled="false" requireSecureConnection="false">
<patch:attribute name="enabled">true</patch:attribute>
</mediaDownload>
<mediaUpload enabled="false" requireSecureConnection="false">
<patch:attribute name="enabled">true</patch:attribute>
</mediaUpload>
</services>
</powershell>
</sitecore>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment