Merge remote-tracking branch 'origin/netcore/dev' into netcore/feature/AB3594_move_exsiting_configuration_to_own_project

This commit is contained in:
Bjarke Berg
2019-11-13 12:45:34 +01:00
30 changed files with 544 additions and 586 deletions

View File

@@ -39,29 +39,6 @@ namespace Umbraco.Core
Guid = guid;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent GuidUdi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>A GuidUdi instance that contains the value that was parsed.</returns>
public new static GuidUdi Parse(string s)
{
var udi = Udi.Parse(s);
if (udi is GuidUdi == false)
throw new FormatException("String \"" + s + "\" is not a guid entity id.");
return (GuidUdi) udi;
}
public static bool TryParse(string s, out GuidUdi udi)
{
Udi tmp;
udi = null;
if (TryParse(s, out tmp) == false) return false;
udi = tmp as GuidUdi;
return udi != null;
}
public override bool Equals(object obj)
{
var other = obj as GuidUdi;

View File

@@ -49,29 +49,6 @@ namespace Umbraco.Core
return string.Join("/", s.Split('/').Select(Uri.EscapeDataString));
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent StringUdi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>A StringUdi instance that contains the value that was parsed.</returns>
public new static StringUdi Parse(string s)
{
var udi = Udi.Parse(s);
if (udi is StringUdi == false)
throw new FormatException("String \"" + s + "\" is not a string entity id.");
return (StringUdi) udi;
}
public static bool TryParse(string s, out StringUdi udi)
{
udi = null;
Udi tmp;
if (TryParse(s, out tmp) == false || tmp is StringUdi == false) return false;
udi = (StringUdi) tmp;
return true;
}
/// <inheritdoc/>
public override bool IsRoot
{

View File

@@ -0,0 +1,171 @@
using System;
using System.ComponentModel;
using System.Linq;
namespace Umbraco.Core
{
/// <summary>
/// Represents an entity identifier.
/// </summary>
/// <remarks>An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.</remarks>
[TypeConverter(typeof(UdiTypeConverter))]
public abstract class Udi : IComparable<Udi>
{
public Uri UriValue { get; }
/// <summary>
/// Initializes a new instance of the Udi class.
/// </summary>
/// <param name="entityType">The entity type part of the identifier.</param>
/// <param name="stringValue">The string value of the identifier.</param>
protected Udi(string entityType, string stringValue)
{
EntityType = entityType;
UriValue = new Uri(stringValue);
}
/// <summary>
/// Initializes a new instance of the Udi class.
/// </summary>
/// <param name="uriValue">The uri value of the identifier.</param>
protected Udi(Uri uriValue)
{
EntityType = uriValue.Host;
UriValue = uriValue;
}
/// <summary>
/// Gets the entity type part of the identifier.
/// </summary>
public string EntityType { get; private set; }
public int CompareTo(Udi other)
{
return string.Compare(UriValue.ToString(), other.UriValue.ToString(), StringComparison.InvariantCultureIgnoreCase);
}
public override string ToString()
{
// UriValue is created in the ctor and is never null
// use AbsoluteUri here and not ToString else it's not encoded!
return UriValue.AbsoluteUri;
}
/// <summary>
/// Creates a root Udi for an entity type.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns>The root Udi for the entity type.</returns>
public static Udi Create(string entityType)
{
return UdiParser.GetRootUdi(entityType);
}
/// <summary>
/// Creates a string Udi.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="id">The identifier.</param>
/// <returns>The string Udi for the entity type and identifier.</returns>
public static Udi Create(string entityType, string id)
{
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (string.IsNullOrWhiteSpace(id))
throw new ArgumentException("Value cannot be null or whitespace.", "id");
if (udiType != UdiType.StringUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have string udis.", entityType));
return new StringUdi(entityType, id);
}
/// <summary>
/// Creates a Guid Udi.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="id">The identifier.</param>
/// <returns>The Guid Udi for the entity type and identifier.</returns>
public static Udi Create(string entityType, Guid id)
{
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (udiType != UdiType.GuidUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
if (id == default(Guid))
throw new ArgumentException("Cannot be an empty guid.", "id");
return new GuidUdi(entityType, id);
}
public static Udi Create(Uri uri)
{
// if it's a know type go fast and use ctors
// else fallback to parsing the string (and guess the type)
if (UdiParser.UdiTypes.TryGetValue(uri.Host, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
if (udiType == UdiType.GuidUdi)
return new GuidUdi(uri);
if (udiType == UdiType.GuidUdi)
return new StringUdi(uri);
throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri));
}
public void EnsureType(params string[] validTypes)
{
if (validTypes.Contains(EntityType) == false)
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
}
/// <summary>
/// Gets a value indicating whether this Udi is a root Udi.
/// </summary>
/// <remarks>A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root.</remarks>
public abstract bool IsRoot { get; }
/// <summary>
/// Ensures that this Udi is not a root Udi.
/// </summary>
/// <returns>This Udi.</returns>
/// <exception cref="Exception">When this Udi is a Root Udi.</exception>
public Udi EnsureNotRoot()
{
if (IsRoot) throw new Exception("Root Udi.");
return this;
}
public override bool Equals(object obj)
{
var other = obj as Udi;
return other != null && GetType() == other.GetType() && UriValue == other.UriValue;
}
public override int GetHashCode()
{
return UriValue.GetHashCode();
}
public static bool operator ==(Udi udi1, Udi udi2)
{
if (ReferenceEquals(udi1, udi2)) return true;
if ((object)udi1 == null || (object)udi2 == null) return false;
return udi1.Equals(udi2);
}
public static bool operator !=(Udi udi1, Udi udi2)
{
return (udi1 == udi2) == false;
}
}
}

View File

@@ -0,0 +1,222 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
namespace Umbraco.Core
{
public sealed class UdiParser
{
private static readonly ConcurrentDictionary<string, Udi> RootUdis = new ConcurrentDictionary<string, Udi>();
internal static ConcurrentDictionary<string, UdiType> UdiTypes { get; private set; }
static UdiParser()
{
// initialize with known (built-in) Udi types
// we will add scanned types later on
UdiTypes = new ConcurrentDictionary<string, UdiType>(GetKnownUdiTypes());
}
/// <summary>
/// Internal API for tests to resets all udi types back to only the known udi types.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static void ResetUdiTypes()
{
UdiTypes = new ConcurrentDictionary<string, UdiType>(GetKnownUdiTypes());
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>An Udi instance that contains the value that was parsed.</returns>
public static Udi Parse(string s)
{
ParseInternal(s, false, false, out var udi);
return udi;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
/// <returns>An Udi instance that contains the value that was parsed.</returns>
/// <remarks>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
/// the entity type was not known, the method succeeds but sets <c>udi</c>to an
/// <see cref="UnknownTypeUdi"/> value.</para>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
/// </remarks>
public static Udi Parse(string s, bool knownTypes)
{
ParseInternal(s, false, knownTypes, out var udi);
return udi;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
public static bool TryParse(string s, out Udi udi)
{
return ParseInternal(s, true, false, out udi);
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
public static bool TryParse<T>(string s, out T udi)
where T : Udi
{
var result = ParseInternal(s, true, false, out var parsed);
if (result && parsed is T)
{
udi = (T)parsed;
return true;
}
udi = null;
return false;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
/// <remarks>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
/// the entity type was not known, the method returns <c>false</c> but still sets <c>udi</c>
/// to an <see cref="UnknownTypeUdi"/> value.</para>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
/// </remarks>
public static bool TryParse(string s, bool knownTypes, out Udi udi)
{
return ParseInternal(s, true, knownTypes, out udi);
}
private static bool ParseInternal(string s, bool tryParse, bool knownTypes, out Udi udi)
{
udi = null;
Uri uri;
if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false
|| Uri.TryCreate(s, UriKind.Absolute, out uri) == false)
{
if (tryParse) return false;
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
}
var entityType = uri.Host;
if (UdiTypes.TryGetValue(entityType, out var udiType) == false)
{
if (knownTypes)
{
// not knowing the type is not an error
// just return the unknown type udi
udi = UnknownTypeUdi.Instance;
return false;
}
if (tryParse) return false;
throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType));
}
var path = uri.AbsolutePath.TrimStart('/');
if (udiType == UdiType.GuidUdi)
{
if (path == string.Empty)
{
udi = GetRootUdi(uri.Host);
return true;
}
if (Guid.TryParse(path, out var guid) == false)
{
if (tryParse) return false;
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
}
udi = new GuidUdi(uri.Host, guid);
return true;
}
if (udiType == UdiType.StringUdi)
{
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path));
return true;
}
if (tryParse) return false;
throw new InvalidOperationException(string.Format("Invalid udi type \"{0}\".", udiType));
}
internal static Udi GetRootUdi(string entityType)
{
return RootUdis.GetOrAdd(entityType, x =>
{
if (UdiTypes.TryGetValue(x, out var udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType));
return udiType == UdiType.StringUdi
? (Udi)new StringUdi(entityType, string.Empty)
: new GuidUdi(entityType, Guid.Empty);
});
}
/// <summary>
/// Registers a custom entity type.
/// </summary>
/// <param name="entityType"></param>
/// <param name="udiType"></param>
public static void RegisterUdiType(string entityType, UdiType udiType) => UdiTypes.TryAdd(entityType, udiType);
public static Dictionary<string, UdiType> GetKnownUdiTypes() =>
new Dictionary<string, UdiType>
{
{ Constants.UdiEntityType.Unknown, UdiType.Unknown },
{ Constants.UdiEntityType.AnyGuid, UdiType.GuidUdi },
{ Constants.UdiEntityType.Document, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentBlueprint, UdiType.GuidUdi },
{ Constants.UdiEntityType.Media, UdiType.GuidUdi },
{ Constants.UdiEntityType.Member, UdiType.GuidUdi },
{ Constants.UdiEntityType.DictionaryItem, UdiType.GuidUdi },
{ Constants.UdiEntityType.Macro, UdiType.GuidUdi },
{ Constants.UdiEntityType.Template, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentType, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentTypeBluePrints, UdiType.GuidUdi },
{ Constants.UdiEntityType.MediaType, UdiType.GuidUdi },
{ Constants.UdiEntityType.MediaTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.DataType, UdiType.GuidUdi },
{ Constants.UdiEntityType.DataTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.MemberType, UdiType.GuidUdi },
{ Constants.UdiEntityType.MemberGroup, UdiType.GuidUdi },
{ Constants.UdiEntityType.RelationType, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsForm, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsPreValue, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsDataSource, UdiType.GuidUdi },
{ Constants.UdiEntityType.AnyString, UdiType.StringUdi },
{ Constants.UdiEntityType.Language, UdiType.StringUdi },
{ Constants.UdiEntityType.MacroScript, UdiType.StringUdi },
{ Constants.UdiEntityType.MediaFile, UdiType.StringUdi },
{ Constants.UdiEntityType.TemplateFile, UdiType.StringUdi },
{ Constants.UdiEntityType.Script, UdiType.StringUdi },
{ Constants.UdiEntityType.PartialView, UdiType.StringUdi },
{ Constants.UdiEntityType.PartialViewMacro, UdiType.StringUdi },
{ Constants.UdiEntityType.Stylesheet, UdiType.StringUdi }
};
}
}

View File

@@ -26,7 +26,7 @@ namespace Umbraco.Core
if (value is string)
{
Udi udi;
if (Udi.TryParse((string)value, out udi))
if (UdiParser.TryParse((string)value, out udi))
{
return udi;
}

View File

@@ -0,0 +1,16 @@
namespace Umbraco.Core
{
internal class UnknownTypeUdi : Udi
{
private UnknownTypeUdi()
: base("unknown", "umb://unknown/")
{ }
public static readonly UnknownTypeUdi Instance = new UnknownTypeUdi();
public override bool IsRoot
{
get { return false; }
}
}
}

View File

@@ -64,7 +64,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
GuidUdi udi = null;
if (relatedLink.IsInternal)
{
var linkIsUdi = GuidUdi.TryParse(relatedLink.Link, out udi);
var linkIsUdi = UdiParser.TryParse(relatedLink.Link, out udi);
if (linkIsUdi == false)
{
// oh no.. probably an integer, yikes!

View File

@@ -1,6 +1,4 @@
using System;
using System.ComponentModel;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.Models
{

View File

@@ -20,7 +20,7 @@ namespace Umbraco.Core.Serialization
{
var jo = JToken.ReadFrom(reader);
var val = jo.ToObject<string>();
return val == null ? null : Udi.Parse(val, true);
return val == null ? null : UdiParser.Parse(val, true);
}
}
}

View File

@@ -20,7 +20,7 @@ namespace Umbraco.Core.Serialization
{
var jo = JToken.ReadFrom(reader);
var val = jo.ToObject<string>();
return val == null ? null : Udi.Parse(val);
return val == null ? null : UdiParser.Parse(val);
}
}
}

View File

@@ -1,385 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Umbraco.Core.Deploy;
using Umbraco.Core.Composing;
namespace Umbraco.Core
{
/// <summary>
/// Represents an entity identifier.
/// </summary>
/// <remarks>An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.</remarks>
[TypeConverter(typeof(UdiTypeConverter))]
public abstract class Udi : IComparable<Udi>
{
// notes - see U4-10409
// if this class is used during application pre-start it cannot scans the assemblies,
// this is addressed by lazily-scanning, with the following caveats:
// - parsing a root udi still requires a scan and therefore still breaks
// - parsing an invalid udi ("umb://should-be-guid/<not-a-guid>") corrupts KnowUdiTypes
private static volatile bool _scanned;
private static readonly object ScanLocker = new object();
private static ConcurrentDictionary<string, UdiType> _udiTypes;
private static readonly ConcurrentDictionary<string, Udi> RootUdis = new ConcurrentDictionary<string, Udi>();
internal readonly Uri UriValue; // internal for UdiRange
/// <summary>
/// Initializes a new instance of the Udi class.
/// </summary>
/// <param name="entityType">The entity type part of the identifier.</param>
/// <param name="stringValue">The string value of the identifier.</param>
protected Udi(string entityType, string stringValue)
{
EntityType = entityType;
UriValue = new Uri(stringValue);
}
/// <summary>
/// Initializes a new instance of the Udi class.
/// </summary>
/// <param name="uriValue">The uri value of the identifier.</param>
protected Udi(Uri uriValue)
{
EntityType = uriValue.Host;
UriValue = uriValue;
}
static Udi()
{
// initialize with known (built-in) Udi types
// we will add scanned types later on
_udiTypes = new ConcurrentDictionary<string, UdiType>(UdiEntityTypeHelper.GetTypes());
}
// for tests, totally unsafe
internal static void ResetUdiTypes()
{
_udiTypes = new ConcurrentDictionary<string, UdiType>(UdiEntityTypeHelper.GetTypes());
_scanned = false;
}
/// <summary>
/// Gets the entity type part of the identifier.
/// </summary>
public string EntityType { get; private set; }
public int CompareTo(Udi other)
{
return string.Compare(UriValue.ToString(), other.UriValue.ToString(), StringComparison.InvariantCultureIgnoreCase);
}
public override string ToString()
{
// UriValue is created in the ctor and is never null
// use AbsoluteUri here and not ToString else it's not encoded!
return UriValue.AbsoluteUri;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>An Udi instance that contains the value that was parsed.</returns>
public static Udi Parse(string s)
{
Udi udi;
ParseInternal(s, false, false, out udi);
return udi;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
/// <returns>An Udi instance that contains the value that was parsed.</returns>
/// <remarks>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
/// the entity type was not known, the method succeeds but sets <c>udi</c>to an
/// <see cref="UnknownTypeUdi"/> value.</para>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
/// </remarks>
public static Udi Parse(string s, bool knownTypes)
{
Udi udi;
ParseInternal(s, false, knownTypes, out udi);
return udi;
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
public static bool TryParse(string s, out Udi udi)
{
return ParseInternal(s, true, false, out udi);
}
/// <summary>
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
/// <remarks>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
/// the entity type was not known, the method returns <c>false</c> but still sets <c>udi</c>
/// to an <see cref="UnknownTypeUdi"/> value.</para>
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
/// </remarks>
public static bool TryParse(string s, bool knownTypes, out Udi udi)
{
return ParseInternal(s, true, knownTypes, out udi);
}
private static bool ParseInternal(string s, bool tryParse, bool knownTypes, out Udi udi)
{
if (knownTypes == false)
EnsureScanForUdiTypes();
udi = null;
Uri uri;
if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false
|| Uri.TryCreate(s, UriKind.Absolute, out uri) == false)
{
if (tryParse) return false;
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
}
var entityType = uri.Host;
UdiType udiType;
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
{
if (knownTypes)
{
// not knowing the type is not an error
// just return the unknown type udi
udi = UnknownTypeUdi.Instance;
return false;
}
if (tryParse) return false;
throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType));
}
var path = uri.AbsolutePath.TrimStart('/');
if (udiType == UdiType.GuidUdi)
{
if (path == string.Empty)
{
udi = GetRootUdi(uri.Host);
return true;
}
Guid guid;
if (Guid.TryParse(path, out guid) == false)
{
if (tryParse) return false;
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
}
udi = new GuidUdi(uri.Host, guid);
return true;
}
if (udiType == UdiType.StringUdi)
{
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path));
return true;
}
if (tryParse) return false;
throw new InvalidOperationException(string.Format("Invalid udi type \"{0}\".", udiType));
}
private static Udi GetRootUdi(string entityType)
{
EnsureScanForUdiTypes();
return RootUdis.GetOrAdd(entityType, x =>
{
UdiType udiType;
if (_udiTypes.TryGetValue(x, out udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType));
return udiType == UdiType.StringUdi
? (Udi)new StringUdi(entityType, string.Empty)
: new GuidUdi(entityType, Guid.Empty);
});
}
/// <summary>
/// When required scan assemblies for known UDI types based on <see cref="IServiceConnector"/> instances
/// </summary>
/// <remarks>
/// This is only required when needing to resolve root udis
/// </remarks>
private static void EnsureScanForUdiTypes()
{
if (_scanned) return;
lock (ScanLocker)
{
// Scan for unknown UDI types
// there is no way we can get the "registered" service connectors, as registration
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
// just pick every service connectors - just making sure that not two of them
// would register the same entity type, with different udi types (would not make
// much sense anyways).
var connectors = Current.TypeLoader.GetTypes<IServiceConnector>();
var result = new Dictionary<string, UdiType>();
foreach (var connector in connectors)
{
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
foreach (var attr in attrs)
{
UdiType udiType;
if (result.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType)
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
result[attr.EntityType] = attr.UdiType;
}
}
// merge these into the known list
foreach (var item in result)
_udiTypes.TryAdd(item.Key, item.Value);
_scanned = true;
}
}
/// <summary>
/// Creates a root Udi for an entity type.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns>The root Udi for the entity type.</returns>
public static Udi Create(string entityType)
{
return GetRootUdi(entityType);
}
/// <summary>
/// Creates a string Udi.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="id">The identifier.</param>
/// <returns>The string Udi for the entity type and identifier.</returns>
public static Udi Create(string entityType, string id)
{
UdiType udiType;
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (string.IsNullOrWhiteSpace(id))
throw new ArgumentException("Value cannot be null or whitespace.", "id");
if (udiType != UdiType.StringUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have string udis.", entityType));
return new StringUdi(entityType, id);
}
/// <summary>
/// Creates a Guid Udi.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="id">The identifier.</param>
/// <returns>The Guid Udi for the entity type and identifier.</returns>
public static Udi Create(string entityType, Guid id)
{
UdiType udiType;
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
if (udiType != UdiType.GuidUdi)
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
if (id == default(Guid))
throw new ArgumentException("Cannot be an empty guid.", "id");
return new GuidUdi(entityType, id);
}
internal static Udi Create(Uri uri)
{
// if it's a know type go fast and use ctors
// else fallback to parsing the string (and guess the type)
UdiType udiType;
if (_udiTypes.TryGetValue(uri.Host, out udiType) == false)
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
if (udiType == UdiType.GuidUdi)
return new GuidUdi(uri);
if (udiType == UdiType.GuidUdi)
return new StringUdi(uri);
throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri));
}
public void EnsureType(params string[] validTypes)
{
if (validTypes.Contains(EntityType) == false)
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
}
/// <summary>
/// Gets a value indicating whether this Udi is a root Udi.
/// </summary>
/// <remarks>A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root.</remarks>
public abstract bool IsRoot { get; }
/// <summary>
/// Ensures that this Udi is not a root Udi.
/// </summary>
/// <returns>This Udi.</returns>
/// <exception cref="Exception">When this Udi is a Root Udi.</exception>
public Udi EnsureNotRoot()
{
if (IsRoot) throw new Exception("Root Udi.");
return this;
}
public override bool Equals(object obj)
{
var other = obj as Udi;
return other != null && GetType() == other.GetType() && UriValue == other.UriValue;
}
public override int GetHashCode()
{
return UriValue.GetHashCode();
}
public static bool operator ==(Udi udi1, Udi udi2)
{
if (ReferenceEquals(udi1, udi2)) return true;
if ((object)udi1 == null || (object)udi2 == null) return false;
return udi1.Equals(udi2);
}
public static bool operator !=(Udi udi1, Udi udi2)
{
return (udi1 == udi2) == false;
}
private class UnknownTypeUdi : Udi
{
private UnknownTypeUdi()
: base("unknown", "umb://unknown/")
{ }
public static readonly UnknownTypeUdi Instance = new UnknownTypeUdi();
public override bool IsRoot
{
get { return false; }
}
}
}
}

View File

@@ -6,43 +6,7 @@ namespace Umbraco.Core
{
public static class UdiEntityTypeHelper
{
internal static Dictionary<string, UdiType> GetTypes() =>
new Dictionary<string, UdiType>
{
{ Constants.UdiEntityType.Unknown, UdiType.Unknown },
{ Constants.UdiEntityType.AnyGuid, UdiType.GuidUdi },
{ Constants.UdiEntityType.Document, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentBlueprint, UdiType.GuidUdi },
{ Constants.UdiEntityType.Media, UdiType.GuidUdi },
{ Constants.UdiEntityType.Member, UdiType.GuidUdi },
{ Constants.UdiEntityType.DictionaryItem, UdiType.GuidUdi },
{ Constants.UdiEntityType.Macro, UdiType.GuidUdi },
{ Constants.UdiEntityType.Template, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentType, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.DocumentTypeBluePrints, UdiType.GuidUdi },
{ Constants.UdiEntityType.MediaType, UdiType.GuidUdi },
{ Constants.UdiEntityType.MediaTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.DataType, UdiType.GuidUdi },
{ Constants.UdiEntityType.DataTypeContainer, UdiType.GuidUdi },
{ Constants.UdiEntityType.MemberType, UdiType.GuidUdi },
{ Constants.UdiEntityType.MemberGroup, UdiType.GuidUdi },
{ Constants.UdiEntityType.RelationType, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsForm, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsPreValue, UdiType.GuidUdi },
{ Constants.UdiEntityType.FormsDataSource, UdiType.GuidUdi },
{ Constants.UdiEntityType.AnyString, UdiType.StringUdi },
{ Constants.UdiEntityType.Language, UdiType.StringUdi },
{ Constants.UdiEntityType.MacroScript, UdiType.StringUdi },
{ Constants.UdiEntityType.MediaFile, UdiType.StringUdi },
{ Constants.UdiEntityType.TemplateFile, UdiType.StringUdi },
{ Constants.UdiEntityType.Script, UdiType.StringUdi },
{ Constants.UdiEntityType.PartialView, UdiType.StringUdi },
{ Constants.UdiEntityType.PartialViewMacro, UdiType.StringUdi },
{ Constants.UdiEntityType.Stylesheet, UdiType.StringUdi }
};
public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType)
{

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Deploy;
using Umbraco.Core.Composing;
namespace Umbraco.Core
{
public static class UdiParserServiceConnectors
{
// notes - see U4-10409
// if this class is used during application pre-start it cannot scans the assemblies,
// this is addressed by lazily-scanning, with the following caveats:
// - parsing a root udi still requires a scan and therefore still breaks
// - parsing an invalid udi ("umb://should-be-guid/<not-a-guid>") corrupts KnowUdiTypes
private static volatile bool _scanned;
private static readonly object ScanLocker = new object();
/// <summary>
/// Scan for deploy <see cref="IServiceConnector"/> in assemblies for known UDI types.
/// </summary>
/// <param name="typeLoader"></param>
public static void ScanDeployServiceConnectorsForUdiTypes(TypeLoader typeLoader)
{
if (typeLoader is null)
throw new ArgumentNullException(nameof(typeLoader));
if (_scanned) return;
lock (ScanLocker)
{
// Scan for unknown UDI types
// there is no way we can get the "registered" service connectors, as registration
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
// just pick every service connectors - just making sure that not two of them
// would register the same entity type, with different udi types (would not make
// much sense anyways)
var connectors = typeLoader.GetTypes<IServiceConnector>();
var result = new Dictionary<string, UdiType>();
foreach (var connector in connectors)
{
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
foreach (var attr in attrs)
{
if (result.TryGetValue(attr.EntityType, out var udiType) && udiType != attr.UdiType)
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
result[attr.EntityType] = attr.UdiType;
}
}
// merge these into the known list
foreach (var item in result)
UdiParser.RegisterUdiType(item.Key, item.Value);
_scanned = true;
}
}
/// <summary>
/// Registers a single <see cref="IServiceConnector"/> to add it's UDI type.
/// </summary>
/// <typeparam name="T"></typeparam>
public static void RegisterServiceConnector<T>()
where T: IServiceConnector
{
var result = new Dictionary<string, UdiType>();
var connector = typeof(T);
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
foreach (var attr in attrs)
{
if (result.TryGetValue(attr.EntityType, out var udiType) && udiType != attr.UdiType)
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
result[attr.EntityType] = attr.UdiType;
}
// merge these into the known list
foreach (var item in result)
UdiParser.RegisterUdiType(item.Key, item.Value);
}
}
}

View File

@@ -446,7 +446,6 @@
<Compile Include="Events\UninstallPackageEventArgs.cs" />
<Compile Include="Composing\LightInject\LightInjectException.cs" />
<Compile Include="FileResources\Files.Designer.cs" />
<Compile Include="GuidUdi.cs" />
<Compile Include="HttpContextExtensions.cs" />
<Compile Include="IO\FileSecurityException.cs" />
<Compile Include="IO\FileSystemExtensions.cs" />
@@ -565,7 +564,6 @@
<Compile Include="Models\UmbracoObjectTypes.cs" />
<Compile Include="Models\UserExtensions.cs" />
<Compile Include="Models\Validation\RequiredForPersistenceAttribute.cs" />
<Compile Include="NamedUdiRange.cs" />
<Compile Include="NameValueCollectionExtensions.cs" />
<Compile Include="ObjectJsonExtensions.cs" />
<Compile Include="Packaging\ConflictingPackageData.cs" />
@@ -993,17 +991,13 @@
<Compile Include="Compose\RelateOnCopyComponent.cs" />
<Compile Include="Compose\RelateOnTrashComponent.cs" />
<Compile Include="Strings\UrlSegmentProviderCollectionBuilder.cs" />
<Compile Include="StringUdi.cs" />
<Compile Include="Sync\ApplicationUrlHelper.cs" />
<Compile Include="Sync\DatabaseServerMessenger.cs" />
<Compile Include="Sync\RefreshInstruction.cs" />
<Compile Include="Sync\ServerMessengerBase.cs" />
<Compile Include="Udi.cs" />
<Compile Include="UdiDefinitionAttribute.cs" />
<Compile Include="UdiEntityTypeHelper.cs" />
<Compile Include="UdiGetterExtensions.cs" />
<Compile Include="UdiRange.cs" />
<Compile Include="UdiTypeConverter.cs" />
<Compile Include="UdiParserServiceConnectors.cs" />
<Compile Include="UriExtensions.cs" />
<Compile Include="PackageActions\IPackageAction.cs" />
<Compile Include="PackageActions\PackageActionCollection.cs" />

View File

@@ -24,21 +24,7 @@ namespace Umbraco.Tests.CoreThings
[SetUp]
public void SetUp()
{
// FIXME: bad in a unit test - but Udi has a static ctor that wants it?!
var container = new Mock<IFactory>();
var ioHelper = IOHelper.Default;
var typeFinder = new TypeFinder(Mock.Of<ILogger>());
container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns(
new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
Current.Factory = container.Object;
Udi.ResetUdiTypes();
}
[TearDown]
public void TearDown()
{
Current.Reset();
UdiParser.ResetUdiTypes();
}
[Test]
@@ -53,7 +39,7 @@ namespace Umbraco.Tests.CoreThings
[Test]
public void StringUdiParseTest()
{
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id");
var udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id");
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
Assert.IsInstanceOf<StringUdi>(udi);
var stringEntityId = udi as StringUdi;
@@ -61,7 +47,7 @@ namespace Umbraco.Tests.CoreThings
Assert.AreEqual("test-id", stringEntityId.Id);
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString());
udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/DA845952BE474EE9BD6F6194272AC750");
udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/DA845952BE474EE9BD6F6194272AC750");
Assert.IsInstanceOf<StringUdi>(udi);
}
@@ -78,7 +64,7 @@ namespace Umbraco.Tests.CoreThings
Assert.AreEqual("%2Fthis%20is%20a%20test", Uri.EscapeDataString("/this is a test"));
Assert.AreEqual("/this%20is%20a%20test", Uri.EscapeUriString("/this is a test"));
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
var udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
Assert.IsInstanceOf<StringUdi>(udi);
var stringEntityId = udi as StringUdi;
@@ -112,7 +98,7 @@ namespace Umbraco.Tests.CoreThings
// with the proper fix in StringUdi this should work:
var udi1 = new StringUdi("partial-view-macro", "path/to/View[1].cshtml");
Assert.AreEqual("umb://partial-view-macro/path/to/View%5B1%5D.cshtml", udi1.ToString());
var udi2 = Udi.Parse("umb://partial-view-macro/path/to/View%5B1%5D.cshtml");
var udi2 = UdiParser.Parse("umb://partial-view-macro/path/to/View%5B1%5D.cshtml");
Assert.AreEqual("path/to/View[1].cshtml", ((StringUdi) udi2).Id);
}
@@ -131,7 +117,7 @@ namespace Umbraco.Tests.CoreThings
{
var guid = Guid.NewGuid();
var s = "umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N");
var udi = Udi.Parse(s);
var udi = UdiParser.Parse(s);
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType);
Assert.IsInstanceOf<GuidUdi>(udi);
var gudi = udi as GuidUdi;
@@ -198,15 +184,15 @@ namespace Umbraco.Tests.CoreThings
Assert.IsTrue(guidUdi.IsRoot);
Assert.AreEqual("umb://any-guid/00000000000000000000000000000000", guidUdi.ToString());
var udi = Udi.Parse("umb://any-string/");
var udi = UdiParser.Parse("umb://any-string/");
Assert.IsTrue(udi.IsRoot);
Assert.IsInstanceOf<StringUdi>(udi);
udi = Udi.Parse("umb://any-guid/00000000000000000000000000000000");
udi = UdiParser.Parse("umb://any-guid/00000000000000000000000000000000");
Assert.IsTrue(udi.IsRoot);
Assert.IsInstanceOf<GuidUdi>(udi);
udi = Udi.Parse("umb://any-guid/");
udi = UdiParser.Parse("umb://any-guid/");
Assert.IsTrue(udi.IsRoot);
Assert.IsInstanceOf<GuidUdi>(udi);
}
@@ -217,13 +203,13 @@ namespace Umbraco.Tests.CoreThings
// can parse open string udi
var stringUdiString = "umb://" + Constants.UdiEntityType.AnyString;
Udi stringUdi;
Assert.IsTrue(Udi.TryParse(stringUdiString, out stringUdi));
Assert.IsTrue(UdiParser.TryParse(stringUdiString, out stringUdi));
Assert.AreEqual(string.Empty, ((StringUdi)stringUdi).Id);
// can parse open guid udi
var guidUdiString = "umb://" + Constants.UdiEntityType.AnyGuid;
Udi guidUdi;
Assert.IsTrue(Udi.TryParse(guidUdiString, out guidUdi));
Assert.IsTrue(UdiParser.TryParse(guidUdiString, out guidUdi));
Assert.AreEqual(Guid.Empty, ((GuidUdi)guidUdi).Guid);
// can create a range
@@ -264,7 +250,7 @@ namespace Umbraco.Tests.CoreThings
[Test]
public void ValidateUdiEntityType()
{
var types = UdiEntityTypeHelper.GetTypes();
var types = UdiParser.GetKnownUdiTypes();
foreach (var fi in typeof(Constants.UdiEntityType).GetFields(BindingFlags.Public | BindingFlags.Static))
{
@@ -294,33 +280,34 @@ namespace Umbraco.Tests.CoreThings
// cannot parse an unknown type, udi is null
// this will scan
Assert.IsFalse(Udi.TryParse("umb://whatever/1234", out udi));
Assert.IsFalse(UdiParser.TryParse("umb://whatever/1234", out udi));
Assert.IsNull(udi);
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
// unless we want to know
Assert.IsFalse(Udi.TryParse("umb://whatever/1234", true, out udi));
Assert.IsFalse(UdiParser.TryParse("umb://whatever/1234", true, out udi));
Assert.AreEqual(Constants.UdiEntityType.Unknown, udi.EntityType);
Assert.AreEqual("Umbraco.Core.Udi+UnknownTypeUdi", udi.GetType().FullName);
Udi.ResetUdiTypes();
Assert.AreEqual("Umbraco.Core.UnknownTypeUdi", udi.GetType().FullName);
UdiParser.ResetUdiTypes();
// not known
Assert.IsFalse(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
Assert.IsFalse(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
Assert.AreEqual(Constants.UdiEntityType.Unknown, udi.EntityType);
Assert.AreEqual("Umbraco.Core.Udi+UnknownTypeUdi", udi.GetType().FullName);
Assert.AreEqual("Umbraco.Core.UnknownTypeUdi", udi.GetType().FullName);
// scanned
Assert.IsTrue(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", out udi));
// scanned
UdiParserServiceConnectors.RegisterServiceConnector<FooConnector>(); // this is the equivalent of scanning but we'll just manually register this one
Assert.IsTrue(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", out udi));
Assert.IsInstanceOf<GuidUdi>(udi);
// known
Assert.IsTrue(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
Assert.IsTrue(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
Assert.IsInstanceOf<GuidUdi>(udi);
// can get method for Deploy compatibility
var method = typeof(Udi).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(bool) }, null);
var method = typeof(UdiParser).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(bool) }, null);
Assert.IsNotNull(method);
}

View File

@@ -1,14 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Web;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
@@ -17,10 +13,7 @@ using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Templates;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Tests.Web
{
@@ -30,37 +23,9 @@ namespace Umbraco.Tests.Web
[SetUp]
public void SetUp()
{
Current.Reset();
// FIXME: now UrlProvider depends on EntityService for GetUrl(guid) - this is bad
// should not depend on more than IdkMap maybe - fix this!
var entityService = new Mock<IEntityService>();
entityService.Setup(x => x.GetId(It.IsAny<Guid>(), It.IsAny<UmbracoObjectTypes>())).Returns(Attempt<int>.Fail());
var serviceContext = ServiceContext.CreatePartial(entityService: entityService.Object);
// FIXME: bad in a unit test - but Udi has a static ctor that wants it?!
var factory = new Mock<IFactory>();
var typeFinder = new TypeFinder(Mock.Of<ILogger>());
var ioHelper = IOHelper.Default;
factory.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns(
new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
factory.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext);
var settings = SettingsForTests.GetDefaultUmbracoSettings();
factory.Setup(x => x.GetInstance(typeof(IUmbracoSettingsSection))).Returns(settings);
Current.Factory = factory.Object;
Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor();
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
}
[TearDown]
public void TearDown()
{
Current.Reset();
}
[TestCase("", "")]
[TestCase("hello href=\"{localLink:1234}\" world ", "hello href=\"/my-test-url\" world ")]
@@ -71,17 +36,7 @@ namespace Umbraco.Tests.Web
[TestCase("hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"#\" world ")]
public void ParseLocalLinks(string input, string result)
{
var serviceCtxMock = new TestObjects(null).GetServiceContextMock();
//setup a mock entity service from the service context to return an integer for a GUID
var entityService = Mock.Get(serviceCtxMock.EntityService);
//entityService.Setup(x => x.GetId(It.IsAny<Guid>(), It.IsAny<UmbracoObjectTypes>()))
// .Returns((Guid id, UmbracoObjectTypes objType) =>
// {
// return Attempt.Succeed(1234);
// });
{
//setup a mock url provider which we'll use for testing
var testUrlProvider = new Mock<IUrlProvider>();
testUrlProvider
@@ -106,8 +61,9 @@ namespace Umbraco.Tests.Web
var mediaCache = Mock.Of<IPublishedMediaCache>();
Mock.Get(mediaCache).Setup(x => x.GetById(It.IsAny<Guid>())).Returns(media);
var umbracoContextAccessor = new TestUmbracoContextAccessor();
var umbracoContextFactory = new UmbracoContextFactory(
Umbraco.Web.Composing.Current.UmbracoContextAccessor,
umbracoContextAccessor,
snapshotService,
new TestVariationContextAccessor(),
new TestDefaultCultureAccessor(),

View File

@@ -176,7 +176,7 @@ namespace Umbraco.Tests.Web
public static void Converting_Boxed_Udi_To_A_Udi_Returns_Original_Udi_Value()
{
// Arrange
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
Udi sample = new GuidUdi(Constants.UdiEntityType.AnyGuid, Guid.NewGuid());
// Act
@@ -198,7 +198,7 @@ namespace Umbraco.Tests.Web
{
// Arrange
SetUpDependencyContainer();
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
Udi sample = new GuidUdi(Constants.UdiEntityType.AnyGuid, Guid.NewGuid());
// Act
@@ -220,7 +220,7 @@ namespace Umbraco.Tests.Web
{
// Arrange
SetUpDependencyContainer();
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
const string sample = "Hello";
// Act
@@ -241,7 +241,7 @@ namespace Umbraco.Tests.Web
public static void Converting_Unsupported_Object_To_A_Udi_Returns_False()
{
// Arrange
Udi.ResetUdiTypes();
UdiParser.ResetUdiTypes();
var clearlyWillNotConvertToGuid = new StringBuilder(0);

View File

@@ -509,7 +509,7 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
if (Udi.TryParse(id, out _))
if (UdiParser.TryParse(id, out _))
{
//Not supported currently
throw new HttpResponseException(HttpStatusCode.NotFound);

View File

@@ -793,10 +793,9 @@ namespace Umbraco.Web.Editors
private int GetParentIdAsInt(string parentId, bool validatePermissions)
{
int intParentId;
GuidUdi parentUdi;
// test for udi
if (GuidUdi.TryParse(parentId, out parentUdi))
if (UdiParser.TryParse(parentId, out GuidUdi parentUdi))
{
parentId = parentUdi.Guid.ToString();
}

View File

@@ -67,7 +67,7 @@ namespace Umbraco.Web.Editors
public RedirectUrlSearchResult RedirectUrlsForContentItem(string contentUdi)
{
var redirectsResult = new RedirectUrlSearchResult();
if (GuidUdi.TryParse(contentUdi, out var guidIdi))
if (UdiParser.TryParse(contentUdi, out GuidUdi guidIdi))
{
var redirectUrlService = Services.RedirectUrlService;
var redirects = redirectUrlService.GetContentRedirectUrls(guidIdi.Guid);

View File

@@ -58,7 +58,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
var nodeIds = source.ToString()
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(Udi.Parse)
.Select(UdiParser.Parse)
.ToArray();
return nodeIds;
}

View File

@@ -55,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
{
var nodeIds = source.ToString()
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(Udi.Parse)
.Select(UdiParser.Parse)
.ToArray();
return nodeIds;
}

View File

@@ -326,7 +326,7 @@ namespace Umbraco.Web.Search
if (sb == null) throw new ArgumentNullException(nameof(sb));
if (entityService == null) throw new ArgumentNullException(nameof(entityService));
Udi.TryParse(searchFrom, true, out var udi);
UdiParser.TryParse(searchFrom, true, out var udi);
searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString();
var entityPath = int.TryParse(searchFrom, out var searchFromId) && searchFromId > 0

View File

@@ -59,7 +59,7 @@ namespace Umbraco.Web.Templates
var id = tag.Groups[1].Value; //.Remove(tag.Groups[1].Value.Length - 1, 1);
//The id could be an int or a UDI
if (Udi.TryParse(id, out var udi))
if (UdiParser.TryParse(id, out var udi))
{
var guidUdi = udi as GuidUdi;
if (guidUdi != null)
@@ -166,7 +166,7 @@ namespace Umbraco.Web.Templates
// - 4 = the data-udi attribute value
// - 5 = anything after group 4 until the image tag is closed
var udi = match.Groups[4].Value;
if(udi.IsNullOrWhiteSpace() || GuidUdi.TryParse(udi, out var guidUdi) == false)
if(udi.IsNullOrWhiteSpace() || UdiParser.TryParse(udi, out GuidUdi guidUdi) == false)
{
return match.Value;
}

View File

@@ -491,7 +491,7 @@ namespace Umbraco.Web.Trees
{
return new Tuple<Guid?, int?>(null, idInt);
}
if (Udi.TryParse(id, out idUdi))
if (UdiParser.TryParse(id, out idUdi))
{
var guidUdi = idUdi as GuidUdi;
if (guidUdi != null)
@@ -523,7 +523,7 @@ namespace Umbraco.Web.Trees
{
entity = Services.EntityService.Get(idInt, UmbracoObjectType);
}
else if (Udi.TryParse(s, out var idUdi))
else if (UdiParser.TryParse(s, out var idUdi))
{
var guidUdi = idUdi as GuidUdi;
entity = guidUdi != null ? Services.EntityService.Get(guidUdi.Guid, UmbracoObjectType) : null;

View File

@@ -621,7 +621,7 @@ namespace Umbraco.Web
switch (id)
{
case string s:
return Udi.TryParse(s, out guidId);
return UdiParser.TryParse(s, out guidId);
case Udi u:
guidId = u;

View File

@@ -87,7 +87,7 @@ namespace Umbraco.Web.WebApi.Filters
{
nodeId = parsedId;
}
else if (Udi.TryParse(argument, true, out Udi udi))
else if (UdiParser.TryParse(argument, true, out Udi udi))
{
// TODO: inject? we can't because this is an attribute but we could provide ctors and empty ctors that pass in the required services
nodeId = Current.Services.EntityService.GetId(udi).Result;