diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index 8ef077a968..14c9d7a4e0 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -4,8 +4,6 @@ using System.Globalization; using System.Linq; using System.Xml.Linq; using System.Xml.XPath; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Umbraco.Core.Dynamics; using Umbraco.Core.PropertyEditors; @@ -18,6 +16,32 @@ namespace Umbraco.Core.Models.PublishedContent /// if the property type changes, then a new class needs to be created. public class PublishedPropertyType { + #region Constructors + + // clone + private PublishedPropertyType(PublishedPropertyType orig) + { + ContentType = orig.ContentType; + PropertyTypeAlias = orig.PropertyTypeAlias; + DataTypeId = orig.DataTypeId; + PropertyEditorAlias = orig.PropertyEditorAlias; + _converter = orig._converter; + _sourceCacheLevel = orig._sourceCacheLevel; + _objectCacheLevel = orig._objectCacheLevel; + _xpathCacheLevel = orig._xpathCacheLevel; + _clrType = orig._clrType; + + // do NOT copy the reduced cache levels + // as we should NOT clone a nested / detached type + } + + /// + /// Initialize a new instance of the class within a , + /// with a . + /// + /// The published content type. + /// The property type. + /// The new published property type belongs to the published content type and corresponds to the property type. public PublishedPropertyType(PublishedContentType contentType, PropertyType propertyType) { // PropertyEditor [1:n] DataTypeDefinition [1:n] PropertyType @@ -31,10 +55,68 @@ namespace Umbraco.Core.Models.PublishedContent InitializeConverters(); } - // for unit tests + /// + /// Initializes a new instance of the class with an existing + /// and a new property type alias. + /// + /// The new property type alias. + /// The existing published property type. + /// + /// The new published property type does not belong to a published content type. + /// It is a copy of the initial published property type, with a different alias. + /// + internal PublishedPropertyType(string propertyTypeAlias, PublishedPropertyType propertyType) + : this(propertyTypeAlias, propertyType.DataTypeId, propertyType.PropertyEditorAlias) + { } + + + /// + /// Initializes a new instance of the class with a property type alias and a property editor alias. + /// + /// The property type alias. + /// The property editor alias. + /// + /// The new published property type does not belong to a published content type. + /// It is based upon the property editor, but has no datatype definition. This will work as long + /// as the datatype definition is not required to process (eg to convert) the property values. For + /// example, this may not work if the related IPropertyValueConverter requires the datatype definition + /// to make decisions, fetch prevalues, etc. + /// The value of is assumed to be valid. + /// + internal PublishedPropertyType(string propertyTypeAlias, string propertyEditorAlias) + : this(propertyTypeAlias, 0, propertyEditorAlias) + { } + + /// + /// Initializes a new instance of the class with a property type alias and a datatype definition. + /// + /// The property type alias. + /// The datatype definition. + /// + /// The new published property type does not belong to a published content type. + /// + internal PublishedPropertyType(string propertyTypeAlias, IDataTypeDefinition dataTypeDefinition) + : this(propertyTypeAlias, dataTypeDefinition.Id, dataTypeDefinition.PropertyEditorAlias) + { } + + /// + /// Initializes a new instance of the class with a property type alias, + /// a datatype definition identifier, and a property editor alias. + /// + /// The property type alias. + /// The datatype definition identifier. + /// The property editor alias. + /// + /// The new published property type does not belong to a published content type. + /// The values of and are + /// assumed to be valid and consistent. + /// internal PublishedPropertyType(string propertyTypeAlias, int dataTypeDefinitionId, string propertyEditorAlias) { - // ContentType to be set by PublishedContentType when creating it + // ContentType + // - in unit tests, to be set by PublishedContentType when creating it + // - in detached types, remains null + PropertyTypeAlias = propertyTypeAlias; DataTypeId = dataTypeDefinitionId; @@ -43,6 +125,8 @@ namespace Umbraco.Core.Models.PublishedContent InitializeConverters(); } + #endregion + #region Property type /// @@ -291,5 +375,132 @@ namespace Umbraco.Core.Models.PublishedContent } #endregion + + #region Detached + + private PropertyCacheLevel _sourceCacheLevelReduced = 0; + private PropertyCacheLevel _objectCacheLevelReduced = 0; + private PropertyCacheLevel _xpathCacheLevelReduced = 0; + + internal bool IsDetachedOrNested + { + // enough to test source + get { return _sourceCacheLevelReduced != 0; } + } + + /// + /// Creates a detached clone of this published property type. + /// + /// A detached clone of this published property type. + /// + /// Only a published property type that has not already been detached or nested, can be detached. + /// Use detached published property type when creating detached properties outside of a published content. + /// + public PublishedPropertyType Detached() + { + // verify + if (IsDetachedOrNested) + throw new Exception("PublishedPropertyType is already detached/nested."); + + var detached = new PublishedPropertyType(this); + detached._sourceCacheLevel + = detached._objectCacheLevel + = detached._xpathCacheLevel + = PropertyCacheLevel.Content; + // set to none to a) indicate it's detached / nested and b) make sure any nested + // types switch all their cache to .Content + detached._sourceCacheLevelReduced + = detached._objectCacheLevelReduced + = detached._xpathCacheLevelReduced + = PropertyCacheLevel.None; + + return detached; + } + + /// + /// Creates a nested clone of this published property type within a specified container published property type. + /// + /// The container published property type. + /// A nested clone of this published property type + /// + /// Only a published property type that has not already been detached or nested, can be nested. + /// Use nested published property type when creating detached properties within a published content. + /// + public PublishedPropertyType Nested(PublishedPropertyType containerType) + { + // verify + if (IsDetachedOrNested) + throw new Exception("PublishedPropertyType is already detached/nested."); + + var nested = new PublishedPropertyType(this); + + // before we reduce, both xpath and object are >= source, and + // the way reduce works, the relative order of resulting xpath, object and source are preserved + + // Reduce() will set _xxxCacheLevelReduced thus indicating that the type is detached / nested + + Reduce(_sourceCacheLevel, _sourceCacheLevelReduced, ref nested._sourceCacheLevel, ref nested._sourceCacheLevelReduced); + Reduce(_objectCacheLevel, _objectCacheLevelReduced, ref nested._objectCacheLevel, ref nested._objectCacheLevelReduced); + Reduce(_xpathCacheLevel, _xpathCacheLevelReduced, ref nested._xpathCacheLevel, ref nested._xpathCacheLevelReduced); + + return nested; + } + + private static void Reduce( + PropertyCacheLevel containerCacheLevel, PropertyCacheLevel containerCacheLevelReduced, + ref PropertyCacheLevel nestedCacheLevel, ref PropertyCacheLevel nestedCacheLevelReduced) + { + // initialize if required + if (containerCacheLevelReduced == 0) + containerCacheLevelReduced = containerCacheLevel; + + switch (containerCacheLevelReduced) + { + case PropertyCacheLevel.None: + // once .None, force .Content for everything + nestedCacheLevel = PropertyCacheLevel.Content; + nestedCacheLevelReduced = PropertyCacheLevel.None; // and propagate + break; + + case PropertyCacheLevel.Request: + // once .Request, force .Content for everything + nestedCacheLevel = PropertyCacheLevel.Content; + nestedCacheLevelReduced = PropertyCacheLevel.Request; // and propagate + break; + + case PropertyCacheLevel.Content: + // as long as .Content, accept anything + nestedCacheLevelReduced = nestedCacheLevel; // and it becomes the nested reduced + break; + + case PropertyCacheLevel.ContentCache: + // once .ContentCache, accept .Request and .Content but not .ContentCache + switch (nestedCacheLevel) + { + case PropertyCacheLevel.Request: + case PropertyCacheLevel.None: + // accept + nestedCacheLevelReduced = nestedCacheLevel; // and it becomes the nested reduced + break; + case PropertyCacheLevel.Content: + // accept + nestedCacheLevelReduced = PropertyCacheLevel.ContentCache; // and propagate + break; + case PropertyCacheLevel.ContentCache: + // force .Content + nestedCacheLevel = PropertyCacheLevel.Content; + nestedCacheLevelReduced = PropertyCacheLevel.ContentCache; // and propagate + break; + default: + throw new Exception("Unsupported PropertyCacheLevel value."); + } + break; + + default: + throw new Exception("Unsupported PropertyCacheLevel value."); + } + } + + #endregion } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyCacheLevel.cs b/src/Umbraco.Core/PropertyEditors/PropertyCacheLevel.cs index e271a01a5e..832aed6b4a 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyCacheLevel.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyCacheLevel.cs @@ -6,6 +6,10 @@ /// By default, Request is assumed. public enum PropertyCacheLevel { + // note: we use the relative values in PublishedPropertyType to ensure that + // object level >= source level + // xpath level >= source level + /// /// Indicates that the property value can be cached at the content level, ie it can be /// cached until the content itself is modified. diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs index d8b3d52668..4474a72484 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs @@ -100,8 +100,7 @@ namespace Umbraco.Tests.PublishedContent return _content.Count > 0; } - public IPublishedContent CreateFragment(string contentTypeAlias, IDictionary dataValues, - bool isPreviewing, bool managed) + public IPublishedProperty CreateDetachedProperty(PublishedPropertyType propertyType, object value, bool isPreviewing) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index fcfc6a6932..4a4a9e188c 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Web; +using Umbraco.Web.Models; namespace Umbraco.Tests.PublishedContent { @@ -632,5 +633,61 @@ namespace Umbraco.Tests.PublishedContent Assert.AreEqual((int)1178, (int)result.Id); } - } + + [Test] + public void DetachedProperty1() + { + var type = new PublishedPropertyType("detached", Constants.PropertyEditors.IntegerAlias); + var prop = PublishedProperty.GetDetached(type.Detached(), "5548"); + Assert.IsInstanceOf(prop.Value); + Assert.AreEqual(5548, prop.Value); + } + + public void CreateDetachedContentSample() + { + bool previewing = false; + var t = PublishedContentType.Get(PublishedItemType.Content, "detachedSomething"); + var values = new Dictionary(); + var properties = t.PropertyTypes.Select(x => + { + object value; + if (values.TryGetValue(x.PropertyTypeAlias, out value) == false) value = null; + return PublishedProperty.GetDetached(x.Detached(), value, previewing); + }); + // and if you want some sort of "model" it's up to you really... + var c = new DetachedContent(properties); + } + + public void CreatedDetachedContentInConverterSample() + { + // the converter args + PublishedPropertyType argPropertyType = null; + object argSource = null; + bool argPreview = false; + + var pt1 = new PublishedPropertyType("legend", 0, Constants.PropertyEditors.TextboxAlias); + var pt2 = new PublishedPropertyType("image", 0, Constants.PropertyEditors.MediaPickerAlias); + string val1 = ""; + int val2 = 0; + + var c = new ImageWithLegendModel( + PublishedProperty.GetDetached(pt1.Nested(argPropertyType), val1, argPreview), + PublishedProperty.GetDetached(pt2.Nested(argPropertyType), val2, argPreview)); + } + + class ImageWithLegendModel + { + private IPublishedProperty _legendProperty; + private IPublishedProperty _imageProperty; + + public ImageWithLegendModel(IPublishedProperty legendProperty, IPublishedProperty imageProperty) + { + _legendProperty = legendProperty; + _imageProperty = imageProperty; + } + + public string Legend { get { return _legendProperty.GetValue(); } } + public IPublishedContent Image { get { return _imageProperty.GetValue(); } } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/DetachedContent.cs b/src/Umbraco.Web/Models/DetachedContent.cs new file mode 100644 index 0000000000..541e1a5185 --- /dev/null +++ b/src/Umbraco.Web/Models/DetachedContent.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Web.Models +{ + public class DetachedContent + { + private readonly Dictionary _properties; + + public DetachedContent(IEnumerable properties) + { + _properties = properties.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase); + } + + public DetachedContent(IPublishedContent content) + { + _properties = content.Properties.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase); + } + + public DetachedContent(IContent content, bool isPreviewing) + { + var publishedContentType = PublishedContentType.Get(PublishedItemType.Content, content.ContentType.Alias); + _properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, content.Properties, + (t, v) => PublishedProperty.GetDetached(t, v, isPreviewing)) + .ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase); + } + + public DetachedContent(IMedia media, bool isPreviewing) + { + var publishedContentType = PublishedContentType.Get(PublishedItemType.Media, media.ContentType.Alias); + _properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, media.Properties, + (t, v) => PublishedProperty.GetDetached(t, v, isPreviewing)) + .ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase); + } + + public DetachedContent(IMember member, bool isPreviewing) + { + var publishedContentType = PublishedContentType.Get(PublishedItemType.Member, member.ContentType.Alias); + _properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, member.Properties, + (t, v) => PublishedProperty.GetDetached(t, v, isPreviewing)) + .ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase); + } + + public ICollection Properties + { + get { return _properties.Values; } + } + + public IPublishedProperty GetProperty(string alias) + { + IPublishedProperty property; + return _properties.TryGetValue(alias, out property) ? property : null; + } + + public bool HasProperty(string alias) + { + var property = GetProperty(alias); + return property != null; + } + + public bool HasValue(string alias) + { + var property = GetProperty(alias); + return property != null && property.HasValue; + } + + public object GetPropertyValue(string alias) + { + var property = GetProperty(alias); + return property == null ? null : property.Value; + } + + public object GetPropertyValue(string alias, string defaultValue) + { + var property = GetProperty(alias); + return property == null || property.HasValue == false ? defaultValue : property.Value; + } + + public object GetPropertyValue(string alias, object defaultValue) + { + var property = GetProperty(alias); + return property == null || property.HasValue == false ? defaultValue : property.Value; + } + + public T GetPropertyValue(string alias) + { + var property = GetProperty(alias); + if (property == null) return default(T); + return property.GetValue(false, default(T)); + } + + public T GetPropertyValue(string alias, T defaultValue) + { + var property = GetProperty(alias); + if (property == null) return defaultValue; + return property.GetValue(true, defaultValue); + } + } +} diff --git a/src/Umbraco.Web/Models/PublishedProperty.cs b/src/Umbraco.Web/Models/PublishedProperty.cs index 402bc23a07..59618c047e 100644 --- a/src/Umbraco.Web/Models/PublishedProperty.cs +++ b/src/Umbraco.Web/Models/PublishedProperty.cs @@ -13,6 +13,21 @@ namespace Umbraco.Web.Models { public static class PublishedProperty { + /// + /// Creates a detached published property. + /// + /// A published property type. + /// The property data raw value. + /// A value indicating whether to evaluate the property value in previewing context. + /// A detached published property holding the value. + internal static IPublishedProperty GetDetached(PublishedPropertyType propertyType, object value, bool isPreviewing = false) + { + if (propertyType.IsDetachedOrNested == false) + throw new ArgumentException("Property type is neither detached nor nested.", "propertyType"); + var property = UmbracoContext.Current.ContentCache.InnerCache.CreateDetachedProperty(propertyType, value, isPreviewing); + return property; + } + /// /// Maps a collection of Property to a collection of IPublishedProperty for a specified collection of PublishedPropertyType. /// diff --git a/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs index f020dc6097..b73e594727 100644 --- a/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; - using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Web.Models; namespace Umbraco.Web.PublishedCache { @@ -35,51 +35,13 @@ namespace Umbraco.Web.PublishedCache string GetRouteById(UmbracoContext umbracoContext, bool preview, int contentId); /// - /// Creates a content fragment. + /// Creates a detached property. /// - /// The content type alias. - /// The content property raw values. - /// A value indicating whether the fragment is previewing. - /// A value indicating whether the fragment is managed by the cache. - /// The newly created content fragment. - // - // notes - // - // in XmlPublishedCache, IPublishedContent instances are not meant to survive longer - // that a request or else we cannot guarantee that the converted property values will - // be properly managed - because XmlPublishedProperty just stores the result of the - // conversion locally. - // - // in DrippingPublishedCache, IPublishedContent instances are meant to survive for as - // long as the content itself has not been modified, and the property respects the - // converter's indication ie whether the converted value should be cached at - // .Content - cache until the content changes - // .ContentCache - cache until any content changes - // .Request - cache for the current request - // - // a fragment can be either "detached" or "managed". - // detached: created from code, managed by code, converted property values are - // cached within the fragment itself for as long as the fragment lives - // managed: created from a property converter as part of a content, managed by - // the cache, converted property values can be cached... - // - // XmlPublishedCache: same as content properties, store the result of the - // conversion locally, neither content nor fragments should survive longer - // than a request - // DrippingPublishedCache: depends - // .Content: cache within the fragment - // .ContentCache, .Request: cache within the cache - // - // in the latter case, use a fragment-owned guid as the cache key. because we - // don't really have any other choice. this opens potential memory leaks: if the - // fragment is re-created on each request and has a property that caches its - // converted value at .ContentCache level then we'll flood that cache with data - // that's never removed (as long as no content is edited). - // - // so a requirement should be that any converter that creates fragment, should - // be marked .Content -- and nothing else - // - IPublishedContent CreateFragment(string contentTypeAlias, IDictionary dataValues, - bool isPreviewing, bool managed); + /// The published property type. + /// The value. + /// A value indicating whether the property is created within a previewing context. + /// A detached property. + /// Implementations must check that propertyType.IsDetachedOrNested is true. + IPublishedProperty CreateDetachedProperty(PublishedPropertyType propertyType, object value, bool isPreviewing); } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs index d0547ad170..fe074cf58c 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs @@ -463,14 +463,15 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache #endregion - #region Fragments + #region Detached - public IPublishedContent CreateFragment(string contentTypeAlias, IDictionary dataValues, - bool isPreviewing, bool managed) + public IPublishedProperty CreateDetachedProperty(PublishedPropertyType propertyType, object value, bool isPreviewing) { - return new PublishedFragment(contentTypeAlias, dataValues, isPreviewing, managed); + if (propertyType.IsDetachedOrNested == false) + throw new ArgumentException("Property type is neither detached nor nested.", "propertyType"); + return new XmlPublishedProperty(propertyType, isPreviewing, value.ToString()); } #endregion } -} +} \ No newline at end of file diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs deleted file mode 100644 index 860f9f043f..0000000000 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Models; - -namespace Umbraco.Web.PublishedCache.XmlPublishedCache -{ - class PublishedFragment : PublishedContentBase - { - private readonly PublishedContentType _contentType; - private readonly IPublishedProperty[] _properties; - - public PublishedFragment(string contentTypeAlias, IDictionary dataValues, - bool isPreviewing, bool managed) - { - IsPreviewing = isPreviewing; - _contentType = PublishedContentType.Get(PublishedItemType.Content, contentTypeAlias); - - // we don't care about managed because in both cases, XmlPublishedCache stores - // converted property values in the IPublishedContent, which is not meant to - // survive the request - - var dataValues2 = new Dictionary(); - foreach (var kvp in dataValues) - dataValues2[kvp.Key.ToLowerInvariant()] = kvp.Value; - - _properties = _contentType.PropertyTypes - .Select(x => - { - object dataValue; - return dataValues2.TryGetValue(x.PropertyTypeAlias.ToLowerInvariant(), out dataValue) - ? new PublishedFragmentProperty(x, this, dataValue) - : new PublishedFragmentProperty(x, this); - }) - .Cast() - .ToArray(); - } - - #region IPublishedContent - - public override int Id - { - get { throw new NotImplementedException(); } - } - - public override int DocumentTypeId - { - get { return _contentType.Id; } - } - - public override string DocumentTypeAlias - { - get { return _contentType.Alias; } - } - - public override PublishedItemType ItemType - { - get { return PublishedItemType.Content; } - } - - public override string Name - { - get { throw new NotImplementedException(); } - } - - public override int Level - { - get { throw new NotImplementedException(); } - } - - public override string Path - { - get { throw new NotImplementedException(); } - } - - public override int SortOrder - { - // note - could a published fragment have a sort order? - get { throw new NotImplementedException(); } - } - - public override Guid Version - { - get { throw new NotImplementedException(); } - } - - public override int TemplateId - { - get { throw new NotImplementedException(); } - } - - public override string UrlName - { - get { return string.Empty; } - } - - public override DateTime CreateDate - { - get { throw new NotImplementedException(); } - } - - public override DateTime UpdateDate - { - get { throw new NotImplementedException(); } - } - - public override int CreatorId - { - get { throw new NotImplementedException(); } - } - - public override string CreatorName - { - get { throw new NotImplementedException(); } - } - - public override int WriterId - { - get { throw new NotImplementedException(); } - } - - public override string WriterName - { - get { throw new NotImplementedException(); } - } - - public override bool IsDraft - { - get { throw new NotImplementedException(); } - } - - public override IPublishedContent Parent - { - get { throw new NotImplementedException(); } - } - - public override IEnumerable Children - { - get { throw new NotImplementedException(); } - } - - public override ICollection Properties - { - get { return _properties; } - } - - public override IPublishedProperty GetProperty(string alias) - { - return _properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); - } - - public override PublishedContentType ContentType - { - get { return _contentType; } - } - - #endregion - - #region Internal - - // used by PublishedFragmentProperty - internal bool IsPreviewing { get; private set; } - - #endregion - } -} diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragmentProperty.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragmentProperty.cs deleted file mode 100644 index 7ae10aebdd..0000000000 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragmentProperty.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Web.PublishedCache.XmlPublishedCache -{ - class PublishedFragmentProperty : PublishedPropertyBase - { - private readonly object _dataValue; - private readonly PublishedFragment _content; - - private readonly Lazy _sourceValue; - private readonly Lazy _objectValue; - private readonly Lazy _xpathValue; - - public PublishedFragmentProperty(PublishedPropertyType propertyType, PublishedFragment content) - : this(propertyType, content, null) - { } - - public PublishedFragmentProperty(PublishedPropertyType propertyType, PublishedFragment content, object dataValue) - : base(propertyType) - { - _dataValue = dataValue; - _content = content; - - _sourceValue = new Lazy(() => PropertyType.ConvertDataToSource(_dataValue, _content.IsPreviewing)); - _objectValue = new Lazy(() => PropertyType.ConvertSourceToObject(_sourceValue.Value, _content.IsPreviewing)); - _xpathValue = new Lazy(() => PropertyType.ConvertSourceToXPath(_sourceValue.Value, _content.IsPreviewing)); - } - - public override bool HasValue - { - get { return _dataValue != null && ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false); } - } - - public override object DataValue - { - get { return _dataValue; } - } - - public override object Value { get { return _objectValue.Value; } } - public override object XPathValue { get { return _xpathValue.Value; } } - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ddf4fc326e..404e201689 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -308,6 +308,7 @@ + @@ -356,8 +357,6 @@ - -