Updates the caching layer to handle GUID keys for content types while preserving backwards compat, fixes unit tests, removes the strongly typed lists for the block editor value since it's unecessary
This commit is contained in:
@@ -1,7 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an <see cref="IPublishedElement"/> type.
|
||||
/// </summary>
|
||||
/// <remarks>Instances implementing the <see cref="IPublishedContentType"/> interface should be
|
||||
/// immutable, ie if the content type changes, then a new instance needs to be created.</remarks>
|
||||
public interface IPublishedContentType2 : IPublishedContentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique key for the content type.
|
||||
/// </summary>
|
||||
Guid Key { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an <see cref="IPublishedElement"/> type.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco. Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates published content types.
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides the published model creation service.
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides strongly typed published content models services.
|
||||
/// </summary>
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </summary>
|
||||
/// <remarks>Instances of the <see cref="PublishedContentType"/> class are immutable, ie
|
||||
/// if the content type changes, then a new class needs to be created.</remarks>
|
||||
public class PublishedContentType : IPublishedContentType
|
||||
public class PublishedContentType : IPublishedContentType2
|
||||
{
|
||||
private readonly IPublishedPropertyType[] _propertyTypes;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// Initializes a new instance of the <see cref="PublishedContentType"/> class with a content type.
|
||||
/// </summary>
|
||||
public PublishedContentType(IContentTypeComposition contentType, IPublishedContentTypeFactory factory)
|
||||
: this(contentType.Id, contentType.Alias, contentType.GetItemType(), contentType.CompositionAliases(), contentType.Variations, contentType.IsElement)
|
||||
: this(contentType.Key, contentType.Id, contentType.Alias, contentType.GetItemType(), contentType.CompositionAliases(), contentType.Variations, contentType.IsElement)
|
||||
{
|
||||
var propertyTypes = contentType.CompositionPropertyTypes
|
||||
.Select(x => factory.CreatePropertyType(this, x))
|
||||
@@ -40,8 +40,20 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <remarks>
|
||||
/// <para>Values are assumed to be consistent and are not checked.</para>
|
||||
/// </remarks>
|
||||
public PublishedContentType(Guid key, int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes, ContentVariation variations, bool isElement = false)
|
||||
: this(key, id, alias, itemType, compositionAliases, variations, isElement)
|
||||
{
|
||||
var propertyTypesA = propertyTypes.ToArray();
|
||||
foreach (var propertyType in propertyTypesA)
|
||||
propertyType.ContentType = this;
|
||||
_propertyTypes = propertyTypesA;
|
||||
|
||||
InitializeIndexes();
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload specifying a key instead")]
|
||||
public PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes, ContentVariation variations, bool isElement = false)
|
||||
: this (id, alias, itemType, compositionAliases, variations, isElement)
|
||||
: this (Guid.Empty, id, alias, itemType, compositionAliases, variations, isElement)
|
||||
{
|
||||
var propertyTypesA = propertyTypes.ToArray();
|
||||
foreach (var propertyType in propertyTypesA)
|
||||
@@ -57,16 +69,26 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <remarks>
|
||||
/// <para>Values are assumed to be consistent and are not checked.</para>
|
||||
/// </remarks>
|
||||
public PublishedContentType(Guid key, int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations, bool isElement = false)
|
||||
: this(key, id, alias, itemType, compositionAliases, variations, isElement)
|
||||
{
|
||||
_propertyTypes = propertyTypes(this).ToArray();
|
||||
|
||||
InitializeIndexes();
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload specifying a key instead")]
|
||||
public PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations, bool isElement = false)
|
||||
: this(id, alias, itemType, compositionAliases, variations, isElement)
|
||||
: this(Guid.Empty, id, alias, itemType, compositionAliases, variations, isElement)
|
||||
{
|
||||
_propertyTypes = propertyTypes(this).ToArray();
|
||||
|
||||
InitializeIndexes();
|
||||
}
|
||||
|
||||
private PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, ContentVariation variations, bool isElement)
|
||||
private PublishedContentType(Guid key, int id, string alias, PublishedItemType itemType, IEnumerable<string> compositionAliases, ContentVariation variations, bool isElement)
|
||||
{
|
||||
Key = key;
|
||||
Id = id;
|
||||
Alias = alias;
|
||||
ItemType = itemType;
|
||||
@@ -116,6 +138,9 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
|
||||
#region Content type
|
||||
|
||||
/// <inheritdoc />
|
||||
public Guid Key { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Id { get; }
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
public static class PublishedContentTypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the GUID key from an <see cref="IPublishedContentType"/>
|
||||
/// </summary>
|
||||
/// <param name="publishedContentType"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryGetKey(this IPublishedContentType publishedContentType, out Guid key)
|
||||
{
|
||||
if (publishedContentType is IPublishedContentType2 contentTypeWithKey)
|
||||
{
|
||||
key = contentTypeWithKey.Key;
|
||||
return true;
|
||||
}
|
||||
key = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,18 +35,18 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// This method is for tests and is not intended to be used directly from application code.
|
||||
/// </summary>
|
||||
/// <remarks>Values are assumed to be consisted and are not checked.</remarks>
|
||||
internal IPublishedContentType CreateContentType(int id, string alias, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations = ContentVariation.Nothing, bool isElement = false)
|
||||
internal IPublishedContentType CreateContentType(Guid key, int id, string alias, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations = ContentVariation.Nothing, bool isElement = false)
|
||||
{
|
||||
return new PublishedContentType(id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, variations, isElement);
|
||||
return new PublishedContentType(key, id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, variations, isElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is for tests and is not intended to be used directly from application code.
|
||||
/// </summary>
|
||||
/// <remarks>Values are assumed to be consisted and are not checked.</remarks>
|
||||
internal IPublishedContentType CreateContentType(int id, string alias, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations = ContentVariation.Nothing, bool isElement = false)
|
||||
internal IPublishedContentType CreateContentType(Guid key, int id, string alias, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes, ContentVariation variations = ContentVariation.Nothing, bool isElement = false)
|
||||
{
|
||||
return new PublishedContentType(id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, variations, isElement);
|
||||
return new PublishedContentType(key, id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, variations, isElement);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
<Compile Include="Models\ContentDataIntegrityReportEntry.cs" />
|
||||
<Compile Include="Models\ContentDataIntegrityReportOptions.cs" />
|
||||
<Compile Include="Models\InstallLog.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentTypeExtensions.cs" />
|
||||
<Compile Include="Models\RelationTypeExtensions.cs" />
|
||||
<Compile Include="Persistence\Repositories\IInstallationRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\Implement\InstallationRepository.cs" />
|
||||
|
||||
@@ -42,9 +42,9 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
var type = new AutoPublishedContentType(22, "myType", new PublishedPropertyType[] { });
|
||||
var image = new AutoPublishedContentType(23, "Image", new PublishedPropertyType[] { });
|
||||
var testMediaType = new AutoPublishedContentType(24, "TestMediaType", new PublishedPropertyType[] { });
|
||||
var type = new AutoPublishedContentType(Guid.NewGuid(), 22, "myType", new PublishedPropertyType[] { });
|
||||
var image = new AutoPublishedContentType(Guid.NewGuid(), 23, "Image", new PublishedPropertyType[] { });
|
||||
var testMediaType = new AutoPublishedContentType(Guid.NewGuid(), 24, "TestMediaType", new PublishedPropertyType[] { });
|
||||
_mediaTypes = new Dictionary<string, PublishedContentType>
|
||||
{
|
||||
{ type.Alias, type },
|
||||
|
||||
@@ -14,7 +14,7 @@ using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
{
|
||||
internal class PublishedContentCache : PublishedCacheBase, IPublishedContentCache
|
||||
internal class PublishedContentCache : PublishedCacheBase, IPublishedContentCache2
|
||||
{
|
||||
private readonly IAppCache _appCache;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
@@ -532,15 +532,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
|
||||
#region Content types
|
||||
|
||||
public override IPublishedContentType GetContentType(int id)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Content, id);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(int id) => _contentTypeCache.Get(PublishedItemType.Content, id);
|
||||
|
||||
public override IPublishedContentType GetContentType(string alias)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Content, alias);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(string alias) => _contentTypeCache.Get(PublishedItemType.Content, alias);
|
||||
|
||||
public override IPublishedContentType GetContentType(Guid key) => _contentTypeCache.Get(PublishedItemType.Content, key);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
/// <remarks>
|
||||
/// NOTE: In the future if we want to properly cache all media this class can be extended or replaced when these classes/interfaces are exposed publicly.
|
||||
/// </remarks>
|
||||
internal class PublishedMediaCache : PublishedCacheBase, IPublishedMediaCache
|
||||
internal class PublishedMediaCache : PublishedCacheBase, IPublishedMediaCache2
|
||||
{
|
||||
private readonly IMediaService _mediaService;
|
||||
private readonly IUserService _userService;
|
||||
@@ -612,15 +612,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
|
||||
#region Content types
|
||||
|
||||
public override IPublishedContentType GetContentType(int id)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Media, id);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(int id) => _contentTypeCache.Get(PublishedItemType.Media, id);
|
||||
|
||||
public override IPublishedContentType GetContentType(string alias)
|
||||
{
|
||||
return _contentTypeCache.Get(PublishedItemType.Media, alias);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(string alias) => _contentTypeCache.Get(PublishedItemType.Media, alias);
|
||||
|
||||
public override IPublishedContentType GetContentType(Guid key) => _contentTypeCache.Get(PublishedItemType.Media, key);
|
||||
|
||||
public override IEnumerable<IPublishedContent> GetByContentType(IPublishedContentType contentType)
|
||||
{
|
||||
|
||||
@@ -18,21 +18,28 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
[TestFixture]
|
||||
public class BlockListPropertyValueConverterTests
|
||||
{
|
||||
private readonly Guid Key1 = Guid.NewGuid();
|
||||
private readonly Guid Key2 = Guid.NewGuid();
|
||||
private readonly string Alias1 = "Test1";
|
||||
private readonly string Alias2 = "Test2";
|
||||
|
||||
/// <summary>
|
||||
/// Setup mocks for IPublishedSnapshotAccessor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IPublishedSnapshotAccessor GetPublishedSnapshotAccessor()
|
||||
{
|
||||
var test1ContentType = Mock.Of<IPublishedContentType>(x =>
|
||||
var test1ContentType = Mock.Of<IPublishedContentType2>(x =>
|
||||
x.IsElement == true
|
||||
&& x.Alias == "Test1");
|
||||
var test2ContentType = Mock.Of<IPublishedContentType>(x =>
|
||||
&& x.Key == Key1
|
||||
&& x.Alias == Alias1);
|
||||
var test2ContentType = Mock.Of<IPublishedContentType2>(x =>
|
||||
x.IsElement == true
|
||||
&& x.Alias == "Test2");
|
||||
var contentCache = new Mock<IPublishedContentCache>();
|
||||
contentCache.Setup(x => x.GetContentType("Test1")).Returns(test1ContentType);
|
||||
contentCache.Setup(x => x.GetContentType("Test2")).Returns(test2ContentType);
|
||||
&& x.Key == Key2
|
||||
&& x.Alias == Alias2);
|
||||
var contentCache = new Mock<IPublishedContentCache2>();
|
||||
contentCache.Setup(x => x.GetContentType(Key1)).Returns(test1ContentType);
|
||||
contentCache.Setup(x => x.GetContentType(Key2)).Returns(test2ContentType);
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshot>(x => x.Content == contentCache.Object);
|
||||
var publishedSnapshotAccessor = Mock.Of<IPublishedSnapshotAccessor>(x => x.PublishedSnapshot == publishedSnapshot);
|
||||
return publishedSnapshotAccessor;
|
||||
@@ -44,7 +51,6 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
var publishedModelFactory = new NoopPublishedModelFactory();
|
||||
var editor = new BlockListPropertyValueConverter(
|
||||
Mock.Of<IProfilingLogger>(),
|
||||
publishedModelFactory,
|
||||
new BlockEditorConverter(publishedSnapshotAccessor, publishedModelFactory));
|
||||
return editor;
|
||||
}
|
||||
@@ -54,11 +60,11 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
Blocks = new[] {
|
||||
new BlockListConfiguration.BlockConfiguration
|
||||
{
|
||||
Alias = "Test1"
|
||||
Key = Key1
|
||||
},
|
||||
new BlockListConfiguration.BlockConfiguration
|
||||
{
|
||||
Alias = "Test2"
|
||||
Key = Key2
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -68,7 +74,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
Blocks = new[] {
|
||||
new BlockListConfiguration.BlockConfiguration
|
||||
{
|
||||
Alias = "Test1"
|
||||
Key = Key1
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -101,7 +107,8 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
var valueType = editor.GetPropertyValueType(propType);
|
||||
|
||||
Assert.AreEqual(typeof(IEnumerable<IPublishedElement>), valueType);
|
||||
// the result is always block list model
|
||||
Assert.AreEqual(typeof(BlockListModel), valueType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -115,10 +122,8 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
var valueType = editor.GetPropertyValueType(propType);
|
||||
|
||||
var modelType = typeof(IEnumerable<>).MakeGenericType(ModelType.For(config.Blocks[0].Alias));
|
||||
|
||||
// we can't compare the exact match of types because ModelType.For generates a new/different type even if the same alias is used
|
||||
Assert.AreEqual(modelType.FullName, valueType.FullName);
|
||||
// the result is always block list model
|
||||
Assert.AreEqual(typeof(BlockListModel), valueType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -225,7 +230,7 @@ data: []}";
|
||||
},
|
||||
data: [
|
||||
{
|
||||
'contentTypeAlias': 'home',
|
||||
'contentTypeKey': '" + Key1 + @"',
|
||||
'key': '1304E1DD-0000-4396-84FE-8A399231CB3D'
|
||||
}
|
||||
]
|
||||
@@ -258,7 +263,7 @@ data: []}";
|
||||
},
|
||||
data: [
|
||||
{
|
||||
'contentTypeAlias': 'Test1',
|
||||
'contentTypeKey': '" + Key1 + @"',
|
||||
'udi': 'umb://element/1304E1DDAC87439684FE8A399231CB3D'
|
||||
}
|
||||
]
|
||||
@@ -300,15 +305,15 @@ data: []}";
|
||||
},
|
||||
data: [
|
||||
{
|
||||
'contentTypeAlias': 'Test1',
|
||||
'contentTypeKey': '" + Key1 + @"',
|
||||
'udi': 'umb://element/1304E1DDAC87439684FE8A399231CB3D'
|
||||
},
|
||||
{
|
||||
'contentTypeAlias': 'Test2',
|
||||
'contentTypeKey': '" + Key2 + @"',
|
||||
'udi': 'umb://element/E05A034704424AB3A520E048E6197E79'
|
||||
},
|
||||
{
|
||||
'contentTypeAlias': 'Test2',
|
||||
'contentTypeKey': '" + Key2 + @"',
|
||||
'udi': 'umb://element/0A4A416E547D464FABCC6F345C17809A'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
})));
|
||||
|
||||
var publishedPropType = new PublishedPropertyType(
|
||||
new PublishedContentType(1234, "test", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing),
|
||||
new PublishedContentType(Guid.NewGuid(), 1234, "test", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing),
|
||||
new PropertyType("test", ValueStorageType.Nvarchar) { DataTypeId = 123 },
|
||||
new PropertyValueConverterCollection(Enumerable.Empty<IPropertyValueConverter>()),
|
||||
Mock.Of<IPublishedModelFactory>(), mockPublishedContentTypeFactory.Object);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.Published
|
||||
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var elementType1 = contentTypeFactory.CreateContentType(1000, "element1", CreatePropertyTypes);
|
||||
var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
|
||||
|
||||
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Umbraco.Tests.Published
|
||||
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
|
||||
|
||||
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
|
||||
=> typeof (int);
|
||||
=> typeof(int);
|
||||
|
||||
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
@@ -83,10 +83,10 @@ namespace Umbraco.Tests.Published
|
||||
=> int.TryParse(source as string, out int i) ? i : 0;
|
||||
|
||||
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
=> (int) inter;
|
||||
=> (int)inter;
|
||||
|
||||
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
=> ((int) inter).ToString();
|
||||
=> ((int)inter).ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -120,11 +120,11 @@ namespace Umbraco.Tests.Published
|
||||
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var elementType1 = contentTypeFactory.CreateContentType(1000, "element1", CreatePropertyTypes);
|
||||
var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
|
||||
|
||||
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
|
||||
|
||||
var cntType1 = contentTypeFactory.CreateContentType(1001, "cnt1", t => Enumerable.Empty<PublishedPropertyType>());
|
||||
var cntType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "cnt1", t => Enumerable.Empty<PublishedPropertyType>());
|
||||
var cnt1 = new SolidPublishedContent(cntType1) { Id = 1234 };
|
||||
cacheContent[cnt1.Id] = cnt1;
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Umbraco.Tests.Published
|
||||
}
|
||||
|
||||
public bool? IsValue(object value, PropertyValueLevel level)
|
||||
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false);
|
||||
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false);
|
||||
|
||||
public bool IsConverter(IPublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
|
||||
@@ -162,10 +162,10 @@ namespace Umbraco.Tests.Published
|
||||
=> int.TryParse(source as string, out int i) ? i : -1;
|
||||
|
||||
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
=> _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById((int) inter);
|
||||
=> _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById((int)inter);
|
||||
|
||||
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
=> ((int) inter).ToString();
|
||||
=> ((int)inter).ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -215,10 +215,10 @@ namespace Umbraco.Tests.Published
|
||||
yield return contentTypeFactory.CreatePropertyType(contentType, "prop" + i, i);
|
||||
}
|
||||
|
||||
var elementType1 = contentTypeFactory.CreateContentType(1000, "element1", t => CreatePropertyTypes(t, 1));
|
||||
var elementType2 = contentTypeFactory.CreateContentType(1001, "element2", t => CreatePropertyTypes(t, 2));
|
||||
var contentType1 = contentTypeFactory.CreateContentType(1002, "content1", t => CreatePropertyTypes(t, 1));
|
||||
var contentType2 = contentTypeFactory.CreateContentType(1003, "content2", t => CreatePropertyTypes(t, 2));
|
||||
var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", t => CreatePropertyTypes(t, 1));
|
||||
var elementType2 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "element2", t => CreatePropertyTypes(t, 2));
|
||||
var contentType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1002, "content1", t => CreatePropertyTypes(t, 1));
|
||||
var contentType2 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1003, "content2", t => CreatePropertyTypes(t, 2));
|
||||
|
||||
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
|
||||
var element2 = new PublishedElement(elementType2, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
|
||||
@@ -239,22 +239,22 @@ namespace Umbraco.Tests.Published
|
||||
// can get the actual property Clr type
|
||||
// ie ModelType gets properly mapped by IPublishedContentModelFactory
|
||||
// must test ModelClrType with special equals 'cos they are not ref-equals
|
||||
Assert.IsTrue(ModelType.Equals(typeof (IEnumerable<>).MakeGenericType(ModelType.For("content1")), contentType2.GetPropertyType("prop2").ModelClrType));
|
||||
Assert.AreEqual(typeof (IEnumerable<PublishedSnapshotTestObjects.TestContentModel1>), contentType2.GetPropertyType("prop2").ClrType);
|
||||
Assert.IsTrue(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("content1")), contentType2.GetPropertyType("prop2").ModelClrType));
|
||||
Assert.AreEqual(typeof(IEnumerable<PublishedSnapshotTestObjects.TestContentModel1>), contentType2.GetPropertyType("prop2").ClrType);
|
||||
|
||||
// can create a model for an element
|
||||
var model1 = factory.CreateModel(element1);
|
||||
Assert.IsInstanceOf<PublishedSnapshotTestObjects.TestElementModel1>(model1);
|
||||
Assert.AreEqual("val1", ((PublishedSnapshotTestObjects.TestElementModel1) model1).Prop1);
|
||||
Assert.AreEqual("val1", ((PublishedSnapshotTestObjects.TestElementModel1)model1).Prop1);
|
||||
|
||||
// can create a model for a published content
|
||||
var model2 = factory.CreateModel(element2);
|
||||
Assert.IsInstanceOf<PublishedSnapshotTestObjects.TestElementModel2>(model2);
|
||||
var mmodel2 = (PublishedSnapshotTestObjects.TestElementModel2) model2;
|
||||
var mmodel2 = (PublishedSnapshotTestObjects.TestElementModel2)model2;
|
||||
|
||||
// and get direct property
|
||||
Assert.IsInstanceOf<PublishedSnapshotTestObjects.TestContentModel1[]>(model2.Value("prop2"));
|
||||
Assert.AreEqual(1, ((PublishedSnapshotTestObjects.TestContentModel1[]) model2.Value("prop2")).Length);
|
||||
Assert.AreEqual(1, ((PublishedSnapshotTestObjects.TestContentModel1[])model2.Value("prop2")).Length);
|
||||
|
||||
// and get model property
|
||||
Assert.IsInstanceOf<IEnumerable<PublishedSnapshotTestObjects.TestContentModel1>>(mmodel2.Prop2);
|
||||
@@ -271,7 +271,7 @@ namespace Umbraco.Tests.Published
|
||||
=> propertyType.EditorAlias == "Umbraco.Void";
|
||||
|
||||
public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
|
||||
=> typeof (string);
|
||||
=> typeof(string);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
@@ -290,7 +290,7 @@ namespace Umbraco.Tests.Published
|
||||
=> propertyType.EditorAlias == "Umbraco.Void.2";
|
||||
|
||||
public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
|
||||
=> typeof (IEnumerable<>).MakeGenericType(ModelType.For("content1"));
|
||||
=> typeof(IEnumerable<>).MakeGenericType(ModelType.For("content1"));
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Elements;
|
||||
@@ -303,7 +303,7 @@ namespace Umbraco.Tests.Published
|
||||
|
||||
public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
{
|
||||
return ((int[]) inter).Select(x => (PublishedSnapshotTestObjects.TestContentModel1) _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(x)).ToArray();
|
||||
return ((int[])inter).Select(x => (PublishedSnapshotTestObjects.TestContentModel1)_publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(x)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,9 +144,9 @@ namespace Umbraco.Tests.Published
|
||||
yield return factory.CreatePropertyType(contentType, "propertyN1", 3);
|
||||
}
|
||||
|
||||
var contentType1 = factory.CreateContentType(1, "content1", CreatePropertyTypes1);
|
||||
var contentType2 = factory.CreateContentType(2, "content2", CreatePropertyTypes2);
|
||||
var contentTypeN1 = factory.CreateContentType(2, "contentN1", CreatePropertyTypesN1, isElement: true);
|
||||
var contentType1 = factory.CreateContentType(Guid.NewGuid(), 1, "content1", CreatePropertyTypes1);
|
||||
var contentType2 = factory.CreateContentType(Guid.NewGuid(), 2, "content2", CreatePropertyTypes2);
|
||||
var contentTypeN1 = factory.CreateContentType(Guid.NewGuid(), 2, "contentN1", CreatePropertyTypesN1, isElement: true);
|
||||
|
||||
// mocked content cache returns content types
|
||||
contentCache
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Tests.Published
|
||||
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes);
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
|
||||
|
||||
// PublishedElementPropertyBase.GetCacheLevels:
|
||||
//
|
||||
@@ -122,7 +122,7 @@ namespace Umbraco.Tests.Published
|
||||
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes);
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
|
||||
|
||||
var elementsCache = new FastDictionaryAppCache();
|
||||
var snapshotCache = new FastDictionaryAppCache();
|
||||
@@ -199,7 +199,7 @@ namespace Umbraco.Tests.Published
|
||||
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes);
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
|
||||
|
||||
Assert.Throws<Exception>(() =>
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var doc = GetContent(true, 1);
|
||||
//change a doc type alias
|
||||
var c = (SolidPublishedContent)doc.Children.ElementAt(0);
|
||||
c.ContentType = new PublishedContentType(22, "DontMatch", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
c.ContentType = new PublishedContentType(Guid.NewGuid(), 22, "DontMatch", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
|
||||
var dt = doc.ChildrenAsTable(Current.Services, "Child");
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
var factory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty<IPropertyValueConverter>()), dataTypeService);
|
||||
var contentTypeAlias = createChildren ? "Parent" : "Child";
|
||||
var contentType = new PublishedContentType(22, contentTypeAlias, PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 22, contentTypeAlias, PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var d = new SolidPublishedContent(contentType)
|
||||
{
|
||||
CreateDate = DateTime.Now,
|
||||
|
||||
@@ -73,14 +73,14 @@ namespace Umbraco.Tests.PublishedContent
|
||||
yield return factory.CreatePropertyType(contentType, "noprop", 1, variations: ContentVariation.Culture);
|
||||
}
|
||||
|
||||
var contentType1 = factory.CreateContentType(1, "ContentType1", Enumerable.Empty<string>(), CreatePropertyTypes1);
|
||||
var contentType1 = factory.CreateContentType(Guid.NewGuid(), 1, "ContentType1", Enumerable.Empty<string>(), CreatePropertyTypes1);
|
||||
|
||||
IEnumerable<IPublishedPropertyType> CreatePropertyTypes2(IPublishedContentType contentType)
|
||||
{
|
||||
yield return factory.CreatePropertyType(contentType, "prop3", 1, variations: ContentVariation.Culture);
|
||||
}
|
||||
|
||||
var contentType2 = factory.CreateContentType(2, "contentType2", Enumerable.Empty<string>(), CreatePropertyTypes2);
|
||||
var contentType2 = factory.CreateContentType(Guid.NewGuid(), 2, "contentType2", Enumerable.Empty<string>(), CreatePropertyTypes2);
|
||||
|
||||
var prop1 = new SolidPublishedPropertyWithLanguageVariants
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Web;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.Composing;
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
@@ -21,9 +22,9 @@ namespace Umbraco.Tests.PublishedContent
|
||||
yield return factory.CreatePropertyType(contentType, "prop1", 1);
|
||||
}
|
||||
|
||||
var contentType1 = factory.CreateContentType(1, "ContentType1", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
var contentType2 = factory.CreateContentType(2, "ContentType2", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
var contentType2Sub = factory.CreateContentType(3, "ContentType2Sub", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
var contentType1 = factory.CreateContentType(Guid.NewGuid(), 1, "ContentType1", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
var contentType2 = factory.CreateContentType(Guid.NewGuid(), 2, "ContentType2", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
var contentType2Sub = factory.CreateContentType(Guid.NewGuid(), 3, "ContentType2Sub", Enumerable.Empty<string>(), CreatePropertyTypes);
|
||||
|
||||
var content = new SolidPublishedContent(contentType1)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Services;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Templates;
|
||||
using Umbraco.Web.Models;
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
@@ -56,7 +57,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "content", 1);
|
||||
}
|
||||
|
||||
var type = new AutoPublishedContentType(0, "anything", CreatePropertyTypes);
|
||||
var type = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", CreatePropertyTypes);
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => type;
|
||||
|
||||
var umbracoContext = GetUmbracoContext("/test");
|
||||
|
||||
@@ -83,8 +83,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
}
|
||||
|
||||
var compositionAliases = new[] { "MyCompositionAlias" };
|
||||
var anythingType = new AutoPublishedContentType(0, "anything", compositionAliases, CreatePropertyTypes);
|
||||
var homeType = new AutoPublishedContentType(0, "home", compositionAliases, CreatePropertyTypes);
|
||||
var anythingType = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", compositionAliases, CreatePropertyTypes);
|
||||
var homeType = new AutoPublishedContentType(Guid.NewGuid(), 0, "home", compositionAliases, CreatePropertyTypes);
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => alias.InvariantEquals("home") ? homeType : anythingType;
|
||||
}
|
||||
|
||||
@@ -398,8 +398,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
[Test]
|
||||
public void Children_GroupBy_DocumentTypeAlias()
|
||||
{
|
||||
var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { });
|
||||
var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { });
|
||||
var home = new AutoPublishedContentType(Guid.NewGuid(), 22, "Home", new PublishedPropertyType[] { });
|
||||
var custom = new AutoPublishedContentType(Guid.NewGuid(), 23, "CustomDocument", new PublishedPropertyType[] { });
|
||||
var contentTypes = new Dictionary<string, PublishedContentType>
|
||||
{
|
||||
{ home.Alias, home },
|
||||
@@ -419,8 +419,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
[Test]
|
||||
public void Children_Where_DocumentTypeAlias()
|
||||
{
|
||||
var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { });
|
||||
var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { });
|
||||
var home = new AutoPublishedContentType(Guid.NewGuid(), 22, "Home", new PublishedPropertyType[] { });
|
||||
var custom = new AutoPublishedContentType(Guid.NewGuid(), 23, "CustomDocument", new PublishedPropertyType[] { });
|
||||
var contentTypes = new Dictionary<string, PublishedContentType>
|
||||
{
|
||||
{ home.Alias, home },
|
||||
@@ -903,7 +903,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
yield return factory.CreatePropertyType(contentType, "detached", 1003);
|
||||
}
|
||||
|
||||
var ct = factory.CreateContentType(0, "alias", CreatePropertyTypes);
|
||||
var ct = factory.CreateContentType(Guid.NewGuid(), 0, "alias", CreatePropertyTypes);
|
||||
var pt = ct.GetPropertyType("detached");
|
||||
var prop = new PublishedElementPropertyBase(pt, null, false, PropertyCacheLevel.None, 5548);
|
||||
Assert.IsInstanceOf<int>(prop.GetValue());
|
||||
@@ -935,7 +935,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
var ct = factory.CreateContentType(0, "alias", CreatePropertyTypes);
|
||||
var ct = factory.CreateContentType(Guid.NewGuid(), 0, "alias", CreatePropertyTypes);
|
||||
|
||||
var c = new ImageWithLegendModel(ct, guid, new Dictionary<string, object>
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
pc.Setup(content => content.Path).Returns("-1,1");
|
||||
pc.Setup(content => content.Parent).Returns(() => null);
|
||||
pc.Setup(content => content.Properties).Returns(new Collection<IPublishedProperty>());
|
||||
pc.Setup(content => content.ContentType).Returns(new PublishedContentType(22, "anything", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing));
|
||||
pc.Setup(content => content.ContentType).Returns(new PublishedContentType(Guid.NewGuid(), 22, "anything", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing));
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{ }
|
||||
}
|
||||
|
||||
class SolidPublishedContentCache : PublishedCacheBase, IPublishedContentCache, IPublishedMediaCache
|
||||
class SolidPublishedContentCache : PublishedCacheBase, IPublishedContentCache2, IPublishedMediaCache2
|
||||
{
|
||||
private readonly Dictionary<int, IPublishedContent> _content = new Dictionary<int, IPublishedContent>();
|
||||
|
||||
@@ -150,6 +150,11 @@ namespace Umbraco.Tests.PublishedContent
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IPublishedContentType GetContentType(Guid key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IEnumerable<IPublishedContent> GetByContentType(IPublishedContentType contentType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -378,7 +383,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
#endregion
|
||||
}
|
||||
|
||||
class PublishedContentStrong1 : PublishedContentModel
|
||||
internal class PublishedContentStrong1 : PublishedContentModel
|
||||
{
|
||||
public PublishedContentStrong1(IPublishedContent content)
|
||||
: base(content)
|
||||
@@ -387,7 +392,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public int StrongValue => this.Value<int>("strongValue");
|
||||
}
|
||||
|
||||
class PublishedContentStrong1Sub : PublishedContentStrong1
|
||||
internal class PublishedContentStrong1Sub : PublishedContentStrong1
|
||||
{
|
||||
public PublishedContentStrong1Sub(IPublishedContent content)
|
||||
: base(content)
|
||||
@@ -396,7 +401,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public int AnotherValue => this.Value<int>("anotherValue");
|
||||
}
|
||||
|
||||
class PublishedContentStrong2 : PublishedContentModel
|
||||
internal class PublishedContentStrong2 : PublishedContentModel
|
||||
{
|
||||
public PublishedContentStrong2(IPublishedContent content)
|
||||
: base(content)
|
||||
@@ -405,7 +410,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public int StrongValue => this.Value<int>("strongValue");
|
||||
}
|
||||
|
||||
class AutoPublishedContentType : PublishedContentType
|
||||
internal class AutoPublishedContentType : PublishedContentType
|
||||
{
|
||||
private static readonly IPublishedPropertyType Default;
|
||||
|
||||
@@ -418,20 +423,20 @@ namespace Umbraco.Tests.PublishedContent
|
||||
Default = factory.CreatePropertyType("*", 666);
|
||||
}
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, ContentVariation.Nothing)
|
||||
public AutoPublishedContentType(Guid key, int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(key, id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, ContentVariation.Nothing)
|
||||
{ }
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes)
|
||||
: base(id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, ContentVariation.Nothing)
|
||||
public AutoPublishedContentType(Guid key, int id, string alias, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes)
|
||||
: base(key, id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, ContentVariation.Nothing)
|
||||
{ }
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, ContentVariation.Nothing)
|
||||
public AutoPublishedContentType(Guid key, int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(key, id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, ContentVariation.Nothing)
|
||||
{ }
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes)
|
||||
: base(id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, ContentVariation.Nothing)
|
||||
public AutoPublishedContentType(Guid key, int id, string alias, IEnumerable<string> compositionAliases, Func<IPublishedContentType, IEnumerable<IPublishedPropertyType>> propertyTypes)
|
||||
: base(key, id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, ContentVariation.Nothing)
|
||||
{ }
|
||||
|
||||
public override IPublishedPropertyType GetPropertyType(string alias)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -27,7 +28,7 @@ namespace Umbraco.Tests.Routing
|
||||
Mock.Of<IPublishedModelFactory>(),
|
||||
Mock.Of<IPublishedContentTypeFactory>()),
|
||||
};
|
||||
_publishedContentType = new PublishedContentType(0, "Doc", PublishedItemType.Content, Enumerable.Empty<string>(), properties, ContentVariation.Nothing);
|
||||
_publishedContentType = new PublishedContentType(Guid.NewGuid(), 0, "Doc", PublishedItemType.Content, Enumerable.Empty<string>(), properties, ContentVariation.Nothing);
|
||||
}
|
||||
|
||||
protected override PublishedContentType GetPublishedContentTypeByAlias(string alias)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -25,7 +26,7 @@ namespace Umbraco.Tests.Routing
|
||||
Mock.Of<IPublishedModelFactory>(),
|
||||
Mock.Of<IPublishedContentTypeFactory>()),
|
||||
};
|
||||
_publishedContentType = new PublishedContentType(0, "Doc", PublishedItemType.Content, Enumerable.Empty<string>(), properties, ContentVariation.Nothing);
|
||||
_publishedContentType = new PublishedContentType(Guid.NewGuid(), 0, "Doc", PublishedItemType.Content, Enumerable.Empty<string>(), properties, ContentVariation.Nothing);
|
||||
}
|
||||
|
||||
protected override PublishedContentType GetPublishedContentTypeByAlias(string alias)
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Umbraco.Tests.Routing
|
||||
property.SetSourceValue("en", enMediaUrl, true);
|
||||
property.SetSourceValue("da", daMediaUrl);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), new [] { umbracoFilePropertyType }, ContentVariation.Culture);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), new [] { umbracoFilePropertyType }, ContentVariation.Culture);
|
||||
var publishedContent = new SolidPublishedContent(contentType) {Properties = new[] {property}};
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, UrlMode.Auto, "da");
|
||||
@@ -150,7 +150,7 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
var umbracoFilePropertyType = CreatePropertyType(propertyEditorAlias, dataTypeConfiguration, ContentVariation.Nothing);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(),
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(),
|
||||
new[] {umbracoFilePropertyType}, ContentVariation.Nothing);
|
||||
|
||||
return new SolidPublishedContent(contentType)
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Umbraco.Tests.Routing
|
||||
frequest.TemplateModel = template;
|
||||
|
||||
var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext);
|
||||
var type = new AutoPublishedContentType(22, "CustomDocument", new PublishedPropertyType[] { });
|
||||
var type = new AutoPublishedContentType(Guid.NewGuid(), 22, "CustomDocument", new PublishedPropertyType[] { });
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => type;
|
||||
|
||||
var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContextAccessor, Mock.Of<ILogger>(), context =>
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Umbraco.Tests.Routing
|
||||
var umbracoSettings = Current.Configs.Settings();
|
||||
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 };
|
||||
|
||||
var publishedContentCache = new Mock<IPublishedContentCache>();
|
||||
@@ -203,7 +203,7 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
var umbracoSettings = Current.Configs.Settings();
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 };
|
||||
|
||||
var publishedContentCache = new Mock<IPublishedContentCache>();
|
||||
@@ -257,7 +257,7 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
var umbracoSettings = Current.Configs.Settings();
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Culture);
|
||||
var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 };
|
||||
|
||||
var publishedContentCache = new Mock<IPublishedContentCache>();
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Templates
|
||||
{
|
||||
//setup a mock url provider which we'll use for testing
|
||||
|
||||
var mediaType = new PublishedContentType(777, "image", PublishedItemType.Media, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var mediaType = new PublishedContentType(Guid.NewGuid(), 777, "image", PublishedItemType.Media, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var media = new Mock<IPublishedContent>();
|
||||
media.Setup(x => x.ContentType).Returns(mediaType);
|
||||
var mediaUrlProvider = new Mock<IMediaUrlProvider>();
|
||||
|
||||
@@ -54,12 +54,12 @@ namespace Umbraco.Tests.Templates
|
||||
contentUrlProvider
|
||||
.Setup(x => x.GetUrl(It.IsAny<UmbracoContext>(), It.IsAny<IPublishedContent>(), It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/my-test-url"));
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var publishedContent = new Mock<IPublishedContent>();
|
||||
publishedContent.Setup(x => x.Id).Returns(1234);
|
||||
publishedContent.Setup(x => x.ContentType).Returns(contentType);
|
||||
|
||||
var mediaType = new PublishedContentType(777, "image", PublishedItemType.Media, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var mediaType = new PublishedContentType(Guid.NewGuid(), 777, "image", PublishedItemType.Media, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var media = new Mock<IPublishedContent>();
|
||||
media.Setup(x => x.ContentType).Returns(mediaType);
|
||||
var mediaUrlProvider = new Mock<IMediaUrlProvider>();
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
new DataType(new VoidEditor(Mock.Of<ILogger>())) { Id = 1 });
|
||||
|
||||
var factory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty<IPropertyValueConverter>()), dataTypeService);
|
||||
var type = new AutoPublishedContentType(0, "anything", new PublishedPropertyType[] { });
|
||||
var type = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", new PublishedPropertyType[] { });
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => GetPublishedContentTypeByAlias(alias) ?? type;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Umbraco.Tests.Testing.TestingTests
|
||||
|
||||
var theUrlProvider = new UrlProvider(umbracoContext, new [] { urlProvider }, Enumerable.Empty<IMediaUrlProvider>(), umbracoContext.VariationContextAccessor);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var publishedContent = Mock.Of<IPublishedContent>();
|
||||
Mock.Get(publishedContent).Setup(x => x.ContentType).Returns(contentType);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
@@ -39,7 +40,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[JsonProperty("contentTypeKey")]
|
||||
public string Key { get; set; }
|
||||
public Guid Key { get; set; }
|
||||
|
||||
[JsonProperty("settingsElementTypeKey")]
|
||||
public string SettingsElementTypeKey { get; set; }
|
||||
|
||||
@@ -23,13 +23,17 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
JObject sourceObject, string contentTypeKeyPropertyKey,
|
||||
PropertyCacheLevel referenceCacheLevel, bool preview)
|
||||
{
|
||||
var elementTypeKey = sourceObject[contentTypeKeyPropertyKey]?.ToObject<string>();
|
||||
if (string.IsNullOrEmpty(elementTypeKey))
|
||||
var elementTypeKey = sourceObject[contentTypeKeyPropertyKey]?.ToObject<Guid>();
|
||||
if (!elementTypeKey.HasValue)
|
||||
return null;
|
||||
|
||||
// hack! we need to cast, we have n ochoice beacuse we cannot make breaking changes.
|
||||
var publishedContentCache = _publishedSnapshotAccessor.PublishedSnapshot.Content as IPublishedContentCache2;
|
||||
if (publishedContentCache == null)
|
||||
throw new InvalidOperationException("The published content cache is not " + typeof(IPublishedContentCache2));
|
||||
|
||||
// only convert element types - content types will cause an exception when PublishedModelFactory creates the model
|
||||
// TODO: make this work with keys.
|
||||
var publishedContentType = _publishedSnapshotAccessor.PublishedSnapshot.Content.GetContentType(elementTypeKey);
|
||||
var publishedContentType = publishedContentCache.GetContentType(elementTypeKey.Value);
|
||||
if (publishedContentType == null || publishedContentType.IsElement == false)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -17,13 +17,11 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
public class BlockListPropertyValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly IProfilingLogger _proflog;
|
||||
private readonly IPublishedModelFactory _publishedModelFactory;
|
||||
private readonly BlockEditorConverter _blockConverter;
|
||||
|
||||
public BlockListPropertyValueConverter(IProfilingLogger proflog, IPublishedModelFactory publishedModelFactory, BlockEditorConverter blockConverter)
|
||||
public BlockListPropertyValueConverter(IProfilingLogger proflog, BlockEditorConverter blockConverter)
|
||||
{
|
||||
_proflog = proflog;
|
||||
_publishedModelFactory = publishedModelFactory;
|
||||
_blockConverter = blockConverter;
|
||||
}
|
||||
|
||||
@@ -54,11 +52,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
var configuration = propertyType.DataType.ConfigurationAs<BlockListConfiguration>();
|
||||
var contentTypes = configuration.Blocks;
|
||||
var contentTypeMap = contentTypes.ToDictionary(x => x.Key);
|
||||
var elements = (contentTypes.Length == 1
|
||||
// TODO: make this work with key
|
||||
? (IList<IPublishedElement>)_publishedModelFactory.CreateModelList(contentTypes[0].Key)
|
||||
: new List<IPublishedElement>())
|
||||
.ToDictionary(x => x.Key, x => x);
|
||||
|
||||
var elements = new Dictionary<Guid, IPublishedElement>();
|
||||
|
||||
var layout = new List<BlockListLayoutReference>();
|
||||
var model = new BlockListModel(elements.Values, layout);
|
||||
@@ -102,8 +97,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
if (!elements.TryGetValue(guidUdi.Guid, out var data))
|
||||
continue;
|
||||
|
||||
// Make this work with Key, not alias, since contentTypeMap is now a dctionary with contentTypeKey as the dictionary key.
|
||||
if (!contentTypeMap.TryGetValue(data.ContentType.Key, out var blockConfig))
|
||||
if (!data.ContentType.TryGetKey(out var contentTypeKey))
|
||||
throw new InvalidOperationException("The content type was not of type " + typeof(IPublishedContentType2));
|
||||
|
||||
if (!contentTypeMap.TryGetValue(contentTypeKey, out var blockConfig))
|
||||
continue;
|
||||
|
||||
// this can happen if they have a settings type, save content, remove the settings type, and display the front-end page before saving the content again
|
||||
|
||||
@@ -7,6 +7,16 @@ using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
public interface IPublishedCache2 : IPublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a content type identified by its alias.
|
||||
/// </summary>
|
||||
/// <param name="key">The content type key.</param>
|
||||
/// <returns>The content type, or null.</returns>
|
||||
IPublishedContentType GetContentType(Guid key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to cached contents.
|
||||
/// </summary>
|
||||
|
||||
@@ -4,6 +4,11 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
public interface IPublishedContentCache2 : IPublishedContentCache, IPublishedCache2
|
||||
{
|
||||
// NOTE: this is here purely to avoid API breaking changes
|
||||
}
|
||||
|
||||
public interface IPublishedContentCache : IPublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
public interface IPublishedMediaCache2 : IPublishedMediaCache, IPublishedCache2
|
||||
{
|
||||
// NOTE: this is here purely to avoid API breaking changes
|
||||
}
|
||||
|
||||
public interface IPublishedMediaCache : IPublishedCache
|
||||
{ }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ using Umbraco.Web.PublishedCache.NuCache.Navigable;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
internal class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigableData, IDisposable
|
||||
internal class ContentCache : PublishedCacheBase, IPublishedContentCache2, INavigableData, IDisposable
|
||||
{
|
||||
private readonly ContentStore.Snapshot _snapshot;
|
||||
private readonly IAppCache _snapshotCache;
|
||||
@@ -384,15 +384,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#region Content types
|
||||
|
||||
public override IPublishedContentType GetContentType(int id)
|
||||
{
|
||||
return _snapshot.GetContentType(id);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(int id) => _snapshot.GetContentType(id);
|
||||
|
||||
public override IPublishedContentType GetContentType(string alias)
|
||||
{
|
||||
return _snapshot.GetContentType(alias);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(string alias) => _snapshot.GetContentType(alias);
|
||||
|
||||
public override IPublishedContentType GetContentType(Guid key) => _snapshot.GetContentType(key);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -37,9 +37,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<ContentNode>> _contentNodes;
|
||||
private LinkedNode<ContentNode> _root;
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<IPublishedContentType>> _contentTypesById;
|
||||
|
||||
// We must keep separate dictionaries for by id and by alias because we track these in snapshot/layers
|
||||
// and it is possible that the alias of a content type can be different for the same id in another layer
|
||||
// whereas the GUID -> INT cross reference can never be different
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<IPublishedContentType>> _contentTypesById;
|
||||
private readonly ConcurrentDictionary<string, LinkedNode<IPublishedContentType>> _contentTypesByAlias;
|
||||
private readonly ConcurrentDictionary<Guid, int> _xmap;
|
||||
private readonly ConcurrentDictionary<Guid, int> _contentTypeKeyToIdMap;
|
||||
private readonly ConcurrentDictionary<Guid, int> _contentKeyToIdMap;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private BPlusTree<int, ContentNodeKit> _localDb;
|
||||
@@ -73,7 +78,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_root = new LinkedNode<ContentNode>(new ContentNode(), 0);
|
||||
_contentTypesById = new ConcurrentDictionary<int, LinkedNode<IPublishedContentType>>();
|
||||
_contentTypesByAlias = new ConcurrentDictionary<string, LinkedNode<IPublishedContentType>>(StringComparer.InvariantCultureIgnoreCase);
|
||||
_xmap = new ConcurrentDictionary<Guid, int>();
|
||||
_contentTypeKeyToIdMap = new ConcurrentDictionary<Guid, int>();
|
||||
_contentKeyToIdMap = new ConcurrentDictionary<Guid, int>();
|
||||
|
||||
_genObjs = new ConcurrentQueue<GenObj>();
|
||||
_genObj = null; // no initial gen exists
|
||||
@@ -136,7 +142,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
Monitor.Enter(_wlocko, ref lockInfo.Taken);
|
||||
|
||||
lock(_rlocko)
|
||||
lock (_rlocko)
|
||||
{
|
||||
// see SnapDictionary
|
||||
try { }
|
||||
@@ -152,7 +158,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_nextGen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Release(WriteLockInfo lockInfo, bool commit = true)
|
||||
@@ -291,8 +297,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
SetValueLocked(_contentTypesById, type.Id, type);
|
||||
SetValueLocked(_contentTypesByAlias, type.Alias, type);
|
||||
SetContentTypeLocked(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,8 +323,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
foreach (var type in index.Values)
|
||||
{
|
||||
SetValueLocked(_contentTypesById, type.Id, type);
|
||||
SetValueLocked(_contentTypesByAlias, type.Alias, type);
|
||||
SetContentTypeLocked(type);
|
||||
}
|
||||
|
||||
foreach (var link in _contentNodes.Values)
|
||||
@@ -354,8 +358,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// set all new content types
|
||||
foreach (var type in types)
|
||||
{
|
||||
SetValueLocked(_contentTypesById, type.Id, type);
|
||||
SetValueLocked(_contentTypesByAlias, type.Alias, type);
|
||||
SetContentTypeLocked(type);
|
||||
}
|
||||
|
||||
// beware! at that point the cache is inconsistent,
|
||||
@@ -419,8 +422,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// perform update of refreshed content types
|
||||
foreach (var type in refreshedTypesA)
|
||||
{
|
||||
SetValueLocked(_contentTypesById, type.Id, type);
|
||||
SetValueLocked(_contentTypesByAlias, type.Alias, type);
|
||||
SetContentTypeLocked(type);
|
||||
}
|
||||
|
||||
// perform update of content with refreshed content type - from the kits
|
||||
@@ -638,7 +640,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
kit.Node.PreviousSiblingContentId = existing.PreviousSiblingContentId;
|
||||
}
|
||||
|
||||
_xmap[kit.Node.Uid] = kit.Node.Id;
|
||||
_contentKeyToIdMap[kit.Node.Uid] = kit.Node.Id;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -734,7 +736,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// this node becomes the previous node
|
||||
previousNode = thisNode;
|
||||
|
||||
_xmap[kit.Node.Uid] = kit.Node.Id;
|
||||
_contentKeyToIdMap[kit.Node.Uid] = kit.Node.Id;
|
||||
}
|
||||
|
||||
return ok;
|
||||
@@ -757,7 +759,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
EnsureLocked();
|
||||
|
||||
var ok = true;
|
||||
|
||||
|
||||
ClearLocked(_contentNodes);
|
||||
ClearRootLocked();
|
||||
|
||||
@@ -778,7 +780,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (_localDb != null) RegisterChange(kit.Node.Id, kit);
|
||||
AddTreeNodeLocked(kit.Node, parent);
|
||||
|
||||
_xmap[kit.Node.Uid] = kit.Node.Id;
|
||||
_contentKeyToIdMap[kit.Node.Uid] = kit.Node.Id;
|
||||
}
|
||||
|
||||
return ok;
|
||||
@@ -807,7 +809,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
EnsureLocked();
|
||||
|
||||
var ok = true;
|
||||
|
||||
|
||||
// get existing
|
||||
_contentNodes.TryGetValue(rootContentId, out var link);
|
||||
var existing = link?.Value;
|
||||
@@ -833,7 +835,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (_localDb != null) RegisterChange(kit.Node.Id, kit);
|
||||
AddTreeNodeLocked(kit.Node, parent);
|
||||
|
||||
_xmap[kit.Node.Uid] = kit.Node.Id;
|
||||
_contentKeyToIdMap[kit.Node.Uid] = kit.Node.Id;
|
||||
}
|
||||
|
||||
return ok;
|
||||
@@ -885,11 +887,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// This should never be null, all code that calls this method is null checking but we've seen
|
||||
// issues of null ref exceptions in issue reports so we'll double check here
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
|
||||
|
||||
SetValueLocked(_contentNodes, content.Id, null);
|
||||
if (_localDb != null) RegisterChange(content.Id, ContentNodeKit.Null);
|
||||
|
||||
_xmap.TryRemove(content.Uid, out _);
|
||||
_contentKeyToIdMap.TryRemove(content.Uid, out _);
|
||||
|
||||
var id = content.FirstChildContentId;
|
||||
while (id > 0)
|
||||
@@ -913,10 +915,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
if (_contentNodes.TryGetValue(id, out var link))
|
||||
{
|
||||
link = GetLinkedNodeGen(link, gen);
|
||||
link = GetLinkedNodeGen(link, gen);
|
||||
if (link != null && link.Value != null)
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
throw new PanicException($"failed to get {description} with id={id}");
|
||||
}
|
||||
@@ -929,13 +931,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
if (content.ParentContentId < 0)
|
||||
{
|
||||
var root = GetLinkedNodeGen(_root, gen);
|
||||
var root = GetLinkedNodeGen(_root, gen);
|
||||
return root;
|
||||
}
|
||||
|
||||
if (_contentNodes.TryGetValue(content.ParentContentId, out var link))
|
||||
link = GetLinkedNodeGen(link, gen);
|
||||
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
@@ -1154,6 +1156,15 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
private void SetContentTypeLocked(IPublishedContentType type)
|
||||
{
|
||||
SetValueLocked(_contentTypesById, type.Id, type);
|
||||
SetValueLocked(_contentTypesByAlias, type.Alias, type);
|
||||
// ensure the key/id map is accurate
|
||||
if (type.TryGetKey(out var key))
|
||||
_contentTypeKeyToIdMap[key] = type.Id;
|
||||
}
|
||||
|
||||
// set a node (just the node, not the tree)
|
||||
private void SetValueLocked<TKey, TValue>(ConcurrentDictionary<TKey, LinkedNode<TValue>> dict, TKey key, TValue value)
|
||||
where TValue : class
|
||||
@@ -1211,14 +1222,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public ContentNode Get(Guid uid, long gen)
|
||||
{
|
||||
return _xmap.TryGetValue(uid, out var id)
|
||||
return _contentKeyToIdMap.TryGetValue(uid, out var id)
|
||||
? GetValue(_contentNodes, id, gen)
|
||||
: null;
|
||||
}
|
||||
|
||||
public IEnumerable<ContentNode> GetAtRoot(long gen)
|
||||
{
|
||||
var root = GetLinkedNodeGen(_root, gen);
|
||||
var root = GetLinkedNodeGen(_root, gen);
|
||||
if (root == null)
|
||||
yield break;
|
||||
|
||||
@@ -1274,13 +1285,20 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return GetValue(_contentTypesByAlias, alias, gen);
|
||||
}
|
||||
|
||||
public IPublishedContentType GetContentType(Guid key, long gen)
|
||||
{
|
||||
if (!_contentTypeKeyToIdMap.TryGetValue(key, out var id))
|
||||
return null;
|
||||
return GetContentType(id, gen);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Snapshots
|
||||
|
||||
public Snapshot CreateSnapshot()
|
||||
{
|
||||
lock(_rlocko)
|
||||
lock (_rlocko)
|
||||
{
|
||||
// if no next generation is required, and we already have one,
|
||||
// use it and create a new snapshot
|
||||
@@ -1606,6 +1624,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return _store.GetContentType(alias, _gen);
|
||||
}
|
||||
|
||||
public IPublishedContentType GetContentType(Guid key)
|
||||
{
|
||||
if (_gen < 0)
|
||||
throw new ObjectDisposedException("snapshot" /*+ " (" + _thisCount + ")"*/);
|
||||
return _store.GetContentType(key, _gen);
|
||||
}
|
||||
|
||||
// this code is here just so you don't try to implement it
|
||||
// the only way we can iterate over "all" without locking the entire cache forever
|
||||
// is by shallow cloning the cache, which is quite expensive, so we should probably not do it,
|
||||
|
||||
@@ -11,7 +11,7 @@ using Umbraco.Web.PublishedCache.NuCache.Navigable;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
internal class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
|
||||
internal class MediaCache : PublishedCacheBase, IPublishedMediaCache2, INavigableData, IDisposable
|
||||
{
|
||||
private readonly ContentStore.Snapshot _snapshot;
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
@@ -155,15 +155,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#region Content types
|
||||
|
||||
public override IPublishedContentType GetContentType(int id)
|
||||
{
|
||||
return _snapshot.GetContentType(id);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(int id) => _snapshot.GetContentType(id);
|
||||
|
||||
public override IPublishedContentType GetContentType(string alias)
|
||||
{
|
||||
return _snapshot.GetContentType(alias);
|
||||
}
|
||||
public override IPublishedContentType GetContentType(string alias) => _snapshot.GetContentType(alias);
|
||||
|
||||
public override IPublishedContentType GetContentType(Guid key) => _snapshot.GetContentType(key);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
abstract class PublishedCacheBase : IPublishedCache
|
||||
internal abstract class PublishedCacheBase : IPublishedCache2
|
||||
{
|
||||
public bool PreviewDefault { get; }
|
||||
|
||||
@@ -89,8 +89,8 @@ namespace Umbraco.Web.PublishedCache
|
||||
}
|
||||
|
||||
public abstract IPublishedContentType GetContentType(int id);
|
||||
|
||||
public abstract IPublishedContentType GetContentType(string alias);
|
||||
public abstract IPublishedContentType GetContentType(Guid key);
|
||||
|
||||
public virtual IEnumerable<IPublishedContent> GetByContentType(IPublishedContentType contentType)
|
||||
{
|
||||
|
||||
@@ -15,8 +15,10 @@ namespace Umbraco.Web.PublishedCache
|
||||
/// <remarks>This cache is not snapshotted, so it refreshes any time things change.</remarks>
|
||||
public class PublishedContentTypeCache
|
||||
{
|
||||
// NOTE: These are not concurrent dictionaries because all access is done within a lock
|
||||
private readonly Dictionary<string, IPublishedContentType> _typesByAlias = new Dictionary<string, IPublishedContentType>();
|
||||
private readonly Dictionary<int, IPublishedContentType> _typesById = new Dictionary<int, IPublishedContentType>();
|
||||
private readonly Dictionary<Guid, int> _keyToIdMap = new Dictionary<Guid, int>();
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly IMediaTypeService _mediaTypeService;
|
||||
private readonly IMemberTypeService _memberTypeService;
|
||||
@@ -130,6 +132,42 @@ namespace Umbraco.Web.PublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a published content type.
|
||||
/// </summary>
|
||||
/// <param name="itemType">An item type.</param>
|
||||
/// <param name="key">An key.</param>
|
||||
/// <returns>The published content type corresponding to the item key.</returns>
|
||||
public IPublishedContentType Get(PublishedItemType itemType, Guid key)
|
||||
{
|
||||
try
|
||||
{
|
||||
_lock.EnterUpgradeableReadLock();
|
||||
|
||||
if (_keyToIdMap.TryGetValue(key, out var id))
|
||||
return Get(itemType, id);
|
||||
|
||||
var type = CreatePublishedContentType(itemType, key);
|
||||
|
||||
try
|
||||
{
|
||||
_lock.EnterWriteLock();
|
||||
_keyToIdMap[key] = type.Id;
|
||||
return _typesByAlias[GetAliasKey(type)] = _typesById[type.Id] = type;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsWriteLockHeld)
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsUpgradeableReadLockHeld)
|
||||
_lock.ExitUpgradeableReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a published content type.
|
||||
/// </summary>
|
||||
@@ -152,7 +190,8 @@ namespace Umbraco.Web.PublishedCache
|
||||
try
|
||||
{
|
||||
_lock.EnterWriteLock();
|
||||
|
||||
if (type.TryGetKey(out var key))
|
||||
_keyToIdMap[key] = type.Id;
|
||||
return _typesByAlias[aliasKey] = _typesById[type.Id] = type;
|
||||
}
|
||||
finally
|
||||
@@ -188,7 +227,8 @@ namespace Umbraco.Web.PublishedCache
|
||||
try
|
||||
{
|
||||
_lock.EnterWriteLock();
|
||||
|
||||
if (type.TryGetKey(out var key))
|
||||
_keyToIdMap[key] = type.Id;
|
||||
return _typesByAlias[GetAliasKey(type)] = _typesById[type.Id] = type;
|
||||
}
|
||||
finally
|
||||
@@ -204,27 +244,32 @@ namespace Umbraco.Web.PublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
private IPublishedContentType CreatePublishedContentType(PublishedItemType itemType, Guid key)
|
||||
{
|
||||
IContentTypeComposition contentType = itemType switch
|
||||
{
|
||||
PublishedItemType.Content => _contentTypeService.Get(key),
|
||||
PublishedItemType.Media => _mediaTypeService.Get(key),
|
||||
PublishedItemType.Member => _memberTypeService.Get(key),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(itemType)),
|
||||
};
|
||||
if (contentType == null)
|
||||
throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with key \"{key}\".");
|
||||
|
||||
return _publishedContentTypeFactory.CreateContentType(contentType);
|
||||
}
|
||||
|
||||
private IPublishedContentType CreatePublishedContentType(PublishedItemType itemType, string alias)
|
||||
{
|
||||
if (GetPublishedContentTypeByAlias != null)
|
||||
return GetPublishedContentTypeByAlias(alias);
|
||||
|
||||
IContentTypeComposition contentType;
|
||||
switch (itemType)
|
||||
IContentTypeComposition contentType = itemType switch
|
||||
{
|
||||
case PublishedItemType.Content:
|
||||
contentType = _contentTypeService.Get(alias);
|
||||
break;
|
||||
case PublishedItemType.Media:
|
||||
contentType = _mediaTypeService.Get(alias);
|
||||
break;
|
||||
case PublishedItemType.Member:
|
||||
contentType = _memberTypeService.Get(alias);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(itemType));
|
||||
}
|
||||
|
||||
PublishedItemType.Content => _contentTypeService.Get(alias),
|
||||
PublishedItemType.Media => _mediaTypeService.Get(alias),
|
||||
PublishedItemType.Member => _memberTypeService.Get(alias),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(itemType)),
|
||||
};
|
||||
if (contentType == null)
|
||||
throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with alias \"{alias}\".");
|
||||
|
||||
@@ -235,23 +280,13 @@ namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
if (GetPublishedContentTypeById != null)
|
||||
return GetPublishedContentTypeById(id);
|
||||
|
||||
IContentTypeComposition contentType;
|
||||
switch (itemType)
|
||||
IContentTypeComposition contentType = itemType switch
|
||||
{
|
||||
case PublishedItemType.Content:
|
||||
contentType = _contentTypeService.Get(id);
|
||||
break;
|
||||
case PublishedItemType.Media:
|
||||
contentType = _mediaTypeService.Get(id);
|
||||
break;
|
||||
case PublishedItemType.Member:
|
||||
contentType = _memberTypeService.Get(id);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(itemType));
|
||||
}
|
||||
|
||||
PublishedItemType.Content => _contentTypeService.Get(id),
|
||||
PublishedItemType.Media => _mediaTypeService.Get(id),
|
||||
PublishedItemType.Member => _memberTypeService.Get(id),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(itemType)),
|
||||
};
|
||||
if (contentType == null)
|
||||
throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with id {id}.");
|
||||
|
||||
@@ -259,6 +294,7 @@ namespace Umbraco.Web.PublishedCache
|
||||
}
|
||||
|
||||
// for unit tests - changing the callback must reset the cache obviously
|
||||
// TODO: Why does this even exist? For testing you'd pass in a mocked service to get by id
|
||||
private Func<string, IPublishedContentType> _getPublishedContentTypeByAlias;
|
||||
internal Func<string, IPublishedContentType> GetPublishedContentTypeByAlias
|
||||
{
|
||||
@@ -282,6 +318,7 @@ namespace Umbraco.Web.PublishedCache
|
||||
}
|
||||
|
||||
// for unit tests - changing the callback must reset the cache obviously
|
||||
// TODO: Why does this even exist? For testing you'd pass in a mocked service to get by id
|
||||
private Func<int, IPublishedContentType> _getPublishedContentTypeById;
|
||||
internal Func<int, IPublishedContentType> GetPublishedContentTypeById
|
||||
{
|
||||
|
||||
+21
-2
@@ -58,8 +58,24 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Web.UI.Client", "ht
|
||||
StartServerOnDebug = "false"
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTest\", "Umbraco.Tests.AcceptanceTest\", "{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}"
|
||||
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTest", "Umbraco.Tests.AcceptanceTest\", "{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}"
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
|
||||
Debug.AspNetCompiler.VirtualPath = "/localhost_62926"
|
||||
Debug.AspNetCompiler.PhysicalPath = "Umbraco.Tests.AcceptanceTest\"
|
||||
Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_62926\"
|
||||
Debug.AspNetCompiler.Updateable = "true"
|
||||
Debug.AspNetCompiler.ForceOverwrite = "true"
|
||||
Debug.AspNetCompiler.FixedNames = "false"
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.VirtualPath = "/localhost_62926"
|
||||
Release.AspNetCompiler.PhysicalPath = "Umbraco.Tests.AcceptanceTest\"
|
||||
Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_62926\"
|
||||
Release.AspNetCompiler.Updateable = "true"
|
||||
Release.AspNetCompiler.ForceOverwrite = "true"
|
||||
Release.AspNetCompiler.FixedNames = "false"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
VWDPort = "62926"
|
||||
SlnRelativePath = "Umbraco.Tests.AcceptanceTest\"
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@@ -123,6 +139,9 @@ Global
|
||||
{4C4C194C-B5E4-4991-8F87-4373E24CC19F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3819A550-DCEC-4153-91B4-8BA9F7F0B9B4}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -157,6 +176,7 @@ Global
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{227C3B55-80E5-4E7E-A802-BE16C5128B9D} = {2849E9D4-3B4E-40A3-A309-F3CB4F0E125F}
|
||||
{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
|
||||
{5D3B8245-ADA6-453F-A008-50ED04BFE770} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
|
||||
{E3F9F378-AFE1-40A5-90BD-82833375DBFE} = {227C3B55-80E5-4E7E-A802-BE16C5128B9D}
|
||||
{5B03EF4E-E0AC-4905-861B-8C3EC1A0D458} = {227C3B55-80E5-4E7E-A802-BE16C5128B9D}
|
||||
@@ -164,7 +184,6 @@ Global
|
||||
{3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
|
||||
{C7311C00-2184-409B-B506-52A5FAEA8736} = {FD962632-184C-4005-A5F3-E705D92FC645}
|
||||
{FB5676ED-7A69-492C-B802-E7B24144C0FC} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
|
||||
{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7A0F2E34-D2AF-4DAB-86A0-7D7764B3D0EC}
|
||||
|
||||
Reference in New Issue
Block a user