From 3f73452bc74e9e75cd52b704d65390cfd779d00a Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 7 May 2018 18:22:23 +0200 Subject: [PATCH] Various fixes, and U4-11287 --- .../Models/Entities/EntitySlim.cs | 10 +++ .../Implement/DocumentRepository.cs | 2 +- .../Implement/EntityRepository.cs | 16 ++--- src/Umbraco.Examine/UmbracoContentIndexer.cs | 2 +- .../Services/EntityServiceTests.cs | 6 +- .../PublishedCache/NuCache/ContentCache.cs | 8 ++- .../Trees/ContentTreeControllerBase.cs | 62 ++++++++++++------- 7 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/Umbraco.Core/Models/Entities/EntitySlim.cs b/src/Umbraco.Core/Models/Entities/EntitySlim.cs index 163879bbe0..7808cea19b 100644 --- a/src/Umbraco.Core/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/EntitySlim.cs @@ -26,6 +26,16 @@ namespace Umbraco.Core.Models.Entities /// public static readonly IEntitySlim Root = new EntitySlim { Path = "-1", Name = "root", HasChildren = true }; + /// + /// Gets the AdditionalData key for culture names. + /// + public const string AdditionalCultureNames = "CultureNames"; + + /// + /// Gets the AdditionalData key for variations. + /// + public const string AdditionalVariations = "Variations"; + // implement IEntity diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index e66e0f125b..e723ece853 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -1062,7 +1062,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement NodeId = content.Id, LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."), Culture = culture, - Edited = !content.IsCulturePublished(culture) || editedCultures.Contains(culture) // if not published, always edited + Edited = !content.IsCulturePublished(culture) || (editedCultures != null && editedCultures.Contains(culture)) // if not published, always edited }; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs index 0dd7a25798..6b74c27f1a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs @@ -435,7 +435,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// - /// The DTO used to fetch results for a content item with it's variation info + /// The DTO used to fetch results for a content item with its variation info /// private class ContentEntityDto : BaseDto { @@ -483,6 +483,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public string Icon { get; set; } public string Thumbnail { get; set; } public bool IsContainer { get; set; } + public ContentVariation Variations { get; set; } // ReSharper restore UnusedAutoPropertyAccessor.Local // ReSharper restore UnusedMember.Local } @@ -506,8 +507,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia) sql - .AndSelect(x => NPocoSqlExtensions.Statics.Alias(x.Id, "versionId")) - .AndSelect(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer); + .AndSelect(x => Alias(x.Id, "versionId")) + .AndSelect(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (isContent) { @@ -616,7 +617,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia) sql .AndBy(x => x.Id) - .AndBy(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer); + .AndBy(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (sort) sql.OrderBy(x => x.SortOrder); @@ -869,6 +870,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement BuildContentEntity(entity, dto); entity.Published = dto.Published; entity.Edited = dto.Edited; + entity.AdditionalData[EntitySlim.AdditionalVariations] = dto.Variations; } private static EntitySlim BuildContentEntity(BaseDto dto) @@ -897,16 +899,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // EntitySlim does not track changes var entity = new DocumentEntitySlim(); BuildDocumentEntity(entity, dto); - var variantInfo = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - if (dto.VariationInfo != null) + if (dto.Variations.Has(ContentVariation.CultureNeutral) && dto.VariationInfo != null && dto.VariationInfo.Count > 0) { + var variantInfo = new Dictionary(StringComparer.InvariantCultureIgnoreCase); foreach (var info in dto.VariationInfo) { var isoCode = _langRepository.GetIsoCodeById(info.LanguageId); if (isoCode != null) variantInfo[isoCode] = info.Name; } - entity.AdditionalData["CultureNames"] = variantInfo; + entity.AdditionalData[EntitySlim.AdditionalCultureNames] = variantInfo; } return entity; } diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs index d799e12eed..487d238c25 100644 --- a/src/Umbraco.Examine/UmbracoContentIndexer.cs +++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs @@ -321,7 +321,7 @@ namespace Umbraco.Examine { foreach (var c in content) { - var urlValue = c.GetUrlSegment(urlSegmentProviders, ""); // for now, index with invariant culture + var urlValue = c.GetUrlSegment(urlSegmentProviders); // for now, index with invariant culture var values = new Dictionary { {"icon", new object[] {c.ContentType.Icon}}, diff --git a/src/Umbraco.Tests/Services/EntityServiceTests.cs b/src/Umbraco.Tests/Services/EntityServiceTests.cs index cdbfb2b66e..053a6f39ac 100644 --- a/src/Umbraco.Tests/Services/EntityServiceTests.cs +++ b/src/Umbraco.Tests/Services/EntityServiceTests.cs @@ -463,8 +463,8 @@ namespace Umbraco.Tests.Services var result = service.Get(c1.Id, UmbracoObjectTypes.Document); Assert.AreEqual("Test", result.Name); - Assert.IsTrue(result.AdditionalData.ContainsKey("CultureNames")); - var cultureNames = (IDictionary)result.AdditionalData["CultureNames"]; + Assert.IsTrue(result.AdditionalData.ContainsKey(EntitySlim.AdditionalCultureNames)); + var cultureNames = (IDictionary)result.AdditionalData[EntitySlim.AdditionalCultureNames]; Assert.AreEqual("Test - FR", cultureNames[_langFr.IsoCode]); Assert.AreEqual("Test - ES", cultureNames[_langEs.IsoCode]); } @@ -501,7 +501,7 @@ namespace Umbraco.Tests.Services if (i % 2 == 0) { Assert.AreEqual(1, entities[i].AdditionalData.Count); - Assert.AreEqual("CultureNames", entities[i].AdditionalData.Keys.First()); + Assert.AreEqual(EntitySlim.AdditionalCultureNames, entities[i].AdditionalData.Keys.First()); var variantInfo = entities[i].AdditionalData.First().Value as IDictionary; Assert.IsNotNull(variantInfo); var keys = variantInfo.Keys.ToList(); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs index 4b235e42b9..221295f770 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs @@ -147,7 +147,13 @@ namespace Umbraco.Web.PublishedCache.NuCache var hasDomains = _domainHelper.NodeHasDomains(n.Id); while (hasDomains == false && n != null) // n is null at root { - var urlSegment = n.GetCulture(culture).UrlSegment; + var varies = n.ContentType.Variations.Has(ContentVariation.CultureNeutral); + var urlSegment = varies ? n.GetCulture(culture)?.UrlSegment : n.UrlSegment; + + // at that point we should have an urlSegment, unless something weird is happening + // at content level, such as n.GetCulture() returning null for some (weird) reason, + // and then what? fallback to the invariant segment... far from perfect but eh... + if (string.IsNullOrWhiteSpace(urlSegment)) urlSegment = n.UrlSegment; pathParts.Add(urlSegment); diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index 0c0308a471..1f7b54e232 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -209,33 +209,47 @@ namespace Umbraco.Web.Trees { result = Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray(); } - - //This should really never be null, but we'll error check anyways - culture = culture ?? Services.LocalizationService.GetDefaultLanguageIsoCode(); - - //Try to see if there is a variant name for the current language for the item and set the name accordingly. - //If any of this fails, the tree node name will remain the default invariant culture name. - - //fixme - what if there is no name found at all ? This could occur if the doc type is variant and the user fills in all language values, then creates a new lang and sets it as the default - //fixme - what if the user changes this document type to not allow culture variants after it's already been created with culture variants, this means we'll be displaying the culture variant name when in fact we should be displaying the invariant name... but that would be null - - if (!culture.IsNullOrWhiteSpace()) - { - foreach (var e in result) - { - if (e.AdditionalData.TryGetValue("CultureNames", out var cultureNames) - && cultureNames is IDictionary cnd) - { - if (cnd.TryGetValue(culture, out var name)) - { - e.Name = name; - } - } - } - } + + // should really never be null, but we'll error check anyways + culture = culture ?? Services.LocalizationService.GetDefaultLanguageIsoCode(); + + // set names according to variations + if (!culture.IsNullOrWhiteSpace()) + foreach (var entity in result) + EnsureName(entity, culture); return result; } + + // set name according to variations + // + private void EnsureName(IEntitySlim entity, string culture) + { + if (culture == null) + { + if (string.IsNullOrWhiteSpace(entity.Name)) + entity.Name = "[[" + entity.Id + "]]"; + return; + } + + // we are getting the tree for a given culture, + // for those items that DO support cultures, we need to get the proper name, IF it exists + // otherwise, invariant is fine + + if (entity.AdditionalData.TryGetValue(EntitySlim.AdditionalVariations, out var variationsObject) && + variationsObject is ContentVariation variations && + variations.Has(ContentVariation.CultureNeutral) && + entity.AdditionalData.TryGetValue(EntitySlim.AdditionalCultureNames, out var namesObject) && + namesObject is IDictionary names && + names.TryGetValue(culture, out var name) && + !string.IsNullOrWhiteSpace(name)) + { + entity.Name = name; + } + + if (string.IsNullOrWhiteSpace(entity.Name)) + entity.Name = "[[" + entity.Id + "]]"; + } /// /// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access