Created
February 11, 2022 09:52
-
-
Save mattbrailsford/cfce147963103dc47247454796840dc6 to your computer and use it in GitHub Desktop.
Published Content Wrapper for v8 + v9
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MyController : Controller | |
{ | |
private readonly PublishedContentWrapperFactory _publishedContentWrapper; | |
public MyController(PublishedContentWrapperFactory publishedContentWrapper) | |
=> _publishedContentWrapper = publishedContentWrapper; | |
[HttpGet] | |
public IActionResult DoSomething() | |
{ | |
var content = _someUmbracoContentApi.GetContent(nodeId); | |
var publishedContent = _publishedContentWrapper.Wrap(content); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Vendr.Common; | |
using Vendr.Extensions; | |
#if NETFRAMEWORK | |
using Umbraco.Core; | |
using Umbraco.Core.Models; | |
using Umbraco.Core.Models.PublishedContent; | |
using Umbraco.Core.PropertyEditors; | |
using Umbraco.Core.Services; | |
using Umbraco.Core.Strings; | |
using IFactory = Vendr.Common.IFactory; | |
using IProperty = Umbraco.Core.Models.Property; | |
#else | |
using Umbraco.Cms.Core.Models; | |
using Umbraco.Cms.Core.Models.PublishedContent; | |
using Umbraco.Cms.Core.Services; | |
using Umbraco.Cms.Core.PropertyEditors; | |
using Umbraco.Cms.Core.Strings; | |
using Umbraco.Extensions; | |
#endif | |
namespace Vendr.Umbraco.Content | |
{ | |
public class PublishedContentWrapperFactory | |
{ | |
private readonly IFactory _factory; | |
public PublishedContentWrapperFactory(IFactory factory) | |
{ | |
_factory = factory; | |
} | |
internal IPublishedContent Wrap(IContent content, bool isPreview = false) | |
{ | |
return new PublishedContentWrapper(_factory, this, content, isPreview); | |
} | |
#region PublishedContentWrapper | |
private class PublishedContentWrapper : IPublishedContent | |
{ | |
private static readonly IReadOnlyDictionary<string, PublishedCultureInfo> NoCultureInfos = new Dictionary<string, PublishedCultureInfo>(); | |
private readonly IContent _inner; | |
private readonly bool _isPreviewing; | |
private readonly IFactory _factory; | |
private readonly Lazy<string> _creatorName; | |
private readonly Lazy<string> _writerName; | |
private readonly Lazy<IPublishedContentType> _contentType; | |
private readonly Lazy<IPublishedProperty[]> _properties; | |
private readonly Lazy<IPublishedContent> _parent; | |
private readonly Lazy<IEnumerable<IPublishedContent>> _children; | |
private readonly Lazy<IReadOnlyDictionary<string, PublishedCultureInfo>> _cultureInfos; | |
private readonly PublishedContentWrapperFactory _contentWrapperFactory; | |
private readonly IUserService _userService; | |
private readonly IContentTypeService _contentTypeService; | |
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory; | |
private readonly IContentService _contentService; | |
public PublishedContentWrapper(IFactory factory, PublishedContentWrapperFactory contentWrapperFactory, IContent inner, bool isPreviewing) | |
{ | |
_factory = factory; | |
_contentWrapperFactory = contentWrapperFactory; | |
_userService = factory.GetInstance<IUserService>(); | |
_contentTypeService = factory.GetInstance<IContentTypeService>(); | |
_publishedContentTypeFactory = factory.GetInstance<IPublishedContentTypeFactory>(); | |
_contentService = factory.GetInstance<IContentService>(); | |
_inner = inner ?? throw new NullReferenceException("inner"); | |
_isPreviewing = isPreviewing; | |
_creatorName = new Lazy<string>(() => _inner.GetCreatorProfile(_userService)?.Name); | |
_writerName = new Lazy<string>(() => _inner.GetWriterProfile(_userService)?.Name); | |
_contentType = new Lazy<IPublishedContentType>(() => | |
{ | |
var ct = _contentTypeService.Get(_inner.ContentTypeId); | |
return _publishedContentTypeFactory.CreateContentType(ct); | |
}); | |
_properties = new Lazy<IPublishedProperty[]>(() => ContentType.PropertyTypes | |
.Select(x => | |
{ | |
var p = _inner.Properties.SingleOrDefault(xx => xx.Alias == x.Alias); | |
return new PublishedPropertyWrapper(this, x, p, _isPreviewing); | |
}) | |
.Cast<IPublishedProperty>() | |
.ToArray()); | |
_parent = new Lazy<IPublishedContent>(() => | |
{ | |
var content = _contentService.GetById(_inner.ParentId); | |
return content != null | |
? _contentWrapperFactory.Wrap(content, _isPreviewing) | |
: null; | |
}); | |
_children = new Lazy<IEnumerable<IPublishedContent>>(() => | |
{ | |
var c = _contentService.GetPagedChildren(_inner.Id, 0, 2000000000, out var totalRecords); | |
return c.Select(x => _contentWrapperFactory.Wrap(x, _isPreviewing)).OrderBy(x => x.SortOrder); | |
}); | |
_cultureInfos = new Lazy<IReadOnlyDictionary<string, PublishedCultureInfo>>(() => | |
{ | |
if (!_inner.ContentType.VariesByCulture()) | |
return NoCultureInfos; | |
return _inner.PublishCultureInfos.Values | |
.ToDictionary(x => x.Culture, x => new PublishedCultureInfo(x.Culture, | |
x.Name, | |
GetUrlSegment(x.Culture), | |
x.Date)); | |
}); | |
} | |
public IPublishedContentType ContentType | |
=> _contentType.Value; | |
public int Id | |
=> _inner.Id; | |
public Guid Key | |
=> _inner.Key; | |
public int? TemplateId | |
=> _inner.TemplateId; | |
public int SortOrder | |
=> _inner.SortOrder; | |
public string Name | |
=> _inner.Name; | |
public IReadOnlyDictionary<string, PublishedCultureInfo> Cultures | |
=> _cultureInfos.Value; | |
public string UrlSegment | |
=> GetUrlSegment(); | |
public string WriterName | |
=> _writerName.Value; | |
public string CreatorName | |
=> _creatorName.Value; | |
public int WriterId | |
=> _inner.WriterId; | |
public int CreatorId | |
=> _inner.CreatorId; | |
public string Path | |
=> _inner.Path; | |
public DateTime CreateDate | |
=> _inner.CreateDate; | |
public DateTime UpdateDate | |
=> _inner.UpdateDate; | |
public int Level | |
=> _inner.Level; | |
public string Url | |
=> null; // TODO: Implement? | |
public PublishedItemType ItemType | |
=> PublishedItemType.Content; | |
public bool IsDraft(string culture = null) | |
=> !IsPublished(culture); | |
public bool IsPublished(string culture = null) | |
=> _inner.IsCulturePublished(culture); | |
public IPublishedContent Parent | |
=> _parent.Value; | |
public IEnumerable<IPublishedContent> Children | |
=> _children.Value; // TODO: Filter by current culture? | |
public IEnumerable<IPublishedContent> ChildrenForAllCultures | |
=> _children.Value; | |
public IEnumerable<IPublishedProperty> Properties | |
=> _properties.Value; | |
public IPublishedProperty GetProperty(string alias) | |
=> _properties.Value.FirstOrDefault(x => Extensions.StringExtensions.InvariantEquals(x.Alias, alias)); | |
private string GetUrlSegment(string culture = null) | |
{ | |
var urlSegmentProviders = _factory.GetInstance<UrlSegmentProviderCollection>(); | |
#if NETFRAMEWORK | |
var defaultUrlSegmentProvider = new DefaultUrlSegmentProvider(); | |
#else | |
var defaultUrlSegmentProvider = new DefaultUrlSegmentProvider(_factory.GetInstance<IShortStringHelper>()); | |
#endif | |
var url = urlSegmentProviders.Select(p => p.GetUrlSegment(_inner, culture)).FirstOrDefault(u => u != null); | |
url = url ?? defaultUrlSegmentProvider.GetUrlSegment(_inner, culture); // be safe | |
return url; | |
} | |
} | |
private class PublishedPropertyWrapper : IPublishedProperty | |
{ | |
private readonly object _sourceValue; | |
private readonly IPublishedContent _content; | |
private readonly bool _isPreviewing; | |
public PublishedPropertyWrapper(IPublishedContent content, IPublishedPropertyType propertyType, IProperty property, bool isPreviewing) | |
: this(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored | |
{ | |
_sourceValue = property?.GetValue(); | |
_content = content; | |
_isPreviewing = isPreviewing; | |
} | |
protected PublishedPropertyWrapper(IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel) | |
{ | |
PropertyType = propertyType ?? throw new ArgumentNullException(nameof(propertyType)); | |
ReferenceCacheLevel = referenceCacheLevel; | |
} | |
public IPublishedPropertyType PropertyType { get; } | |
public PropertyCacheLevel ReferenceCacheLevel { get; } | |
public string Alias => PropertyType.Alias; | |
public bool HasValue(string culture = null, string segment = null) | |
{ | |
return _sourceValue != null && ((_sourceValue is string) == false || string.IsNullOrWhiteSpace((string)_sourceValue) == false); | |
} | |
public object GetSourceValue(string culture = null, string segment = null) | |
{ | |
return _sourceValue; | |
} | |
public object GetValue(string culture = null, string segment = null) | |
{ | |
var source = PropertyType.ConvertSourceToInter(_content, _sourceValue, _isPreviewing); | |
return PropertyType.ConvertInterToObject(_content, PropertyCacheLevel.Unknown, source, _isPreviewing); | |
} | |
public object GetXPathValue(string culture = null, string segment = null) | |
{ | |
var source = PropertyType.ConvertSourceToInter(_content, _sourceValue, _isPreviewing); | |
return PropertyType.ConvertInterToXPath(_content, PropertyCacheLevel.Unknown, source, _isPreviewing); | |
} | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
builder.Services.AddSingleton<PublishedContentWrapperFactory>(); | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment