diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 6de1a9d909..815812279d 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -246,14 +246,17 @@ namespace Umbraco.Core.Models // clears all publish names private void ClearPublishNames() { + PublishName = null; _publishNames = null; - } + } + + /// + public bool IsCultureAvailable(int? languageId) + => !string.IsNullOrWhiteSpace(GetName(languageId)); /// public bool IsCulturePublished(int? languageId) - { - return !string.IsNullOrWhiteSpace(GetPublishName(languageId)); - } + => !string.IsNullOrWhiteSpace(GetPublishName(languageId)); [IgnoreDataMember] public int PublishedVersionId { get; internal set; } @@ -273,7 +276,8 @@ namespace Umbraco.Core.Models property.PublishAllValues(); // Name and PublishName are managed by the repository, but Names and PublishNames - // must be managed here as they depend on the existing / supported variations. + // must be managed here as they depend on the existing / supported variations. + PublishName = Name; foreach (var (languageId, name) in Names) SetPublishName(languageId, name); @@ -331,7 +335,7 @@ namespace Umbraco.Core.Models // Name and PublishName are managed by the repository, but Names and PublishNames // must be managed here as they depend on the existing / supported variations. - ClearPublishNames(); + ClearPublishNames(); _publishedState = PublishedState.Publishing; } diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 64144748e0..5b7e825d68 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -171,19 +171,6 @@ namespace Umbraco.Core.Models return content.PropertyTypes.Any(x => x.Variations == ContentVariation.CultureNeutral); } - /// - /// Returns true if the content has a variation for the language/segment combination - /// - /// - /// - /// - /// - public static bool HasVariation(this IContent content, int langId, string segment = null) - { - // fixme - wire - but: purpose? are we looking for a 'published' variation? what is this? - return false; - } - #endregion /// diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index a294040dbc..3f7a335620 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -84,8 +84,18 @@ namespace Umbraco.Core.Models /// Gets a value indicating whether a given culture is available. /// /// - /// A culture becomes available whenever values for this culture are published, - /// and it becomes unavailable whenever values for this culture are unpublished. + /// A culture becomes available whenever the content name for this culture is + /// non-null, and it becomes unavailable whenever the content name is null. + /// + bool IsCultureAvailable(int? languageId); + + /// + /// Gets a value indicating whether a given culture is published. + /// + /// + /// A culture becomes published whenever values for this culture are published, + /// and the content published name for this culture is non-null. It becomes non-published + /// whenever values for this culture are unpublished. /// bool IsCulturePublished(int? languageId); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 2a1aa5c403..8463010d0f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -344,7 +344,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (content.PublishedState == PublishedState.Publishing) { content.Published = true; - content.PublishName = content.Name; content.PublishTemplate = content.Template; content.PublisherId = content.WriterId; content.PublishDate = content.UpdateDate; @@ -354,7 +353,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishName = null; content.PublishTemplate = null; content.PublisherId = null; content.PublishDate = null; @@ -497,7 +495,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (content.PublishedState == PublishedState.Publishing) { content.Published = true; - content.PublishName = content.Name; content.PublishTemplate = content.Template; content.PublisherId = content.WriterId; content.PublishDate = content.UpdateDate; @@ -507,7 +504,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishName = null; content.PublishTemplate = null; content.PublisherId = null; content.PublishDate = null; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 723418ace1..88a3f7821d 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -2480,22 +2480,27 @@ namespace Umbraco.Tests.Services var languageService = ServiceContext.LocalizationService; var langFr = new Language("fr-FR"); - var langUk = new Language("en-UK"); + var langUk = new Language("en-UK"); + var langDe = new Language("de-DE"); languageService.Save(langFr); - languageService.Save(langUk); + languageService.Save(langUk); + languageService.Save(langDe); var contentTypeService = ServiceContext.ContentTypeService; var contentType = contentTypeService.Get("umbTextpage"); contentType.Variations = ContentVariation.CultureNeutral; - contentTypeService.Save(contentType); - + contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Nvarchar, "prop") { Variations = ContentVariation.CultureNeutral }); + contentTypeService.Save(contentType); + var contentService = ServiceContext.ContentService; var content = contentService.Create("Home US", - 1, "umbTextpage"); // act - content.SetValue("author", "Barack Obama"); + content.SetValue("author", "Barack Obama"); + content.SetValue("prop", "value-fr1", langFr.Id); + content.SetValue("prop", "value-uk1", langUk.Id); content.SetName(langFr.Id, "name-fr"); content.SetName(langUk.Id, "name-uk"); contentService.Save(content); @@ -2507,12 +2512,21 @@ namespace Umbraco.Tests.Services Assert.AreEqual("Home US", content2.Name); Assert.AreEqual("name-fr", content2.GetName(langFr.Id)); - Assert.AreEqual("name-uk", content2.GetName(langUk.Id)); + Assert.AreEqual("name-uk", content2.GetName(langUk.Id)); + + Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id)); + Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true)); + Assert.IsNull(content2.GetValue("prop", langUk.Id, published: true)); Assert.IsNull(content2.PublishName); Assert.IsNull(content2.GetPublishName(langFr.Id)); Assert.IsNull(content2.GetPublishName(langUk.Id)); + Assert.IsTrue(content.IsCultureAvailable(langFr.Id)); + Assert.IsTrue(content.IsCultureAvailable(langUk.Id)); + Assert.IsFalse(content.IsCultureAvailable(langDe.Id)); + Assert.IsFalse(content.IsCulturePublished(langFr.Id)); Assert.IsFalse(content.IsCulturePublished(langUk.Id)); @@ -2536,6 +2550,11 @@ namespace Umbraco.Tests.Services Assert.AreEqual("name-fr", content2.GetPublishName(langFr.Id)); Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); + Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id)); + Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id, published: true)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); + Assert.IsTrue(content.IsCulturePublished(langFr.Id)); Assert.IsTrue(content.IsCulturePublished(langUk.Id)); @@ -2544,6 +2563,9 @@ namespace Umbraco.Tests.Services content.SetName(null, "Home US2"); content.SetName(langFr.Id, "name-fr2"); content.SetName(langUk.Id, "name-uk2"); + content.SetValue("author", "Barack Obama2"); + content.SetValue("prop", "value-fr2", langFr.Id); + content.SetValue("prop", "value-uk2", langUk.Id); contentService.Save(content); // content has been saved, @@ -2558,7 +2580,15 @@ namespace Umbraco.Tests.Services Assert.AreEqual("Home US", content2.PublishName); Assert.AreEqual("name-fr", content2.GetPublishName(langFr.Id)); Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); + + Assert.AreEqual("Barack Obama2", content2.GetValue("author")); + Assert.IsNull(content2.GetValue("author", published: true)); // because, we never published the InvariantNeutral variation + Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id)); + Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id, published: true)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); + Assert.IsTrue(content.IsCulturePublished(langFr.Id)); Assert.IsTrue(content.IsCulturePublished(langUk.Id)); @@ -2577,10 +2607,15 @@ namespace Umbraco.Tests.Services Assert.AreEqual("name-fr2", content2.GetName(langFr.Id)); Assert.AreEqual("name-uk2", content2.GetName(langUk.Id)); - Assert.AreEqual("Home US2", content2.PublishName); // fixme why? -- and what about properties? + Assert.AreEqual("Home US2", content2.PublishName); // fixme why? -- and what about properties? -- we haven't published invariants?! Assert.IsNull(content2.GetPublishName(langFr.Id)); Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); + Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id)); + Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); + Assert.IsFalse(content.IsCulturePublished(langFr.Id)); Assert.IsTrue(content.IsCulturePublished(langUk.Id)); @@ -2592,7 +2627,14 @@ namespace Umbraco.Tests.Services // but properties, names, etc. retain their 'published' values so the content // can be re-published in its exact original state (before being unpublished) // - // fixme should PublishName, GetPublishName and IsCulturePublished check content.Published? + // BEWARE! + // in order for a content to be unpublished as a whole, and then republished in + // its exact previous state, properties and names etc. retain their published + // values even though the content is not published - hence many things being + // non-null or true below - always check against content.Published to be sure + + // FIXME + // still, we have some inconsistencies, publishName should go NULL when unpublishing it whole, see repository? content2 = contentService.GetById(content.Id); @@ -2606,6 +2648,11 @@ namespace Umbraco.Tests.Services Assert.IsNull(content2.GetPublishName(langFr.Id)); Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); // not null, see note above + Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id)); + Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); // has value, see note above + Assert.IsFalse(content.IsCulturePublished(langFr.Id)); Assert.IsTrue(content.IsCulturePublished(langUk.Id)); // still true, see note above @@ -2628,6 +2675,11 @@ namespace Umbraco.Tests.Services Assert.IsNull(content2.GetPublishName(langFr.Id)); Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); + Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id)); + Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id)); + Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true)); + Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); + Assert.IsFalse(content.IsCulturePublished(langFr.Id)); Assert.IsTrue(content.IsCulturePublished(langUk.Id)); } diff --git a/src/Umbraco.Web/Models/Mapping/VariationResolver.cs b/src/Umbraco.Web/Models/Mapping/VariationResolver.cs index 7106b58fbd..9d3de07d77 100644 --- a/src/Umbraco.Web/Models/Mapping/VariationResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/VariationResolver.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.Models.Mapping Language = x, Mandatory = x.Mandatory, Name = source.GetName(x.Id), - Exists = source.HasVariation(x.Id), // fixme - what's the purpose? "exists" or "published"? exists is a new thing? + Exists = source.IsCultureAvailable(x.Id), // segments ?? PublishedState = source.PublishedState.ToString(), //Segment = ?? We'll need to populate this one day when we support segments }).ToList();