Refactor content culture & variations
This commit is contained in:
@@ -225,7 +225,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
/// <inheritdoc/>
|
||||
[IgnoreDataMember]
|
||||
//public IReadOnlyDictionary<string, string> PublishNames => _publishNames ?? NoNames;
|
||||
public IReadOnlyDictionary<string, string> PublishNames => _publishInfos?.ToDictionary(x => x.Key, x => x.Value.Name) ?? NoNames;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -263,7 +262,7 @@ namespace Umbraco.Core.Models
|
||||
=> !string.IsNullOrWhiteSpace(GetPublishName(culture));
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime GetDateCulturePublished(string culture)
|
||||
public DateTime GetCulturePublishDate(string culture)
|
||||
{
|
||||
if (_publishInfos != null && _publishInfos.TryGetValue(culture, out var infos))
|
||||
return infos.Date;
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -25,7 +26,7 @@ namespace Umbraco.Core.Models
|
||||
protected IContentTypeComposition ContentTypeBase;
|
||||
private int _writerId;
|
||||
private PropertyCollection _properties;
|
||||
private Dictionary<string, string> _names;
|
||||
private Dictionary<string, (string Name, DateTime Date)> _cultureInfos;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentBase"/> class.
|
||||
@@ -139,16 +140,30 @@ namespace Umbraco.Core.Models
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public virtual IReadOnlyDictionary<string, string> Names
|
||||
{
|
||||
get => _names ?? NoNames;
|
||||
set
|
||||
{
|
||||
foreach (var (culture, name) in value)
|
||||
SetName(culture, name);
|
||||
}
|
||||
}
|
||||
public virtual IReadOnlyDictionary<string, string> Names => _cultureInfos?.ToDictionary(x => x.Key, x => x.Value.Name) ?? NoNames;
|
||||
|
||||
// sets culture infos
|
||||
// internal for repositories
|
||||
// clear by clearing name
|
||||
internal void SetCultureInfos(string culture, string name, DateTime date)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
|
||||
if (culture == null)
|
||||
{
|
||||
Name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
// private method, assume that culture is valid
|
||||
|
||||
if (_cultureInfos == null)
|
||||
_cultureInfos = new Dictionary<string, (string Name, DateTime Date)>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
_cultureInfos[culture] = (name, date);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SetName(string culture, string name)
|
||||
{
|
||||
@@ -166,11 +181,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
if (!ContentTypeBase.Variations.HasAny(ContentVariation.CultureNeutral | ContentVariation.CultureSegment))
|
||||
throw new NotSupportedException("Content type does not support varying name by culture.");
|
||||
|
||||
if (_cultureInfos == null)
|
||||
_cultureInfos = new Dictionary<string, (string Name, DateTime Date)>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (_names == null)
|
||||
_names = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
_names[culture] = name;
|
||||
_cultureInfos[culture] = (name, DateTime.Now) ;
|
||||
OnPropertyChanged(Ps.Value.NamesSelector);
|
||||
}
|
||||
|
||||
@@ -178,8 +193,8 @@ namespace Umbraco.Core.Models
|
||||
public virtual string GetName(string culture)
|
||||
{
|
||||
if (culture == null) return Name;
|
||||
if (_names == null) return null;
|
||||
return _names.TryGetValue(culture, out var name) ? name : null;
|
||||
if (_cultureInfos == null) return null;
|
||||
return _cultureInfos.TryGetValue(culture, out var infos) ? infos.Name : null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -194,17 +209,25 @@ namespace Umbraco.Core.Models
|
||||
return;
|
||||
}
|
||||
|
||||
if (_names == null) return;
|
||||
_names.Remove(culture);
|
||||
if (_names.Count == 0)
|
||||
_names = null;
|
||||
if (_cultureInfos == null) return;
|
||||
_cultureInfos.Remove(culture);
|
||||
if (_cultureInfos.Count == 0)
|
||||
_cultureInfos = null;
|
||||
}
|
||||
|
||||
protected virtual void ClearNames()
|
||||
{
|
||||
_names = null;
|
||||
_cultureInfos = null;
|
||||
OnPropertyChanged(Ps.Value.NamesSelector);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime GetCultureDate(string culture)
|
||||
{
|
||||
if (_cultureInfos != null && _cultureInfos.TryGetValue(culture, out var infos))
|
||||
return infos.Date;
|
||||
throw new InvalidOperationException($"Culture \"{culture}\" is not available.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Gets the date a culture was published.
|
||||
/// </summary>
|
||||
DateTime GetDateCulturePublished(string culture);
|
||||
DateTime GetCulturePublishDate(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicated whether a given culture is edited.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -46,13 +47,13 @@ namespace Umbraco.Core.Models
|
||||
string GetName(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the names of the content item.
|
||||
/// Gets the names of the content item.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get nor set the invariant
|
||||
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get the invariant
|
||||
/// name, which must be get or set via the <see cref="TreeEntityBase.Name"/> property.</para>
|
||||
/// </remarks>
|
||||
IReadOnlyDictionary<string, string> Names { get; set; }
|
||||
IReadOnlyDictionary<string, string> Names { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a given culture is available.
|
||||
@@ -63,6 +64,11 @@ namespace Umbraco.Core.Models
|
||||
/// </remarks>
|
||||
bool IsCultureAvailable(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date a culture was created.
|
||||
/// </summary>
|
||||
DateTime GetCultureDate(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// List of properties, which make up all the data available for this Content object
|
||||
/// </summary>
|
||||
|
||||
@@ -3,21 +3,6 @@ using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the culture specific data for a <see cref="IPublishedContent"/> item
|
||||
/// </summary>
|
||||
public struct PublishedCultureName
|
||||
{
|
||||
public PublishedCultureName(string name, string urlName) : this()
|
||||
{
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
UrlName = urlName ?? throw new ArgumentNullException(nameof(urlName));
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public string UrlName { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains culture specific values for <see cref="IPublishedContent"/>.
|
||||
/// </summary>
|
||||
@@ -945,7 +945,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
{
|
||||
if (contentVariations.TryGetValue(content.VersionId, out var contentVariation))
|
||||
foreach (var v in contentVariation)
|
||||
content.SetName(v.Culture, v.Name);
|
||||
content.SetCultureInfos(v.Culture, v.Name, v.Date);
|
||||
if (content.PublishedVersionId > 0 && contentVariations.TryGetValue(content.PublishedVersionId, out contentVariation))
|
||||
foreach (var v in contentVariation)
|
||||
content.SetPublishInfos(v.Culture, v.Name, v.Date);
|
||||
@@ -1028,7 +1028,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
|
||||
Culture = culture,
|
||||
Name = name,
|
||||
Date = content.UpdateDate
|
||||
Date = content.GetCultureDate(culture)
|
||||
};
|
||||
|
||||
// if not publishing, we're just updating the 'current' (non-published) version,
|
||||
@@ -1043,7 +1043,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
|
||||
Culture = culture,
|
||||
Name = name,
|
||||
Date = content.GetDateCulturePublished(culture)
|
||||
Date = content.GetCulturePublishDate(culture)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
<Compile Include="Models\PathValidationExtensions.cs" />
|
||||
<Compile Include="Models\Entities\TreeEntityBase.cs" />
|
||||
<Compile Include="Models\PropertyTagsExtensions.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedCultureName.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedCultureInfos.cs" />
|
||||
<Compile Include="Models\PublishedContent\IPublishedVariationContextAccessor.cs" />
|
||||
<Compile Include="Models\PublishedContent\IPublishedValueFallback.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedVariationContext.cs" />
|
||||
|
||||
@@ -336,19 +336,19 @@ namespace Umbraco.Tests.Models
|
||||
Assert.IsTrue(content.IsCultureAvailable(langFr));
|
||||
Assert.IsTrue(content.IsCulturePublished(langFr));
|
||||
Assert.AreEqual("name-fr", content.GetPublishName(langFr));
|
||||
Assert.AreNotEqual(DateTime.MinValue, content.GetDateCulturePublished(langFr));
|
||||
Assert.AreNotEqual(DateTime.MinValue, content.GetCulturePublishDate(langFr));
|
||||
Assert.IsFalse(content.IsCultureEdited(langFr)); // once published, edited is *wrong* until saved
|
||||
|
||||
Assert.IsTrue(content.IsCultureAvailable(langUk));
|
||||
Assert.IsFalse(content.IsCulturePublished(langUk));
|
||||
Assert.IsNull(content.GetPublishName(langUk));
|
||||
Assert.Throws<InvalidOperationException>(() => content.GetDateCulturePublished(langUk)); // not published!
|
||||
Assert.Throws<InvalidOperationException>(() => content.GetCulturePublishDate(langUk)); // not published!
|
||||
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
|
||||
|
||||
Assert.IsFalse(content.IsCultureAvailable(langEs));
|
||||
Assert.IsFalse(content.IsCulturePublished(langEs));
|
||||
Assert.IsNull(content.GetPublishName(langEs));
|
||||
Assert.Throws<InvalidOperationException>(() => content.GetDateCulturePublished(langEs)); // not published!
|
||||
Assert.Throws<InvalidOperationException>(() => content.GetCulturePublishDate(langEs)); // not published!
|
||||
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
|
||||
|
||||
// cannot test IsCultureEdited here - as that requires the content service and repository
|
||||
|
||||
@@ -14,11 +14,11 @@ using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Changes;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Stubs;
|
||||
using Umbraco.Tests.Testing.Objects.Accessors;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -34,7 +34,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
SettingsForTests.ConfigureSettings(SettingsForTests.GenerateMockUmbracoSettings());
|
||||
var globalSettings = UmbracoConfig.For.GlobalSettings();
|
||||
|
||||
// fixme - missing variant names here, and what else?
|
||||
var kit = new ContentNodeKit
|
||||
{
|
||||
ContentTypeId = 2,
|
||||
@@ -45,14 +44,26 @@ namespace Umbraco.Tests.PublishedContent
|
||||
new PropertyData { Value = "val2" },
|
||||
new PropertyData { Culture = "fr-FR", Value = "val-fr2" },
|
||||
new PropertyData { Culture = "en-UK", Value = "val-uk2" }
|
||||
} } } },
|
||||
} } },
|
||||
CultureInfos = new Dictionary<string, CultureVariation>
|
||||
{
|
||||
{ "fr-FR", new CultureVariation { Name = "name-fr2", Date = new DateTime(2018, 01, 03, 01, 00, 00) } },
|
||||
{ "en-UK", new CultureVariation { Name = "name-uk2", Date = new DateTime(2018, 01, 04, 01, 00, 00) } }
|
||||
}
|
||||
},
|
||||
PublishedData = new ContentData { Name="It Works1!", Published = true, TemplateId = 0, VersionId = 1, VersionDate = DateTime.Now, WriterId = 0,
|
||||
Properties = new Dictionary<string, PropertyData[]> { { "prop", new[]
|
||||
{
|
||||
new PropertyData { Value = "val1" },
|
||||
new PropertyData { Culture = "fr-FR", Value = "val-fr1" },
|
||||
new PropertyData { Culture = "en-UK", Value = "val-uk1" }
|
||||
} } } }
|
||||
} } },
|
||||
CultureInfos = new Dictionary<string, CultureVariation>
|
||||
{
|
||||
{ "fr-FR", new CultureVariation { Name = "name-fr1", Date = new DateTime(2018, 01, 01, 01, 00, 00) } },
|
||||
{ "en-UK", new CultureVariation { Name = "name-uk1", Date = new DateTime(2018, 01, 02, 01, 00, 00) } }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var dataSource = new TestDataSource(kit);
|
||||
@@ -78,18 +89,16 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
var contentTypeService = Mock.Of<IContentTypeService>();
|
||||
Mock.Get(contentTypeService).Setup(x => x.GetAll()).Returns(contentTypes);
|
||||
Mock.Get(contentTypeService).Setup(x => x.GetAll(It.IsAny<int[]>())).Returns(contentTypes);
|
||||
|
||||
var dataTypeService = Mock.Of<IDataTypeService>();
|
||||
Mock.Get(dataTypeService).Setup(x => x.GetAll()).Returns(dataTypes);
|
||||
|
||||
var serviceContext = new ServiceContext(
|
||||
dataTypeService : dataTypeService,
|
||||
|
||||
memberTypeService: Mock.Of<IMemberTypeService>(),
|
||||
memberService: Mock.Of<IMemberService>(),
|
||||
|
||||
contentTypeService : contentTypeService,
|
||||
|
||||
localizationService: Mock.Of<ILocalizationService>()
|
||||
);
|
||||
|
||||
@@ -117,9 +126,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
var variationAccessor = new TestPublishedVariationContextAccessor();
|
||||
|
||||
// invariant is the current default
|
||||
variationAccessor.Context = new PublishedVariationContext();
|
||||
|
||||
var options = new PublishedSnapshotService.Options { IgnoreLocalDb = true };
|
||||
var snapshotService = new PublishedSnapshotService(options,
|
||||
null,
|
||||
@@ -134,7 +140,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
documentRepository,
|
||||
mediaRepository,
|
||||
memberRepository,
|
||||
new TestSystemDefaultCultureAccessor(),
|
||||
new TestSystemDefaultCultureAccessor(),
|
||||
dataSource,
|
||||
globalSettings,
|
||||
new SiteDomainHelper());
|
||||
@@ -142,26 +148,59 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var snapshot = snapshotService.CreatePublishedSnapshot(previewToken: null);
|
||||
var publishedContent = snapshot.Content.GetById(1);
|
||||
|
||||
// invariant is the current default
|
||||
variationAccessor.Context = new PublishedVariationContext();
|
||||
|
||||
Assert.IsNotNull(publishedContent);
|
||||
Assert.AreEqual("It Works1!", publishedContent.Name);
|
||||
Assert.AreEqual("val1", publishedContent.Value<string>("prop"));
|
||||
Assert.AreEqual("val-fr1", publishedContent.Value<string>("prop", "fr-FR"));
|
||||
Assert.AreEqual("val-uk1", publishedContent.Value<string>("prop", "en-UK"));
|
||||
|
||||
Assert.AreEqual("name-fr1", publishedContent.GetCulture("fr-FR").Name);
|
||||
Assert.AreEqual("name-uk1", publishedContent.GetCulture("en-UK").Name);
|
||||
|
||||
var draftContent = snapshot.Content.GetById(true, 1);
|
||||
Assert.AreEqual("It Works2!", draftContent.Name);
|
||||
Assert.AreEqual("val2", draftContent.Value<string>("prop"));
|
||||
Assert.AreEqual("val-fr2", draftContent.Value<string>("prop", "fr-FR"));
|
||||
Assert.AreEqual("val-uk2", draftContent.Value<string>("prop", "en-UK"));
|
||||
|
||||
Assert.AreEqual("name-fr2", draftContent.GetCulture("fr-FR").Name);
|
||||
Assert.AreEqual("name-uk2", draftContent.GetCulture("en-UK").Name);
|
||||
|
||||
// now french is default
|
||||
variationAccessor.Context = new PublishedVariationContext("fr-FR");
|
||||
Assert.AreEqual("val-fr1", publishedContent.Value<string>("prop"));
|
||||
Assert.AreEqual("name-fr1", publishedContent.GetCulture().Name);
|
||||
Assert.AreEqual("name-fr1", publishedContent.Name);
|
||||
Assert.AreEqual(new DateTime(2018, 01, 01, 01, 00, 00), publishedContent.GetCulture().PublishedDate);
|
||||
|
||||
// now uk is default
|
||||
variationAccessor.Context = new PublishedVariationContext("en-UK");
|
||||
Assert.AreEqual("val-uk1", publishedContent.Value<string>("prop"));
|
||||
Assert.AreEqual("name-uk1", publishedContent.GetCulture().Name);
|
||||
Assert.AreEqual("name-uk1", publishedContent.Name);
|
||||
Assert.AreEqual(new DateTime(2018, 01, 02, 01, 00, 00), publishedContent.GetCulture().PublishedDate);
|
||||
|
||||
// invariant needs to be retrieved explicitely, when it's not default
|
||||
Assert.AreEqual("val1", publishedContent.Value<string>("prop", culture: null));
|
||||
|
||||
// but,
|
||||
// if the content type / property type does not vary, then it's all invariant again
|
||||
contentType.Variations = ContentVariation.InvariantNeutral;
|
||||
propertyType.Variations = ContentVariation.InvariantNeutral;
|
||||
snapshotService.Notify(new[] { new ContentTypeCacheRefresher.JsonPayload("IContentType", publishedContent.ContentType.Id, ContentTypeChangeTypes.RefreshMain) });
|
||||
|
||||
var anotherSnapshot = snapshotService.CreatePublishedSnapshot(previewToken: null);
|
||||
var againContent = anotherSnapshot.Content.GetById(1);
|
||||
|
||||
Assert.AreEqual(ContentVariation.InvariantNeutral, againContent.ContentType.Variations);
|
||||
Assert.AreEqual(ContentVariation.InvariantNeutral, againContent.ContentType.GetPropertyType("prop").Variations);
|
||||
|
||||
Assert.AreEqual("It Works1!", againContent.Name);
|
||||
Assert.AreEqual("val1", againContent.Value<string>("prop"));
|
||||
|
||||
// then, test fallback
|
||||
}
|
||||
|
||||
|
||||
@@ -2583,8 +2583,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
|
||||
// note that content and content2 culture published dates might be slightly different due to roundtrip to database
|
||||
|
||||
@@ -2644,8 +2644,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
|
||||
|
||||
|
||||
// act
|
||||
@@ -2687,8 +2687,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
|
||||
|
||||
// act
|
||||
@@ -2734,8 +2734,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
|
||||
|
||||
// act
|
||||
@@ -2774,8 +2774,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
|
||||
|
||||
// act
|
||||
@@ -2797,8 +2797,8 @@ namespace Umbraco.Tests.Services
|
||||
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
|
||||
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
|
||||
|
||||
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
AssertPerCulture(content2, (x, c) => x.GetCulturePublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
|
||||
|
||||
|
||||
// act
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
for (var i = 0; i < pcount; i++)
|
||||
{
|
||||
var languageId = PrimitiveSerializer.String.ReadFrom(stream);
|
||||
var cultureVariation = new CultureVariation { Name = ReadStringObject(stream) };
|
||||
var cultureVariation = new CultureVariation { Name = ReadStringObject(stream), Date = ReadDateTime(stream) };
|
||||
dict[languageId] = cultureVariation;
|
||||
}
|
||||
return dict;
|
||||
@@ -40,6 +40,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
|
||||
PrimitiveSerializer.String.WriteTo(culture, stream); // should never be null
|
||||
WriteObject(variation.Name, stream); // write an object in case it's null (though... should not happen)
|
||||
PrimitiveSerializer.DateTime.WriteTo(variation.Date, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,18 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
// represents everything that is specific to edited or published version
|
||||
internal class ContentData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int VersionId { get; set; }
|
||||
public DateTime VersionDate { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int TemplateId { get; set; }
|
||||
public bool Published { get; set; }
|
||||
|
||||
public IDictionary<string, PropertyData[]> Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The collection of language Id to name for the content item
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, CultureVariation> CultureInfos { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public int VersionId { get; set; }
|
||||
//TODO: This will not make a lot of sense since we'll have dates for each variant publishing, need to wait on Stephane
|
||||
public DateTime VersionDate { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int TemplateId { get; set; }
|
||||
|
||||
public IDictionary<string, PropertyData[]> Properties { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
@@ -10,6 +11,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
//TODO: We may want some date stamps here
|
||||
[JsonProperty("date")]
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
@@ -19,6 +21,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private readonly bool _isPreviewing;
|
||||
private readonly bool _isMember;
|
||||
private readonly PublishedContent _content;
|
||||
private readonly ContentVariation _variations;
|
||||
|
||||
private readonly object _locko = new object();
|
||||
|
||||
@@ -68,6 +71,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_isPreviewing = content.IsPreviewing;
|
||||
_isMember = content.ContentType.ItemType == PublishedItemType.Member;
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
_variations = propertyType.Variations;
|
||||
}
|
||||
|
||||
// clone for previewing as draft a published content that is published and has no draft
|
||||
@@ -82,6 +86,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_isPreviewing = true;
|
||||
_isMember = origin._isMember;
|
||||
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
|
||||
_variations = origin._variations;
|
||||
}
|
||||
|
||||
public override bool HasValue(string culture = ".", string segment = ".") => _sourceValue != null
|
||||
@@ -185,9 +190,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (culture != "." && segment != ".") return;
|
||||
|
||||
// use context values
|
||||
// fixme CultureSegment?
|
||||
var publishedVariationContext = _content.VariationContextAccessor?.Context;
|
||||
if (culture == ".") culture = publishedVariationContext?.Culture;
|
||||
if (segment == ".") segment = publishedVariationContext?.Segment;
|
||||
if (culture == ".") culture = _variations.Has(ContentVariation.CultureNeutral) ? publishedVariationContext?.Culture : null;
|
||||
if (segment == ".") segment = _variations.Has(ContentVariation.CultureNeutral) ? publishedVariationContext?.Segment : null;
|
||||
}
|
||||
|
||||
public override object GetValue(string culture = ".", string segment = ".")
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
internal readonly ContentData _contentData; // internal for ContentNode cloning
|
||||
|
||||
private readonly string _urlSegment;
|
||||
private IReadOnlyDictionary<string, PublishedCultureName> _cultureNames;
|
||||
|
||||
#region Constructors
|
||||
|
||||
@@ -265,7 +264,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (_cultureInfos != null) return _cultureInfos;
|
||||
|
||||
return _cultureInfos = _contentData.CultureInfos // fixme can it be null?
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfos(x.Key, x.Value.Name, false, DateTime.MinValue)); // fixme values!
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfos(x.Key, x.Value.Name, false, x.Value.Date)); // fixme values!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -722,7 +722,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
Notify<IContentType>(_contentStore, payloads, RefreshContentTypesLocked);
|
||||
Notify<IMediaType>(_mediaStore, payloads, RefreshMediaTypesLocked);
|
||||
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync(); // fixme all
|
||||
}
|
||||
|
||||
private void Notify<T>(ContentStore store, ContentTypeCacheRefresher.JsonPayload[] payloads, Action<IEnumerable<int>, IEnumerable<int>, IEnumerable<int>, IEnumerable<int>> action)
|
||||
@@ -799,7 +799,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync(); // fixme elsewhere!
|
||||
}
|
||||
|
||||
public override void Notify(DomainCacheRefresher.JsonPayload[] payloads)
|
||||
@@ -900,8 +900,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// contentStore is wlocked (so readable, only no new views)
|
||||
// and it can be wlocked by 1 thread only at a time
|
||||
|
||||
if (!(_serviceContext.ContentService is ContentService))
|
||||
throw new Exception("oops");
|
||||
// fixme wtf?
|
||||
//if (!(_serviceContext.ContentService is ContentService))
|
||||
// throw new Exception("oops");
|
||||
|
||||
var refreshedIdsA = refreshedIds.ToArray();
|
||||
|
||||
@@ -1219,7 +1220,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
var cultureData = new Dictionary<string, CultureVariation>();
|
||||
|
||||
// fixme refactor!!!
|
||||
var names = content is IContent document
|
||||
? (published
|
||||
? document.PublishNames
|
||||
@@ -1228,7 +1228,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
foreach (var (culture, name) in names)
|
||||
{
|
||||
cultureData[culture] = new CultureVariation { Name = name };
|
||||
cultureData[culture] = new CultureVariation { Name = name, Date = content.GetCultureDate(culture) };
|
||||
}
|
||||
|
||||
//the dictionary that will be serialized
|
||||
|
||||
@@ -408,7 +408,6 @@ namespace umbraco
|
||||
private readonly PublishedContentType _contentType;
|
||||
private readonly IPublishedProperty[] _properties;
|
||||
private readonly IPublishedContent _parent;
|
||||
private IReadOnlyDictionary<string, PublishedCultureName> _cultureNames;
|
||||
private IReadOnlyDictionary<string, PublishedCultureInfos> _cultureInfos;
|
||||
private readonly IPublishedVariationContextAccessor _variationContextAccessor;
|
||||
|
||||
@@ -500,8 +499,8 @@ namespace umbraco
|
||||
if (_cultureInfos != null)
|
||||
return _cultureInfos;
|
||||
|
||||
return _cultureInfos = _inner.Names
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfos(x.Key, x.Value, false, DateTime.MinValue)); // fixme values!
|
||||
return _cultureInfos = _inner.Names // fixme names, or PublishNames?
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfos(x.Key, x.Value, false, _inner.GetCulturePublishDate(x.Key))); // fixme values!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user