diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
index 01519bc1c3..7902774f4d 100644
--- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
+++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
@@ -78,7 +78,7 @@ namespace Umbraco.Cms.Core.Services
///
bool HasContainerInPath(params int[] ids);
- Attempt> CreateContainer(int parentContainerId, string name, int userId = Constants.Security.SuperUserId);
+ Attempt> CreateContainer(int parentContainerId, Guid key, string name, int userId = Constants.Security.SuperUserId);
Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId);
EntityContainer GetContainer(int containerId);
EntityContainer GetContainer(Guid containerId);
diff --git a/src/Umbraco.Core/Services/IDataTypeService.cs b/src/Umbraco.Core/Services/IDataTypeService.cs
index c7b13c04e1..727851ef02 100644
--- a/src/Umbraco.Core/Services/IDataTypeService.cs
+++ b/src/Umbraco.Core/Services/IDataTypeService.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Services
///
IReadOnlyDictionary> GetReferences(int id);
- Attempt> CreateContainer(int parentId, string name, int userId = Constants.Security.SuperUserId);
+ Attempt> CreateContainer(int parentId, Guid key, string name, int userId = Constants.Security.SuperUserId);
Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId);
EntityContainer GetContainer(int containerId);
EntityContainer GetContainer(Guid containerId);
@@ -68,7 +68,7 @@ namespace Umbraco.Cms.Core.Services
/// to save
/// Id of the user issuing the save
void Save(IEnumerable dataTypeDefinitions, int userId = Constants.Security.SuperUserId);
-
+
///
/// Deletes an
///
diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs
index 8f9352ce22..c691b74a0c 100644
--- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs
+++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs
@@ -546,13 +546,33 @@ namespace Umbraco.Cms.Infrastructure.Packaging
{
var alias = documentType.Element("Info").Element("Alias").Value;
var folders = foldersAttribute.Value.Split(Constants.CharArrays.ForwardSlash);
+
+ var folderKeysAttribute = documentType.Attribute("FolderKeys");
+
+ var folderKeys = Array.Empty();
+ if (folderKeysAttribute != null)
+ {
+ folderKeys = folderKeysAttribute.Value.Split(Constants.CharArrays.ForwardSlash).Select(x=>Guid.Parse(x)).ToArray();
+ }
+
var rootFolder = WebUtility.UrlDecode(folders[0]);
- //level 1 = root level folders, there can only be one with the same name
- var current = _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault();
+
+ EntityContainer current;
+ Guid? rootFolderKey = null;
+ if (folderKeys.Length == folders.Length && folderKeys.Length > 0)
+ {
+ rootFolderKey = folderKeys[0];
+ current = _contentTypeService.GetContainer(rootFolderKey.Value);
+ }
+ else
+ {
+ //level 1 = root level folders, there can only be one with the same name
+ current = _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault();
+ }
if (current == null)
{
- var tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolder);
+ var tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolderKey ?? Guid.NewGuid(), rootFolder);
if (tryCreateFolder == false)
{
_logger.LogError(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder);
@@ -567,7 +587,8 @@ namespace Umbraco.Cms.Infrastructure.Packaging
for (var i = 1; i < folders.Length; i++)
{
var folderName = WebUtility.UrlDecode(folders[i]);
- current = CreateContentTypeChildFolder(folderName, current);
+ Guid? folderKey = (folderKeys.Length == folders.Length) ? folderKeys[i] : null;
+ current = CreateContentTypeChildFolder(folderName, folderKey ?? Guid.NewGuid(), current);
importedFolders[alias] = current.Id;
}
}
@@ -576,17 +597,17 @@ namespace Umbraco.Cms.Infrastructure.Packaging
return importedFolders;
}
- private EntityContainer CreateContentTypeChildFolder(string folderName, IUmbracoEntity current)
+ private EntityContainer CreateContentTypeChildFolder(string folderName, Guid folderKey, IUmbracoEntity current)
{
var children = _entityService.GetChildren(current.Id).ToArray();
- var found = children.Any(x => x.Name.InvariantEquals(folderName));
+ var found = children.Any(x => x.Name.InvariantEquals(folderName) ||x.Key.Equals(folderKey));
if (found)
{
var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id;
return _contentTypeService.GetContainer(containerId);
}
- var tryCreateFolder = _contentTypeService.CreateContainer(current.Id, folderName);
+ var tryCreateFolder = _contentTypeService.CreateContainer(current.Id, folderKey, folderName);
if (tryCreateFolder == false)
{
_logger.LogError(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName);
@@ -1057,17 +1078,26 @@ namespace Umbraco.Cms.Infrastructure.Packaging
foreach (var datatypeElement in datatypeElements)
{
var foldersAttribute = datatypeElement.Attribute("Folders");
+
if (foldersAttribute != null)
{
var name = datatypeElement.Attribute("Name").Value;
var folders = foldersAttribute.Value.Split(Constants.CharArrays.ForwardSlash);
+ var folderKeysAttribute = datatypeElement.Attribute("FolderKeys");
+
+ var folderKeys = Array.Empty();
+ if (folderKeysAttribute != null)
+ {
+ folderKeys = folderKeysAttribute.Value.Split(Constants.CharArrays.ForwardSlash).Select(x=>Guid.Parse(x)).ToArray();
+ }
var rootFolder = WebUtility.UrlDecode(folders[0]);
+ var rootFolderKey = folderKeys.Length > 0 ? folderKeys[0] : Guid.NewGuid();
//there will only be a single result by name for level 1 (root) containers
var current = _dataTypeService.GetContainers(rootFolder, 1).FirstOrDefault();
if (current == null)
{
- var tryCreateFolder = _dataTypeService.CreateContainer(-1, rootFolder);
+ var tryCreateFolder = _dataTypeService.CreateContainer(-1, rootFolderKey, rootFolder);
if (tryCreateFolder == false)
{
_logger.LogError(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder);
@@ -1081,7 +1111,8 @@ namespace Umbraco.Cms.Infrastructure.Packaging
for (var i = 1; i < folders.Length; i++)
{
var folderName = WebUtility.UrlDecode(folders[i]);
- current = CreateDataTypeChildFolder(folderName, current);
+ Guid? folderKey = (folderKeys.Length == folders.Length) ? folderKeys[i] : null;
+ current = CreateDataTypeChildFolder(folderName, folderKey ?? Guid.NewGuid(), current);
importedFolders[name] = current.Id;
}
}
@@ -1090,17 +1121,17 @@ namespace Umbraco.Cms.Infrastructure.Packaging
return importedFolders;
}
- private EntityContainer CreateDataTypeChildFolder(string folderName, IUmbracoEntity current)
+ private EntityContainer CreateDataTypeChildFolder(string folderName, Guid folderKey, IUmbracoEntity current)
{
var children = _entityService.GetChildren(current.Id).ToArray();
- var found = children.Any(x => x.Name.InvariantEquals(folderName));
+ var found = children.Any(x => x.Name.InvariantEquals(folderName) ||x.Key.Equals(folderKey));
if (found)
{
var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id;
return _dataTypeService.GetContainer(containerId);
}
- var tryCreateFolder = _dataTypeService.CreateContainer(current.Id, folderName);
+ var tryCreateFolder = _dataTypeService.CreateContainer(current.Id, folderKey,folderName);
if (tryCreateFolder == false)
{
_logger.LogError(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName);
diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
index fd23db2615..8f0c8ce49b 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
@@ -830,7 +830,7 @@ namespace Umbraco.Cms.Core.Services.Implement
protected Guid ContainerObjectType => EntityContainer.GetContainerObjectType(ContainedObjectType);
- public Attempt> CreateContainer(int parentId, string name, int userId = Cms.Core.Constants.Security.SuperUserId)
+ public Attempt> CreateContainer(int parentId, Guid key, string name, int userId = Cms.Core.Constants.Security.SuperUserId)
{
EventMessages eventMessages = EventMessagesFactory.Get();
using (IScope scope = ScopeProvider.CreateScope())
@@ -843,7 +843,8 @@ namespace Umbraco.Cms.Core.Services.Implement
{
Name = name,
ParentId = parentId,
- CreatorId = userId
+ CreatorId = userId,
+ Key = key
};
var savingNotification = new EntityContainerSavingNotification(container, eventMessages);
diff --git a/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs b/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs
index 50caca0ec8..d63335ba33 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs
@@ -59,7 +59,7 @@ namespace Umbraco.Cms.Core.Services.Implement
#region Containers
- public Attempt> CreateContainer(int parentId, string name, int userId = Cms.Core.Constants.Security.SuperUserId)
+ public Attempt> CreateContainer(int parentId, Guid key, string name, int userId = Cms.Core.Constants.Security.SuperUserId)
{
var evtMsgs = EventMessagesFactory.Get();
using (var scope = ScopeProvider.CreateScope())
@@ -70,7 +70,8 @@ namespace Umbraco.Cms.Core.Services.Implement
{
Name = name,
ParentId = parentId,
- CreatorId = userId
+ CreatorId = userId,
+ Key = key
};
var savingEntityContainerNotification = new EntityContainerSavingNotification(container, evtMsgs);
diff --git a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs
index d2c3189447..06b279cdac 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs
@@ -191,18 +191,23 @@ namespace Umbraco.Cms.Core.Services.Implement
xml.Add(new XAttribute("Configuration", _configurationEditorJsonSerializer.Serialize(dataType.Configuration)));
var folderNames = string.Empty;
+ var folderKeys = string.Empty;
if (dataType.Level != 1)
{
//get URL encoded folder names
var folders = _dataTypeService.GetContainers(dataType)
- .OrderBy(x => x.Level)
- .Select(x => WebUtility.UrlEncode(x.Name));
+ .OrderBy(x => x.Level);
- folderNames = string.Join("/", folders.ToArray());
+ folderNames = string.Join("/", folders.Select(x => WebUtility.UrlEncode(x.Name)).ToArray());
+ folderKeys = string.Join("/", folders.Select(x => x.Key).ToArray());
}
if (string.IsNullOrWhiteSpace(folderNames) == false)
+ {
xml.Add(new XAttribute("Folders", folderNames));
+ xml.Add(new XAttribute("FolderKeys", folderKeys));
+ }
+
return xml;
}
@@ -490,19 +495,24 @@ namespace Umbraco.Cms.Core.Services.Implement
tabs);
var folderNames = string.Empty;
+ var folderKeys = string.Empty;
//don't add folders if this is a child doc type
if (contentType.Level != 1 && masterContentType == null)
{
//get URL encoded folder names
var folders = _contentTypeService.GetContainers(contentType)
- .OrderBy(x => x.Level)
- .Select(x => WebUtility.UrlEncode(x.Name));
+ .OrderBy(x => x.Level);
- folderNames = string.Join("/", folders.ToArray());
+ folderNames = string.Join("/", folders.Select(x => WebUtility.UrlEncode(x.Name)).ToArray());
+ folderKeys = string.Join("/", folders.Select(x => x.Key).ToArray());
}
if (string.IsNullOrWhiteSpace(folderNames) == false)
+ {
xml.Add(new XAttribute("Folders", folderNames));
+ xml.Add(new XAttribute("FolderKeys", folderKeys));
+ }
+
return xml;
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
index ad9ec91353..b78ac1fdfd 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
@@ -292,7 +292,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public IActionResult PostCreateContainer(int parentId, string name)
{
- var result = _contentTypeService.CreateContainer(parentId, name, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id);
+ var result = _contentTypeService.CreateContainer(parentId, Guid.NewGuid(), name, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id);
if (result.Success)
return Ok(result.Result); //return the id
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
index d68c3f06f5..19ee05d4e9 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
@@ -260,7 +260,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
public IActionResult PostCreateContainer(int parentId, string name)
{
var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
- var result = _dataTypeService.CreateContainer(parentId, name, currentUser.Id);
+ var result = _dataTypeService.CreateContainer(parentId, Guid.NewGuid(), name, currentUser.Id);
if (result.Success)
return Ok(result.Result); //return the id
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
index 3233679ad9..cd1e9037ec 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
@@ -261,7 +261,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaTypes)]
public IActionResult PostCreateContainer(int parentId, string name)
{
- var result = _mediaTypeService.CreateContainer(parentId, name, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id);
+ var result = _mediaTypeService.CreateContainer(parentId, Guid.NewGuid(), name, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id);
if (result.Success)
return Ok(result.Result); //return the id