This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Helix.Skeleton.Foundation.EditorExtensions.Services | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Xml.Linq; | |
using Helix.Skeleton.Foundation.EditorExtensions.Consts.CopyPage; | |
using Helix.Skeleton.Foundation.EditorExtensions.Models.CopyPage; | |
using Sitecore; | |
using Sitecore.Configuration; | |
using Sitecore.Data; | |
using Sitecore.Data.Fields; | |
using Sitecore.Data.Items; | |
using Sitecore.Globalization; | |
using Sitecore.Layouts; | |
using Sitecore.Rules.ConditionalRenderings; | |
public class CopyPageService : ICopyPageService | |
{ | |
private const string ContentFolderName = "Content"; | |
private const string GetItemsByNameAndTemplateQueryFormat = "{0}/*[@@name='{1}' and @@templateid='{2}']"; | |
public Item GetContentFolder(string currentItemPath, string databaseName) | |
{ | |
var foundContentItems = Factory | |
.GetDatabase(databaseName) | |
.SelectItems(string.Format(GetItemsByNameAndTemplateQueryFormat, currentItemPath.Replace("-", "#-#").Replace("$", "#$#"), ContentFolderName, TemplateIDs.Folder.ToString())); | |
if (foundContentItems.Length > 1) | |
{ | |
return null; | |
} | |
return foundContentItems.FirstOrDefault(); | |
} | |
public Item CopyLastVersion(Database database, Language language, Item source, Item destinationWithoutVersion) | |
{ | |
var languageSpecificSource = database.GetItem(source.ID, language); | |
if (languageSpecificSource.Versions.Count == 0) | |
{ | |
return null; | |
} | |
var languageSpecificDestination = database.GetItem(destinationWithoutVersion.ID, language); | |
languageSpecificDestination = languageSpecificDestination.Versions.AddVersion(); | |
languageSpecificDestination.Editing.BeginEdit(); | |
languageSpecificSource.Fields.ReadAll(); | |
foreach (Field field in languageSpecificSource.Fields) | |
{ | |
languageSpecificDestination.Fields[field.ID].SetValue(field.Value, true); | |
} | |
languageSpecificDestination.Editing.EndEdit(); | |
languageSpecificDestination.Editing.AcceptChanges(); | |
return languageSpecificDestination; | |
} | |
public void AdjustLayout(Database database, Item newItem, Item oldItem, ID layoutFieldId) | |
{ | |
var allDevices = database.Resources.Devices.GetAll(); | |
var newLayoutField = new LayoutField(newItem.Fields[layoutFieldId]); | |
var oldDatasources = new List<IOldDatasourceItem>(); | |
foreach (var device in allDevices) | |
{ | |
var renderingReferences = newLayoutField.GetReferences(device); | |
if (renderingReferences == null) | |
{ | |
continue; | |
} | |
// Collect datasource references | |
oldDatasources.AddRange(this.GetOldReferences(database, renderingReferences.Where(r => r != null), r => r.Settings.DataSource)); | |
// Collect personalization references | |
var conditionalRenderings = renderingReferences | |
.Where(r => r?.Settings?.Rules?.Rules != null) | |
.SelectMany(r => r.Settings.Rules.Rules | |
.SelectMany(rule => rule?.Actions | |
.Select(a => a as SetDataSourceAction<ConditionalRenderingsRuleContext>).Where(a => a != null))); | |
oldDatasources.AddRange(this.GetOldReferences(database, conditionalRenderings, c => c.DataSource)); | |
} | |
var newLayoutDefinition = LayoutDefinition.Parse(newLayoutField.Value); | |
foreach (var device in newLayoutDefinition.Devices.Cast<DeviceDefinition>()) | |
{ | |
var renderings = device.Renderings.Cast<RenderingDefinition>(); | |
// Set datasource referneces | |
this.SetNewReferences( | |
new SetNewReferencesParameters<RenderingDefinition> | |
{ | |
Database = database, | |
NewItem = newItem, | |
OldItem = oldItem, | |
NewLayout = newLayoutField, | |
NewLayoutDefinition = newLayoutDefinition, | |
OldDatasources = oldDatasources, | |
SourceList = renderings.Where(r => r.Datasource != null), | |
GetIdValue = r => r.Datasource, | |
SetIdValue = (r, d) => r.Datasource = d | |
}); | |
// Set personalization references | |
var actions = renderings | |
.Where(r => r?.Rules?.Descendants(RuleAttributeKeys.ActionKey) != null) | |
.SelectMany(r => r.Rules.Descendants(RuleAttributeKeys.ActionKey) | |
.Select(a => a.Attribute(RuleAttributeKeys.DatasourceKey)) | |
.Where(a => a != null)); | |
this.SetNewReferences( | |
new SetNewReferencesParameters<XAttribute> | |
{ | |
Database = database, | |
NewItem = newItem, | |
OldItem = oldItem, | |
NewLayout = newLayoutField, | |
NewLayoutDefinition = newLayoutDefinition, | |
OldDatasources = oldDatasources, | |
SourceList = actions, | |
GetIdValue = r => r.Value, | |
SetIdValue = (r, d) => r.SetValue(d) | |
}); | |
} | |
} | |
private IEnumerable<IOldDatasourceItem> GetOldReferences<T>(Database database, IEnumerable<T> sourceList, Func<T, string> getDatasourceId) | |
{ | |
var oldDatasources = new List<IOldDatasourceItem>(); | |
if (sourceList == null) | |
{ | |
return oldDatasources; | |
} | |
foreach (var rendering in sourceList) | |
{ | |
ID oldDatasourceId; | |
if (!ID.TryParse(getDatasourceId.Invoke(rendering), out oldDatasourceId)) | |
{ | |
continue; | |
} | |
var oldDatasource = database.GetItem(oldDatasourceId); | |
if (oldDatasource == null) | |
{ | |
continue; | |
} | |
// Handle duplicated paths | |
var oldDatasourcesWithSamePath = database.SelectItems(oldDatasource.Paths.FullPath).ToList(); | |
oldDatasources.Add( | |
new OldDatasourceItem | |
{ | |
Id = oldDatasourceId, | |
Path = oldDatasource.Paths.FullPath, | |
Index = oldDatasourcesWithSamePath.IndexOf(oldDatasourcesWithSamePath.FirstOrDefault(d => d.ID == oldDatasourceId)) | |
}); | |
} | |
return oldDatasources; | |
} | |
private void SetNewReferences<T>(ISetNewReferencesParameters<T> parameters) | |
{ | |
foreach (var rendering in parameters.SourceList) | |
{ | |
var datasource = parameters.GetIdValue.Invoke(rendering); | |
var matchedOldDatasource = parameters.OldDatasources.FirstOrDefault(d => d.Id.ToString() == datasource); | |
if (matchedOldDatasource == null) | |
{ | |
continue; | |
} | |
string newDatasourcePath = matchedOldDatasource.Path.ToString().Replace(parameters.OldItem.Paths.FullPath, parameters.NewItem.Paths.FullPath); | |
var newDatasource = parameters.Database.SelectItems(newDatasourcePath)[matchedOldDatasource.Index]; | |
parameters.SetIdValue.Invoke(rendering, newDatasource.ID.ToString()); | |
parameters.NewItem.Editing.BeginEdit(); | |
parameters.NewLayout.Value = parameters.NewLayoutDefinition.ToXml(); | |
parameters.NewItem.Editing.EndEdit(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment