From 63de9e6691723bc6c2b12ef495f432f44d7a4c8d Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 21 Mar 2013 12:34:10 -0100 Subject: [PATCH] Refactoring package installer to use the new PackagingService. Refactoring ImportDocumentType dialog to import through the PackagingService. Making a few corrections to the ProppertyGroup and PropertyType classes to support bulk saving. --- src/Umbraco.Core/Models/ContentTypeBase.cs | 2 +- .../Models/ContentTypeCompositionBase.cs | 9 +- src/Umbraco.Core/Models/PropertyGroup.cs | 20 +- src/Umbraco.Core/Models/PropertyType.cs | 6 +- .../Factories/PropertyGroupFactory.cs | 6 +- .../Repositories/ContentTypeBaseRepository.cs | 24 +- src/Umbraco.Core/Services/PackagingService.cs | 42 +- src/Umbraco.Core/TopologicalSorter.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../Repositories/ContentTypeRepositoryTest.cs | 2 +- .../Importing/ImportResources.Designer.cs | 54 +- .../Services/Importing/ImportResources.resx | 10 +- .../Importing/InheritedDocTypes-Package.xml | 445 ++++ .../Services/Importing/PackageImportTests.cs | 114 +- .../{package.xml => StandardMvc-Package.xml} | 0 .../Services/Importing/uBlogsy-Package.xml | 2163 +++++++++++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 4 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- .../controls/ContentTypeControlNew.ascx.cs | 22 +- .../dialogs/importDocumenttype.aspx.cs | 55 +- .../businesslogic/Packager/Installer.cs | 892 ++++--- .../PackageInstance/InstalledPackage.cs | 14 +- src/umbraco.cms/umbraco.cms.csproj | 1 + 23 files changed, 3389 insertions(+), 501 deletions(-) create mode 100644 src/Umbraco.Tests/Services/Importing/InheritedDocTypes-Package.xml rename src/Umbraco.Tests/Services/Importing/{package.xml => StandardMvc-Package.xml} (100%) create mode 100644 src/Umbraco.Tests/Services/Importing/uBlogsy-Package.xml diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 0877354bba..35bc9bee3c 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -381,7 +381,7 @@ namespace Umbraco.Core.Models oldPropertyGroup.PropertyTypes.RemoveItem(propertyTypeAlias); } - propertyType.PropertyGroupId = default(int); + propertyType.PropertyGroupId = new Lazy(() => default(int)); propertyType.ResetDirtyProperties(); var propertyGroup = PropertyGroups.First(x => x.Name == propertyGroupName); diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs index 72c0a6f72a..02a5e7d8f7 100644 --- a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -140,8 +140,8 @@ namespace Umbraco.Core.Models if (CompositionPropertyGroups.Any(x => x.Name == groupName)) { - var first = CompositionPropertyGroups.First(x => x.Name == groupName && x.ParentId.HasValue == false); - propertyGroup.ParentId = first.Id; + var firstGroup = CompositionPropertyGroups.First(x => x.Name == groupName && x.ParentId.HasValue == false); + propertyGroup.SetLazyParentId(new Lazy(() => firstGroup.Id)); } if (PropertyGroups.Any()) @@ -166,7 +166,7 @@ namespace Umbraco.Core.Models { if (PropertyGroups.Contains(propertyGroupName)) { - propertyType.PropertyGroupId = PropertyGroups[propertyGroupName].Id; + propertyType.PropertyGroupId = new Lazy(() => PropertyGroups[propertyGroupName].Id); PropertyGroups[propertyGroupName].PropertyTypes.Add(propertyType); } else @@ -179,7 +179,8 @@ namespace Umbraco.Core.Models { var parentPropertyGroup = CompositionPropertyGroups.First(x => x.Name == propertyGroupName && x.ParentId.HasValue == false); propertyGroup.SortOrder = parentPropertyGroup.SortOrder; - propertyGroup.ParentId = parentPropertyGroup.Id; + //propertyGroup.ParentId = parentPropertyGroup.Id; + propertyGroup.SetLazyParentId(new Lazy(() => parentPropertyGroup.Id)); } PropertyGroups.Add(propertyGroup); diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Core/Models/PropertyGroup.cs index 8b1467ec48..d01d7cbbac 100644 --- a/src/Umbraco.Core/Models/PropertyGroup.cs +++ b/src/Umbraco.Core/Models/PropertyGroup.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Models public class PropertyGroup : Entity, IEquatable { private string _name; - private int? _parentId; + private Lazy _parentId; private int _sortOrder; private PropertyTypeCollection _propertyTypes; @@ -60,10 +60,15 @@ namespace Umbraco.Core.Models [DataMember] public int? ParentId { - get { return _parentId; } + get + { + if (_parentId == null) + return default(int?); + return _parentId.Value; + } set { - _parentId = value; + _parentId = new Lazy(() => value); OnPropertyChanged(ParentIdSelector); } } @@ -96,6 +101,15 @@ namespace Umbraco.Core.Models } } + /// + /// Sets the ParentId from the lazy integer id + /// + /// Id of the Parent + internal void SetLazyParentId(Lazy id) + { + _parentId = id; + } + public bool Equals(PropertyGroup other) { //Check whether the compared object is null. diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 874e58ea6f..55bec87bf3 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Models private string _alias; private string _description; private int _dataTypeDefinitionId; - private int _propertyGroupId; + private Lazy _propertyGroupId; private Guid _dataTypeId; private DataTypeDatabaseType _dataTypeDatabaseType; private bool _mandatory; @@ -61,7 +61,7 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo HelpTextSelector = ExpressionHelper.GetPropertyInfo(x => x.HelpText); private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); private static readonly PropertyInfo ValidationRegExpSelector = ExpressionHelper.GetPropertyInfo(x => x.ValidationRegExp); - private static readonly PropertyInfo PropertyGroupIdSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroupId); + private static readonly PropertyInfo PropertyGroupIdSelector = ExpressionHelper.GetPropertyInfo>(x => x.PropertyGroupId); /// /// Gets of Sets the Name of the PropertyType @@ -153,7 +153,7 @@ namespace Umbraco.Core.Models /// Gets or Sets the PropertyGroup's Id for which this PropertyType belongs /// [DataMember] - internal int PropertyGroupId + internal Lazy PropertyGroupId { get { return _propertyGroupId; } set diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs index 9449f2c375..3139fe5fa4 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -44,6 +45,7 @@ namespace Umbraco.Core.Persistence.Factories var typeDtos = groupDto.PropertyTypeDtos.Where(x => x.Id > 0); foreach (var typeDto in typeDtos) { + var tempGroupDto = groupDto; var propertyType = new PropertyType(typeDto.DataTypeDto.ControlId, typeDto.DataTypeDto.DbType.EnumParse(true)) { @@ -56,7 +58,7 @@ namespace Umbraco.Core.Persistence.Factories Mandatory = typeDto.Mandatory, SortOrder = typeDto.SortOrder, ValidationRegExp = typeDto.ValidationRegExp, - PropertyGroupId = groupDto.Id + PropertyGroupId = new Lazy(() => tempGroupDto.Id) }; propertyType.ResetDirtyProperties(); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index 33c9020e44..93bd973fb0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -108,7 +108,12 @@ namespace Umbraco.Core.Persistence.Repositories //Insert collection of allowed content types foreach (var allowedContentType in entity.AllowedContentTypes) { - Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id.Value, SortOrder = allowedContentType.SortOrder }); + Database.Insert(new ContentTypeAllowedContentTypeDto + { + Id = entity.Id, + AllowedId = allowedContentType.Id.Value, + SortOrder = allowedContentType.SortOrder + }); } var propertyFactory = new PropertyGroupFactory(nodeDto.NodeId); @@ -125,14 +130,18 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var propertyType in propertyGroup.PropertyTypes) { if (propertyType.IsPropertyDirty("PropertyGroupId") == false) - propertyType.PropertyGroupId = propertyGroup.Id; + { + var tempGroup = propertyGroup; + propertyType.PropertyGroupId = new Lazy(() => tempGroup.Id); + } } } //Insert PropertyTypes foreach (var propertyType in entity.PropertyTypes) { - var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyType.PropertyGroupId, propertyType); + var tabId = propertyType.PropertyGroupId != null ? propertyType.PropertyGroupId.Value : default(int); + var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(tabId, propertyType); int typePrimaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto)); propertyType.Id = typePrimaryKey; //Set Id on new PropertyType @@ -272,15 +281,18 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var propertyType in propertyGroup.PropertyTypes) { if (propertyType.IsPropertyDirty("PropertyGroupId") == false) - propertyType.PropertyGroupId = propertyGroup.Id; + { + var tempGroup = propertyGroup; + propertyType.PropertyGroupId = new Lazy(() => tempGroup.Id); + } } } //Run through all PropertyTypes to insert or update entries foreach (var propertyType in entity.PropertyTypes) { - var propertyTypeDto = propertyGroupFactory.BuildPropertyTypeDto(propertyType.PropertyGroupId, - propertyType); + var tabId = propertyType.PropertyGroupId != null ? propertyType.PropertyGroupId.Value : default(int); + var propertyTypeDto = propertyGroupFactory.BuildPropertyTypeDto(tabId, propertyType); int typePrimaryKey = propertyType.HasIdentity ? Database.Update(propertyTypeDto) : Convert.ToInt32(Database.Insert(propertyTypeDto)); diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 571a883b2a..8d67e7ab1d 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Text.RegularExpressions; using System.Threading; @@ -47,9 +46,10 @@ namespace Umbraco.Core.Services /// Imports and saves package xml as /// /// Xml to import - /// + /// Optional parent Id for the content being imported + /// Optional Id of the user performing the import /// An enumrable list of generated content - public IEnumerable ImportContent(XElement element, int userId = 0) + public IEnumerable ImportContent(XElement element, int parentId = -1, int userId = 0) { var name = element.Name.LocalName; if (name.Equals("DocumentSet")) @@ -59,7 +59,7 @@ namespace Umbraco.Core.Services where (string)doc.Attribute("isDoc") == "" select doc; - var contents = ParseDocumentRootXml(roots); + var contents = ParseDocumentRootXml(roots, parentId); _contentService.Save(contents, userId); return contents; @@ -70,7 +70,7 @@ namespace Umbraco.Core.Services { //This is a single doc import var elements = new List { element }; - var contents = ParseDocumentRootXml(elements); + var contents = ParseDocumentRootXml(elements, parentId); _contentService.Save(contents, userId); return contents; @@ -81,7 +81,7 @@ namespace Umbraco.Core.Services "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); } - private IEnumerable ParseDocumentRootXml(IEnumerable roots) + private IEnumerable ParseDocumentRootXml(IEnumerable roots, int parentId) { var contents = new List(); foreach (var root in roots) @@ -97,7 +97,7 @@ namespace Umbraco.Core.Services _importedContentTypes.Add(contentTypeAlias, contentType); } - var content = CreateContentFromXml(root, _importedContentTypes[contentTypeAlias], null, -1, isLegacySchema); + var content = CreateContentFromXml(root, _importedContentTypes[contentTypeAlias], null, parentId, isLegacySchema); contents.Add(content); var children = from child in root.Elements() @@ -264,6 +264,9 @@ namespace Umbraco.Core.Services Alias = infoElement.Element("Alias").Value }; + if (parent != null) + contentType.AddContentType(parent); + return UpdateContentTypeFromXml(documentType, contentType); } @@ -311,17 +314,20 @@ namespace Umbraco.Core.Services contentType.AllowedTemplates = allowedTemplates; } - var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value); - if (defaultTemplate != null) + if (string.IsNullOrEmpty(defaultTemplateElement.Value) == false) { - contentType.SetDefaultTemplate(defaultTemplate); - } - else - { - LogHelper.Warn( - string.Format( - "Packager: Error handling default template. Default template with alias '{0}' could not be found.", - defaultTemplateElement.Value)); + var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value); + if (defaultTemplate != null) + { + contentType.SetDefaultTemplate(defaultTemplate); + } + else + { + LogHelper.Warn( + string.Format( + "Packager: Error handling default template. Default template with alias '{0}' could not be found.", + defaultTemplateElement.Value)); + } } } @@ -561,7 +567,7 @@ namespace Umbraco.Core.Services fields.Add(field); } //Sort templates by dependencies to a potential master template - var sortedElements = TopologicalSorter.RetrieveMappedItems(fields); + var sortedElements = TopologicalSorter.GetSortedItems(fields); foreach (var templateElement in sortedElements) { var templateName = templateElement.Element("Name").Value; diff --git a/src/Umbraco.Core/TopologicalSorter.cs b/src/Umbraco.Core/TopologicalSorter.cs index 6324e6e10b..56cdc73051 100644 --- a/src/Umbraco.Core/TopologicalSorter.cs +++ b/src/Umbraco.Core/TopologicalSorter.cs @@ -110,7 +110,7 @@ namespace Umbraco.Core #endregion #region Internal Staic methods - internal static IEnumerable RetrieveMappedItems(List> fields) where T : class + internal static IEnumerable GetSortedItems(List> fields) where T : class { int[] sortOrder = GetTopologicalSortOrder(fields); var list = new List(); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 11fd35fb97..981b4cb41d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -707,7 +707,6 @@ umbraco.interfaces -