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:
Shannon
2020-06-10 16:12:00 +10:00
parent aa447bc704
commit a5adb322f1
44 changed files with 392 additions and 224 deletions
@@ -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 />
+1
View File
@@ -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);
+21 -21
View File
@@ -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>();
+1 -1
View File
@@ -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
View File
@@ -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}