U4-9935 UmbracoHelper doesn't have querying methods for handling UDI

This commit is contained in:
Shannon
2017-05-19 11:42:58 +10:00
parent 120cb964a5
commit 54967e0150
12 changed files with 256 additions and 140 deletions

View File

@@ -1,23 +1,22 @@
using Umbraco.Core;
using System;
using System.ComponentModel;
using Umbraco.Core;
using Umbraco.Core.Models;
namespace Umbraco.Web.Extensions
{
[Obsolete("Use methods on UmbracoHelper instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static class UdiExtensions
{
/// <summary>
/// An extension method to easily acquire a typed version of content, media or member item for a given Udi
/// </summary>
/// <param name="udi"></param>
/// <returns>An <see cref="IPublishedContent"/> item if the item is a Document, Media or Member</returns>
[Obsolete("Use methods on UmbracoHelper instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static IPublishedContent ToPublishedContent(this Udi udi)
{
Udi identifier;
if (Udi.TryParse(udi.ToString(), out identifier) == false)
return null;
var guidUdi = udi as GuidUdi;
if (guidUdi == null) return null;
var guidUdi = GuidUdi.Parse(udi.ToString());
var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(identifier.EntityType);
var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(guidUdi.EntityType);
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
var entityService = ApplicationContext.Current.Services.EntityService;

View File

@@ -11,8 +11,20 @@ namespace Umbraco.Web
/// </summary>
public interface ITypedPublishedContentQuery
{
/// <summary>
/// Gets a content item from the cache
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IPublishedContent TypedContent(int id);
/// <summary>
/// Gets a content item from the cache
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IPublishedContent TypedContent(Guid id);
IPublishedContent TypedContentSingleAtXPath(string xpath, params XPathVariable[] vars);
IEnumerable<IPublishedContent> TypedContent(IEnumerable<int> ids);
IEnumerable<IPublishedContent> TypedContent(IEnumerable<Guid> ids);
@@ -20,8 +32,8 @@ namespace Umbraco.Web
IEnumerable<IPublishedContent> TypedContentAtXPath(XPathExpression xpath, params XPathVariable[] vars);
IEnumerable<IPublishedContent> TypedContentAtRoot();
// note: we CANNOT implement TypedMedia by Guid in v7 without break-changing IPublishedCache,
// since we don't support XPath navigation of the media tree.
// TODO: we CANNOT implement TypedMedia by Guid in v7 without break-changing IPublishedCache, since we don't support XPath navigation of the media tree.
// surely there is a way we can support this without XPath, it's needed so we can query properly by UDI
IPublishedContent TypedMedia(int id);
//IPublishedContent TypedMedia(Guid id);

View File

@@ -106,25 +106,26 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
return null;
}
if (UmbracoContext.Current != null)
if (UmbracoContext.Current == null) return source;
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.Contains(propertyType.PropertyTypeAlias.ToLower(CultureInfo.InvariantCulture))) == false)
{
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.Contains(propertyType.PropertyTypeAlias.ToLower(CultureInfo.InvariantCulture))) == false)
IPublishedContent content;
if (source is int)
{
IPublishedContent content;
if (source is int)
{
var sourceInt = (int)source;
content = UmbracoContext.Current.ContentCache.GetById(sourceInt);
if(content != null)
return content;
}
else
{
var sourceUdi = source as Udi;
content = sourceUdi.ToPublishedContent();
if (content != null)
return content;
}
var sourceInt = (int)source;
content = UmbracoContext.Current.ContentCache.GetById(sourceInt);
if(content != null)
return content;
}
else
{
var sourceUdi = source as Udi;
if (sourceUdi == null) return null;
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
content = umbHelper.TypedContent(sourceUdi);
if (content != null)
return content;
}
}
return source;

View File

@@ -42,37 +42,38 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
try
{
var obj = JsonConvert.DeserializeObject<JArray>(sourceString);
//update the internal links if we have a context
if (UmbracoContext.Current != null)
if (UmbracoContext.Current == null) return obj;
var helper = new UmbracoHelper(UmbracoContext.Current);
foreach (var a in obj)
{
var helper = new UmbracoHelper(UmbracoContext.Current);
foreach (var a in obj)
var type = a.Value<string>("type");
if (type.IsNullOrWhiteSpace() == false)
{
var type = a.Value<string>("type");
if (type.IsNullOrWhiteSpace() == false)
if (type == "internal")
{
if (type == "internal")
switch (propertyType.PropertyEditorAlias)
{
switch (propertyType.PropertyEditorAlias)
{
case Constants.PropertyEditors.RelatedLinksAlias:
var intLinkId = a.Value<int>("link");
var intLink = helper.NiceUrl(intLinkId);
a["link"] = intLink;
break;
case Constants.PropertyEditors.RelatedLinks2Alias:
var strLinkId = a.Value<string>("link");
var udiAttempt = strLinkId.TryConvertTo<Udi>();
if (udiAttempt)
{
var content = udiAttempt.Result.ToPublishedContent();
a["link"] = helper.NiceUrl(content.Id);
}
break;
}
}
case Constants.PropertyEditors.RelatedLinksAlias:
var intLinkId = a.Value<int>("link");
var intLink = helper.NiceUrl(intLinkId);
a["link"] = intLink;
break;
case Constants.PropertyEditors.RelatedLinks2Alias:
var strLinkId = a.Value<string>("link");
var udiAttempt = strLinkId.TryConvertTo<Udi>();
if (udiAttempt)
{
var content = helper.TypedContent(udiAttempt.Result);
if (content == null) break;
a["link"] = helper.NiceUrl(content.Id);
}
break;
}
}
}
}
}
return obj;
}

View File

@@ -173,11 +173,13 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
var udis = (Udi[])source;
var mediaItems = new List<IPublishedContent>();
if (UmbracoContext.Current == null) return source;
var helper = new UmbracoHelper(UmbracoContext.Current);
if (udis.Any())
{
foreach (var udi in udis)
{
var item = udi.ToPublishedContent();
var item = helper.TypedMedia(udi);
if (item != null)
mediaItems.Add(item);
}

View File

@@ -41,23 +41,22 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
if (source == null)
return null;
if (UmbracoContext.Current != null)
if (UmbracoContext.Current == null) return source;
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
IPublishedContent member;
if (source is int)
{
member = umbracoHelper.TypedMember((int)source);
if (member != null)
return member;
}
else
{
IPublishedContent member;
if (source is int)
{
var membershipHelper = new MembershipHelper(UmbracoContext.Current);
member = membershipHelper.GetById((int)source);
if (member != null)
return member;
}
else
{
var sourceUdi = source as Udi;
member = sourceUdi.ToPublishedContent();
if (member != null)
return member;
}
var sourceUdi = source as Udi;
member = umbracoHelper.TypedMember(sourceUdi);
if (member != null)
return member;
}
return source;

View File

@@ -119,68 +119,67 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
}
//TODO: Inject an UmbracoHelper and create a GetUmbracoHelper method based on either injected or singleton
if (UmbracoContext.Current != null)
if (UmbracoContext.Current == null) return source;
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePickerAlias))
{
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePickerAlias))
var nodeIds = (int[])source;
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.InvariantContains(propertyType.PropertyTypeAlias)) == false)
{
var nodeIds = (int[])source;
var multiNodeTreePicker = new List<IPublishedContent>();
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.InvariantContains(propertyType.PropertyTypeAlias)) == false)
var objectType = UmbracoObjectTypes.Unknown;
foreach (var nodeId in nodeIds)
{
var multiNodeTreePicker = new List<IPublishedContent>();
var multiNodeTreePickerItem =
GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
if (nodeIds.Length > 0)
if (multiNodeTreePickerItem != null)
{
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
var objectType = UmbracoObjectTypes.Unknown;
foreach (var nodeId in nodeIds)
{
var multiNodeTreePickerItem =
GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
if (multiNodeTreePickerItem != null)
{
multiNodeTreePicker.Add(multiNodeTreePickerItem);
}
}
multiNodeTreePicker.Add(multiNodeTreePickerItem);
}
return multiNodeTreePicker;
}
// return the first nodeId as this is one of the excluded properties that expects a single id
return nodeIds.FirstOrDefault();
return multiNodeTreePicker;
}
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePicker2Alias))
// return the first nodeId as this is one of the excluded properties that expects a single id
return nodeIds.FirstOrDefault();
}
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePicker2Alias))
{
var udis = (Udi[])source;
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.InvariantContains(propertyType.PropertyTypeAlias)) == false)
{
var udis = (Udi[])source;
var multiNodeTreePicker = new List<IPublishedContent>();
if ((propertyType.PropertyTypeAlias != null && PropertiesToExclude.InvariantContains(propertyType.PropertyTypeAlias)) == false)
var objectType = UmbracoObjectTypes.Unknown;
foreach (var udi in udis)
{
var multiNodeTreePicker = new List<IPublishedContent>();
if (udis.Length > 0)
var multiNodeTreePickerItem =
GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
if (multiNodeTreePickerItem != null)
{
foreach (var udi in udis)
{
var item = udi.ToPublishedContent();
if (item != null)
{
multiNodeTreePicker.Add(item);
}
}
multiNodeTreePicker.Add(multiNodeTreePickerItem);
}
return multiNodeTreePicker;
}
// return the first nodeId as this is one of the excluded properties that expects a single id
return udis.FirstOrDefault();
return multiNodeTreePicker;
}
// return the first nodeId as this is one of the excluded properties that expects a single id
return udis.FirstOrDefault();
}
return source;
}
@@ -193,7 +192,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
/// <param name="expectedType">The type of content expected/supported by <paramref name="contentFetcher"/></param>
/// <param name="contentFetcher">A function to fetch content of type <paramref name="expectedType"/></param>
/// <returns>The requested content, or null if either it does not exist or <paramref name="actualType"/> does not match <paramref name="expectedType"/></returns>
private IPublishedContent GetPublishedContent(int nodeId, ref UmbracoObjectTypes actualType, UmbracoObjectTypes expectedType, Func<int, IPublishedContent> contentFetcher)
private IPublishedContent GetPublishedContent<T>(T nodeId, ref UmbracoObjectTypes actualType, UmbracoObjectTypes expectedType, Func<T, IPublishedContent> contentFetcher)
{
// is the actual type supported by the content fetcher?
if (actualType != UmbracoObjectTypes.Unknown && actualType != expectedType)

View File

@@ -88,6 +88,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
var relatedLinksData = JsonConvert.DeserializeObject<IEnumerable<RelatedLink>>(sourceString);
var relatedLinks = new List<RelatedLink>();
if (UmbracoContext.Current == null) return source;
var helper = new UmbracoHelper(UmbracoContext.Current);
foreach (var linkData in relatedLinksData)
{
var relatedLink = new RelatedLink
@@ -111,7 +115,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
var udiAttempt = strLinkId.TryConvertTo<Udi>();
if (udiAttempt.Success)
{
var content = udiAttempt.Result.ToPublishedContent();
var content = helper.TypedContent(udiAttempt.Result);
if (content != null)
{
relatedLink.Id = content.Id;

View File

@@ -12,7 +12,11 @@ namespace Umbraco.Web.PublishedCache
/// Provides access to cached contents in a specified context.
/// </summary>
public abstract class ContextualPublishedCache
{
{
//TODO: We need to add:
//* GetById(Guid contentId)
//* GetById(UDI contentId)
protected readonly UmbracoContext UmbracoContext;
/// <summary>

View File

@@ -0,0 +1,23 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Models;
namespace Umbraco.Web
{
public static class PublishedContentQueryExtensions
{
/// <summary>
/// Gets a content item from the cache
/// </summary>
/// <param name="contentQuery"></param>
/// <param name="id"></param>
/// <returns></returns>
public static IPublishedContent TypedContent(this ITypedPublishedContentQuery contentQuery, Udi id)
{
var guidUdi = id as GuidUdi;
if (guidUdi == null)
throw new InvalidOperationException("UDIs for content items must be " + typeof(GuidUdi));
return contentQuery.TypedContent(guidUdi.Guid);
}
}
}

View File

@@ -412,6 +412,7 @@
<Compile Include="PropertyEditors\ValueConverters\MemberPickerPropertyConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MultiNodeTreePickerPropertyConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MultipleMediaPickerPropertyConverter.cs" />
<Compile Include="PublishedContentQueryExtensions.cs" />
<Compile Include="Routing\RedirectTrackingEventHandler.cs" />
<Compile Include="Editors\RedirectUrlManagementController.cs" />
<Compile Include="Models\ContentEditing\RedirectUrlSearchResults.cs" />

View File

@@ -527,11 +527,23 @@ namespace Umbraco.Web
public string UrlAbsolute(int contentId)
{
return UrlProvider.GetUrl(contentId, true);
}
#endregion
#region Members
public IPublishedContent TypedMember(Udi id)
{
var guidUdi = id as GuidUdi;
if (guidUdi == null) return null;
return TypedMember(guidUdi.Guid);
}
#endregion
#region Members
public IPublishedContent TypedMember(Guid id)
{
return MembershipHelper.GetByProviderKey(id);
}
public IPublishedContent TypedMember(object id)
{
@@ -593,6 +605,9 @@ namespace Umbraco.Web
Guid guidId;
if (ConvertIdObjectToGuid(id, out guidId))
return ContentQuery.TypedContent(guidId);
Udi udiId;
if (ConvertIdObjectToUdi(id, out udiId))
return ContentQuery.TypedContent(udiId);
return null;
}
@@ -615,6 +630,16 @@ namespace Umbraco.Web
{
return ContentQuery.TypedContent(id);
}
/// <summary>
/// Gets a content item from the cache
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public IPublishedContent TypedContent(Udi id)
{
return ContentQuery.TypedContent(id);
}
/// <summary>
/// Gets a content item from the cache.
@@ -907,6 +932,22 @@ namespace Umbraco.Web
return false;
}
private static bool ConvertIdObjectToUdi(object id, out Udi guidId)
{
var s = id as string;
if (s != null)
{
return Udi.TryParse(s, out guidId);
}
if (id is Udi)
{
guidId = (Udi)id;
return true;
}
guidId = null;
return false;
}
private static bool ConvertIdsObjectToInts(IEnumerable<object> ids, out IEnumerable<int> intIds)
{
var list = new List<int>();
@@ -937,29 +978,59 @@ namespace Umbraco.Web
}
guidIds = list;
return true;
}
#endregion
#region Media
public IPublishedContent TypedMedia(Udi id)
{
var guidUdi = id as GuidUdi;
if (guidUdi == null) return null;
return TypedMedia(guidUdi.Guid);
}
#endregion
public IPublishedContent TypedMedia(Guid id)
{
//TODO: This is horrible but until the media cache properly supports GUIDs we have no choice here and
// currently there won't be any way to add this method correctly to `ITypedPublishedContentQuery` without breaking an interface and adding GUID support for media
var entityService = UmbracoContext.Application.Services.EntityService;
var mediaAttempt = entityService.GetIdForKey(id, UmbracoObjectTypes.Media);
return mediaAttempt.Success ? ContentQuery.TypedMedia(mediaAttempt.Result) : null;
}
/// <summary>
/// Overloaded method accepting an 'object' type
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <remarks>
/// We accept an object type because GetPropertyValue now returns an 'object', we still want to allow people to pass
/// this result in to this method.
/// This method will throw an exception if the value is not of type int or string.
/// </remarks>
public IPublishedContent TypedMedia(object id)
{
return TypedMediaForObject(id);
}
#region Media
/// <summary>
/// Overloaded method accepting an 'object' type
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <remarks>
/// We accept an object type because GetPropertyValue now returns an 'object', we still want to allow people to pass
/// this result in to this method.
/// This method will throw an exception if the value is not of type int or string.
/// </remarks>
public IPublishedContent TypedMedia(object id)
{
private IPublishedContent TypedMediaForObject(object id)
{
int intId;
return ConvertIdObjectToInt(id, out intId) ? ContentQuery.TypedMedia(intId) : null;
}
public IPublishedContent TypedMedia(int id)
if (ConvertIdObjectToInt(id, out intId))
return ContentQuery.TypedMedia(intId);
Guid guidId;
if (ConvertIdObjectToGuid(id, out guidId))
return TypedMedia(guidId);
Udi udiId;
if (ConvertIdObjectToUdi(id, out udiId))
return TypedMedia(udiId);
return null;
}
public IPublishedContent TypedMedia(int id)
{
return ContentQuery.TypedMedia(id);
}