Last active
December 12, 2023 22:55
-
-
Save gregwiechec/012d640dfa6d47d562e3022b8ece88b2 to your computer and use it in GitHub Desktop.
Copying inline blocks when translating pages
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
using System.Collections.Generic; | |
using EPiServer; | |
using EPiServer.Cms.Shell.UI.Rest; | |
using EPiServer.Cms.Shell.Workspace.Committers; | |
using EPiServer.Core; | |
using EPiServer.Data.Entity; | |
using EPiServer.DataAccess; | |
using EPiServer.Framework; | |
using EPiServer.Framework.Initialization; | |
using EPiServer.Security; | |
using EPiServer.ServiceLocation; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace AlloyTemplates.Business; | |
[ServiceConfiguration(typeof(InlineBlocksCopier))] | |
public class InlineBlocksCopier | |
{ | |
private readonly IContentRepository _contentRepository; | |
private readonly IBlockPropertyFactory _blockPropertyFactory; | |
public InlineBlocksCopier(IContentRepository contentRepository, | |
IBlockPropertyFactory blockPropertyFactory) | |
{ | |
_contentRepository = contentRepository; | |
_blockPropertyFactory = blockPropertyFactory; | |
} | |
public void CopyInlineBlocks(ContentReference masterLanguageId, ContentReference translatedReference) | |
{ | |
var master = _contentRepository.Get<IContent>(masterLanguageId); | |
var translated = _contentRepository.Get<IContent>(translatedReference); | |
if (translated is IReadOnly) | |
{ | |
translated = (IContent)((IReadOnly) translated).CreateWritableClone(); | |
} | |
var needSave = false; | |
foreach (var propertyData in master.Property) | |
{ | |
if (propertyData.PropertyValueType != typeof(ContentArea)) | |
{ | |
continue; | |
} | |
if (propertyData.Value == null) | |
{ | |
continue; | |
} | |
if (!propertyData.IsLanguageSpecific) | |
{ | |
continue; | |
} | |
var contentArea = (ContentArea)propertyData.Value; | |
foreach (var contentAreaItem in contentArea.Items) | |
{ | |
if (ContentReference.IsNullOrEmpty(contentAreaItem.ContentLink)) | |
{ | |
var translatedPropertyData = translated.Property[propertyData.Name]; | |
if (translatedPropertyData.Value == null) | |
{ | |
translatedPropertyData.Value = new ContentArea(); | |
} | |
var translatedContentArea = (ContentArea) translatedPropertyData.Value; | |
var blockData = _blockPropertyFactory.CreateFromSharedInstance(contentAreaItem.InlineBlock); | |
translatedContentArea.Items.Add(new ContentAreaItem | |
{ | |
InlineBlock = blockData, | |
RenderSettings = contentAreaItem.RenderSettings | |
}); | |
needSave = true; | |
} | |
} | |
} | |
if (needSave) | |
{ | |
_contentRepository.Save(translated, SaveAction.ForceCurrentVersion, AccessLevel.NoAccess); | |
} | |
} | |
} | |
public class ExtendedChangeManager: IContentChangeManager | |
{ | |
private readonly IContentChangeManager _defaultContentChangeManager; | |
private readonly IHttpContextAccessor _httpContextAccessor; | |
private readonly InlineBlocksCopier _inlineBlocksCopier; | |
public ExtendedChangeManager(IContentChangeManager defaultContentChangeManager) : this(defaultContentChangeManager, | |
ServiceLocator.Current.GetInstance<IHttpContextAccessor>(), | |
ServiceLocator.Current.GetInstance<InlineBlocksCopier>()) | |
{ | |
_defaultContentChangeManager = defaultContentChangeManager; | |
} | |
public ExtendedChangeManager(IContentChangeManager defaultContentChangeManager, | |
IHttpContextAccessor httpContextAccessor, | |
InlineBlocksCopier inlineBlocksCopier) | |
{ | |
_defaultContentChangeManager = defaultContentChangeManager; | |
_httpContextAccessor = httpContextAccessor; | |
_inlineBlocksCopier = inlineBlocksCopier; | |
} | |
public CommitResult Commit(ContentReference contentReference, SaveAction action) | |
{ | |
return _defaultContentChangeManager.Commit(contentReference, action); | |
} | |
public ContentReference Create(ContentReference parentLink, int contentTypeId, long? resourceFolderId, bool createAsLocalAsset, | |
ILocalAssetNameGenerator nameGenerator, IDictionary<string, object> properties) | |
{ | |
return _defaultContentChangeManager.Create(parentLink, contentTypeId, resourceFolderId, createAsLocalAsset, | |
nameGenerator, properties); | |
} | |
public ContentReference Create(ContentReference parentLink, int contentTypeId, long? resourceFolderId, bool createAsLocalAsset, | |
string name, IDictionary<string, object> properties) | |
{ | |
return _defaultContentChangeManager.Create(parentLink, contentTypeId, resourceFolderId, createAsLocalAsset, | |
name, properties); | |
} | |
public ContentReference GetOrCreateContentAssetsFolder(ContentReference parentLink) | |
{ | |
return _defaultContentChangeManager.GetOrCreateContentAssetsFolder(parentLink); | |
} | |
public ContentReference CreateLanguageBranch(ContentReference contentReference, string name, string languageBranch, | |
IDictionary<string, object> properties) | |
{ | |
var copyInlineBlocks = false; | |
var fakeKey = "ichangetrackable_createdby"; | |
if (properties.ContainsKey(fakeKey)) | |
{ | |
copyInlineBlocks = properties[fakeKey]?.ToString() == "true"; | |
properties.Remove(fakeKey); | |
} | |
var result = _defaultContentChangeManager.CreateLanguageBranch(contentReference, name, languageBranch, properties); | |
if (copyInlineBlocks) | |
{ | |
_inlineBlocksCopier.CopyInlineBlocks(contentReference, result); | |
} | |
return result; | |
} | |
public ContentReference Copy(IContent source, IContent destination, bool createAsLocalAsset) | |
{ | |
return _defaultContentChangeManager.Copy(source, destination, createAsLocalAsset); | |
} | |
public ContentReference Move(IContent source, IContent destination, bool createAsLocalAsset) | |
{ | |
return _defaultContentChangeManager.Move(source, destination, createAsLocalAsset); | |
} | |
public IEnumerable<ContentReference> TranslateAncestors(IContent content) | |
{ | |
return _defaultContentChangeManager.TranslateAncestors(content); | |
} | |
public PropertiesUpdateResult UpdateContentProperties(ContentReference contentReference, IDictionary<string, string> properties) | |
{ | |
return _defaultContentChangeManager.UpdateContentProperties( contentReference, properties); | |
} | |
public PropertiesUpdateResult UpdateContentProperties(ContentReference contentReference, IDictionary<string, string> properties, | |
SaveAction saveAction) | |
{ | |
return _defaultContentChangeManager.UpdateContentProperties(contentReference, properties, saveAction); | |
} | |
} | |
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))] | |
public class ChangeManagerInitializer : IConfigurableModule | |
{ | |
public void ConfigureContainer(ServiceConfigurationContext context) | |
{ | |
context.Services.Intercept<IContentChangeManager>( | |
(locator, defaultChangeManager) => new ExtendedChangeManager(defaultChangeManager)); | |
} | |
public void Initialize(InitializationEngine context) | |
{ | |
} | |
public void Uninitialize(InitializationEngine context) | |
{ | |
} | |
} |
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
define([ | |
"dojo/_base/declare", | |
"dojo/when", | |
"epi/_Module", | |
"epi", | |
"epi/dependency", | |
"epi/shell/DialogService", | |
"epi-cms/contentediting/CreateLanguageBranch", | |
"epi-cms/contentediting/viewmodel/CreateLanguageBranchViewModel", | |
"epi/i18n!epi/nls/admin.convertpagetype" | |
], function ( | |
declare, | |
when, | |
_Module, | |
epi, | |
dependency, | |
dialogService, | |
CreateLanguageBranch, | |
CreateLanguageBranchViewModel, | |
adminResources | |
) { | |
var ExtendedCreateLanguageBranchViewModel = declare([CreateLanguageBranchViewModel], { | |
buildContentObject: function() { | |
var result = this.inherited(arguments); | |
if (typeof this.convertLocalBlocks !== "undefined") { | |
result.properties["ichangetrackable_createdby"] = this.convertLocalBlocks.toString(); | |
} | |
return result; | |
} | |
}) | |
function patchSaveMethod() { | |
var originalOnSave = CreateLanguageBranch.prototype._onSave; | |
CreateLanguageBranch.prototype._onSave = function (e) { | |
var self = this; | |
hasInlineBlocks(this.model.masterLanguageVersionId).then(result => { | |
if (!result) { | |
self.model.convertLocalBlocks = undefined; | |
originalOnSave.apply(self, arguments); | |
return; | |
} | |
dialogService.confirmation({ | |
title: "Confirm", | |
description: "Should copy all ContentArea inline blocks?", | |
confirmActionText: adminResources.convert, | |
cancelActionText: epi.resources.action.ignore | |
}).then(function () { | |
self.model.convertLocalBlocks = true; | |
originalOnSave.apply(self, arguments); | |
}).otherwise(function() { | |
self.model.convertLocalBlocks = false; | |
originalOnSave.apply(self, arguments); | |
}); | |
}); | |
} | |
CreateLanguageBranch.prototype._onSave.nom = "_onSave"; | |
} | |
// check if content contains contentarea with inline blocks | |
let metadataManager, contentDataStore; | |
function hasInlineBlocks(contentLink) { | |
metadataManager = metadataManager || dependency.resolve("epi.shell.MetadataManager"); | |
return new Promise(resolve => { | |
metadataManager.getMetadataForType("EPiServer.Core.ContentData", {contentLink: contentLink}).then((metadata) => { | |
const contentAreaProperties = metadata.properties | |
.filter(x => x.modelType === "EPiServer.Core.ContentArea" && x.settings && x.settings.isLanguageSpecific) | |
.map(x => x.name); | |
if (contentAreaProperties.length === 0) { | |
resolve(false); | |
return; | |
} | |
contentDataStore = contentDataStore || dependency.resolve("epi.storeregistry").get("epi.cms.contentdata"); | |
when(contentDataStore.get(contentLink)).then(function (content) { | |
const hasInlineBlocks = contentAreaProperties.some(x => { | |
const propertyName = Object.keys(content.properties).find(key=> key.toLowerCase() === x.toLowerCase()); | |
const property = content.properties[propertyName]; | |
if (property && property.some(p => p.inlineBlockData)) { | |
return true; | |
} | |
return false; | |
}); | |
resolve(hasInlineBlocks); | |
}); | |
}); | |
}); | |
} | |
return declare([_Module], { | |
initialize: function () { | |
this.inherited(arguments); | |
CreateLanguageBranch.prototype.modelType = ExtendedCreateLanguageBranchViewModel; | |
patchSaveMethod(); | |
} | |
}); | |
}); |
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
public class StandardPage : SitePageData | |
{ | |
[CultureSpecific] | |
public virtual ContentArea LocalizableContentArea { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment