From e062ea8d31238fc53abf86259ddfab3874d1595a Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 17 Apr 2019 10:03:49 +0200 Subject: [PATCH] Refactor IPublishedContent.CultureDate(), .Cultures --- .../PublishedContent/IPublishedContent.cs | 11 +++--- .../PublishedContentWrapped.cs | 4 +- .../DictionaryPublishedContent.cs | 7 ++-- .../XmlPublishedContent.cs | 7 ++-- .../Published/NestedContentTests.cs | 4 +- .../PublishedContent/NuCacheTests.cs | 4 +- .../PublishedContentDataTableTests.cs | 4 +- .../SolidPublishedSnapshot.cs | 4 +- .../TestHelpers/Stubs/TestPublishedContent.cs | 13 ++++--- .../Editors/MacroRenderingController.cs | 18 +++++++-- .../PublishedContentHashtableConverter.cs | 29 +++++++------- .../Models/PublishedContentBase.cs | 4 +- .../NuCache/PublishedContent.cs | 39 ++++++++----------- .../PublishedCache/PublishedMember.cs | 4 +- src/Umbraco.Web/PublishedContentExtensions.cs | 2 +- src/Umbraco.Web/Routing/PublishedRouter.cs | 2 +- .../Routing/RedirectTrackingComponent.cs | 4 +- 17 files changed, 84 insertions(+), 76 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 978958413a..2d1c48b854 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -88,7 +88,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// /// For published content items, this is also the date the item was published. - /// This date is always global to the content item, see GetCulture().Date for the + /// This date is always global to the content item, see CultureDate() for the /// date each culture was published. /// DateTime UpdateDate { get; } @@ -104,19 +104,20 @@ namespace Umbraco.Core.Models.PublishedContent string Url(string culture = null, UrlMode mode = UrlMode.Auto); /// - /// Gets culture infos for a culture. + /// Gets the culture date of the content item. /// - PublishedCultureInfo GetCulture(string culture = null); + /// The specific culture to get the name for. If null is used the current culture is used (Default is null). + DateTime CultureDate(string culture = null); /// - /// Gets culture infos. + /// Gets all available cultures. /// /// /// Contains only those culture that are available. For a published content, these are /// the cultures that are published. For a draft content, those that are 'available' ie /// have a non-empty content name. /// - IReadOnlyDictionary Cultures { get; } + IReadOnlyList Cultures { get; } /// /// Gets a value indicating whether the content is draft. diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs index cd92888f7e..9132fb1f85 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs @@ -97,10 +97,10 @@ namespace Umbraco.Core.Models.PublishedContent public virtual string Url(string culture = null, UrlMode mode = UrlMode.Auto) => _content.Url(culture, mode); /// - public PublishedCultureInfo GetCulture(string culture = null) => _content.GetCulture(culture); + public DateTime CultureDate(string culture = null) => _content.CultureDate(culture); /// - public IReadOnlyDictionary Cultures => _content.Cultures; + public IReadOnlyList Cultures => _content.Cultures; /// public virtual bool IsDraft(string culture = null) => _content.IsDraft(culture); diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/DictionaryPublishedContent.cs index 40d7146248..7c6ecf5934 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/DictionaryPublishedContent.cs @@ -153,10 +153,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache public override string Name(string culture = null) => _name; - public override PublishedCultureInfo GetCulture(string culture = null) => null; + public override DateTime CultureDate(string culture = null) => UpdateDate; - private static readonly Lazy> NoCultures = new Lazy>(() => new Dictionary()); - public override IReadOnlyDictionary Cultures => NoCultures.Value; + // ReSharper disable once CollectionNeverUpdated.Local + private static readonly List EmptyListOfString = new List(); + public override IReadOnlyList Cultures => EmptyListOfString; public override string UrlSegment(string culture = null) => _urlName; diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs index b738b22e2c..a1395b46bc 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs @@ -142,10 +142,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache return _name; } - public override PublishedCultureInfo GetCulture(string culture = null) => null; + public override DateTime CultureDate(string culture = null) => UpdateDate; - private static readonly Lazy> NoCultures = new Lazy>(() => new Dictionary()); - public override IReadOnlyDictionary Cultures => NoCultures.Value; + // ReSharper disable once CollectionNeverUpdated.Local + private static readonly List EmptyListOfString = new List(); + public override IReadOnlyList Cultures => EmptyListOfString; public override string WriterName { diff --git a/src/Umbraco.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs index e91f456922..b92724b033 100644 --- a/src/Umbraco.Tests/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests/Published/NestedContentTests.cs @@ -284,8 +284,8 @@ namespace Umbraco.Tests.Published public override int? TemplateId { get; } public override int SortOrder { get; } public override string Name(string culture = null) => default; - public override PublishedCultureInfo GetCulture(string culture = ".") => throw new NotSupportedException(); - public override IReadOnlyDictionary Cultures => throw new NotSupportedException(); + public override DateTime CultureDate(string culture = null) => throw new NotSupportedException(); + public override IReadOnlyList Cultures => throw new NotSupportedException(); public override string UrlSegment(string culture = null) => default; public override string WriterName { get; } public override string CreatorName { get; } diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 073ebf58ca..7d5fb8e736 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -223,13 +223,13 @@ namespace Umbraco.Tests.PublishedContent _variationAccesor.VariationContext = new VariationContext("fr-FR"); Assert.AreEqual("val-fr1", publishedContent.Value("prop")); Assert.AreEqual("name-fr1", publishedContent.Name()); - Assert.AreEqual(new DateTime(2018, 01, 01, 01, 00, 00), publishedContent.GetCulture().Date); + Assert.AreEqual(new DateTime(2018, 01, 01, 01, 00, 00), publishedContent.CultureDate()); // now uk is default _variationAccesor.VariationContext = new VariationContext("en-UK"); Assert.AreEqual("val-uk1", publishedContent.Value("prop")); Assert.AreEqual("name-uk1", publishedContent.Name()); - Assert.AreEqual(new DateTime(2018, 01, 02, 01, 00, 00), publishedContent.GetCulture().Date); + Assert.AreEqual(new DateTime(2018, 01, 02, 01, 00, 00), publishedContent.CultureDate()); // invariant needs to be retrieved explicitly, when it's not default Assert.AreEqual("val1", publishedContent.Value("prop", culture: "")); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 41b5588234..7f3c77cc72 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -205,8 +205,8 @@ namespace Umbraco.Tests.PublishedContent public int SortOrder { get; set; } public string Name(string culture = null) => _names.TryGetValue(culture ?? "", out var name) ? name : null; public void SetName(string name, string culture = null) => _names[culture ?? ""] = name; - public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); - public IReadOnlyDictionary Cultures => throw new NotSupportedException(); + public DateTime CultureDate(string culture = null) => throw new NotSupportedException(); + public IReadOnlyList Cultures => throw new NotSupportedException(); public string UrlSegment(string culture = null) => _urlSegments.TryGetValue(culture ?? "", out var urlSegment) ? urlSegment : null; public void SetUrlSegment(string urlSegment, string culture = null) => _urlSegments[culture ?? ""] = urlSegment; public string WriterName { get; set; } diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs index 77f25c0b0b..22d6fe8ef1 100644 --- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs @@ -183,8 +183,8 @@ namespace Umbraco.Tests.PublishedContent public int SortOrder { get; set; } public string Name(string culture = null) => _names.TryGetValue(culture ?? "", out var name) ? name : null; public void SetName(string name, string culture = null) => _names[culture ?? ""] = name; - public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); - public IReadOnlyDictionary Cultures => throw new NotSupportedException(); + public DateTime CultureDate(string culture = null) => throw new NotSupportedException(); + public IReadOnlyList Cultures => throw new NotSupportedException(); public string UrlSegment(string culture = null) => _urlSegments.TryGetValue(culture ?? "", out var urlSegment) ? urlSegment : null; public void SetUrlSegment(string urlSegment, string culture = null) => _urlSegments[culture ?? ""] = urlSegment; public string WriterName { get; set; } diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs index 8a092c3453..6dd25b966e 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs @@ -9,12 +9,13 @@ namespace Umbraco.Tests.TestHelpers.Stubs { private readonly Dictionary _names = new Dictionary(); private readonly Dictionary _urlSegments = new Dictionary(); + private readonly Dictionary _cultures; - public TestPublishedContent(IPublishedContentType contentType, int id, Guid key, Dictionary values, bool previewing, Dictionary cultures = null) + public TestPublishedContent(IPublishedContentType contentType, int id, Guid key, Dictionary values, bool previewing, Dictionary cultures = null) : base(contentType, key, values, previewing) { Id = id; - Cultures = cultures; + _cultures = cultures ?? new Dictionary(); } public int Id { get; } @@ -23,19 +24,19 @@ namespace Umbraco.Tests.TestHelpers.Stubs public string Name(string culture = null) => _names.TryGetValue(culture ?? "", out var name) ? name : null; public void SetName(string name, string culture = null) => _names[culture ?? ""] = name; public IVariationContextAccessor VariationContextAccessor { get; set; } - public PublishedCultureInfo GetCulture(string culture = null) + public DateTime CultureDate(string culture = null) { // handle context culture if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture; // no invariant culture infos - if (culture == "" || Cultures == null) return null; + if (culture == "" || Cultures == null) return UpdateDate; // get - return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos : null; + return _cultures.TryGetValue(culture, out var date) ? date : DateTime.MinValue; } - public IReadOnlyDictionary Cultures { get; set; } + public IReadOnlyList Cultures { get; set; } public string UrlSegment(string culture = null) => _urlSegments.TryGetValue(culture ?? "", out var urlSegment) ? urlSegment : null; public void SetUrlSegment(string urlSegment, string culture = null) => _urlSegments[culture ?? ""] = urlSegment; public string DocumentTypeAlias => ContentType.Alias; diff --git a/src/Umbraco.Web/Editors/MacroRenderingController.cs b/src/Umbraco.Web/Editors/MacroRenderingController.cs index a2bbfe1dfd..64706a7f04 100644 --- a/src/Umbraco.Web/Editors/MacroRenderingController.cs +++ b/src/Umbraco.Web/Editors/MacroRenderingController.cs @@ -123,12 +123,22 @@ namespace Umbraco.Web.Editors // Since a Macro might contain thing thats related to the culture of the "IPublishedContent" (ie Dictionary keys) we want // to set the current culture to the culture related to the content item. This is hacky but it works. - var culture = publishedContent.GetCulture(); - _variationContextAccessor.VariationContext = new VariationContext(); //must have an active variation context! + // fixme I don't even know how this ever worked?! + + // assume this was some sort of "the culture of the item" + // but... with multilingual it does not make any sense?! + //var culture = publishedContent.GetCulture(); + + string culture = ""; // needs to be eg fr-FR + if (culture != null) { - Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture.Culture); - _variationContextAccessor.VariationContext = new VariationContext(Thread.CurrentThread.CurrentCulture.Name); + Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); + _variationContextAccessor.VariationContext = new VariationContext(culture); + } + else + { + _variationContextAccessor.VariationContext = new VariationContext(); //must have an active variation context! } var result = Request.CreateResponse(); diff --git a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs index 108f58e929..be7bbc37a8 100644 --- a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs +++ b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs @@ -230,32 +230,31 @@ namespace Umbraco.Web.Macros public string Name(string culture = null) => _inner.GetCultureName(culture); - public PublishedCultureInfo GetCulture(string culture = null) + public DateTime CultureDate(string culture = null) { - // handle context culture + // invariant has invariant value (whatever the requested culture) + if (!ContentType.VariesByCulture()) + return UpdateDate; + + // handle context culture for variant if (culture == null) culture = _variationContextAccessor.VariationContext.Culture; - // no invariant culture infos - if (culture == "") return null; - // get - return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos : null; + return culture != "" && _inner.PublishCultureInfos.TryGetValue(culture, out var infos) ? infos.Date : DateTime.MinValue; } - public IReadOnlyDictionary Cultures + // ReSharper disable once CollectionNeverUpdated.Local + private static readonly List EmptyListOfString = new List(); + private IReadOnlyList _cultures; + + public IReadOnlyList Cultures { get { if (!_inner.ContentType.VariesByCulture()) - return NoCultureInfos; - - if (_cultureInfos != null) - return _cultureInfos; - - var urlSegmentProviders = Current.UrlSegmentProviders; // TODO inject - return _cultureInfos = _inner.PublishCultureInfos.Values - .ToDictionary(x => x.Culture, x => new PublishedCultureInfo(x.Culture, x.Name, _inner.GetUrlSegment(urlSegmentProviders, x.Culture), x.Date)); + return EmptyListOfString; + return _cultures ?? (_cultures = _inner.PublishCultureInfos.Values.Select(x => x.Culture).ToList()); } } diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 7017e84882..22a76fb907 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -135,10 +135,10 @@ namespace Umbraco.Web.Models } /// - public abstract PublishedCultureInfo GetCulture(string culture = null); + public abstract DateTime CultureDate(string culture = null); /// - public abstract IReadOnlyDictionary Cultures { get; } + public abstract IReadOnlyList Cultures { get; } /// public abstract bool IsDraft(string culture = null); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 2e745aacb0..86ed272b13 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -196,7 +196,7 @@ namespace Umbraco.Web.PublishedCache.NuCache culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; // get - return culture != "" && Cultures.TryGetValue(culture, out var infos) ? infos.Name : null; + return culture != "" && ContentData.CultureInfos.TryGetValue(culture, out var infos) ? infos.Name : null; } /// @@ -206,12 +206,12 @@ namespace Umbraco.Web.PublishedCache.NuCache if (!ContentType.VariesByCulture()) return _urlSegment; - // handle context culture fpr variant + // handle context culture for variant if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; // get - return culture != "" && Cultures.TryGetValue(culture, out var infos) ? infos.UrlSegment : null; + return ContentData.CultureInfos.TryGetValue(culture, out var infos) ? infos.UrlSegment : null; } /// @@ -244,39 +244,34 @@ namespace Umbraco.Web.PublishedCache.NuCache /// public override DateTime UpdateDate => ContentData.VersionDate; - private IReadOnlyDictionary _cultureInfos; - - private static readonly IReadOnlyDictionary NoCultureInfos = new Dictionary(); - /// - public override PublishedCultureInfo GetCulture(string culture = null) + public override DateTime CultureDate(string culture = null) { - // handle context culture + // invariant has invariant value (whatever the requested culture) + if (!ContentType.VariesByCulture()) + return UpdateDate; + + // handle context culture for variant if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; - // no invariant culture infos - if (culture == "") return null; - // get - return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos : null; + return culture != "" && ContentData.CultureInfos.TryGetValue(culture, out var infos) ? infos.Date : DateTime.MinValue; } + // ReSharper disable once CollectionNeverUpdated.Local + private static readonly List EmptyListOfString = new List(); + private IReadOnlyList _cultures; + /// - public override IReadOnlyDictionary Cultures + public override IReadOnlyList Cultures { get { if (!ContentType.VariesByCulture()) - return NoCultureInfos; + return EmptyListOfString; - if (_cultureInfos != null) return _cultureInfos; - - if (ContentData.CultureInfos == null) - throw new Exception("oops: _contentDate.CultureInfos is null."); - - return _cultureInfos = ContentData.CultureInfos - .ToDictionary(x => x.Key, x => new PublishedCultureInfo(x.Key, x.Value.Name, x.Value.UrlSegment, x.Value.Date), StringComparer.OrdinalIgnoreCase); + return _cultures ?? (_cultures = ContentData.CultureInfos.Keys.ToList()); } } diff --git a/src/Umbraco.Web/PublishedCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/PublishedMember.cs index 68b742caa3..46b12b5ca3 100644 --- a/src/Umbraco.Web/PublishedCache/PublishedMember.cs +++ b/src/Umbraco.Web/PublishedCache/PublishedMember.cs @@ -140,9 +140,9 @@ namespace Umbraco.Web.PublishedCache return _member.Name; } - public override PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); + public override DateTime CultureDate(string culture = null) => throw new NotSupportedException(); - public override IReadOnlyDictionary Cultures => throw new NotSupportedException(); + public override IReadOnlyList Cultures => throw new NotSupportedException(); public override string UrlSegment(string culture = null) => throw new NotSupportedException(); diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 7776a7c8ac..d7996034a8 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -168,7 +168,7 @@ namespace Umbraco.Web /// /// Culture is case-insensitive. public static bool HasCulture(this IPublishedContent content, string culture) - => content.Cultures.ContainsKey(culture ?? string.Empty); + => content.Cultures.Contains(culture ?? string.Empty); /// /// Filters a sequence of to return invariant items, and items that are published for the specified culture. diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index c93b7c06b2..aeb329a9e9 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -276,7 +276,7 @@ namespace Umbraco.Web.Routing return true; // variant, ensure that the culture corresponding to the domain's language is published - return domainDocument.Cultures.ContainsKey(domain.Culture.Name); + return domainDocument.Cultures.Contains(domain.Culture.Name); } domains = domains.Where(IsPublishedContentDomain).ToList(); diff --git a/src/Umbraco.Web/Routing/RedirectTrackingComponent.cs b/src/Umbraco.Web/Routing/RedirectTrackingComponent.cs index 0d82467179..4f9086e50b 100644 --- a/src/Umbraco.Web/Routing/RedirectTrackingComponent.cs +++ b/src/Umbraco.Web/Routing/RedirectTrackingComponent.cs @@ -171,12 +171,12 @@ namespace Umbraco.Web.Routing if (entityContent == null) continue; // get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures) - var defaultCultures = entityContent.AncestorsOrSelf()?.FirstOrDefault(a => a.Cultures.Any())?.Cultures.Select(c => c.Key).ToArray() + var defaultCultures = entityContent.AncestorsOrSelf()?.FirstOrDefault(a => a.Cultures.Any())?.Cultures.ToArray() ?? new[] {(string) null}; foreach (var x in entityContent.DescendantsOrSelf()) { // if this entity defines specific cultures, use those instead of the default ones - var cultures = x.Cultures.Any() ? x.Cultures.Select(c => c.Key) : defaultCultures; + var cultures = x.Cultures.Any() ? x.Cultures : defaultCultures; foreach (var culture in cultures) {