From eda46a16d0c87f2568da6b29fb91a95117d6a36f Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 3 Jan 2019 09:27:52 +0100 Subject: [PATCH 01/37] 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 => From 6490f57f70e07c9aba5b4fd3b7bdf40b1bbf73a8 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 3 Jan 2019 10:53:33 +0100 Subject: [PATCH 02/37] Removed commented out code. --- src/Umbraco.Core/ContentExtensions.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index 632036a21e..15ba6b1a22 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -156,16 +156,6 @@ 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 + "."); -// } - #region SetValue for setting file contents /// From 586a7a167a17d3add83e935b37203234bdabd8fe Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 11 Jan 2019 08:55:25 +0100 Subject: [PATCH 03/37] Merged v8 --- src/Umbraco.Core/ContentExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index 1431396d01..0e119e0aee 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -180,7 +180,7 @@ namespace Umbraco.Core 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, contentTypeService propertyTypeAlias); + var property = GetProperty(content, contentTypeService, propertyTypeAlias); // Fixes https://github.com/umbraco/Umbraco-CMS/issues/3937 - Assigning a new file to an // existing IMedia with extension SetValue causes exception 'Illegal characters in path' From 5f3596c7d9427d178408f011031bf36ea819668c Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 16 Jan 2019 13:11:46 +0100 Subject: [PATCH 04/37] Fixes after merge of temp8 --- src/Umbraco.Core/Models/ISimpleContentType.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Core/Models/ISimpleContentType.cs b/src/Umbraco.Core/Models/ISimpleContentType.cs index 320913819a..679a69520c 100644 --- a/src/Umbraco.Core/Models/ISimpleContentType.cs +++ b/src/Umbraco.Core/Models/ISimpleContentType.cs @@ -15,6 +15,7 @@ namespace Umbraco.Core.Models bool IsContainer { get; } string Name { get; } bool AllowedAsRoot { get; } + bool IsElement { get; } bool SupportsPropertyVariation(string culture, string s, bool b); } @@ -31,6 +32,7 @@ namespace Umbraco.Core.Models Icon = contentType.Icon; Name = contentType.Name; AllowedAsRoot = contentType.AllowedAsRoot; + IsElement = contentType.IsElement; } public string Alias { get; } @@ -41,6 +43,7 @@ namespace Umbraco.Core.Models public bool IsContainer { get; } public string Name { get; } public bool AllowedAsRoot { get; } + public bool IsElement { get; } /// public bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false) From ec8c455635e410203f7149bfe56f6df8467bbcf8 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 24 Jan 2019 11:28:27 +0100 Subject: [PATCH 05/37] Fixes for search of members + Removed fixme in member that apparently are not necessary after tags refactoring --- .../MemberValueSetValidator.cs | 4 ++-- src/Umbraco.Web/Editors/EntityController.cs | 21 +++++++------------ src/Umbraco.Web/Editors/MemberController.cs | 5 ----- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Examine/MemberValueSetValidator.cs b/src/Umbraco.Examine/MemberValueSetValidator.cs index 71de6001ce..0c585854e9 100644 --- a/src/Umbraco.Examine/MemberValueSetValidator.cs +++ b/src/Umbraco.Examine/MemberValueSetValidator.cs @@ -23,10 +23,10 @@ namespace Umbraco.Examine /// /// By default these are the member fields we index /// - public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email" }; + public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email", UmbracoExamineIndex.NodeKeyFieldName }; private static readonly IEnumerable ValidCategories = new[] { IndexTypes.Member }; protected override IEnumerable ValidIndexCategories => ValidCategories; - + } } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index b25f3f5af1..392ad7a8df 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -43,12 +43,16 @@ namespace Umbraco.Web.Editors public class EntityController : UmbracoAuthorizedJsonController { private readonly ITreeService _treeService; + private readonly UmbracoTreeSearcher _treeSearcher; + private readonly SearchableTreeCollection _searchableTreeCollection; public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, - ITreeService treeService) + ITreeService treeService, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState) { _treeService = treeService; + _searchableTreeCollection = searchableTreeCollection; + _treeSearcher = treeSearcher; } /// @@ -69,15 +73,6 @@ namespace Umbraco.Web.Editors } } - private readonly UmbracoTreeSearcher _treeSearcher; - private readonly SearchableTreeCollection _searchableTreeCollection; - - public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher) - { - _searchableTreeCollection = searchableTreeCollection; - _treeSearcher = treeSearcher; - } - /// /// Returns an Umbraco alias given a string /// @@ -242,7 +237,7 @@ namespace Umbraco.Web.Editors }; } - + /// /// Gets an entity by a xpath query /// @@ -932,7 +927,7 @@ namespace Umbraco.Web.Editors throw new NotSupportedException("Filtering on stylesheets is not currently supported"); return Services.FileService.GetStylesheets().Select(Mapper.Map); - + case UmbracoEntityTypes.Language: if (!postFilter.IsNullOrWhiteSpace() || (postFilterParams != null && postFilterParams.Count > 0)) @@ -993,7 +988,7 @@ namespace Umbraco.Web.Editors GetChildItemsForList(childItem, list); } - } + } #endregion } diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 92ca648c3f..399cb13360 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -592,11 +592,6 @@ namespace Umbraco.Web.Editors if (builtInAliases.Contains(p.Alias) == false && valueMapped != null) { p.SetValue(valueMapped.GetValue()); - - // fixme/task - ok, I give up, at that point tags are dead here, until we figure it out - //p.TagChanges.Behavior = valueMapped.TagChanges.Behavior; - //p.TagChanges.Enable = valueMapped.TagChanges.Enable; - //p.TagChanges.Tags = valueMapped.TagChanges.Tags; } } } From 414f838476653170ede3266230a480078c4b29fe Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 29 Jan 2019 15:30:25 +0100 Subject: [PATCH 06/37] #3645 - Lists available languages in the preview bar (if more than 1) Reads the culture from hash instead of query and updates the hash when changing culture. --- .../components/content/edit.controller.js | 2 +- .../src/preview/preview.controller.js | 54 +++++++++++-------- .../Umbraco/Views/Preview/Index.cshtml | 11 ++++ .../Editors/BackOfficePreviewLinkModel.cs | 8 +++ .../Editors/BackOfficePreviewModel.cs | 14 +++-- src/Umbraco.Web/Editors/PreviewController.cs | 20 +++++-- .../Mvc/UmbracoViewPageOfTModel.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + 8 files changed, 80 insertions(+), 32 deletions(-) create mode 100644 src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index fc7fff7e3c..9850f251f3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -785,7 +785,7 @@ // Build the correct path so both /#/ and #/ work. var query = 'id=' + content.id; if ($scope.culture) { - query += "&culture=" + $scope.culture; + query += "#?culture=" + $scope.culture; } var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?' + query; diff --git a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js index fe0bb28aeb..5eb985a582 100644 --- a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js @@ -68,16 +68,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi return; } - $scope.pageId = $location.search().id || getParameterByName("id"); - var culture = $location.search().culture || getParameterByName("culture"); - - if ($scope.pageId) { - var query = 'id=' + $scope.pageId; - if (culture) { - query += "&culture=" + culture; - } - $scope.pageUrl = "frame?" + query; - } + setPageUrl(); $scope.isOpen = false; $scope.frameLoaded = false; @@ -93,6 +84,19 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi ]; $scope.previewDevice = $scope.devices[0]; + + function setPageUrl(){ + $scope.pageId = $location.search().id || getParameterByName("id"); + var culture = $location.search().culture || getParameterByName("culture"); + + if ($scope.pageId) { + var query = 'id=' + $scope.pageId; + if (culture) { + query += "&culture=" + culture; + } + $scope.pageUrl = "frame?" + query; + } + } /*****************************************************************************/ /* Preview devices */ /*****************************************************************************/ @@ -107,28 +111,39 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi /*****************************************************************************/ $scope.exitPreview = function () { - window.top.location.href = "../preview/end?redir=%2f" + $scope.pageId; + + var culture = $location.search().culture || getParameterByName("culture"); + var relativeUrl = "/" + $scope.pageId +'?culture='+ culture; + window.top.location.href = "../preview/end?redir=" + encodeURIComponent(relativeUrl); }; $scope.onFrameLoaded = function (iframe) { $scope.frameLoaded = true; configureSignalR(iframe); - } + }; /*****************************************************************************/ - /* Panel managment */ + /* Panel management */ /*****************************************************************************/ $scope.openPreviewDevice = function () { $scope.showDevicesPreview = true; - } + }; + + /*****************************************************************************/ + /* Change culture */ + /*****************************************************************************/ + $scope.changeCulture = function (culture) { + // $scope.frameLoaded = false; + $location.search("culture", culture); + setPageUrl(); + }; }) .component('previewIFrame', { - - template: "
", + template: "
", controller: function ($element, $scope, angularHelper) { var vm = this; @@ -136,22 +151,15 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi vm.$postLink = function () { var resultFrame = $element.find("#resultFrame"); resultFrame.on("load", iframeReady); - vm.srcDelayed = vm.src; }; function iframeReady() { var iframe = $element.find("#resultFrame").get(0); - hideUmbracoPreviewBadge(iframe); angularHelper.safeApply($scope, function () { vm.onLoaded({ iframe: iframe }); }); } - function hideUmbracoPreviewBadge (iframe) { - if (iframe && iframe.contentDocument && iframe.contentDocument.getElementById("umbracoPreviewBadge")) { - iframe.contentDocument.getElementById("umbracoPreviewBadge").style.display = "none"; - } - }; }, controllerAs: "vm", diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index fcd375da45..db9fc2d3bf 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -46,6 +46,17 @@
  • + + @if (Model.PreviewLinks != null && Model.PreviewLinks.Count() > 2) + { + foreach (var previewLink in Model.PreviewLinks) + { +
  • + @previewLink.CultureName +
  • + } + } +
  • diff --git a/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs b/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs new file mode 100644 index 0000000000..c47db0811a --- /dev/null +++ b/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Web.Editors +{ + public class BackOfficePreviewLinkModel + { + public string CultureName { get; set; } + public string CultureId { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs index 1298575e50..89b055d9d7 100644 --- a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs @@ -1,15 +1,21 @@ -using Umbraco.Core.Configuration; +using System.Collections.Generic; +using Umbraco.Core.Configuration; using Umbraco.Web.Features; namespace Umbraco.Web.Editors { public class BackOfficePreviewModel : BackOfficeModel { - public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings) : base(features, globalSettings) + private readonly UmbracoFeatures _features; + public IEnumerable PreviewLinks { get; } + + public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable previewLinks) : base(features, globalSettings) { + _features = features; + PreviewLinks = previewLinks; } - public bool DisableDevicePreview => Features.Disabled.DisableDevicePreview; - public string PreviewExtendedHeaderView => Features.Enabled.PreviewExtendedView; + public bool DisableDevicePreview => _features.Disabled.DisableDevicePreview; + public string PreviewExtendedHeaderView => _features.Enabled.PreviewExtendedView; } } diff --git a/src/Umbraco.Web/Editors/PreviewController.cs b/src/Umbraco.Web/Editors/PreviewController.cs index bd14a6c6f4..a71f963678 100644 --- a/src/Umbraco.Web/Editors/PreviewController.cs +++ b/src/Umbraco.Web/Editors/PreviewController.cs @@ -1,12 +1,13 @@ using System; +using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.UI; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Features; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.UI.JavaScript; @@ -21,20 +22,33 @@ namespace Umbraco.Web.Editors private readonly IGlobalSettings _globalSettings; private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly UmbracoContext _umbracoContext; + private readonly ILocalizationService _localizationService; - public PreviewController(UmbracoFeatures features, IGlobalSettings globalSettings, IPublishedSnapshotService publishedSnapshotService, UmbracoContext umbracoContext) + public PreviewController( + UmbracoFeatures features, + IGlobalSettings globalSettings, + IPublishedSnapshotService publishedSnapshotService, + UmbracoContext umbracoContext, + ILocalizationService localizationService) { _features = features; _globalSettings = globalSettings; _publishedSnapshotService = publishedSnapshotService; _umbracoContext = umbracoContext; + _localizationService = localizationService; } [UmbracoAuthorize(redirectToUmbracoLogin: true)] [DisableBrowserCache] public ActionResult Index() { - var model = new BackOfficePreviewModel(_features, _globalSettings); + var availableLanguages = _localizationService.GetAllLanguages(); + var previewLinks = availableLanguages.Select(x => new BackOfficePreviewLinkModel() { + CultureName = x.CultureName, + CultureId = x.IsoCode} + ); + + var model = new BackOfficePreviewModel(_features, _globalSettings, previewLinks); if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false) { diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index a16f9661aa..748efbb27a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -217,7 +217,7 @@ namespace Umbraco.Web.Mvc markupToInject = string.Format(Current.Configs.Settings().Content.PreviewBadge, IOHelper.ResolveUrl(SystemDirectories.Umbraco), - Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Path)); + Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Url?.PathAndQuery)); } else { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ccf8c49485..c9c33ceb8d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -138,6 +138,7 @@ + From cf0095dc1c88b452e648c820be9fbda67f4871fd Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 30 Jan 2019 07:49:45 +0100 Subject: [PATCH 07/37] #3645 - removed viewmodel and uses ILanguage directly in the view --- src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml | 6 +++--- src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs | 8 -------- src/Umbraco.Web/Editors/BackOfficePreviewModel.cs | 7 ++++--- src/Umbraco.Web/Editors/PreviewController.cs | 6 +----- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 5 files changed, 8 insertions(+), 20 deletions(-) delete mode 100644 src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index db9fc2d3bf..b656942020 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -47,12 +47,12 @@ - @if (Model.PreviewLinks != null && Model.PreviewLinks.Count() > 2) + @if (Model.Languages != null && Model.Languages.Count() > 2) { - foreach (var previewLink in Model.PreviewLinks) + foreach (var previewLink in Model.Languages) {
  • - @previewLink.CultureName + @previewLink.CultureName
  • } } diff --git a/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs b/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs deleted file mode 100644 index c47db0811a..0000000000 --- a/src/Umbraco.Web/Editors/BackOfficePreviewLinkModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Umbraco.Web.Editors -{ - public class BackOfficePreviewLinkModel - { - public string CultureName { get; set; } - public string CultureId { get; set; } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs index 89b055d9d7..b66e432699 100644 --- a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Umbraco.Core.Configuration; +using Umbraco.Core.Models; using Umbraco.Web.Features; namespace Umbraco.Web.Editors @@ -7,12 +8,12 @@ namespace Umbraco.Web.Editors public class BackOfficePreviewModel : BackOfficeModel { private readonly UmbracoFeatures _features; - public IEnumerable PreviewLinks { get; } + public IEnumerable Languages { get; } - public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable previewLinks) : base(features, globalSettings) + public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable languages) : base(features, globalSettings) { _features = features; - PreviewLinks = previewLinks; + Languages = languages; } public bool DisableDevicePreview => _features.Disabled.DisableDevicePreview; diff --git a/src/Umbraco.Web/Editors/PreviewController.cs b/src/Umbraco.Web/Editors/PreviewController.cs index 2b0bee052f..5507104860 100644 --- a/src/Umbraco.Web/Editors/PreviewController.cs +++ b/src/Umbraco.Web/Editors/PreviewController.cs @@ -44,12 +44,8 @@ namespace Umbraco.Web.Editors public ActionResult Index() { var availableLanguages = _localizationService.GetAllLanguages(); - var previewLinks = availableLanguages.Select(x => new BackOfficePreviewLinkModel() { - CultureName = x.CultureName, - CultureId = x.IsoCode} - ); - var model = new BackOfficePreviewModel(_features, _globalSettings, previewLinks); + var model = new BackOfficePreviewModel(_features, _globalSettings, availableLanguages); if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false) { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 376f1fe313..91ffbe68b5 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -138,7 +138,6 @@ - From 2287c0e402e228836febdb123b7fce111421552b Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 30 Jan 2019 08:24:47 +0100 Subject: [PATCH 08/37] #3645 - remove badge again in preview mode + added spinner --- src/Umbraco.Web.UI.Client/package-lock.json | 96 +++++++++---------- .../src/preview/preview.controller.js | 16 +++- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index fe657ae470..ed28a93caf 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -937,7 +937,7 @@ }, "ansi-colors": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { @@ -955,7 +955,7 @@ }, "ansi-escapes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, @@ -1170,7 +1170,7 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, "array-sort": { @@ -1216,7 +1216,7 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", "dev": true }, "asap": { @@ -1269,7 +1269,7 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", "dev": true }, "asynckit": { @@ -2379,7 +2379,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -2459,7 +2459,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "continuable-cache": { @@ -2502,7 +2502,7 @@ "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4=", "dev": true }, "core-util-is": { @@ -3425,7 +3425,7 @@ "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", "dev": true, "requires": { "esutils": "^2.0.2" @@ -3953,7 +3953,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -3989,7 +3989,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4153,7 +4153,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -4248,7 +4248,7 @@ "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -4258,13 +4258,13 @@ "eslint-utils": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=", "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", "dev": true }, "espree": { @@ -4287,7 +4287,7 @@ "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -4296,7 +4296,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", "dev": true, "requires": { "estraverse": "^4.1.0" @@ -4356,7 +4356,7 @@ "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=", "dev": true }, "exec-buffer": { @@ -4571,7 +4571,7 @@ "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { "is-number": "^2.1.0", @@ -5891,7 +5891,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -6461,7 +6461,7 @@ "gulp-eslint": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-5.0.0.tgz", - "integrity": "sha512-9GUqCqh85C7rP9120cpxXuZz2ayq3BZc85pCTuPJS03VQYxne0aWPIXWx6LSvsGPa3uRqtSO537vaugOh+5cXg==", + "integrity": "sha1-KiaECV93Syz3kxAmIHjFbMehK1I=", "dev": true, "requires": { "eslint": "^5.0.1", @@ -7415,7 +7415,7 @@ "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", "dev": true, "requires": { "isarray": "2.0.1" @@ -7566,7 +7566,7 @@ "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", "dev": true, "requires": { "eventemitter3": "^3.0.0", @@ -7860,7 +7860,7 @@ "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { "is-relative": "^1.0.0", @@ -8155,7 +8155,7 @@ "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { "is-unc-path": "^1.0.0" @@ -8164,7 +8164,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", "dev": true }, "is-retry-allowed": { @@ -8212,7 +8212,7 @@ "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { "unc-path-regex": "^0.1.2" @@ -8369,7 +8369,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -8496,7 +8496,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -9146,7 +9146,7 @@ "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -9327,7 +9327,7 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", "dev": true }, "minimatch": { @@ -12855,7 +12855,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true }, "posix-character-classes": { @@ -13345,7 +13345,7 @@ "qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", "dev": true }, "qs": { @@ -13541,7 +13541,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -14039,7 +14039,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", "dev": true }, "sax": { @@ -14226,7 +14226,7 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", "dev": true }, "shebang-command": { @@ -14516,7 +14516,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -14796,7 +14796,7 @@ "stream-consume": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "integrity": "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=", "dev": true }, "stream-shift": { @@ -14808,7 +14808,7 @@ "streamroller": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", "dev": true, "requires": { "date-format": "^1.2.0", @@ -14835,7 +14835,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -14850,7 +14850,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -14867,7 +14867,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -15409,7 +15409,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -15573,7 +15573,7 @@ "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", "dev": true, "requires": { "media-typer": "0.3.0", @@ -15615,7 +15615,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, "unc-path-regex": { @@ -15777,13 +15777,13 @@ "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", "dev": true }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", "dev": true, "requires": { "punycode": "^2.1.0" @@ -16218,7 +16218,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", "dev": true, "requires": { "async-limiter": "~1.0.0", diff --git a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js index 5eb985a582..7d6584d2f1 100644 --- a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js @@ -134,9 +134,11 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi /* Change culture */ /*****************************************************************************/ $scope.changeCulture = function (culture) { - // $scope.frameLoaded = false; - $location.search("culture", culture); - setPageUrl(); + if($location.search().culture !== culture){ + $scope.frameLoaded = false; + $location.search("culture", culture); + setPageUrl(); + } }; }) @@ -155,11 +157,19 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi function iframeReady() { var iframe = $element.find("#resultFrame").get(0); + hideUmbracoPreviewBadge(iframe); angularHelper.safeApply($scope, function () { vm.onLoaded({ iframe: iframe }); + $scope.frameLoaded = true; }); } + function hideUmbracoPreviewBadge (iframe) { + if (iframe && iframe.contentDocument && iframe.contentDocument.getElementById("umbracoPreviewBadge")) { + iframe.contentDocument.getElementById("umbracoPreviewBadge").style.display = "none"; + } + }; + }, controllerAs: "vm", From 88eb29e1991aa552012f8f1a072b800700c62192 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 30 Jan 2019 11:46:15 +0000 Subject: [PATCH 09/37] Removes EmbedProviders.config & moves into C# types (As its a config file that is rarely ammended IMO) --- src/Umbraco.Core/Media/IEmbedProvider.cs | 20 +- .../Media/{Result.cs => OEmbedResult.cs} | 6 +- .../Media/{Status.cs => OEmbedStatus.cs} | 4 +- src/Umbraco.Core/Media/ProviderSetting.cs | 8 - src/Umbraco.Core/Umbraco.Core.csproj | 5 +- .../config/EmbeddedMedia.config | 205 +++++++----------- .../Media/EmbedProviders/AbstractProvider.cs | 14 -- ...OEmbedProvider.cs => EmbedProviderBase.cs} | 42 ++-- .../EmbedProvidersCollection.cs | 13 ++ .../EmbedProvidersCollectionBuilder.cs | 17 ++ .../Media/EmbedProviders/Flickr.cs | 31 +++ .../Media/EmbedProviders/GettyImages.cs | 27 +++ .../Media/EmbedProviders/Instagram.cs | 25 +++ .../Media/EmbedProviders/Kickstarter.cs | 24 ++ .../Media/EmbedProviders/OEmbedJson.cs | 13 -- .../Media/EmbedProviders/OEmbedPhoto.cs | 22 -- .../Media/EmbedProviders/OEmbedResponse.cs | 8 +- .../Media/EmbedProviders/OEmbedRich.cs | 6 - .../Media/EmbedProviders/OEmbedVideo.cs | 15 -- .../EmbedProviders/Settings/Dictionary.cs | 14 -- .../Media/EmbedProviders/Settings/String.cs | 13 -- .../Media/EmbedProviders/Slideshare.cs | 24 ++ .../Media/EmbedProviders/Twitgoo.cs | 23 -- .../Media/EmbedProviders/Twitter.cs | 24 ++ .../PropertyEditors/RteEmbedController.cs | 90 ++++---- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 11 + src/Umbraco.Web/Umbraco.Web.csproj | 20 +- 27 files changed, 365 insertions(+), 359 deletions(-) rename src/Umbraco.Core/Media/{Result.cs => OEmbedResult.cs} (53%) rename src/Umbraco.Core/Media/{Status.cs => OEmbedStatus.cs} (55%) delete mode 100644 src/Umbraco.Core/Media/ProviderSetting.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/AbstractProvider.cs rename src/Umbraco.Web/Media/EmbedProviders/{AbstractOEmbedProvider.cs => EmbedProviderBase.cs} (73%) create mode 100644 src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollection.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Flickr.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/GettyImages.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Instagram.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Kickstarter.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/OEmbedJson.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/OEmbedPhoto.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/OEmbedRich.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/OEmbedVideo.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/Settings/Dictionary.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/Settings/String.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Slideshare.cs delete mode 100644 src/Umbraco.Web/Media/EmbedProviders/Twitgoo.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Twitter.cs diff --git a/src/Umbraco.Core/Media/IEmbedProvider.cs b/src/Umbraco.Core/Media/IEmbedProvider.cs index 62faa45563..99b162e0b7 100644 --- a/src/Umbraco.Core/Media/IEmbedProvider.cs +++ b/src/Umbraco.Core/Media/IEmbedProvider.cs @@ -1,8 +1,24 @@ -namespace Umbraco.Core.Media +using System.Collections.Generic; + +namespace Umbraco.Core.Media { public interface IEmbedProvider { - bool SupportsDimensions { get; } + /// + /// The OEmbed API Endpoint + /// + string ApiEndpoint { get; } + + /// + /// A string array of Regex patterns to match against the pasted OEmbed URL + /// + string[] UrlSchemeRegex { get; } + + /// + /// A collection of querystring request parameters to append to the API Url + /// + /// ?key=value&key2=value2 + Dictionary RequestParams { get; } string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0); } diff --git a/src/Umbraco.Core/Media/Result.cs b/src/Umbraco.Core/Media/OEmbedResult.cs similarity index 53% rename from src/Umbraco.Core/Media/Result.cs rename to src/Umbraco.Core/Media/OEmbedResult.cs index a8683d03d5..bed07d9b5e 100644 --- a/src/Umbraco.Core/Media/Result.cs +++ b/src/Umbraco.Core/Media/OEmbedResult.cs @@ -1,10 +1,8 @@ namespace Umbraco.Core.Media { - - // TODO: Could definitely have done with a better name - public class Result + public class OEmbedResult { - public Status Status { get; set; } + public OEmbedStatus OEmbedStatus { get; set; } public bool SupportsDimensions { get; set; } public string Markup { get; set; } } diff --git a/src/Umbraco.Core/Media/Status.cs b/src/Umbraco.Core/Media/OEmbedStatus.cs similarity index 55% rename from src/Umbraco.Core/Media/Status.cs rename to src/Umbraco.Core/Media/OEmbedStatus.cs index abbcca97da..0f1f22b0e2 100644 --- a/src/Umbraco.Core/Media/Status.cs +++ b/src/Umbraco.Core/Media/OEmbedStatus.cs @@ -1,8 +1,6 @@ namespace Umbraco.Core.Media { - - //NOTE: Could definitely have done with a better name - public enum Status + public enum OEmbedStatus { NotSupported, Error, diff --git a/src/Umbraco.Core/Media/ProviderSetting.cs b/src/Umbraco.Core/Media/ProviderSetting.cs deleted file mode 100644 index 9fef5efabf..0000000000 --- a/src/Umbraco.Core/Media/ProviderSetting.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Umbraco.Core.Media -{ - public class ProviderSetting : Attribute - { - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 86c37ca54d..b71eb9755c 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -668,9 +668,8 @@ - - - + + diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config index c466b14f1c..262dc2993f 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.config @@ -1,134 +1,77 @@  - - - - - - - - - - - - xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - json - - - - - - - - - - - - - - - - - - - - 1 - xml - https - - - - - - - - - - - - - - xml - - - - - - - - xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + 1 + xml + https + + + + + + + + + + + + + + + + + + + + + + + json + + + + + + + + + + + + + + + + + + + + + + + xml + + + + + + + + + xml + + + + + + + + + + diff --git a/src/Umbraco.Web/Media/EmbedProviders/AbstractProvider.cs b/src/Umbraco.Web/Media/EmbedProviders/AbstractProvider.cs deleted file mode 100644 index 32f9f5c5c9..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/AbstractProvider.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Umbraco.Core.Media; - -namespace Umbraco.Web.Media.EmbedProviders -{ - public abstract class AbstractProvider : IEmbedProvider - { - public virtual bool SupportsDimensions - { - get { return true; } - } - - public abstract string GetMarkup(string url, int maxWidth, int maxHeight); - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs b/src/Umbraco.Web/Media/EmbedProviders/EmbedProviderBase.cs similarity index 73% rename from src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs rename to src/Umbraco.Web/Media/EmbedProviders/EmbedProviderBase.cs index c73e732268..9e34815def 100644 --- a/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs +++ b/src/Umbraco.Web/Media/EmbedProviders/EmbedProviderBase.cs @@ -1,46 +1,39 @@ -using System; -using System.Text; -using System.Xml; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using System.Net; +using System.Linq; using System.Net.Http; +using System.Text; using System.Web; -using Newtonsoft.Json; +using System.Xml; using Umbraco.Core.Media; namespace Umbraco.Web.Media.EmbedProviders { - // TODO: Make all Http calls async - - public abstract class AbstractOEmbedProvider : IEmbedProvider + public abstract class EmbedProviderBase : IEmbedProvider { private static HttpClient _httpClient; - public virtual bool SupportsDimensions - { - get { return true; } - } + public abstract string ApiEndpoint { get; } - [ProviderSetting] - public string APIEndpoint { get; set; } + public abstract string[] UrlSchemeRegex { get; } - [ProviderSetting] - public Dictionary RequestParams { get; set; } + public abstract Dictionary RequestParams { get; } + + public abstract string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0); - public abstract string GetMarkup(string url, int maxWidth, int maxHeight); - - public virtual string BuildFullUrl(string url, int maxWidth, int maxHeight) + public virtual string GetEmbedProviderUrl(string url, int maxWidth, int maxHeight) { if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute) == false) throw new ArgumentException("Not a valid Url"); var fullUrl = new StringBuilder(); - fullUrl.Append(APIEndpoint); + fullUrl.Append(ApiEndpoint); fullUrl.Append("?url=" + HttpUtility.UrlEncode(url)); - foreach (var p in RequestParams) - fullUrl.Append(string.Format("&{0}={1}", p.Key, p.Value)); + foreach (var param in RequestParams) + fullUrl.Append($"&{param.Key}={param.Value}"); if (maxWidth > 0) fullUrl.Append("&maxwidth=" + maxWidth); @@ -50,7 +43,7 @@ namespace Umbraco.Web.Media.EmbedProviders return fullUrl.ToString(); } - + public virtual string DownloadResponse(string url) { if (_httpClient == null) @@ -83,6 +76,5 @@ namespace Umbraco.Web.Media.EmbedProviders var selectSingleNode = doc.SelectSingleNode(property); return selectSingleNode != null ? selectSingleNode.InnerText : string.Empty; } - } -} +}; diff --git a/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollection.cs b/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollection.cs new file mode 100644 index 0000000000..88a317c545 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollection.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Umbraco.Core.Media; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class EmbedProvidersCollection : BuilderCollectionBase + { + public EmbedProvidersCollection(IEnumerable items) + : base(items) + { } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs b/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs new file mode 100644 index 0000000000..d11cf5f56f --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs @@ -0,0 +1,17 @@ +using Umbraco.Core.Composing; +using Umbraco.Core.Media; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class EmbedProvidersCollectionBuilder : OrderedCollectionBuilderBase + { + protected override EmbedProvidersCollectionBuilder This => this; + + public override EmbedProvidersCollection CreateCollection(IFactory factory) + { + // No fancy magic here of reading package.manifest or using typeloader + // Have to explicitly add a OEmbedProvider to this collection + return base.CreateCollection(factory); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Flickr.cs b/src/Umbraco.Web/Media/EmbedProviders/Flickr.cs new file mode 100644 index 0000000000..2ce014c639 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Flickr.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Web; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Flickr : EmbedProviderBase + { + public override string ApiEndpoint => "http://www.flickr.com/services/oembed/"; + + public override string[] UrlSchemeRegex => new string[] + { + @"flickr.com\/photos\/*", + @"flic.kr\/p\/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + var imageUrl = GetXmlProperty(xmlDocument, "/oembed/url"); + var imageWidth = GetXmlProperty(xmlDocument, "/oembed/width"); + var imageHeight = GetXmlProperty(xmlDocument, "/oembed/height"); + var imageTitle = GetXmlProperty(xmlDocument, "/oembed/title"); + + return string.Format("\"{3}\"", imageUrl, imageWidth, imageHeight, HttpUtility.HtmlEncode(imageTitle)); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/GettyImages.cs b/src/Umbraco.Web/Media/EmbedProviders/GettyImages.cs new file mode 100644 index 0000000000..34b383614d --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/GettyImages.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class GettyImages : EmbedProviderBase + { + public override string ApiEndpoint => "http://embed.gettyimages.com/oembed"; + + //http://gty.im/74917285 + //http://www.gettyimages.com/detail/74917285 + public override string[] UrlSchemeRegex => new string[] + { + @"gty\.im/*", + @"gettyimages.com\/detail\/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Instagram.cs b/src/Umbraco.Web/Media/EmbedProviders/Instagram.cs new file mode 100644 index 0000000000..1862d77cad --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Instagram.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Instagram : EmbedProviderBase + { + public override string ApiEndpoint => "http://api.instagram.com/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"instagram.com\/p\/*", + @"instagr.am\/p\/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Kickstarter.cs b/src/Umbraco.Web/Media/EmbedProviders/Kickstarter.cs new file mode 100644 index 0000000000..4de45ae2e3 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Kickstarter.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Kickstarter : EmbedProviderBase + { + public override string ApiEndpoint => "http://www.kickstarter.com/services/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"kickstarter\.com/projects/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/OEmbedJson.cs b/src/Umbraco.Web/Media/EmbedProviders/OEmbedJson.cs deleted file mode 100644 index 161294be76..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/OEmbedJson.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Umbraco.Web.Media.EmbedProviders -{ - public class OEmbedJson : AbstractOEmbedProvider - { - public override string GetMarkup(string url, int maxWidth, int maxHeight) - { - string requestUrl = BuildFullUrl(url, maxWidth, maxHeight); - - var jsonResponse = GetJsonResponse(requestUrl); - return jsonResponse.GetHtml(); - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/OEmbedPhoto.cs b/src/Umbraco.Web/Media/EmbedProviders/OEmbedPhoto.cs deleted file mode 100644 index 26dbf38d31..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/OEmbedPhoto.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Web; -using System.Xml; - -namespace Umbraco.Web.Media.EmbedProviders -{ - public class OEmbedPhoto : AbstractOEmbedProvider - { - public override string GetMarkup(string url, int maxWidth, int maxHeight) - { - string requestUrl = BuildFullUrl(url, maxWidth, maxHeight); - - XmlDocument doc = GetXmlResponse(requestUrl); - string imageUrl = GetXmlProperty(doc, "/oembed/url"); - string imageWidth = GetXmlProperty(doc, "/oembed/width"); - string imageHeight = GetXmlProperty(doc, "/oembed/height"); - string imageTitle = GetXmlProperty(doc, "/oembed/title"); - - return string.Format("\"{3}\"", - imageUrl, imageWidth, imageHeight, HttpUtility.HtmlEncode(imageTitle)); - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/OEmbedResponse.cs b/src/Umbraco.Web/Media/EmbedProviders/OEmbedResponse.cs index e6577dea1f..64b18f52d3 100644 --- a/src/Umbraco.Web/Media/EmbedProviders/OEmbedResponse.cs +++ b/src/Umbraco.Web/Media/EmbedProviders/OEmbedResponse.cs @@ -31,18 +31,18 @@ namespace Umbraco.Web.Media.EmbedProviders public string ThumbnailUrl { get; set; } [JsonProperty("thumbnail_height")] - public int? ThumbnailHeight { get; set; } + public double? ThumbnailHeight { get; set; } [JsonProperty("thumbnail_width")] - public int? ThumbnailWidth { get; set; } + public double? ThumbnailWidth { get; set; } public string Html { get; set; } public string Url { get; set; } - public int? Height { get; set; } + public double? Height { get; set; } - public int? Width { get; set; } + public double? Width { get; set; } /// /// Gets the HTML. diff --git a/src/Umbraco.Web/Media/EmbedProviders/OEmbedRich.cs b/src/Umbraco.Web/Media/EmbedProviders/OEmbedRich.cs deleted file mode 100644 index 8f578ada59..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/OEmbedRich.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Umbraco.Web.Media.EmbedProviders -{ - public class OEmbedRich : OEmbedVideo - { - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/OEmbedVideo.cs b/src/Umbraco.Web/Media/EmbedProviders/OEmbedVideo.cs deleted file mode 100644 index 53bc8602d8..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/OEmbedVideo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Xml; - -namespace Umbraco.Web.Media.EmbedProviders -{ - public class OEmbedVideo : AbstractOEmbedProvider - { - public override string GetMarkup(string url, int maxWidth, int maxHeight) - { - string requestUrl = BuildFullUrl(url, maxWidth, maxHeight); - - XmlDocument doc = GetXmlResponse(requestUrl); - return GetXmlProperty(doc, "/oembed/html"); - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Settings/Dictionary.cs b/src/Umbraco.Web/Media/EmbedProviders/Settings/Dictionary.cs deleted file mode 100644 index 1c0a98205a..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/Settings/Dictionary.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Linq; -using System.Xml; -using Umbraco.Core.Media; - -namespace Umbraco.Web.Media.EmbedProviders.Settings -{ - public class Dictionary : IEmbedSettingProvider - { - public object GetSetting(XmlNode settingNode) - { - return settingNode.ChildNodes.Cast().ToDictionary(item => item.Attributes != null ? item.Attributes["name"].Value : null, item => item.InnerText); - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Settings/String.cs b/src/Umbraco.Web/Media/EmbedProviders/Settings/String.cs deleted file mode 100644 index f1d3642d79..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/Settings/String.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Xml; -using Umbraco.Core.Media; - -namespace Umbraco.Web.Media.EmbedProviders.Settings -{ - public class String : IEmbedSettingProvider - { - public object GetSetting(XmlNode settingNode) - { - return settingNode.InnerText; - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Slideshare.cs b/src/Umbraco.Web/Media/EmbedProviders/Slideshare.cs new file mode 100644 index 0000000000..6d3a010c7a --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Slideshare.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Slideshare : EmbedProviderBase + { + public override string ApiEndpoint => "http://www.slideshare.net/api/oembed/2"; + + public override string[] UrlSchemeRegex => new string[] + { + @"slideshare\.net/" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Twitgoo.cs b/src/Umbraco.Web/Media/EmbedProviders/Twitgoo.cs deleted file mode 100644 index 3b7816a902..0000000000 --- a/src/Umbraco.Web/Media/EmbedProviders/Twitgoo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using HtmlAgilityPack; - -namespace Umbraco.Web.Media.EmbedProviders -{ - public class Twitgoo : AbstractProvider - { - public override bool SupportsDimensions - { - get { return false; } - } - - public override string GetMarkup(string url, int maxWidth, int maxHeight) - { - var web = new HtmlWeb(); - var doc = web.Load(url); - - var img = doc.DocumentNode.SelectSingleNode("//img [@id = 'fullsize']").Attributes["src"]; - - return string.Format("", - img.Value); - } - } -} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Twitter.cs b/src/Umbraco.Web/Media/EmbedProviders/Twitter.cs new file mode 100644 index 0000000000..9286934a4d --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Twitter.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Twitter : EmbedProviderBase + { + public override string ApiEndpoint => "http://publish.twitter.com/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"twitter.com/.*/status/.*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs b/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs index 4cebc5c829..b3498c16ae 100644 --- a/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs +++ b/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs @@ -1,14 +1,10 @@ using System; -using System.Linq; using System.Text.RegularExpressions; -using System.Xml; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Web.Editors; using Umbraco.Web.Mvc; using Umbraco.Core.Media; -using System.IO; -using Umbraco.Core.IO; +using Umbraco.Web.Media.EmbedProviders; namespace Umbraco.Web.PropertyEditors { @@ -18,60 +14,56 @@ namespace Umbraco.Web.PropertyEditors [PluginController("UmbracoApi")] public class RteEmbedController : UmbracoAuthorizedJsonController { - public Result GetEmbed(string url, int width, int height) + private EmbedProvidersCollection _embedCollection; + + public RteEmbedController(EmbedProvidersCollection embedCollection) { - var result = new Result(); + _embedCollection = embedCollection ?? throw new ArgumentNullException(nameof(embedCollection)); + } - // TODO: cache embed doc - var xmlConfig = new XmlDocument(); - xmlConfig.Load(IOHelper.GetRootDirectorySafe() + Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar + "EmbeddedMedia.config"); + public OEmbedResult GetEmbed(string url, int width, int height) + { + var result = new OEmbedResult(); + var foundMatch = false; + IEmbedProvider matchedProvider = null; - foreach (XmlNode node in xmlConfig.SelectNodes("//provider")) + foreach (var provider in _embedCollection) { - var regexPattern = new Regex(node.SelectSingleNode("./urlShemeRegex").InnerText, RegexOptions.IgnoreCase); - - if (regexPattern.IsMatch(url)) + //Url Scheme Regex is an array of possible regex patterns to match against the URL + foreach(var urlPattern in provider.UrlSchemeRegex) { - var prov = (IEmbedProvider)Activator.CreateInstance(Type.GetType(node.Attributes["type"].Value)); - - if (node.Attributes["supportsDimensions"] != null) - result.SupportsDimensions = node.Attributes["supportsDimensions"].Value == "True"; - else - result.SupportsDimensions = prov.SupportsDimensions; - - var settings = node.ChildNodes.Cast().ToDictionary(settingNode => settingNode.Name); - - foreach (var prop in prov.GetType().GetProperties().Where(prop => prop.IsDefined(typeof(ProviderSetting), true))) + var regexPattern = new Regex(urlPattern, RegexOptions.IgnoreCase); + if (regexPattern.IsMatch(url)) { - - if (settings.Any(s => s.Key.ToLower() == prop.Name.ToLower())) - { - var setting = settings.FirstOrDefault(s => s.Key.ToLower() == prop.Name.ToLower()).Value; - var settingType = typeof(Media.EmbedProviders.Settings.String); - - if (setting.Attributes["type"] != null) - settingType = Type.GetType(setting.Attributes["type"].Value); - - var settingProv = (IEmbedSettingProvider)Activator.CreateInstance(settingType); - prop.SetValue(prov, settingProv.GetSetting(settings.FirstOrDefault(s => s.Key.ToLower() == prop.Name.ToLower()).Value), null); - } + foundMatch = true; + matchedProvider = provider; + break; } - try - { - result.Markup = prov.GetMarkup(url, width, height); - result.Status = Status.Success; - } - catch(Exception ex) - { - Logger.Error(ex, "Error embedding url {Url} - width: {Width} height: {Height}", url, width, height); - result.Status = Status.Error; - } - - return result; } + + if (foundMatch) + break; + } + + if(foundMatch == false) + { + //No matches return/ exit + result.OEmbedStatus = OEmbedStatus.NotSupported; + return result; + } + + try + { + result.SupportsDimensions = true; + result.Markup = matchedProvider.GetMarkup(url, width, height); + result.OEmbedStatus = OEmbedStatus.Success; + } + catch(Exception ex) + { + Logger.Error(ex, "Error embedding url {Url} - width: {Width} height: {Height}", url, width, height); + result.OEmbedStatus = OEmbedStatus.Error; } - result.Status = Status.NotSupported; return result; } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 3c593d383f..e4c295e6d8 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -23,6 +23,7 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; +using Umbraco.Web.Media.EmbedProviders; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; @@ -212,6 +213,16 @@ namespace Umbraco.Web.Runtime // and will filter out those that are not attributed with TreeAttribute composition.WithCollectionBuilder() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); + + // register OEmbed providers + // no type scanning - all explicit opt-in of adding types + composition.WithCollectionBuilder() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ccf8c49485..759763756b 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -143,6 +143,16 @@ + + + + + + + + + + @@ -668,9 +678,6 @@ - - - @@ -1097,13 +1104,6 @@ - - - - - - - From 880faeebd3485bae962f02dffd8c1fddec44950b Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 30 Jan 2019 16:50:08 +0000 Subject: [PATCH 10/37] Adds a few more providers to the collection --- .../Media/IEmbedSettingProvider.cs | 9 ------ src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../config/EmbeddedMedia.config | 28 ------------------- .../Media/EmbedProviders/SoundCloud.cs | 24 ++++++++++++++++ src/Umbraco.Web/Media/EmbedProviders/Ted.cs | 24 ++++++++++++++++ src/Umbraco.Web/Media/EmbedProviders/Vimeo.cs | 24 ++++++++++++++++ src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 6 +++- src/Umbraco.Web/Umbraco.Web.csproj | 3 ++ 8 files changed, 80 insertions(+), 39 deletions(-) delete mode 100644 src/Umbraco.Core/Media/IEmbedSettingProvider.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/SoundCloud.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Ted.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Vimeo.cs diff --git a/src/Umbraco.Core/Media/IEmbedSettingProvider.cs b/src/Umbraco.Core/Media/IEmbedSettingProvider.cs deleted file mode 100644 index b9ba611100..0000000000 --- a/src/Umbraco.Core/Media/IEmbedSettingProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Xml; - -namespace Umbraco.Core.Media -{ - public interface IEmbedSettingProvider - { - object GetSetting(XmlNode settingNode); - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index f44db01738..2edb39fc86 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -647,7 +647,6 @@ - diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config index 262dc2993f..0e2c5aa988 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.config @@ -12,20 +12,6 @@ - - - - - - - - - - - - - - @@ -35,20 +21,6 @@ - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web/Media/EmbedProviders/SoundCloud.cs b/src/Umbraco.Web/Media/EmbedProviders/SoundCloud.cs new file mode 100644 index 0000000000..080437a246 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/SoundCloud.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Soundcloud : EmbedProviderBase + { + public override string ApiEndpoint => "https://soundcloud.com/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"soundcloud.com\/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Ted.cs b/src/Umbraco.Web/Media/EmbedProviders/Ted.cs new file mode 100644 index 0000000000..aa14423349 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Ted.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Ted : EmbedProviderBase + { + public override string ApiEndpoint => "http://www.ted.com/talks/oembed.xml"; + + public override string[] UrlSchemeRegex => new string[] + { + @"ted.com\/talks\/*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Vimeo.cs b/src/Umbraco.Web/Media/EmbedProviders/Vimeo.cs new file mode 100644 index 0000000000..806f40a10c --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Vimeo.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Vimeo : EmbedProviderBase + { + public override string ApiEndpoint => "https://vimeo.com/api/oembed.xml"; + + public override string[] UrlSchemeRegex => new string[] + { + @"vimeo\.com/" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 444a4e6098..5696589647 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -222,7 +222,11 @@ namespace Umbraco.Web.Runtime .Append() .Append() .Append() - .Append(); + .Append() + .Append() + .Append() + .Append(); } } } + diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 4f20e30b68..3e767f97a8 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -148,6 +148,9 @@ + + + From fe9700b3f79eeeee12cafd5e82aa91b9592a01ed Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 30 Jan 2019 21:52:12 +0000 Subject: [PATCH 11/37] A handful more providers moved across & removed any that no longer supported --- .../config/EmbeddedMedia.config | 25 ----------------- src/Umbraco.Web/Media/EmbedProviders/Hulu.cs | 24 ++++++++++++++++ src/Umbraco.Web/Media/EmbedProviders/Issuu.cs | 28 +++++++++++++++++++ src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 9 +++++- src/Umbraco.Web/Umbraco.Web.csproj | 2 ++ 5 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Hulu.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Issuu.cs diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config index 0e2c5aa988..a5edaf3834 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.config @@ -11,15 +11,6 @@ https - - - - - - - json - - @@ -29,21 +20,5 @@ xml - - - - - - - xml - - - - - - - - - diff --git a/src/Umbraco.Web/Media/EmbedProviders/Hulu.cs b/src/Umbraco.Web/Media/EmbedProviders/Hulu.cs new file mode 100644 index 0000000000..150439832a --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Hulu.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Hulu : EmbedProviderBase + { + public override string ApiEndpoint => "http://www.hulu.com/api/oembed.json"; + + public override string[] UrlSchemeRegex => new string[] + { + @"hulu.com/watch/.*" + }; + + public override Dictionary RequestParams => new Dictionary(); + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Issuu.cs b/src/Umbraco.Web/Media/EmbedProviders/Issuu.cs new file mode 100644 index 0000000000..2b33473453 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Issuu.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class Issuu : EmbedProviderBase + { + public override string ApiEndpoint => "https://issuu.com/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"issuu.com/.*/docs/.*" + }; + + public override Dictionary RequestParams => new Dictionary() + { + //ApiUrl/?format=xml + {"format", "xml"} + }; + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 5696589647..5974288daf 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -225,7 +225,14 @@ namespace Umbraco.Web.Runtime .Append() .Append() .Append() - .Append(); + .Append() + .Append() + .Append(); + + + //Giphy + //Meetup + //Spotify } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3e767f97a8..e418cf8872 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -149,7 +149,9 @@ + + From a36b1962c6288541fb1c1c0cefd743382ae765e2 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 09:32:50 +0000 Subject: [PATCH 12/37] Last of providers moved across & the old config file gone --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 - .../config/EmbeddedMedia.Release.config | 134 ------------------ .../config/EmbeddedMedia.config | 24 ---- .../Media/EmbedProviders/DailyMotion.cs | 28 ++++ .../Media/EmbedProviders/Youtube.cs | 29 ++++ src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 + 7 files changed, 64 insertions(+), 170 deletions(-) delete mode 100644 src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config delete mode 100644 src/Umbraco.Web.UI/config/EmbeddedMedia.config create mode 100644 src/Umbraco.Web/Media/EmbedProviders/DailyMotion.cs create mode 100644 src/Umbraco.Web/Media/EmbedProviders/Youtube.cs diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 38f43f344f..e0660f8f12 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -178,9 +178,6 @@ Designer - - EmbeddedMedia.config - Designer @@ -300,7 +297,6 @@ Designer - diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config deleted file mode 100644 index 442493e3d6..0000000000 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - json - - - - - - - - - - - - - - - - - - - - 1 - xml - https - - - - - - - - - - - - - - xml - - - - - - - - xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config deleted file mode 100644 index a5edaf3834..0000000000 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - 1 - xml - https - - - - - - - - - xml - - - - diff --git a/src/Umbraco.Web/Media/EmbedProviders/DailyMotion.cs b/src/Umbraco.Web/Media/EmbedProviders/DailyMotion.cs new file mode 100644 index 0000000000..78ea0b8662 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/DailyMotion.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class DailyMotion : EmbedProviderBase + { + public override string ApiEndpoint => "https://www.dailymotion.com/services/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"dailymotion.com/video/.*" + }; + + public override Dictionary RequestParams => new Dictionary() + { + //ApiUrl/?format=xml + {"format", "xml"} + }; + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var xmlDocument = base.GetXmlResponse(requestUrl); + + return GetXmlProperty(xmlDocument, "/oembed/html"); + } + } +} diff --git a/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs new file mode 100644 index 0000000000..7755a36958 --- /dev/null +++ b/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Media.EmbedProviders +{ + public class YouTube : EmbedProviderBase + { + public override string ApiEndpoint => "https://www.youtube.com/oembed"; + + public override string[] UrlSchemeRegex => new string[] + { + @"youtu.be/.*", + @"youtu.be/.*" + }; + + public override Dictionary RequestParams => new Dictionary() + { + //ApiUrl/?format=json + {"format", "json"} + }; + + public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) + { + var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); + var oembed = base.GetJsonResponse(requestUrl); + + return oembed.GetHtml(); + } + } +} diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 5974288daf..43add0f15e 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -217,22 +217,19 @@ namespace Umbraco.Web.Runtime // register OEmbed providers // no type scanning - all explicit opt-in of adding types composition.WithCollectionBuilder() + .Append() + .Append() + .Append() + .Append() + .Append() .Append() .Append() .Append() .Append() - .Append() - .Append() - .Append() .Append() .Append() .Append() .Append(); - - - //Giphy - //Meetup - //Spotify } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f9fdb5aabb..8be153889e 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -143,11 +143,13 @@ + + From 92d53eb527cad1faf1ce6e91ad0f49efe33d142d Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 31 Jan 2019 11:10:27 +0100 Subject: [PATCH 13/37] #3648 - Besides mculture also retain cculture in querystring on navigation --- .../src/common/services/navigation.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index 76fcc2d1d8..d9c505aa23 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -28,7 +28,7 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve //A list of query strings defined that when changed will not cause a reload of the route var nonRoutingQueryStrings = ["mculture", "cculture", "lq"]; - var retainedQueryStrings = ["mculture"]; + var retainedQueryStrings = ["mculture", "cculture"]; function setMode(mode) { From 8d55340325b457427661d0ae31d8b0a5e66b255a Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 10:23:54 +0000 Subject: [PATCH 14/37] Fix up youtube URL regex matching --- src/Umbraco.Web/Media/EmbedProviders/Youtube.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs index 7755a36958..4e6f437047 100644 --- a/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs +++ b/src/Umbraco.Web/Media/EmbedProviders/Youtube.cs @@ -9,7 +9,7 @@ namespace Umbraco.Web.Media.EmbedProviders public override string[] UrlSchemeRegex => new string[] { @"youtu.be/.*", - @"youtu.be/.*" + @"youtube.com/watch.*" }; public override Dictionary RequestParams => new Dictionary() From 14b97b6abe3858101a5945c46c83547efb9477a5 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 10:24:15 +0000 Subject: [PATCH 15/37] Fix up JS as the API model had changed --- .../infiniteeditors/embed/embed.controller.js | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js index fb66552731..06a5f028ef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js @@ -54,21 +54,22 @@ $scope.model.embed.preview = ""; - switch (response.data.Status) { + + switch (response.data.OEmbedStatus) { case 0: - //not supported - $scope.model.embed.info = "Not supported"; - break; + //not supported + $scope.model.embed.info = "Not supported"; + break; case 1: - //error - $scope.model.embed.info = "Could not embed media - please ensure the URL is valid"; - break; + //error + $scope.model.embed.info = "Could not embed media - please ensure the URL is valid"; + break; case 2: - $scope.model.embed.preview = response.data.Markup; - vm.trustedPreview = $sce.trustAsHtml(response.data.Markup); - $scope.model.embed.supportsDimensions = response.data.SupportsDimensions; - $scope.model.embed.success = true; - break; + $scope.model.embed.preview = response.data.Markup; + vm.trustedPreview = $sce.trustAsHtml(response.data.Markup); + $scope.model.embed.supportsDimensions = response.data.SupportsDimensions; + $scope.model.embed.success = true; + break; } }, function() { $scope.model.embed.supportsDimensions = false; From 34be548aec4593433d21c31d0499c22419074023 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 10:56:09 +0000 Subject: [PATCH 16/37] Start work on adding AppSettings keys into a constants class & use new prefix of Umbraco.Core. --- build/NuSpecs/tools/install.ps1 | 2 +- src/Umbraco.Core/Composing/RegisterFactory.cs | 4 ++-- .../Configuration/GlobalSettings.cs | 6 +++--- src/Umbraco.Core/Constants-AppSettings.cs | 20 +++++++++++++++++++ .../Migrations/Upgrade/UmbracoPlan.cs | 4 ++-- .../Migrations/Upgrade/UmbracoUpgrader.cs | 4 ++-- src/Umbraco.Core/Umbraco.Core.csproj | 1 + src/Umbraco.Tests/App.config | 2 +- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 2 +- .../Security/BackOfficeCookieManagerTests.cs | 2 +- src/Umbraco.Web.UI/web.Template.config | 2 +- 11 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 src/Umbraco.Core/Constants-AppSettings.cs diff --git a/build/NuSpecs/tools/install.ps1 b/build/NuSpecs/tools/install.ps1 index 9cc7bd5b26..5ca42b54a1 100644 --- a/build/NuSpecs/tools/install.ps1 +++ b/build/NuSpecs/tools/install.ps1 @@ -54,7 +54,7 @@ if ($project) { [xml]$config = Get-Content $destinationWebConfig $config.configuration.appSettings.ChildNodes | ForEach-Object { - if($_.key -eq "umbracoConfigurationStatus") + if($_.key -eq "Umbraco.Core.ConfigurationStatus") { # The web.config has an umbraco-specific appSetting in it # don't overwrite it and let config transforms do their thing diff --git a/src/Umbraco.Core/Composing/RegisterFactory.cs b/src/Umbraco.Core/Composing/RegisterFactory.cs index 8ee6e5a94c..975de7647d 100644 --- a/src/Umbraco.Core/Composing/RegisterFactory.cs +++ b/src/Umbraco.Core/Composing/RegisterFactory.cs @@ -18,14 +18,14 @@ namespace Umbraco.Core.Composing /// Creates a new instance of the configured container. /// /// - /// To override the default LightInjectContainer, add an appSetting named umbracoContainerType with + /// To override the default LightInjectContainer, add an appSetting named umbracoRegisterType with /// a fully qualified type name to a class with a static method "Create" returning an IRegister. /// public static IRegister Create() { Type type; - var configuredTypeName = ConfigurationManager.AppSettings["umbracoRegisterType"]; + var configuredTypeName = ConfigurationManager.AppSettings[Constants.AppSettings.RegisterType]; if (configuredTypeName.IsNullOrWhiteSpace()) { // try to get the web LightInject container type, diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index b89a4d1daf..b9bce30cd8 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -161,13 +161,13 @@ namespace Umbraco.Core.Configuration { get { - return ConfigurationManager.AppSettings.ContainsKey("umbracoConfigurationStatus") - ? ConfigurationManager.AppSettings["umbracoConfigurationStatus"] + return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ConfigurationStatus) + ? ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus] : string.Empty; } set { - SaveSetting("umbracoConfigurationStatus", value); + SaveSetting(Constants.AppSettings.ConfigurationStatus, value); } } diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs new file mode 100644 index 0000000000..800f476c2a --- /dev/null +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -0,0 +1,20 @@ +using System; +using System.ComponentModel; + +namespace Umbraco.Core +{ + public static partial class Constants + { + /// + /// Defines the identifiers for Umbraco system nodes. + /// + public static class AppSettings + { + public const string RegisterType = "Umbraco.Core.RegisterType"; + + public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; //umbracoConfigurationStatus + + + } + } +} diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 9bf58c8d2f..0d0e733591 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -36,8 +36,8 @@ namespace Umbraco.Core.Migrations.Upgrade get { // no state in database yet - assume we have something in web.config that makes some sense - if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var currentVersion)) - throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting."); + if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var currentVersion)) + throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting."); // we currently support upgrading from 7.10.0 and later if (currentVersion < new SemVersion(7, 10)) diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs index fa29e80a6b..ac87b8c94d 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs @@ -35,8 +35,8 @@ namespace Umbraco.Core.Migrations.Upgrade public override void AfterMigrations(IScope scope, ILogger logger) { // assume we have something in web.config that makes some sense = the origin version - if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var originVersion)) - throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting."); + if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var originVersion)) + throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting."); // target version is the code version var targetVersion = UmbracoVersion.SemanticVersion; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 4e6e832294..64a62d1cf0 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -285,6 +285,7 @@ + diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config index 4c5bb57aa2..6607a288b5 100644 --- a/src/Umbraco.Tests/App.config +++ b/src/Umbraco.Tests/App.config @@ -4,7 +4,7 @@ - + diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 3790a49cfc..49bc8149a9 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Runtimes // settings // reset the current version to 0.0.0, clear connection strings - ConfigurationManager.AppSettings["umbracoConfigurationStatus"] = ""; + ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus] = ""; // FIXME: we need a better management of settings here (and, true config files?) // create the very basic and essential things we need diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index f0409d8928..e32df610b9 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Security public void ShouldAuthenticateRequest_When_Not_Configured() { //should force app ctx to show not-configured - ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", ""); + ConfigurationManager.AppSettings.Set(Constants.AppSettings.ConfigurationStatus, ""); var globalSettings = TestObjects.GetGlobalSettings(); var umbracoContext = new UmbracoContext( diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 2eb3551797..06c055b98e 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -30,7 +30,7 @@ - + From 69f7a1b7b9b2467346af2e7c895aea5d7e7bd37a Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 12:05:56 +0000 Subject: [PATCH 17/37] Finish up remaining AppSetting keys as Constants --- src/Umbraco.Core/Composing/TypeFinder.cs | 2 +- src/Umbraco.Core/Configuration/CoreDebug.cs | 4 +- .../Configuration/GlobalSettings.cs | 34 ++++++++--------- .../Configuration/UmbracoVersion.cs | 2 +- src/Umbraco.Core/Constants-AppSettings.cs | 37 +++++++++++++++++++ src/Umbraco.Core/IO/SystemFiles.cs | 5 ++- src/Umbraco.Core/Models/Language.cs | 2 +- .../Persistence/UmbracoDatabaseFactory.cs | 2 +- .../Runtime/CoreRuntimeComposer.cs | 2 +- src/Umbraco.Tests/App.config | 15 ++++---- .../PublishedMediaCache.cs | 2 +- src/Umbraco.Web.UI/web.Template.config | 14 +++---- .../Runtime/WebRuntimeComponent.cs | 2 +- ...eDirectoryBackOfficeUserPasswordChecker.cs | 1 + 14 files changed, 81 insertions(+), 43 deletions(-) diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index 308d0ecfd7..5ad1e43580 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -32,7 +32,7 @@ namespace Umbraco.Core.Composing if (_assembliesAcceptingLoadExceptions != null) return _assembliesAcceptingLoadExceptions; - var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"]; + var s = ConfigurationManager.AppSettings[Constants.AppSettings.AssembliesAcceptingLoadExceptions]; return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s) ? Array.Empty() : s.Split(',').Select(x => x.Trim()).ToArray(); diff --git a/src/Umbraco.Core/Configuration/CoreDebug.cs b/src/Umbraco.Core/Configuration/CoreDebug.cs index 3e39eb6db5..b24e8a3329 100644 --- a/src/Umbraco.Core/Configuration/CoreDebug.cs +++ b/src/Umbraco.Core/Configuration/CoreDebug.cs @@ -7,8 +7,8 @@ namespace Umbraco.Core.Configuration public CoreDebug() { var appSettings = System.Configuration.ConfigurationManager.AppSettings; - LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase); - DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase); + LogUncompletedScopes = string.Equals("true", appSettings[Constants.AppSettings.Debug.LogUncompletedScopes], StringComparison.OrdinalIgnoreCase); + DumpOnTimeoutThreadAbort = string.Equals("true", appSettings[Constants.AppSettings.Debug.DumpOnTimeoutThreadAbort], StringComparison.OrdinalIgnoreCase); } // when true, Scope logs the stack trace for any scope that gets disposed without being completed. diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index b9bce30cd8..e30bf85fd0 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -85,8 +85,8 @@ namespace Umbraco.Core.Configuration { if (_reservedUrls != null) return _reservedUrls; - var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls") - ? ConfigurationManager.AppSettings["umbracoReservedUrls"] + var urls = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedUrls) + ? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedUrls] : string.Empty; //ensure the built on (non-changeable) reserved paths are there at all times @@ -107,14 +107,14 @@ namespace Umbraco.Core.Configuration if (_reservedPaths != null) return _reservedPaths; var reservedPaths = StaticReservedPaths; - var umbPath = ConfigurationManager.AppSettings.ContainsKey("umbracoPath") && !ConfigurationManager.AppSettings["umbracoPath"].IsNullOrWhiteSpace() - ? ConfigurationManager.AppSettings["umbracoPath"] + var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) && !ConfigurationManager.AppSettings[Constants.AppSettings.Path].IsNullOrWhiteSpace() + ? ConfigurationManager.AppSettings[Constants.AppSettings.Path] : "~/umbraco"; //always add the umbraco path to the list reservedPaths += umbPath.EnsureEndsWith(','); - var allPaths = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths") - ? ConfigurationManager.AppSettings["umbracoReservedPaths"] + var allPaths = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedPaths) + ? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedPaths] : string.Empty; _reservedPaths = reservedPaths + allPaths; @@ -133,8 +133,8 @@ namespace Umbraco.Core.Configuration { get { - return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXML") - ? ConfigurationManager.AppSettings["umbracoContentXML"] + return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ContentXML) + ? ConfigurationManager.AppSettings[Constants.AppSettings.ContentXML] : "~/App_Data/umbraco.config"; } } @@ -147,8 +147,8 @@ namespace Umbraco.Core.Configuration { get { - return ConfigurationManager.AppSettings.ContainsKey("umbracoPath") - ? IOHelper.ResolveUrl(ConfigurationManager.AppSettings["umbracoPath"]) + return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) + ? IOHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path]) : string.Empty; } } @@ -249,7 +249,7 @@ namespace Umbraco.Core.Configuration { try { - return int.Parse(ConfigurationManager.AppSettings["umbracoTimeOutInMinutes"]); + return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.TimeOutInMinutes]); } catch { @@ -268,7 +268,7 @@ namespace Umbraco.Core.Configuration { try { - return int.Parse(ConfigurationManager.AppSettings["umbracoVersionCheckPeriod"]); + return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.VersionCheckPeriod]); } catch { @@ -287,7 +287,7 @@ namespace Umbraco.Core.Configuration { get { - var setting = ConfigurationManager.AppSettings["umbracoLocalTempStorage"]; + var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage]; if (!string.IsNullOrWhiteSpace(setting)) return Enum.Parse(setting); @@ -304,8 +304,8 @@ namespace Umbraco.Core.Configuration { get { - return ConfigurationManager.AppSettings.ContainsKey("umbracoDefaultUILanguage") - ? ConfigurationManager.AppSettings["umbracoDefaultUILanguage"] + return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.DefaultUILanguage) + ? ConfigurationManager.AppSettings[Constants.AppSettings.DefaultUILanguage] : string.Empty; } } @@ -322,7 +322,7 @@ namespace Umbraco.Core.Configuration { try { - return bool.Parse(ConfigurationManager.AppSettings["umbracoHideTopLevelNodeFromPath"]); + return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.HideTopLevelNodeFromPath]); } catch { @@ -340,7 +340,7 @@ namespace Umbraco.Core.Configuration { try { - return bool.Parse(ConfigurationManager.AppSettings["umbracoUseHttps"]); + return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.UseHttps]); } catch { diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 7ab97500f0..2f615d26b3 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -82,7 +82,7 @@ namespace Umbraco.Core.Configuration try { // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings - var value = ConfigurationManager.AppSettings["umbracoConfigurationStatus"]; + var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus]; return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null; } catch diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs index 800f476c2a..67f92f4046 100644 --- a/src/Umbraco.Core/Constants-AppSettings.cs +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -10,11 +10,48 @@ namespace Umbraco.Core ///
    public static class AppSettings { + // TODO: Kill me - still used in Umbraco.Core.IO.SystemFiles:27 + [Obsolete("We need to kill this appsetting as we do not use XML content cache umbraco.config anymore due to NuCache")] + public const string ContentXML = "Umbraco.Core.ContentXML"; //umbracoContentXML + + public const string RegisterType = "Umbraco.Core.RegisterType"; + + public const string PublishedMediaCacheSeconds = "Umbraco.Core.PublishedMediaCacheSeconds"; //"Umbraco.PublishedMediaCache.Seconds" + + public const string AssembliesAcceptingLoadExceptions = "Umbraco.Core.AssembliesAcceptingLoadExceptions"; //Umbraco.AssembliesAcceptingLoadExceptions public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; //umbracoConfigurationStatus + + public const string Path = "Umbraco.Core.Path"; //umbracoPath + + public const string ReservedUrls = "Umbraco.Core.ReservedUrls"; //umbracoReservedUrls + + public const string ReservedPaths = "Umbraco.Core.ReservedPaths"; //umbracoReservedPaths + + public const string TimeOutInMinutes = "Umbraco.Core.TimeOutInMinutes"; //umbracoTimeOutInMinutes + + public const string VersionCheckPeriod = "Umbraco.Core.VersionCheckPeriod"; //umbracoVersionCheckPeriod + + public const string LocalTempStorage = "Umbraco.Core.LocalTempStorage"; //umbracoLocalTempStorage + + public const string DefaultUILanguage = "Umbraco.Core.DefaultUILanguage"; //umbracoDefaultUILanguage + + public const string HideTopLevelNodeFromPath = "Umbraco.Core.HideTopLevelNodeFromPath"; //umbracoHideTopLevelNodeFromPath + + public const string UseHttps = "Umbraco.Core.UseHttps"; //umbracoUseHttps + + public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer"; //umbracoDisableElectionForSingleServer + + public const string DatabaseFactoryServerVersion = "Umbraco.Core.DatabaseFactoryServerVersion"; //Umbraco.DatabaseFactory.ServerVersion + public static class Debug + { + public const string LogUncompletedScopes = "Umbraco.Core.LogUncompletedScopes"; //"Umbraco.CoreDebug.LogUncompletedScopes" + + public const string DumpOnTimeoutThreadAbort = "Umbraco.Core.DumpOnTimeoutThreadAbort"; //Umbraco.CoreDebug.DumpOnTimeoutThreadAbort + } } } } diff --git a/src/Umbraco.Core/IO/SystemFiles.cs b/src/Umbraco.Core/IO/SystemFiles.cs index 0e5ae8388b..f3376901a9 100644 --- a/src/Umbraco.Core/IO/SystemFiles.cs +++ b/src/Umbraco.Core/IO/SystemFiles.cs @@ -8,7 +8,8 @@ namespace Umbraco.Core.IO public class SystemFiles { public static string TinyMceConfig => SystemDirectories.Config + "/tinyMceConfig.config"; - + + // TODO: Kill this off we don't have umbraco.config XML cache we now have NuCache public static string GetContentCacheXml(IGlobalSettings globalSettings) { switch (globalSettings.LocalTempStorageLocation) @@ -24,7 +25,7 @@ namespace Umbraco.Core.IO appDomainHash); return Path.Combine(cachePath, "umbraco.config"); case LocalTempStorage.Default: - return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config"); + return IOHelper.ReturnPath(Constants.AppSettings.ContentXML, "~/App_Data/umbraco.config"); default: throw new ArgumentOutOfRangeException(); } diff --git a/src/Umbraco.Core/Models/Language.cs b/src/Umbraco.Core/Models/Language.cs index 03f8f87cd3..b02eb4805c 100644 --- a/src/Umbraco.Core/Models/Language.cs +++ b/src/Umbraco.Core/Models/Language.cs @@ -67,7 +67,7 @@ namespace Umbraco.Core.Models // culture // // I assume that, on a site, all language names should be in the SAME language, in DB, - // and that would be the umbracoDefaultUILanguage (app setting) - BUT if by accident + // and that would be the Umbraco.Core.DefaultUILanguage (app setting) - BUT if by accident // ANY culture has been retrieved with another current thread culture - it's now corrupt // // so, the logic below ensures that the name always end up being the correct name diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index eab0ae5509..3d0d49a5f0 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence { // replace NPoco database type by a more efficient one - var setting = ConfigurationManager.AppSettings["Umbraco.DatabaseFactory.ServerVersion"]; + var setting = ConfigurationManager.AppSettings[Constants.AppSettings.DatabaseFactoryServerVersion]; var fromSettings = false; if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComposer.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComposer.cs index ee289ddcfa..2d1a4c1650 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComposer.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComposer.cs @@ -76,7 +76,7 @@ namespace Umbraco.Core.Runtime // TODO: this is a hack, use proper configuration! // also: we still register the full IServerMessenger because // even on 1 single server we can have 2 concurrent app domains - var singleServer = "true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]); + var singleServer = "true".InvariantEquals(ConfigurationManager.AppSettings[Constants.AppSettings.DisableElectionForSingleServer]); return singleServer ? (IServerRegistrar) new SingleServerRegistrar(f.GetInstance()) : new DatabaseServerRegistrar( diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config index 6607a288b5..5e366eef33 100644 --- a/src/Umbraco.Tests/App.config +++ b/src/Umbraco.Tests/App.config @@ -5,14 +5,13 @@ - - - - - - - - + + + + + + + diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs index 8cfc06c501..c62614ef22 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs @@ -645,7 +645,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private static void InitializeCacheConfig() { - var value = ConfigurationManager.AppSettings["Umbraco.PublishedMediaCache.Seconds"]; + var value = ConfigurationManager.AppSettings[Constants.AppSettings.PublishedMediaCacheSeconds]; int seconds; if (int.TryParse(value, out seconds) == false) seconds = PublishedMediaCacheTimespanSeconds; diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 06c055b98e..d93089fe21 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -31,13 +31,13 @@ - - - - - - - + + + + + + + diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 4fb8dadf17..123cb952d7 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -248,7 +248,7 @@ namespace Umbraco.Web.Runtime XmlFileMapper.FileMapDefaultFolder = SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency"; BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings; - // Now we need to detect if we are running umbracoLocalTempStorage as EnvironmentTemp and in that case we want to change the CDF file + // Now we need to detect if we are running 'Umbraco.Core.LocalTempStorage' as EnvironmentTemp and in that case we want to change the CDF file // location to be there if (globalSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp) { diff --git a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs index 5b571f304e..036a1718b0 100644 --- a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs +++ b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs @@ -13,6 +13,7 @@ namespace Umbraco.Web.Security { get { + // TODO: Verify this AppSetting key is used in .NET Framework & canot be changed to Umbraco.Core. prefix return ConfigurationManager.AppSettings["ActiveDirectoryDomain"]; } } From bc7748aed618019785b62474238b7d26dfed81b9 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 12:37:54 +0000 Subject: [PATCH 18/37] Adds in XML docs summary - still need assitance with a few keys so put in some TODOs --- src/Umbraco.Core/Composing/RegisterFactory.cs | 2 +- src/Umbraco.Core/Constants-AppSettings.cs | 135 +++++++++++++----- .../Persistence/UmbracoDatabaseFactory.cs | 2 +- 3 files changed, 103 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Core/Composing/RegisterFactory.cs b/src/Umbraco.Core/Composing/RegisterFactory.cs index 975de7647d..ea25d6a135 100644 --- a/src/Umbraco.Core/Composing/RegisterFactory.cs +++ b/src/Umbraco.Core/Composing/RegisterFactory.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Composing /// Creates a new instance of the configured container. ///
    /// - /// To override the default LightInjectContainer, add an appSetting named umbracoRegisterType with + /// To override the default LightInjectContainer, add an appSetting named 'Umbraco.Core.RegisterType' with /// a fully qualified type name to a class with a static method "Create" returning an IRegister. /// public static IRegister Create() diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs index 67f92f4046..ac0cbde8de 100644 --- a/src/Umbraco.Core/Constants-AppSettings.cs +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -1,12 +1,11 @@ using System; -using System.ComponentModel; namespace Umbraco.Core { public static partial class Constants { /// - /// Defines the identifiers for Umbraco system nodes. + /// Specific web.config AppSetting keys for Umbraco.Core application /// public static class AppSettings { @@ -14,43 +13,111 @@ namespace Umbraco.Core [Obsolete("We need to kill this appsetting as we do not use XML content cache umbraco.config anymore due to NuCache")] public const string ContentXML = "Umbraco.Core.ContentXML"; //umbracoContentXML - + /// + /// TODO: FILL ME IN + /// public const string RegisterType = "Umbraco.Core.RegisterType"; + + /// + /// This is used for a unit test in PublishedMediaCache + /// + public const string PublishedMediaCacheSeconds = "Umbraco.Core.PublishedMediaCacheSeconds"; + + /// + /// TODO: FILL ME IN + /// + public const string AssembliesAcceptingLoadExceptions = "Umbraco.Core.AssembliesAcceptingLoadExceptions"; + + /// + /// This will return the version number of the currently installed umbraco instance + /// + /// + /// Umbraco will automatically set & modify this value when installing & upgrading + /// + public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; + + /// + /// Gets the path to umbraco's root directory (/umbraco by default). + /// + public const string Path = "Umbraco.Core.Path"; + + /// + /// The reserved urls from web.config. + /// + public const string ReservedUrls = "Umbraco.Core.ReservedUrls"; + + /// + /// The reserved paths from web.config + /// + public const string ReservedPaths = "Umbraco.Core.ReservedPaths"; + + /// + /// Set the timeout for the Umbraco backoffice in minutes + /// + public const string TimeOutInMinutes = "Umbraco.Core.TimeOutInMinutes"; + + /// + /// The number of days to check for a new version of Umbraco + /// + /// + /// Default is set to 7. Setting this to 0 will never check + /// This is used to help track statistics + /// + public const string VersionCheckPeriod = "Umbraco.Core.VersionCheckPeriod"; + + /// + /// This is the location type to store temporary files such as cache files or other localized files for a given machine + /// + /// + /// Currently used for the xml cache file and the plugin cache files + /// + public const string LocalTempStorage = "Umbraco.Core.LocalTempStorage"; + + /// + /// The default UI language of the backoffice such as 'en-US' + /// + public const string DefaultUILanguage = "Umbraco.Core.DefaultUILanguage"; + + /// + /// A true/false value indicating whether umbraco should hide top level nodes from generated urls. + /// + public const string HideTopLevelNodeFromPath = "Umbraco.Core.HideTopLevelNodeFromPath"; + + /// + /// A true or false indicating whether umbraco should force a secure (https) connection to the backoffice. + /// + public const string UseHttps = "Umbraco.Core.UseHttps"; + + /// + /// TODO: FILL ME IN + /// + public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer"; + - public const string PublishedMediaCacheSeconds = "Umbraco.Core.PublishedMediaCacheSeconds"; //"Umbraco.PublishedMediaCache.Seconds" - - public const string AssembliesAcceptingLoadExceptions = "Umbraco.Core.AssembliesAcceptingLoadExceptions"; //Umbraco.AssembliesAcceptingLoadExceptions - - public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; //umbracoConfigurationStatus - - public const string Path = "Umbraco.Core.Path"; //umbracoPath - - public const string ReservedUrls = "Umbraco.Core.ReservedUrls"; //umbracoReservedUrls - - public const string ReservedPaths = "Umbraco.Core.ReservedPaths"; //umbracoReservedPaths - - public const string TimeOutInMinutes = "Umbraco.Core.TimeOutInMinutes"; //umbracoTimeOutInMinutes - - public const string VersionCheckPeriod = "Umbraco.Core.VersionCheckPeriod"; //umbracoVersionCheckPeriod - - public const string LocalTempStorage = "Umbraco.Core.LocalTempStorage"; //umbracoLocalTempStorage - - public const string DefaultUILanguage = "Umbraco.Core.DefaultUILanguage"; //umbracoDefaultUILanguage - - public const string HideTopLevelNodeFromPath = "Umbraco.Core.HideTopLevelNodeFromPath"; //umbracoHideTopLevelNodeFromPath - - public const string UseHttps = "Umbraco.Core.UseHttps"; //umbracoUseHttps - - public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer"; //umbracoDisableElectionForSingleServer - - public const string DatabaseFactoryServerVersion = "Umbraco.Core.DatabaseFactoryServerVersion"; //Umbraco.DatabaseFactory.ServerVersion - - + /// + /// Debug specific web.config AppSetting keys for Umbraco + /// + /// + /// Do not use these keys in a production environment + /// public static class Debug { - public const string LogUncompletedScopes = "Umbraco.Core.LogUncompletedScopes"; //"Umbraco.CoreDebug.LogUncompletedScopes" + /// + /// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed. + /// this helps troubleshooting rogue scopes that we forget to complete + /// + public const string LogUncompletedScopes = "Umbraco.Core.Debug.LogUncompletedScopes"; - public const string DumpOnTimeoutThreadAbort = "Umbraco.Core.DumpOnTimeoutThreadAbort"; //Umbraco.CoreDebug.DumpOnTimeoutThreadAbort + /// + /// When set to true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs + /// an error due to a ThreadAbortException that is due to a timeout. + /// + public const string DumpOnTimeoutThreadAbort = "Umbraco.Core.Debug.DumpOnTimeoutThreadAbort"; + + /// + /// TODO: FILL ME IN + /// + public const string DatabaseFactoryServerVersion = "Umbraco.Core.Debug.DatabaseFactoryServerVersion"; } } } diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index 3d0d49a5f0..681eb1232e 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence { // replace NPoco database type by a more efficient one - var setting = ConfigurationManager.AppSettings[Constants.AppSettings.DatabaseFactoryServerVersion]; + var setting = ConfigurationManager.AppSettings[Constants.AppSettings.Debug.DatabaseFactoryServerVersion]; var fromSettings = false; if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") From 14c43d76c112a42f0de3e67de592b0f2eee6257d Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 31 Jan 2019 13:37:47 +0000 Subject: [PATCH 19/37] Adds OEmbedProviders to the composition extension to make it easier to add/append the collection --- src/Umbraco.Web/CompositionExtensions.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 6039d97a72..4302cdaeee 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -6,6 +6,7 @@ using Umbraco.Web.ContentApps; using Umbraco.Web.Dashboards; using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; +using Umbraco.Web.Media.EmbedProviders; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -101,6 +102,13 @@ namespace Umbraco.Web public static DashboardCollectionBuilder Dashboards(this Composition composition) => composition.WithCollectionBuilder(); + /// + /// Gets the backoffice OEmbed Providers collection builder. + /// + /// The composition. + public static EmbedProvidersCollectionBuilder OEmbedProviders(this Composition composition) + => composition.WithCollectionBuilder(); + #endregion #region Uniques From 6bf3b19d8624f2ea991eacf632ee0edd31f1daa7 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 31 Jan 2019 15:09:57 +0100 Subject: [PATCH 20/37] #4068 - Fix for ordering of grid --- .../propertyeditors/grid/grid.controller.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index be92128280..f7e69a2683 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -60,8 +60,8 @@ angular.module("umbraco") start: function (e, ui) { // Fade out row when sorting - ui.item.context.style.display = "block"; - ui.item.context.style.opacity = "0.5"; + ui.item[0].style.display = "block"; + ui.item[0].style.opacity = "0.5"; draggedRteSettings = {}; ui.item.find(".mceNoEditor").each(function () { @@ -75,7 +75,7 @@ angular.module("umbraco") stop: function (e, ui) { // Fade in row when sorting stops - ui.item.context.style.opacity = "1"; + ui.item[0].style.opacity = "1"; // reset all RTEs affected by the dragging ui.item.parents(".umb-column").find(".mceNoEditor").each(function () { @@ -185,12 +185,12 @@ angular.module("umbraco") startingArea = area; // fade out control when sorting - ui.item.context.style.display = "block"; - ui.item.context.style.opacity = "0.5"; + ui.item[0].style.display = "block"; + ui.item[0].style.opacity = "0.5"; // reset dragged RTE settings in case a RTE isn't dragged draggedRteSettings = undefined; - ui.item.context.style.display = "block"; + ui.item[0].style.display = "block"; ui.item.find(".mceNoEditor").each(function () { notIncludedRte = []; var editors = _.findWhere(tinyMCE.editors, { id: $(this).attr("id") }); @@ -210,7 +210,7 @@ angular.module("umbraco") stop: function (e, ui) { // Fade in control when sorting stops - ui.item.context.style.opacity = "1"; + ui.item[0].style.opacity = "1"; ui.item.offsetParent().find(".mceNoEditor").each(function () { if ($.inArray($(this).attr("id"), notIncludedRte) < 0) { @@ -400,7 +400,7 @@ angular.module("umbraco") } $scope.editGridItemSettings = function (gridItem, itemType) { - + placeHolder = "{0}"; var styles, config; @@ -658,7 +658,7 @@ angular.module("umbraco") // ********************************************* $scope.initContent = function () { var clear = true; - + //settings indicator shortcut if (($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) { $scope.hasSettings = true; @@ -755,7 +755,7 @@ angular.module("umbraco") // Init layout / row // ********************************************* $scope.initRow = function (row) { - + //merge the layout data with the original config data //if there are no config info on this, splice it out var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; }); From 4a480ab3918be8f0bce3c57027bd2ce750a361ba Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 31 Jan 2019 15:10:19 +0100 Subject: [PATCH 21/37] #4068 - Added interceptor to remove `$` variables from post data --- .../src/common/interceptors/_module.js | 1 + ...tpostdollarvariablesrequest.interceptor.js | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js index 765f44a636..05263cebf2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js @@ -6,4 +6,5 @@ angular.module('umbraco.interceptors', []) $httpProvider.interceptors.push('securityInterceptor'); $httpProvider.interceptors.push('debugRequestInterceptor'); + $httpProvider.interceptors.push('doNotPostDollarVariablesOnPostRequestInterceptor'); }]); diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js new file mode 100644 index 0000000000..0a5f6d837d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js @@ -0,0 +1,38 @@ +(function() { + 'use strict'; + + function removeProperty(obj, propertyPrefix) { + for (var property in obj) { + if (obj.hasOwnProperty(property)) { + + if (property.startsWith(propertyPrefix) && obj[property]) { + obj[property] = undefined; + } + + if (typeof obj[property] == "object") { + removeProperty(obj[property], propertyPrefix); + } + } + } + + } + + function transform(data){ + removeProperty(data, "$"); + } + + function doNotPostDollarVariablesRequestInterceptor($q, urlHelper) { + return { + //dealing with requests: + 'request': function(config) { + if(config.method === "POST"){ + config.transformRequest.push(transform); + } + + return config; + } + }; + } + + angular.module('umbraco.interceptors').factory('doNotPostDollarVariablesOnPostRequestInterceptor', doNotPostDollarVariablesRequestInterceptor); +})(); From 045020e739f277d016516e34e200018bfcd495b0 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 1 Feb 2019 08:37:06 +0100 Subject: [PATCH 22/37] #4068 - Changed `save` event triggered when save dialog is opened. `save` is still broadcasted on the actual save. Changed the grid event listener to only execute on `save` events --- .../common/directives/components/content/edit.controller.js | 2 +- .../donotpostdollarvariablesrequest.interceptor.js | 2 +- .../src/views/propertyeditors/grid/grid.controller.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 5c5b1f933e..4f71fb0686 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -617,7 +617,7 @@ // TODO: Add "..." to save button label if there are more than one variant to publish - currently it just adds the elipses if there's more than 1 variant if (isContentCultureVariant()) { //before we launch the dialog we want to execute all client side validations first - if (formHelper.submitForm({ scope: $scope, action: "save" })) { + if (formHelper.submitForm({ scope: $scope, action: "openSaveDialog" })) { var dialog = { parentScope: $scope, diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js index 0a5f6d837d..1bae002df9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js @@ -26,7 +26,7 @@ //dealing with requests: 'request': function(config) { if(config.method === "POST"){ - config.transformRequest.push(transform); + transform(config.data); } return config; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index f7e69a2683..b40305f5f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -909,9 +909,9 @@ angular.module("umbraco") // needs to be merged in at runtime to ensure that the real config values are used // if they are ever updated. - var unsubscribe = $scope.$on("formSubmitting", function () { - - if ($scope.model.value && $scope.model.value.sections) { + var unsubscribe = $scope.$on("formSubmitting", function (e, args) { + + if (args.action === "save" && $scope.model.value && $scope.model.value.sections) { _.each($scope.model.value.sections, function(section) { if (section.rows) { _.each(section.rows, function (row) { From fc6e17f3f9032b0fc9b9dbf3a2cb82421c048fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 1 Feb 2019 10:49:09 +0100 Subject: [PATCH 23/37] =?UTF-8?q?V8:=20UI=20=E2=80=94=20umb-content-grid?= =?UTF-8?q?=20color=20change?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/less/components/umb-content-grid.less | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less index 5a2821eb9e..ccf86e7ea6 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less @@ -15,10 +15,6 @@ box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16); border-radius: 3px; - color: @ui-option-type; - &:hover { - color:@ui-option-type-hover; - } } .umb-content-grid__item.-selected { @@ -70,9 +66,13 @@ .umb-content-grid__item-name { font-weight: bold; margin-bottom: 15px; - //color: @black; line-height: 1.4em; display: inline-flex; + + color: @ui-option-type; + &:hover { + color:@ui-option-type-hover; + } } .umb-content-grid__item-name:hover span { From 979f7b404cc32639392fcf1aa0dbc90584d2a8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 1 Feb 2019 10:51:14 +0100 Subject: [PATCH 24/37] V8: refactoring of layers add and removal methods --- .../components/editor/umbeditors.directive.js | 234 +++++++++--------- .../less/components/editor/umb-editor.less | 16 +- 2 files changed, 130 insertions(+), 120 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js index 0db239c56a..c25dd0a76f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js @@ -13,145 +13,145 @@ function addEditor(editor) { + + if (!editor.style) + editor.style = {}; + editor.animating = true; - + showOverlayOnPrevEditor(); - // start collapsing editors to make room for new ones - $timeout(function() { - - var editorsElement = el[0]; - // only select the editors which are allowed to be - // shown so we don't animate a lot of editors which aren't necessary - var moveEditors = editorsElement.querySelectorAll('.umb-editor:nth-last-child(-n+'+ allowedNumberOfVisibleEditors +')'); - - // collapse open editors before opening the new one - var collapseEditorAnimation = anime({ - targets: moveEditors, - width: function(el, index, length) { - // we have to resize all small editors when they move to the - // left side so they don't leave a gap - if(el.classList.contains("umb-editor--small")) { - return "100%"; - } - }, - left: function(el, index, length){ - if(length >= allowedNumberOfVisibleEditors) { - return index * editorIndent; - } - return (index + 1) * editorIndent; - }, + var i = allowedNumberOfVisibleEditors; + var len = scope.editors.length; + while(i= allowedNumberOfVisibleEditors) { - indentValue = allowedNumberOfVisibleEditors * editorIndent; } - - // indent all large editors - if(editor.size !== "small") { - lastEditor.style.left = indentValue + "px"; + + if(scope.editors[i].size !== "small") { + animeConfig.width = "100%"; } + + if(len >= allowedNumberOfVisibleEditors) { + animeConfig.left = i * editorIndent; + } else { + animeConfig.left = (i + 1) * editorIndent; + } + + anime(animeConfig); + + i++; + } + + + // push the new editor to the dom + scope.editors.push(editor); + + + + var indentValue = scope.editors.length * editorIndent; - // animation config - var addEditorAnimation = anime({ - targets: lastEditor, - translateX: [100 + '%', 0], - opacity: [0, 1], - easing: 'easeInOutQuint', - duration: 300, - complete: function() { - $timeout(function(){ - editor.animating = false; - }); - } - }); + // don't allow indent larger than what + // fits the max number of visible editors + if(scope.editors.length >= allowedNumberOfVisibleEditors) { + indentValue = allowedNumberOfVisibleEditors * editorIndent; + } + // indent all large editors + if(editor.size !== "small") { + editor.style.left = indentValue + "px"; + } + + editor.style._tx = 100; + //editor.style.opacity = 0; + editor.style.transform = "translateX("+editor.style._tx+"%)"; + + // animation config + anime({ + targets: editor.style, + _tx: [100, 0], + //opacity: [0, 1], + easing: 'easeOutExpo', + duration: 480, + update: () => { + editor.style.transform = "translateX("+editor.style._tx+"%)"; + scope.$digest(); + }, + complete: function() { + //$timeout(function(){ + editor.animating = false; + scope.$digest(); + //}); + } }); + } function removeEditor(editor) { editor.animating = true; - - $timeout(function(){ - - var editorsElement = el[0]; - var lastEditor = editorsElement.querySelector('.umb-editor:last-of-type'); - - var removeEditorAnimation = anime({ - targets: lastEditor, - translateX: [0, 100 + '%'], - opacity: [1, 0], - easing: 'easeInOutQuint', - duration: 300, - complete: function(a) { - $timeout(function(){ - scope.editors.splice(-1,1); - removeOverlayFromPrevEditor(); - }); - } - }); - - expandEditors(); - + + editor.style._tx = 0; + editor.style.transform = "translateX("+editor.style._tx+"%)"; + + // animation config + anime({ + targets: editor.style, + _tx: [0, 100], + //opacity: [1, 0], + easing: 'easeInExpo', + duration: 360, + update: () => { + editor.style.transform = "translateX("+editor.style._tx+"%)"; + scope.$digest(); + }, + complete: function() { + //$timeout(function(){ + scope.editors.splice(-1,1); + removeOverlayFromPrevEditor(); + scope.$digest(); + //}) + } }); - + + + expandEditors(); + + } function expandEditors() { - // expand hidden editors - $timeout(function() { - - var editorsElement = el[0]; - // only select the editors which are allowed to be - // shown so we don't animate a lot of editors which aren't necessary - // as the last element hasn't been removed from the dom yet we have to select the last four and then skip the last child (as it is the one closing). - var moveEditors = editorsElement.querySelectorAll('.umb-editor:nth-last-child(-n+'+ allowedNumberOfVisibleEditors + 1 +'):not(:last-child)'); - var editorWidth = editorsElement.offsetWidth; - - var expandEditorAnimation = anime({ - targets: moveEditors, - left: function(el, index, length){ - // move the editor all the way to the right if the top one is a small - if(el.classList.contains("umb-editor--small")) { - // only change the size if it is the editor on top - if(index + 1 === length) { - return editorWidth - 500; - } - } else { - return (index + 1) * editorIndent; - } - }, - width: function(el, index, length) { - // set the correct size if the top editor is of type "small" - if(el.classList.contains("umb-editor--small") && index + 1 === length) { - return "500px"; - } - }, + + var i = allowedNumberOfVisibleEditors + 1; + var len = scope.editors.length-1; + while(i Date: Fri, 1 Feb 2019 09:58:10 +0000 Subject: [PATCH 25/37] Fix count bug - so it works with two languages --- src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index b656942020..17a2f3c66a 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -47,7 +47,7 @@ - @if (Model.Languages != null && Model.Languages.Count() > 2) + @if (Model.Languages != null && Model.Languages.Count() > 1) { foreach (var previewLink in Model.Languages) { From 0bb69aeeeeac4c7d27463a3318202beadf52909c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 1 Feb 2019 11:10:20 +0100 Subject: [PATCH 26/37] V8: preview colors changed for brandcolors 2019 --- .../src/less/canvas-designer.less | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less index 146f9b8a67..7f67d5c3b2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less +++ b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less @@ -275,7 +275,7 @@ a, a:hover{ font-family: "Lato", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 16px; - background: #413659; + background: #1b264f; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; @@ -306,7 +306,7 @@ a, a:hover{ ul.sections { display: block; - background: #413659; + background: #1b264f; height: 100%; position:absolute; top: 90px; @@ -322,7 +322,7 @@ ul.sections { ul.sections li { display: block; - border-left: 4px #413659 solid; + border-left: 4px #1b264f solid; -webkit-transition: all .3s linear; -moz-transition: all .3s linear; transition: all .3s linear; @@ -330,7 +330,8 @@ ul.sections li { .fix-left-menu ul.sections li a span, .fix-left-menu ul.sections li a i { - color: #8d869b; + color: #fff; + opacity: .7; -webkit-transition: all .3s linear; -moz-transition: all .3s linear; transition: all .3s linear; @@ -345,6 +346,11 @@ ul.sections li a { text-align: center; text-decoration: none; border-bottom: 1px solid #2E2246; + &:hover { + span, i { + opacity: 1; + } + } } ul.sections li a i { @@ -367,7 +373,7 @@ ul.sections li.current a i { } ul.sections li.current, ul.sections li:hover { - border-left: 4px #00AEA2 solid; + border-left: 4px #f5c1bc solid; } .fix-left-menu:hover ul.sections li a span, From d38dba16600fcc45e05b8a6aa5b4a8821342470e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 1 Feb 2019 10:14:29 +0000 Subject: [PATCH 27/37] Update nuspec to include new hosted image/icon for Nuget packages from .com site --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- build/NuSpecs/UmbracoCms.Web.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.nuspec | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index dc1224842e..9758c05dd6 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -8,7 +8,7 @@ Umbraco HQ http://opensource.org/licenses/MIT http://umbraco.com/ - http://umbraco.com/media/357769/100px_transparent.png + https://umbraco.com/dist/nuget/logo-small.png false Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project. Contains the core assemblies needed to run Umbraco Cms diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index 30fa303b30..fabd1e25a8 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -8,13 +8,13 @@ Umbraco HQ http://opensource.org/licenses/MIT http://umbraco.com/ - http://umbraco.com/media/357769/100px_transparent.png + https://umbraco.com/dist/nuget/logo-small.png false Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project. Contains the core assemblies needed to run Umbraco Cms en-US umbraco - + - + + diff --git a/src/Umbraco.Web.UI/config/serilog.user.config b/src/Umbraco.Web.UI/config/serilog.user.config index 374657795e..24e5e4e4be 100644 --- a/src/Umbraco.Web.UI/config/serilog.user.config +++ b/src/Umbraco.Web.UI/config/serilog.user.config @@ -3,7 +3,8 @@ - + +