From eda46a16d0c87f2568da6b29fb91a95117d6a36f Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 3 Jan 2019 09:27:52 +0100 Subject: [PATCH] Changed IContentType on IContent to a more simple class with lesser properties --- src/Umbraco.Core/ContentExtensions.cs | 38 +++++----- .../ContentVariationExtensions.cs | 10 +++ src/Umbraco.Core/Models/Content.cs | 20 ++--- src/Umbraco.Core/Models/IContent.cs | 2 +- src/Umbraco.Core/Models/ISimpleContentType.cs | 76 +++++++++++++++++++ .../Services/Implement/ContentService.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Manifest/ManifestContentAppTests.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 29 ++----- .../Mapping/ContentWebModelMappingTests.cs | 16 +++- src/Umbraco.Tests/Models/VariationTests.cs | 10 ++- .../Repositories/DocumentRepositoryTest.cs | 10 ++- .../PublishedContent/NuCacheTests.cs | 3 +- .../Scoping/ScopedNuCacheTests.cs | 3 +- .../Services/ContentServiceTests.cs | 50 ++++++------ .../ContentTypeServiceVariantsTests.cs | 23 +----- .../UmbracoExamine/IndexInitializer.cs | 4 +- .../UmbracoExamine/SearchTests.cs | 4 +- .../Web/Controllers/ContentControllerTests.cs | 10 +++ .../Umbraco/dialogs/ChangeDocType.aspx.cs | 13 ++-- src/Umbraco.Web/Editors/ContentController.cs | 3 +- .../Editors/ContentTypeController.cs | 9 ++- src/Umbraco.Web/Editors/MediaController.cs | 20 ++--- .../Models/Mapping/ContentMapperProfile.cs | 33 ++++++-- .../Mapping/ContentTypeBasicResolver.cs | 17 +++-- .../Models/Mapping/MediaMapperProfile.cs | 8 +- .../NuCache/PublishedSnapshotService.cs | 7 +- src/Umbraco.Web/umbraco.presentation/page.cs | 5 +- 28 files changed, 278 insertions(+), 150 deletions(-) create mode 100644 src/Umbraco.Core/Models/ISimpleContentType.cs diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index b15e371e87..632036a21e 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -127,7 +127,7 @@ namespace Umbraco.Core } return false; } - + /// /// Returns properties that do not belong to a group /// @@ -156,15 +156,15 @@ namespace Umbraco.Core .Contains(property.PropertyTypeId)); } - public static IContentTypeComposition GetContentType(this IContentBase contentBase) - { - if (contentBase == null) throw new ArgumentNullException(nameof(contentBase)); - - if (contentBase is IContent content) return content.ContentType; - if (contentBase is IMedia media) return media.ContentType; - if (contentBase is IMember member) return member.ContentType; - throw new NotSupportedException("Unsupported IContentBase implementation: " + contentBase.GetType().FullName + "."); - } +// public static IContentTypeComposition GetContentType(this IContentBase contentBase) +// { +// if (contentBase == null) throw new ArgumentNullException(nameof(contentBase)); +// +// if (contentBase is IContent content) return content.ContentType; +// if (contentBase is IMedia media) return media.ContentType; +// if (contentBase is IMember member) return member.ContentType; +// throw new NotSupportedException("Unsupported IContentBase implementation: " + contentBase.GetType().FullName + "."); +// } #region SetValue for setting file contents @@ -174,7 +174,7 @@ namespace Umbraco.Core /// This really is for FileUpload fields only, and should be obsoleted. For anything else, /// you need to store the file by yourself using Store and then figure out /// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself. - public static void SetValue(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) + public static void SetValue(this IContentBase content, IContentTypeService contentTypeService, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) { if (filename == null || filestream == null) return; @@ -183,24 +183,25 @@ namespace Umbraco.Core if (string.IsNullOrWhiteSpace(filename)) return; filename = filename.ToLower(); // fixme - er... why? - SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment); + SetUploadFile(content,contentTypeService, propertyTypeAlias, filename, filestream, culture, segment); } - private static void SetUploadFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) + private static void SetUploadFile(this IContentBase content, IContentTypeService contentTypeService, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) { - var property = GetProperty(content, propertyTypeAlias); + var property = GetProperty(content, contentTypeService, propertyTypeAlias); var oldpath = property.GetValue(culture, segment) is string svalue ? MediaFileSystem.GetRelativePath(svalue) : null; var filepath = MediaFileSystem.StoreFile(content, property.PropertyType, filename, filestream, oldpath); property.SetValue(MediaFileSystem.GetUrl(filepath), culture, segment); } // gets or creates a property for a content item. - private static Property GetProperty(IContentBase content, string propertyTypeAlias) + private static Property GetProperty(IContentBase content, IContentTypeService contentTypeService, string propertyTypeAlias) { var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); if (property != null) return property; - var propertyType = content.GetContentType().CompositionPropertyTypes + var contentType = contentTypeService.Get(content.ContentTypeId); + var propertyType = contentType.CompositionPropertyTypes .FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); if (propertyType == null) throw new Exception("No property type exists with alias " + propertyTypeAlias + "."); @@ -226,9 +227,10 @@ namespace Umbraco.Core /// the "folder number" that was assigned to the previous file referenced by the property, /// if any. /// - public static string StoreFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string filepath) + public static string StoreFile(this IContentBase content, IContentTypeService contentTypeService, string propertyTypeAlias, string filename, Stream filestream, string filepath) { - var propertyType = content.GetContentType() + var contentType = contentTypeService.Get(content.ContentTypeId); + var propertyType = contentType .CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); if (propertyType == null) throw new ArgumentException("Invalid property type alias " + propertyTypeAlias + "."); return MediaFileSystem.StoreFile(content, propertyType, filename, filestream, filepath); diff --git a/src/Umbraco.Core/ContentVariationExtensions.cs b/src/Umbraco.Core/ContentVariationExtensions.cs index 516192b905..d25997b5f0 100644 --- a/src/Umbraco.Core/ContentVariationExtensions.cs +++ b/src/Umbraco.Core/ContentVariationExtensions.cs @@ -9,6 +9,16 @@ namespace Umbraco.Core /// public static class ContentVariationExtensions { + /// + /// Determines whether the content type is invariant. + /// + public static bool VariesByNothing(this ISimpleContentType contentType) => contentType.Variations.VariesByNothing(); + + /// + /// Determines whether the content type varies by culture. + /// + public static bool VariesByCulture(this ISimpleContentType contentType) => contentType.Variations.VariesByCulture(); + /// /// Determines whether the content type is invariant. /// diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 3f6e387dec..3ae5b4f534 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class Content : ContentBase, IContent { - private IContentType _contentType; + private ISimpleContentType _contentType; private ITemplate _template; private ContentScheduleCollection _schedule; private bool _published; @@ -48,7 +48,8 @@ namespace Umbraco.Core.Models public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties, string culture = null) : base(name, parent, contentType, properties, culture) { - _contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); + if (contentType == null) throw new ArgumentNullException(nameof(contentType)); + _contentType = new SimpleContentType(contentType); _publishedState = PublishedState.Unpublished; PublishedVersionId = 0; } @@ -75,7 +76,8 @@ namespace Umbraco.Core.Models public Content(string name, int parentId, IContentType contentType, PropertyCollection properties, string culture = null) : base(name, parentId, contentType, properties, culture) { - _contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); + if (contentType == null) throw new ArgumentNullException(nameof(contentType)); + _contentType = new SimpleContentType(contentType); _publishedState = PublishedState.Unpublished; PublishedVersionId = 0; } @@ -181,7 +183,7 @@ namespace Umbraco.Core.Models /// Gets the ContentType used by this content object /// [IgnoreDataMember] - public IContentType ContentType => _contentType; + public ISimpleContentType ContentType => _contentType; /// [IgnoreDataMember] @@ -423,7 +425,7 @@ namespace Umbraco.Core.Models public void ChangeContentType(IContentType contentType) { ContentTypeId = contentType.Id; - _contentType = contentType; + _contentType = new SimpleContentType(contentType); ContentTypeBase = contentType; Properties.EnsurePropertyTypes(PropertyTypes); @@ -442,7 +444,7 @@ namespace Umbraco.Core.Models if(clearProperties) { ContentTypeId = contentType.Id; - _contentType = contentType; + _contentType = new SimpleContentType(contentType); ContentTypeBase = contentType; Properties.EnsureCleanPropertyTypes(PropertyTypes); @@ -460,8 +462,6 @@ namespace Umbraco.Core.Models if (Template != null) Template.ResetDirtyProperties(rememberDirty); - if (ContentType != null) - ContentType.ResetDirtyProperties(rememberDirty); // take care of the published state _publishedState = _published ? PublishedState.Published : PublishedState.Unpublished; @@ -502,7 +502,9 @@ namespace Umbraco.Core.Models var clonedContent = (Content)clone; //need to manually clone this since it's not settable - clonedContent._contentType = (IContentType) ContentType.DeepClone(); + clonedContent._contentType = ContentType; + + //if culture infos exist then deal with event bindings if (clonedContent._publishInfos != null) diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index a414a03d2f..aadd920995 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Models /// /// Gets the content type of this content. /// - IContentType ContentType { get; } + ISimpleContentType ContentType { get; } /// /// Gets a value indicating whether a culture is published. diff --git a/src/Umbraco.Core/Models/ISimpleContentType.cs b/src/Umbraco.Core/Models/ISimpleContentType.cs new file mode 100644 index 0000000000..320913819a --- /dev/null +++ b/src/Umbraco.Core/Models/ISimpleContentType.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Models +{ + /// + /// Defines a ContentType, which Content is based on + /// + public interface ISimpleContentType + { + string Alias { get; } + int Id { get; } + ITemplate DefaultTemplate { get; } + ContentVariation Variations { get; } + string Icon { get; } + bool IsContainer { get; } + string Name { get; } + bool AllowedAsRoot { get; } + bool SupportsPropertyVariation(string culture, string s, bool b); + } + + public class SimpleContentType : ISimpleContentType + { + public SimpleContentType(IContentType contentType) + { + Id = contentType.Id; + Alias = contentType.Alias; + DefaultTemplate = contentType.DefaultTemplate; + Variations = contentType.Variations; + Icon = contentType.Icon; + IsContainer = contentType.IsContainer; + Icon = contentType.Icon; + Name = contentType.Name; + AllowedAsRoot = contentType.AllowedAsRoot; + } + + public string Alias { get; } + public int Id { get; } + public ITemplate DefaultTemplate { get; } + public ContentVariation Variations { get; } + public string Icon { get; } + public bool IsContainer { get; } + public string Name { get; } + public bool AllowedAsRoot { get; } + + /// + public bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false) + { + // non-exact validation: can accept a 'null' culture if the property type varies + // by culture, and likewise for segment + // wildcard validation: can accept a '*' culture or segment + return Variations.ValidateVariation(culture, segment, false, wildcards, false); + } + + + protected bool Equals(SimpleContentType other) + { + return string.Equals(Alias, other.Alias) && Id == other.Id; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((SimpleContentType) obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((Alias != null ? Alias.GetHashCode() : 0) * 397) ^ Id; + } + } + } +} diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 22ff9d5917..741a483bbe 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -2739,7 +2739,7 @@ namespace Umbraco.Core.Services.Implement { if (blueprint == null) throw new ArgumentNullException(nameof(blueprint)); - var contentType = blueprint.ContentType; + var contentType = _contentTypeRepository.Get(blueprint.ContentType.Id); var content = new Content(name, -1, contentType); content.Path = string.Concat(content.ParentId.ToString(), ",", content.Id); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 8ef76ade37..d83a08483a 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -404,6 +404,7 @@ + diff --git a/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs b/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs index 016eb4113a..1e02f562e3 100644 --- a/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.Manifest var contentType = Mock.Of(); Mock.Get(contentType).Setup(x => x.Alias).Returns("type1"); var content = Mock.Of(); - Mock.Get(content).Setup(x => x.ContentType).Returns(contentType); + Mock.Get(content).Setup(x => x.ContentType).Returns(new SimpleContentType(contentType)); var group1 = Mock.Of(); Mock.Get(group1).Setup(x => x.Alias).Returns("group1"); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index d31fcbf744..bec1b15e90 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -51,7 +51,7 @@ namespace Umbraco.Tests.Models var content = new Content("content", -1, contentType) { Id = 1, VersionId = 1 }; const string langFr = "fr-FR"; - + contentType.Variations = ContentVariation.Culture; Assert.IsFalse(content.IsPropertyDirty("CultureInfos")); //hasn't been changed @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Models Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); - Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); + Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); Assert.IsTrue(content.IsPropertyDirty("CultureInfos")); //it's true now since we've updated a name } @@ -83,6 +83,8 @@ namespace Umbraco.Tests.Models contentType.Variations = ContentVariation.Culture; + content.ChangeContentType(contentType); + Assert.IsFalse(content.IsPropertyDirty("PublishCultureInfos")); //hasn't been changed Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date @@ -100,7 +102,7 @@ namespace Umbraco.Tests.Models Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); content.PublishCulture(langFr); //we've set the name, now we're publishing it - Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); + Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); Assert.IsTrue(content.IsPropertyDirty("PublishCultureInfos")); //it's true now since we've updated a name } @@ -305,7 +307,7 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - + // Act var clone = (Content)content.DeepClone(); @@ -315,20 +317,7 @@ namespace Umbraco.Tests.Models Assert.AreEqual(clone, content); Assert.AreEqual(clone.Id, content.Id); Assert.AreEqual(clone.VersionId, content.VersionId); - Assert.AreNotSame(clone.ContentType, content.ContentType); Assert.AreEqual(clone.ContentType, content.ContentType); - Assert.AreEqual(clone.ContentType.PropertyGroups.Count, content.ContentType.PropertyGroups.Count); - for (var index = 0; index < content.ContentType.PropertyGroups.Count; index++) - { - Assert.AreNotSame(clone.ContentType.PropertyGroups[index], content.ContentType.PropertyGroups[index]); - Assert.AreEqual(clone.ContentType.PropertyGroups[index], content.ContentType.PropertyGroups[index]); - } - Assert.AreEqual(clone.ContentType.PropertyTypes.Count(), content.ContentType.PropertyTypes.Count()); - for (var index = 0; index < content.ContentType.PropertyTypes.Count(); index++) - { - Assert.AreNotSame(clone.ContentType.PropertyTypes.ElementAt(index), content.ContentType.PropertyTypes.ElementAt(index)); - Assert.AreEqual(clone.ContentType.PropertyTypes.ElementAt(index), content.ContentType.PropertyTypes.ElementAt(index)); - } Assert.AreEqual(clone.ContentTypeId, content.ContentTypeId); Assert.AreEqual(clone.CreateDate, content.CreateDate); Assert.AreEqual(clone.CreatorId, content.CreatorId); @@ -402,7 +391,7 @@ namespace Umbraco.Tests.Models content.SetCultureName("Hello", "en-US"); content.SetCultureName("World", "es-ES"); content.PublishCulture("en-US"); - + var i = 200; foreach (var property in content.Properties) { @@ -420,13 +409,12 @@ namespace Umbraco.Tests.Models { Id = 88 }; - + content.Trashed = true; content.UpdateDate = DateTime.Now; content.WriterId = 23; content.Template.UpdateDate = DateTime.Now; //update a child object - content.ContentType.UpdateDate = DateTime.Now; //update a child object // Act content.ResetDirtyProperties(); @@ -466,7 +454,6 @@ namespace Umbraco.Tests.Models } //verify child objects were reset too Assert.IsTrue(content.Template.WasPropertyDirty("UpdateDate")); - Assert.IsTrue(content.ContentType.WasPropertyDirty("UpdateDate")); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index 03a59584a3..d2a5faa17f 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -27,6 +27,7 @@ namespace Umbraco.Tests.Models.Mapping base.Compose(); Container.RegisterSingleton(f => Mock.Of()); + Container.RegisterSingleton(f => Mock.Of()); } [DataEditor("Test.Test", "Test", "~/Test.html")] @@ -117,7 +118,12 @@ namespace Umbraco.Tests.Models.Mapping public void To_Display_Model() { var contentType = MockedContentTypes.CreateSimpleContentType(); + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType); + var content = MockedContent.CreateSimpleContent(contentType); + + FixUsers(content); // need ids for tabs @@ -146,6 +152,10 @@ namespace Umbraco.Tests.Models.Mapping { var contentType = MockedContentTypes.CreateSimpleContentType(); contentType.PropertyGroups.Clear(); + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType); + + var content = new Content("Home", -1, contentType) { Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 }; var result = Mapper.Map(content); @@ -158,7 +168,7 @@ namespace Umbraco.Tests.Models.Mapping AssertBasicProperty(invariantContent, p); AssertDisplayProperty(invariantContent, p); } - + Assert.AreEqual(content.PropertyGroups.Count(), invariantContent.Tabs.Count()); } @@ -177,6 +187,10 @@ namespace Umbraco.Tests.Models.Mapping p.Id = idSeed; idSeed++; } + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType); + + var content = MockedContent.CreateSimpleContent(contentType); FixUsers(content); diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index e6f4e53d26..a5b6b71b9a 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Models if (x == typeof(ILocalizedTextService)) return serviceContext.LocalizationService; throw new Exception("oops"); }); - + } [Test] @@ -285,6 +285,7 @@ namespace Umbraco.Tests.Models // change - now we vary by culture contentType.Variations |= ContentVariation.Culture; propertyType.Variations |= ContentVariation.Culture; + content.ChangeContentType(contentType); // can set value // and get values @@ -401,9 +402,12 @@ namespace Umbraco.Tests.Models var content = new Content("content", -1, contentType) { Id = 1, VersionId = 1 }; // change - now we vary by culture + contentType.Variations |= ContentVariation.Culture; propertyType.Variations |= ContentVariation.Culture; + content.ChangeContentType(contentType); + Assert.Throws(() => content.SetValue("prop", "a")); // invariant = no content.SetValue("prop", "a-fr", langFr); content.SetValue("prop", "a-uk", langUk); @@ -430,7 +434,7 @@ namespace Umbraco.Tests.Models Assert.IsTrue(content.IsCultureAvailable(langUk)); Assert.IsFalse(content.IsCulturePublished(langUk)); Assert.IsNull(content.GetPublishName(langUk)); - Assert.IsNull(content.GetPublishDate(langUk)); // not published + Assert.IsNull(content.GetPublishDate(langUk)); // not published Assert.IsFalse(content.IsCultureAvailable(langEs)); Assert.IsFalse(content.IsCultureEdited(langEs)); // not avail, so... not edited @@ -438,7 +442,7 @@ namespace Umbraco.Tests.Models // not published! Assert.IsNull(content.GetPublishName(langEs)); - Assert.IsNull(content.GetPublishDate(langEs)); + Assert.IsNull(content.GetPublishDate(langEs)); // cannot test IsCultureEdited here - as that requires the content service and repository // see: ContentServiceTests.Can_SaveRead_Variations diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 9f84d9faf5..8827766d4a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -302,13 +302,15 @@ namespace Umbraco.Tests.Persistence.Repositories var emptyContentType = MockedContentTypes.CreateBasicContentType(); var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage"); + contentTypeRepository.Save(emptyContentType); + contentTypeRepository.Save(hasPropertiesContentType); + ServiceContext.FileService.SaveTemplate(hasPropertiesContentType.DefaultTemplate); // else, FK violation on contentType! var content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType); var content2 = MockedContent.CreateBasicContent(emptyContentType); var content3 = MockedContent.CreateSimpleContent(hasPropertiesContentType); - contentTypeRepository.Save(emptyContentType); - contentTypeRepository.Save(hasPropertiesContentType); + repository.Save(content1); repository.Save(content2); repository.Save(content3); @@ -424,9 +426,9 @@ namespace Umbraco.Tests.Persistence.Repositories var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); contentType.AllowedTemplates = Enumerable.Empty(); // because CreateSimpleContentType assigns one already contentType.SetDefaultTemplate(template); - var textpage = MockedContent.CreateSimpleContent(contentType); - contentTypeRepository.Save(contentType); + + var textpage = MockedContent.CreateSimpleContent(contentType); repository.Save(textpage); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 492f1f7dc0..8e3f99c543 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -148,7 +148,8 @@ namespace Umbraco.Tests.PublishedContent new TestDefaultCultureAccessor(), dataSource, globalSettings, - new SiteDomainHelper()); + new SiteDomainHelper(), + contentTypeService); // get a snapshot, get a published content var snapshot = snapshotService.CreatePublishedSnapshot(previewToken: null); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 211bdc3cdb..045a6ad147 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -82,6 +82,7 @@ namespace Umbraco.Tests.Scoping var documentRepository = Mock.Of(); var mediaRepository = Mock.Of(); var memberRepository = Mock.Of(); + var contentTypeService = Current.Services.ContentTypeService; return new PublishedSnapshotService( options, @@ -97,7 +98,7 @@ namespace Umbraco.Tests.Scoping documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Container.GetInstance(), new SiteDomainHelper()); + Container.GetInstance(), new SiteDomainHelper(), contentTypeService); } protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index d3ebf703a5..0cd7207e6c 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -139,29 +139,33 @@ namespace Umbraco.Tests.Services [Test] public void Create_Content_From_Blueprint() { - var contentService = ServiceContext.ContentService; - var contentTypeService = ServiceContext.ContentTypeService; + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) + { + var contentService = ServiceContext.ContentService; + var contentTypeService = ServiceContext.ContentTypeService; - var contentType = MockedContentTypes.CreateTextPageContentType(); - ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); - contentTypeService.Save(contentType); + var contentType = MockedContentTypes.CreateTextPageContentType(); + ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); + contentTypeService.Save(contentType); - var blueprint = MockedContent.CreateTextpageContent(contentType, "hello", -1); - blueprint.SetValue("title", "blueprint 1"); - blueprint.SetValue("bodyText", "blueprint 2"); - blueprint.SetValue("keywords", "blueprint 3"); - blueprint.SetValue("description", "blueprint 4"); + var blueprint = MockedContent.CreateTextpageContent(contentType, "hello", -1); + blueprint.SetValue("title", "blueprint 1"); + blueprint.SetValue("bodyText", "blueprint 2"); + blueprint.SetValue("keywords", "blueprint 3"); + blueprint.SetValue("description", "blueprint 4"); - contentService.SaveBlueprint(blueprint); + contentService.SaveBlueprint(blueprint); - var fromBlueprint = contentService.CreateContentFromBlueprint(blueprint, "hello world"); - contentService.Save(fromBlueprint); + var fromBlueprint = contentService.CreateContentFromBlueprint(blueprint, "hello world"); + contentService.Save(fromBlueprint); + + Assert.IsTrue(fromBlueprint.HasIdentity); + Assert.AreEqual("blueprint 1", fromBlueprint.Properties["title"].GetValue()); + Assert.AreEqual("blueprint 2", fromBlueprint.Properties["bodyText"].GetValue()); + Assert.AreEqual("blueprint 3", fromBlueprint.Properties["keywords"].GetValue()); + Assert.AreEqual("blueprint 4", fromBlueprint.Properties["description"].GetValue()); + } - Assert.IsTrue(fromBlueprint.HasIdentity); - Assert.AreEqual("blueprint 1", fromBlueprint.Properties["title"].GetValue()); - Assert.AreEqual("blueprint 2", fromBlueprint.Properties["bodyText"].GetValue()); - Assert.AreEqual("blueprint 3", fromBlueprint.Properties["keywords"].GetValue()); - Assert.AreEqual("blueprint 4", fromBlueprint.Properties["description"].GetValue()); } [Test] @@ -222,7 +226,7 @@ namespace Umbraco.Tests.Services c.ContentSchedule.Add(now.AddSeconds(5), null); //release in 5 seconds var r = ServiceContext.ContentService.Save(c); Assert.IsTrue(r.Success, r.Result.ToString()); - } + } else { c.ContentSchedule.Add(null, now.AddSeconds(5)); //expire in 5 seconds @@ -258,7 +262,7 @@ namespace Umbraco.Tests.Services variant.Add(c); } - + var runSched = ServiceContext.ContentService.PerformScheduledPublish( now.AddMinutes(1)).ToList(); //process anything scheduled before a minute from now @@ -742,7 +746,7 @@ namespace Umbraco.Tests.Services public void Can_Unpublish_Content_Variation() { // Arrange - + var langUk = new Language("en-GB") { IsDefault = true }; var langFr = new Language("fr-FR"); @@ -1066,7 +1070,7 @@ namespace Umbraco.Tests.Services foreach (var x in descendants) Console.WriteLine(" ".Substring(0, x.Level) + x.Id); } - + Console.WriteLine(); // publish parent & its branch @@ -1420,7 +1424,7 @@ namespace Umbraco.Tests.Services var descendants = new List(); while(page * pageSize < total) descendants.AddRange(contentService.GetPagedDescendants(content.Id, page++, pageSize, out total)); - + Assert.AreNotEqual(-20, content.ParentId); Assert.IsFalse(content.Trashed); Assert.AreEqual(3, descendants.Count); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index c28d4f7955..8f453c6d53 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -53,6 +53,7 @@ namespace Umbraco.Tests.Services var documentRepository = Container.GetInstance(); var mediaRepository = Mock.Of(); var memberRepository = Mock.Of(); + var contentTypeService = Current.Services.ContentTypeService; return new PublishedSnapshotService( options, @@ -68,7 +69,7 @@ namespace Umbraco.Tests.Services documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Container.GetInstance(), new SiteDomainHelper()); + Container.GetInstance(), new SiteDomainHelper(), contentTypeService); } public class LocalServerMessenger : ServerMessengerBase @@ -173,8 +174,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1en", document.GetValue("value1")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -192,8 +191,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1en", document.GetValue("value1")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -210,8 +207,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1fr", document.GetValue("value1", "fr")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -286,8 +281,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1", document.GetValue("value1")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -303,8 +296,6 @@ namespace Umbraco.Tests.Services Assert.IsNull(document.GetValue("value1", "fr")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'en','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -322,8 +313,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1", document.GetValue("value1")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -399,8 +388,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1en", document.GetValue("value1")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -417,8 +404,6 @@ namespace Umbraco.Tests.Services Assert.AreEqual("v1fr", document.GetValue("value1", "fr")); Assert.AreEqual("v2", document.GetValue("value2")); - Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':"); @@ -437,8 +422,6 @@ namespace Umbraco.Tests.Services Assert.IsNull(document.GetValue("value2", "fr")); Assert.IsNull(document.GetValue("value2")); - Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value2").VariesByCulture()); - Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith(document.Id, "{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'en','seg':'','val':'v2'}]},'cultureData':"); @@ -770,4 +753,4 @@ namespace Umbraco.Tests.Services "{'properties':{'value11':[{'culture':'','seg':'','val':'v11'}],'value12':[{'culture':'','seg':'','val':'v12'}],'value31':[{'culture':'','seg':'','val':'v31'}],'value32':[{'culture':'','seg':'','val':'v32'}]},'cultureData':"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 4435a5e829..8565321bae 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -70,7 +70,7 @@ namespace Umbraco.Tests.UmbracoExamine m.GetCultureName(It.IsAny()) == (string)x.Attribute("nodeName") && m.Path == (string)x.Attribute("path") && m.Properties == new PropertyCollection() && - m.ContentType == Mock.Of(mt => + m.ContentType == Mock.Of(mt => mt.Icon == "test" && mt.Alias == x.Name.LocalName && mt.Id == (int)x.Attribute("nodeType")))) @@ -161,7 +161,7 @@ namespace Umbraco.Tests.UmbracoExamine if (validator == null) validator = new ContentValueSetValidator(true); - + var i = new UmbracoContentIndex( "testIndexer", new UmbracoFieldDefinitionCollection(), diff --git a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs index 747bab3c6d..85100410be 100644 --- a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs +++ b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.UmbracoExamine m.Path == (string)x.Attribute("path") && m.Properties == new PropertyCollection() && m.Published == true && - m.ContentType == Mock.Of(mt => + m.ContentType == Mock.Of(mt => mt.Icon == "test" && mt.Alias == x.Name.LocalName && mt.Id == (int)x.Attribute("nodeType")))) @@ -62,7 +62,7 @@ namespace Umbraco.Tests.UmbracoExamine { indexer.CreateIndex(); rebuilder.Populate(indexer); - + var searcher = indexer.GetSearcher(); var numberSortedCriteria = searcher.CreateQuery() diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 9bd00f3d96..2a2aa536aa 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -82,6 +82,7 @@ namespace Umbraco.Tests.Web.Controllers textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns("text"); Container.RegisterSingleton(f => Mock.Of()); + Container.RegisterSingleton(f => Mock.Of()); Container.RegisterSingleton(f => userServiceMock.Object); Container.RegisterSingleton(f => entityService.Object); Container.RegisterSingleton(f => dataTypeService.Object); @@ -308,6 +309,9 @@ namespace Umbraco.Tests.Web.Controllers contentServiceMock.Setup(x => x.Save(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType()); + var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(propertyEditorCollection); Container.InjectProperties(usersController); @@ -340,6 +344,9 @@ namespace Umbraco.Tests.Web.Controllers contentServiceMock.Setup(x => x.Save(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType()); + var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(propertyEditorCollection); Container.InjectProperties(usersController); @@ -376,6 +383,9 @@ namespace Umbraco.Tests.Web.Controllers contentServiceMock.Setup(x => x.Save(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success + var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService); + contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType()); + var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(propertyEditorCollection); Container.InjectProperties(usersController); diff --git a/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs b/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs index 8111410edd..cb145ee282 100644 --- a/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs +++ b/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs @@ -104,8 +104,9 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs { // Below root, so only include those allowed as sub-nodes for the parent var parentNode = Services.ContentService.GetById(_content.ParentId); + var parentContentType = Services.ContentTypeService.Get(parentNode.ContentTypeId); return documentTypes - .Where(x => parentNode.ContentType.AllowedContentTypes + .Where(x => parentContentType.AllowedContentTypes .Select(y => y.Id.Value) .Contains(x.Id)); } @@ -149,7 +150,8 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs private void PopulatePropertyMappingWithSources() { - PropertyMappingRepeater.DataSource = GetPropertiesOfContentType(_content.ContentType); + var contentType = Services.ContentTypeService.Get(_content.ContentTypeId); + PropertyMappingRepeater.DataSource = contentType.CompositionPropertyTypes; PropertyMappingRepeater.DataBind(); } @@ -159,7 +161,7 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs var contentType = GetSelectedDocumentType(); // Get properties of new document type (including any from parent types) - var properties = GetPropertiesOfContentType(contentType); + var properties = contentType.CompositionPropertyTypes; // Loop through list of source properties and populate destination options with all those of same property type foreach (RepeaterItem ri in PropertyMappingRepeater.Items) @@ -193,10 +195,7 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs return Services.ContentTypeService.Get(int.Parse(NewDocumentTypeList.SelectedItem.Value)); } - private IEnumerable GetPropertiesOfContentType(IContentType contentType) - { - return contentType.CompositionPropertyTypes; - } + private void DisplayNotAvailable() { diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 55862d14b8..d0699c4ad4 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1834,8 +1834,9 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } + var parentContentType = Services.ContentTypeService.Get(parent.ContentTypeId); //check if the item is allowed under this one - if (parent.ContentType.AllowedContentTypes.Select(x => x.Id).ToArray() + if (parentContentType.AllowedContentTypes.Select(x => x.Id).ToArray() .Any(x => x.Value == toMove.ContentType.Id) == false) { throw new HttpResponseException( diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 397f6b3e9d..703e2d1e54 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -193,7 +193,7 @@ namespace Umbraco.Web.Editors ? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id : Request.CreateNotificationValidationErrorResponse(result.Exception.Message); } - + public CreatedContentTypeCollectionResult PostCreateCollection(int parentId, string collectionName, bool collectionCreateTemplate, string collectionItemName, bool collectionItemCreateTemplate, string collectionIcon, string collectionItemIcon) { // create item doctype @@ -201,7 +201,7 @@ namespace Umbraco.Web.Editors itemDocType.Name = collectionItemName; itemDocType.Alias = collectionItemName.ToSafeAlias(true); itemDocType.Icon = collectionItemIcon; - + // create item doctype template if (collectionItemCreateTemplate) { @@ -222,7 +222,7 @@ namespace Umbraco.Web.Editors { new ContentTypeSort(itemDocType.Id, 0) }; - + // create collection doctype template if (collectionCreateTemplate) { @@ -382,7 +382,8 @@ namespace Umbraco.Web.Editors return Enumerable.Empty(); } - var ids = contentItem.ContentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray(); + var contentType = Services.ContentTypeService.Get(contentItem.ContentTypeId); + var ids = contentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray(); if (ids.Any() == false) return Enumerable.Empty(); diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index e0ee7c85a9..1f73b0c629 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -50,9 +50,10 @@ namespace Umbraco.Web.Editors [MediaControllerControllerConfiguration] public class MediaController : ContentControllerBase { - public MediaController(PropertyEditorCollection propertyEditors) + public MediaController(PropertyEditorCollection propertyEditors, IContentTypeService contentTypeService) { _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors)); + _contentTypeService = contentTypeService; } /// @@ -236,6 +237,7 @@ namespace Umbraco.Web.Editors private int[] _userStartNodes; private readonly PropertyEditorCollection _propertyEditors; + private readonly IContentTypeService _contentTypeService; protected int[] UserStartNodes { @@ -295,7 +297,7 @@ namespace Umbraco.Web.Editors else { //better to not use this without paging where possible, currently only the sort dialog does - children = Services.MediaService.GetPagedChildren(id, 0, int.MaxValue, out var total).ToList(); + children = Services.MediaService.GetPagedChildren(id,0, int.MaxValue, out var total).ToList(); totalChildren = children.Count; } @@ -426,7 +428,7 @@ namespace Umbraco.Web.Editors var toMove = ValidateMoveOrCopy(move); var destinationParentID = move.ParentId; var sourceParentID = toMove.ParentId; - + var moveResult = Services.MediaService.Move(toMove, move.ParentId); if (sourceParentID == destinationParentID) @@ -544,7 +546,7 @@ namespace Umbraco.Web.Editors return display; } - + /// /// Empties the recycle bin /// @@ -597,11 +599,11 @@ namespace Umbraco.Web.Editors throw; } } - + public MediaItemDisplay PostAddFolder(PostedFolder folder) { var intParentId = GetParentIdAsInt(folder.ParentId, validatePermissions:true); - + var mediaService = Services.MediaService; var f = mediaService.CreateMedia(folder.Name, intParentId, Constants.Conventions.MediaTypes.Folder); @@ -641,10 +643,10 @@ namespace Umbraco.Web.Editors //get the string json from the request string currentFolderId = result.FormData["currentFolder"]; int parentId = GetParentIdAsInt(currentFolderId, validatePermissions: true); - + var tempFiles = new PostedFiles(); var mediaService = Services.MediaService; - + //in case we pass a path with a folder in it, we will create it and upload media to it. if (result.FormData.ContainsKey("path")) { @@ -727,7 +729,7 @@ namespace Umbraco.Web.Editors if (fs == null) throw new InvalidOperationException("Could not acquire file stream"); using (fs) { - f.SetValue(Constants.Conventions.Media.File, fileName, fs); + f.SetValue(_contentTypeService, Constants.Conventions.Media.File,fileName, fs); } var saveResult = mediaService.Save(f, Security.CurrentUser.Id); diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 6de3bdc02c..1f078a9990 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using AutoMapper; using Umbraco.Core; @@ -29,7 +30,8 @@ namespace Umbraco.Web.Models.Mapping var creatorResolver = new CreatorResolver(userService); var actionButtonsResolver = new ActionButtonsResolver(userService, contentService); var childOfListViewResolver = new ContentChildOfListViewResolver(contentService, contentTypeService); - var contentTypeBasicResolver = new ContentTypeBasicResolver(); + var contentTypeBasicResolver = new ContentTypeBasicResolver(contentTypeService); + var allowedTemplatesResolver = new AllowedTemplatesResolver(contentTypeService); var defaultTemplateResolver = new DefaultTemplateResolver(); var variantResolver = new ContentVariantResolver(localizationService); var schedPublishReleaseDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Release); @@ -56,10 +58,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Notifications, opt => opt.Ignore()) .ForMember(dest => dest.Errors, opt => opt.Ignore()) .ForMember(dest => dest.DocumentType, opt => opt.ResolveUsing(contentTypeBasicResolver)) - .ForMember(dest => dest.AllowedTemplates, opt => - opt.MapFrom(content => content.ContentType.AllowedTemplates - .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) - .ToDictionary(t => t.Alias, t => t.Name))) + .ForMember(dest => dest.AllowedTemplates, opt => opt.ResolveUsing(allowedTemplatesResolver)) .ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src))) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); @@ -140,5 +139,27 @@ namespace Umbraco.Web.Models.Mapping return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; } } - } + + + private class AllowedTemplatesResolver : IValueResolver> + { + private readonly IContentTypeService _contentTypeService; + + public AllowedTemplatesResolver(IContentTypeService contentTypeService) + { + _contentTypeService = contentTypeService; + } + + public IDictionary Resolve(IContent source, ContentItemDisplay destination, IDictionary destMember, ResolutionContext context) + { + var contentType = _contentTypeService.Get(source.ContentTypeId); + + return contentType.AllowedTemplates + .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) + .ToDictionary(t => t.Alias, t => t.Name); + } + } + } + + } diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeBasicResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeBasicResolver.cs index 01ff458bd5..c219df8596 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeBasicResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeBasicResolver.cs @@ -4,6 +4,7 @@ using System.Web; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping @@ -15,6 +16,13 @@ namespace Umbraco.Web.Models.Mapping internal class ContentTypeBasicResolver : IValueResolver where TSource : IContentBase { + private readonly IContentTypeService _contentTypeService; + + public ContentTypeBasicResolver(IContentTypeService contentTypeService) + { + _contentTypeService = contentTypeService; + } + public ContentTypeBasic Resolve(TSource source, TDestination destination, ContentTypeBasic destMember, ResolutionContext context) { //TODO: We can resolve the UmbracoContext from the IValueResolver options! @@ -22,13 +30,8 @@ namespace Umbraco.Web.Models.Mapping if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null && UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) { - ContentTypeBasic contentTypeBasic; - if (source is IContent content) - contentTypeBasic = Mapper.Map(content.ContentType); - else if (source is IMedia media) - contentTypeBasic = Mapper.Map(media.ContentType); - else - throw new NotSupportedException($"Expected TSource to be IContent or IMedia, got {typeof(TSource).Name}."); + var contentType = _contentTypeService.Get(source.ContentTypeId); + var contentTypeBasic = Mapper.Map(contentType); return contentTypeBasic; } diff --git a/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs index dc16ed5fe4..feaa2917fe 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs @@ -15,8 +15,7 @@ namespace Umbraco.Web.Models.Mapping /// internal class MediaMapperProfile : Profile { - public MediaMapperProfile( - TabsAndPropertiesResolver tabsAndPropertiesResolver, + public MediaMapperProfile(TabsAndPropertiesResolver tabsAndPropertiesResolver, ContentTreeNodeUrlResolver contentTreeNodeUrlResolver, MediaAppResolver mediaAppResolver, IUserService userService, @@ -24,12 +23,13 @@ namespace Umbraco.Web.Models.Mapping IDataTypeService dataTypeService, IMediaService mediaService, IMediaTypeService mediaTypeService, - ILogger logger) + ILogger logger, + IContentTypeService contentTypeService) { // create, capture, cache var mediaOwnerResolver = new OwnerResolver(userService); var childOfListViewResolver = new MediaChildOfListViewResolver(mediaService, mediaTypeService); - var mediaTypeBasicResolver = new ContentTypeBasicResolver(); + var mediaTypeBasicResolver = new ContentTypeBasicResolver(contentTypeService); //FROM IMedia TO MediaItemDisplay CreateMap() diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 4d6115f02d..4df0cf2ae7 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -43,6 +43,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IMemberRepository _memberRepository; private readonly IGlobalSettings _globalSettings; private readonly ISiteDomainHelper _siteDomainHelper; + private readonly IContentTypeService _contentTypeService; private readonly IDefaultCultureAccessor _defaultCultureAccessor; // volatile because we read it with no lock @@ -85,7 +86,7 @@ namespace Umbraco.Web.PublishedCache.NuCache ILogger logger, IScopeProvider scopeProvider, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, - IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper) + IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IContentTypeService contentTypeService) : base(publishedSnapshotAccessor, variationContextAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -102,6 +103,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _defaultCultureAccessor = defaultCultureAccessor; _globalSettings = globalSettings; _siteDomainHelper = siteDomainHelper; + _contentTypeService = contentTypeService; // we always want to handle repository events, configured or not // assuming no repository event will trigger before the whole db is ready @@ -1196,7 +1198,8 @@ namespace Umbraco.Web.PublishedCache.NuCache var cultureData = new Dictionary(); // sanitize - names should be ok but ... never knows - if (content.GetContentType().VariesByCulture()) + var contentType = _contentTypeService.Get(content.ContentTypeId); + if (contentType.VariesByCulture()) { var infos = content is IContent document ? (published diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index 219e2101be..9e6c85c9ea 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -141,7 +141,7 @@ namespace umbraco _elements.Add("path", path); _elements.Add("splitpath", _splitpath); } - + /// /// Puts the properties of the node into the elements table /// @@ -328,7 +328,8 @@ namespace umbraco _creatorName = _inner.GetCreatorProfile().Name; _writerName = _inner.GetWriterProfile().Name; - _contentType = Current.PublishedContentTypeFactory.CreateContentType(_inner.ContentType); + + _contentType = Current.PublishedContentTypeFactory.CreateContentType(Current.Services.ContentTypeService.Get(_inner.ContentTypeId)); _properties = _contentType.PropertyTypes .Select(x =>