diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index faca2e14f4..60c7d0ed22 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -86,8 +86,8 @@ public class AppCaches : IDisposable { if (disposing) { - RuntimeCache.DisposeIfDisposable(); - RequestCache.DisposeIfDisposable(); + (RuntimeCache as IDisposable)?.Dispose(); + (RequestCache as IDisposable)?.Dispose(); IsolatedCaches.Dispose(); } diff --git a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs index 1cf3b1461e..788e95f909 100644 --- a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs +++ b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs @@ -81,9 +81,9 @@ public abstract class AppPolicedCacheDictionary : IDisposable { if (disposing) { - foreach (IAppPolicyCache value in _caches.Values) + foreach (IDisposable value in _caches.Values.OfType()) { - value.DisposeIfDisposable(); + value.Dispose(); } } diff --git a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs index acbc5b37a7..ae9fb11c96 100644 --- a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs +++ b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs @@ -135,7 +135,7 @@ public class DeepCloneAppCache : IAppPolicyCache, IDisposable { if (disposing) { - InnerCache.DisposeIfDisposable(); + (InnerCache as IDisposable)?.Dispose(); } _disposedValue = true; diff --git a/src/Umbraco.Core/Composing/ComponentCollection.cs b/src/Umbraco.Core/Composing/ComponentCollection.cs index ba49a6f482..3d1b2c5c26 100644 --- a/src/Umbraco.Core/Composing/ComponentCollection.cs +++ b/src/Umbraco.Core/Composing/ComponentCollection.cs @@ -59,6 +59,7 @@ public class ComponentCollection : BuilderCollectionBase try { await component.TerminateAsync(isRestarting, cancellationToken); + (component as IDisposable)?.Dispose(); } catch (Exception ex) { diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs index 0b6c268b78..83b377493a 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs @@ -1,6 +1,4 @@ -using Umbraco.Cms.Core.Extensions; using Umbraco.Cms.Core.Scoping; -using Umbraco.Extensions; namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; @@ -30,7 +28,9 @@ public class FurthestAncestorOrSelfDynamicRootQueryStep : IDynamicRootQueryStep } using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); - var result = (await _nodeFilterRepository.FurthestAncestorOrSelfAsync(origins, filter))?.ToSingleItemCollection() ?? Array.Empty(); + var result = (await _nodeFilterRepository.FurthestAncestorOrSelfAsync(origins, filter)) is Guid key + ? [key] + : Array.Empty(); return Attempt>.Succeed(result); } diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs index 8378d841d4..8fd8016160 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs @@ -1,6 +1,4 @@ -using Umbraco.Cms.Core.Extensions; using Umbraco.Cms.Core.Scoping; -using Umbraco.Extensions; namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; @@ -30,7 +28,9 @@ public class NearestAncestorOrSelfDynamicRootQueryStep : IDynamicRootQueryStep } using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); - var result = (await _nodeFilterRepository.NearestAncestorOrSelfAsync(origins, filter))?.ToSingleItemCollection() ?? Array.Empty(); + var result = (await _nodeFilterRepository.NearestAncestorOrSelfAsync(origins, filter)) is Guid key + ? [key] + : Array.Empty(); return Attempt>.Succeed(result); } diff --git a/src/Umbraco.Core/Extensions/AssemblyExtensions.cs b/src/Umbraco.Core/Extensions/AssemblyExtensions.cs index 488dc38c3c..5cd48d6fb4 100644 --- a/src/Umbraco.Core/Extensions/AssemblyExtensions.cs +++ b/src/Umbraco.Core/Extensions/AssemblyExtensions.cs @@ -42,20 +42,6 @@ public static class AssemblyExtensions return _rootDir; } - /// - /// Returns the file used to load the assembly - /// - /// - /// - [Obsolete("This extension method is no longer used and will be removed in Umbraco 17.")] - public static FileInfo GetAssemblyFile(this Assembly assembly) - { - var codeBase = assembly.Location; - var uri = new Uri(codeBase); - var path = uri.LocalPath; - return new FileInfo(path); - } - /// /// Returns true if the assembly is the App_Code assembly /// @@ -90,25 +76,6 @@ public static class AssemblyExtensions // only way I can figure out how to test is by the name assembly.FullName!.StartsWith("App_global.asax"); - /// - /// Returns the file used to load the assembly - /// - /// - /// - [Obsolete("This extension method is no longer used and will be removed in Umbraco 17.")] - public static FileInfo? GetAssemblyFile(this AssemblyName assemblyName) - { - var codeBase = assemblyName.CodeBase; - if (!string.IsNullOrEmpty(codeBase)) - { - var uri = new Uri(codeBase); - var path = uri.LocalPath; - return new FileInfo(path); - } - - return null; - } - /// /// Gets the assembly informational version for the specified . /// diff --git a/src/Umbraco.Core/Extensions/CollectionExtensions.cs b/src/Umbraco.Core/Extensions/CollectionExtensions.cs deleted file mode 100644 index 6e8903bf0f..0000000000 --- a/src/Umbraco.Core/Extensions/CollectionExtensions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Umbraco.Cms.Core.Extensions; - -public static class CollectionExtensions -{ - [Obsolete("Please replace uses of this extension method with collection expression. This method will be removed in Umbraco 17.")] - public static ICollection ToSingleItemCollection(this T item) => - new T[] { item }; -} diff --git a/src/Umbraco.Core/Extensions/DataTableExtensions.cs b/src/Umbraco.Core/Extensions/DataTableExtensions.cs deleted file mode 100644 index 557a856472..0000000000 --- a/src/Umbraco.Core/Extensions/DataTableExtensions.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Data; - -namespace Umbraco.Extensions; - -/// -/// Static and extension methods for the DataTable object -/// -public static class DataTableExtensions -{ - /// - /// Creates a DataTable with the specified alias and columns and uses a callback to populate the headers. - /// - /// - /// - /// - /// - /// - /// This has been migrated from the Node class and uses proper locking now. It is now used by the Node class and the - /// DynamicPublishedContent extensions for legacy reasons. - /// - [Obsolete("This no longer has a use in Umbraco and so will be removed in Umbraco 17.")] - public static DataTable GenerateDataTable( - string tableAlias, - Func>> getHeaders, - Func>, IEnumerable>>>> - rowData) - { - var dt = new DataTable(tableAlias); - - // get all row data - Tuple>, IEnumerable>>[] tableData = - rowData().ToArray(); - - // get all headers - IDictionary propertyHeaders = GetPropertyHeaders(tableAlias, getHeaders); - foreach (KeyValuePair h in propertyHeaders) - { - dt.Columns.Add(new DataColumn(h.Value)); - } - - // add row data - foreach (Tuple>, IEnumerable>> r in - tableData) - { - dt.PopulateRow( - propertyHeaders, - r.Item1, - r.Item2); - } - - return dt; - } - - /// - /// Helper method to return this ugly object - /// - /// - /// - /// This is for legacy code, I didn't want to go creating custom classes for these - /// - [Obsolete("This no longer has a use in Umbraco and so will be removed in Umbraco 17.")] - public static List>, IEnumerable>>> - CreateTableData() => - new List>, IEnumerable>>>(); - - /// - /// Helper method to deal with these ugly objects - /// - /// - /// - /// - /// - /// This is for legacy code, I didn't want to go creating custom classes for these - /// - [Obsolete("This no longer has a use in Umbraco and so will be removed in Umbraco 17.")] - public static void AddRowData( - List>, IEnumerable>>> rowData, - IEnumerable> standardVals, - IEnumerable> userVals) => - rowData.Add(new Tuple>, IEnumerable>>( - standardVals, - userVals)); - - private static IDictionary GetPropertyHeaders( - string alias, - Func>> getHeaders) - { - IEnumerable> headers = getHeaders(alias); - var def = headers.ToDictionary(pt => pt.Key, pt => pt.Value); - return def; - } - - private static void PopulateRow( - this DataTable dt, - IDictionary aliasesToNames, - IEnumerable> standardVals, - IEnumerable> userPropertyVals) - { - DataRow dr = dt.NewRow(); - foreach (KeyValuePair r in standardVals) - { - dr[r.Key] = r.Value; - } - - foreach (KeyValuePair p in userPropertyVals.Where(p => p.Value != null)) - { - dr[aliasesToNames[p.Key]] = p.Value; - } - - dt.Rows.Add(dr); - } -} diff --git a/src/Umbraco.Core/Extensions/DelegateExtensions.cs b/src/Umbraco.Core/Extensions/DelegateExtensions.cs deleted file mode 100644 index 4528d9f0b8..0000000000 --- a/src/Umbraco.Core/Extensions/DelegateExtensions.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Diagnostics; -using Umbraco.Cms.Core; - -namespace Umbraco.Extensions; - -public static class DelegateExtensions -{ - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static Attempt RetryUntilSuccessOrTimeout(this Func> task, TimeSpan timeout, TimeSpan pause) - { - if (pause.TotalMilliseconds < 0) - { - throw new ArgumentException("pause must be >= 0 milliseconds"); - } - - var stopwatch = Stopwatch.StartNew(); - do - { - Attempt result = task(); - if (result.Success) - { - return result; - } - - Thread.Sleep((int)pause.TotalMilliseconds); - } - while (stopwatch.Elapsed < timeout); - - return Attempt.Fail(); - } - - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static Attempt RetryUntilSuccessOrMaxAttempts(this Func> task, int totalAttempts, TimeSpan pause) - { - if (pause.TotalMilliseconds < 0) - { - throw new ArgumentException("pause must be >= 0 milliseconds"); - } - - var attempts = 0; - do - { - attempts++; - Attempt result = task(attempts); - if (result.Success) - { - return result; - } - - Thread.Sleep((int)pause.TotalMilliseconds); - } - while (attempts < totalAttempts); - - return Attempt.Fail(); - } -} diff --git a/src/Umbraco.Core/Extensions/DictionaryExtensions.cs b/src/Umbraco.Core/Extensions/DictionaryExtensions.cs index db3a01cee5..a0e0e17371 100644 --- a/src/Umbraco.Core/Extensions/DictionaryExtensions.cs +++ b/src/Umbraco.Core/Extensions/DictionaryExtensions.cs @@ -260,7 +260,7 @@ public static class DictionaryExtensions /// /// /// - public static string ToQueryString(this IDictionary d) + public static string ToQueryString(this IDictionary d) { if (!d.Any()) { @@ -268,7 +268,7 @@ public static class DictionaryExtensions } var builder = new StringBuilder(); - foreach (KeyValuePair i in d) + foreach (KeyValuePair i in d) { builder.Append(WebUtility.UrlEncode(i.Key)); builder.Append('='); diff --git a/src/Umbraco.Core/Extensions/EnumExtensions.cs b/src/Umbraco.Core/Extensions/EnumExtensions.cs deleted file mode 100644 index be31c9e76c..0000000000 --- a/src/Umbraco.Core/Extensions/EnumExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -namespace Umbraco.Extensions -{ - /// - /// Provides extension methods to . - /// - public static class EnumExtensions - { - /// - /// Determines whether any of the flags/bits are set within the enum value. - /// - /// The enum type. - /// The value. - /// The flags. - /// - /// true if any of the flags/bits are set within the enum value; otherwise, false. - /// - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static bool HasFlagAny(this T value, T flags) - where T : Enum - { - var v = Convert.ToUInt64(value); - var f = Convert.ToUInt64(flags); - - return (v & f) > 0; - } - } -} diff --git a/src/Umbraco.Core/Extensions/KeyValuePairExtensions.cs b/src/Umbraco.Core/Extensions/KeyValuePairExtensions.cs deleted file mode 100644 index 760700a624..0000000000 --- a/src/Umbraco.Core/Extensions/KeyValuePairExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -namespace Umbraco.Extensions; - -/// -/// Provides extension methods for the struct. -/// -public static class KeyValuePairExtensions -{ - /// - /// Implements key/value pair deconstruction. - /// - /// Allows for foreach ((var k, var v) in ...). - [Obsolete("Please replace uses of this extension method with native language features. This method will be removed in Umbraco 17.")] - public static void Deconstruct(this KeyValuePair kvp, out TKey key, out TValue value) - { - key = kvp.Key; - value = kvp.Value; - } -} diff --git a/src/Umbraco.Core/Extensions/NameValueCollectionExtensions.cs b/src/Umbraco.Core/Extensions/NameValueCollectionExtensions.cs deleted file mode 100644 index e5e780ccbc..0000000000 --- a/src/Umbraco.Core/Extensions/NameValueCollectionExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Collections.Specialized; -using Umbraco.Cms.Core; - -namespace Umbraco.Extensions; - -public static class NameValueCollectionExtensions -{ - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static IEnumerable> AsEnumerable(this NameValueCollection nvc) - { - foreach (var key in nvc.AllKeys) - { - yield return new KeyValuePair(key, nvc[key]); - } - } - - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static bool ContainsKey(this NameValueCollection collection, string key) => - collection.Keys.Cast().Any(k => (string)k == key); - - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static T? GetValue(this NameValueCollection collection, string key, T defaultIfNotFound) - { - if (collection.ContainsKey(key) == false) - { - return defaultIfNotFound; - } - - var val = collection[key]; - if (val == null) - { - return defaultIfNotFound; - } - - Attempt result = val.TryConvertTo(); - - return result.Success ? result.Result : defaultIfNotFound; - } -} diff --git a/src/Umbraco.Core/Extensions/ObjectExtensions.cs b/src/Umbraco.Core/Extensions/ObjectExtensions.cs index c720c85ecc..808e14d4b3 100644 --- a/src/Umbraco.Core/Extensions/ObjectExtensions.cs +++ b/src/Umbraco.Core/Extensions/ObjectExtensions.cs @@ -4,7 +4,6 @@ using System.Collections; using System.Collections.Concurrent; using System.ComponentModel; -using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Xml; @@ -15,81 +14,148 @@ using Umbraco.Cms.Core.Collections; namespace Umbraco.Extensions; /// -/// Provides object extension methods. +/// Provides object extension methods. /// public static class ObjectExtensions { - private static readonly ConcurrentDictionary NullableGenericCache = new(); - private static readonly ConcurrentDictionary InputTypeConverterCache = new(); - - private static readonly ConcurrentDictionary DestinationTypeConverterCache = - new(); - - private static readonly ConcurrentDictionary AssignableTypeCache = new(); - private static readonly ConcurrentDictionary BoolConvertCache = new(); - - private static readonly char[] NumberDecimalSeparatorsToNormalize = { '.', ',' }; - private static readonly CustomBooleanTypeConverter CustomBooleanTypeConverter = new(); - - // private static readonly ConcurrentDictionary> ObjectFactoryCache = new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary _nullableGenericCache = new(); + private static readonly ConcurrentDictionary _inputTypeConverterCache = new(); + private static readonly ConcurrentDictionary _destinationTypeConverterCache = new(); + private static readonly ConcurrentDictionary _assignableTypeCache = new(); + private static readonly ConcurrentDictionary _boolConvertCache = new(); + private static readonly char[] _numberDecimalSeparatorsToNormalize = ['.', ',']; + private static readonly CustomBooleanTypeConverter _customBooleanTypeConverter = new(); /// + /// Returns an XML serialized safe string representation for the value and type. /// - /// - /// - /// - public static IEnumerable AsEnumerableOfOne(this T input) => Enumerable.Repeat(input, 1); + /// The type of the value. + /// The value. + /// + /// The XML serialized safe string representation. + /// + public static string ToXmlString(this object value) => value.ToXmlString(typeof(T)); /// - /// Disposes the object if it implements . + /// Returns an XML serialized safe string representation for the value and type. /// - /// The object. - [Obsolete("Please replace uses of this extension method with (input as IDisposable)?.Dispose(). This extension method will be removed in Umbraco 17.")] - public static void DisposeIfDisposable(this object input) + /// The value. + /// The type of the value. This can only be a primitive type or and , otherwise an exception is thrown. + /// + /// The XML serialized safe string representation. + /// + public static string ToXmlString(this object value, Type type) { - if (input is IDisposable disposable) + if (value == null) { - try - { - disposable.Dispose(); - } - catch (ObjectDisposedException) - { - // ignore if it is already disposed - } + return string.Empty; + } + + if (type == typeof(string)) + { + return value.ToString().OrIfNullOrWhiteSpace(string.Empty); + } + + if (type == typeof(bool)) + { + return XmlConvert.ToString((bool)value); + } + + if (type == typeof(byte)) + { + return XmlConvert.ToString((byte)value); + } + + if (type == typeof(char)) + { + return XmlConvert.ToString((char)value); + } + + if (type == typeof(DateTime)) + { + return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Unspecified); + } + + if (type == typeof(DateTimeOffset)) + { + return XmlConvert.ToString((DateTimeOffset)value); + } + + if (type == typeof(decimal)) + { + return XmlConvert.ToString((decimal)value); + } + + if (type == typeof(double)) + { + return XmlConvert.ToString((double)value); + } + + if (type == typeof(float)) + { + return XmlConvert.ToString((float)value); + } + + if (type == typeof(Guid)) + { + return XmlConvert.ToString((Guid)value); + } + + if (type == typeof(int)) + { + return XmlConvert.ToString((int)value); + } + + if (type == typeof(long)) + { + return XmlConvert.ToString((long)value); + } + + if (type == typeof(sbyte)) + { + return XmlConvert.ToString((sbyte)value); + } + + if (type == typeof(short)) + { + return XmlConvert.ToString((short)value); + } + + if (type == typeof(TimeSpan)) + { + return XmlConvert.ToString((TimeSpan)value); + } + + if (type == typeof(uint)) + { + return XmlConvert.ToString((uint)value); + } + + if (type == typeof(ulong)) + { + return XmlConvert.ToString((ulong)value); + } + + if (type == typeof(ushort)) + { + return XmlConvert.ToString((ushort)value); + } + + throw new NotSupportedException($"Cannot convert type {type.FullName} to a string using ToXmlString, as it is not supported by XmlConvert."); } /// - /// Provides a shortcut way of safely casting an input when you cannot guarantee the is - /// an instance type (i.e., when the C# AS keyword is not applicable). + /// Attempts to convert the input object to the output type. /// - /// + /// The type to convert to. /// The input. - /// - [Obsolete("This extension method is not longer used and will be removed in Umbraco 17.")] - public static T? SafeCast(this object input) - { - if (ReferenceEquals(null, input) || ReferenceEquals(default(T), input)) - { - return default; - } - - if (input is T variable) - { - return variable; - } - - return default; - } - - /// - /// Attempts to convert the input object to the output type. - /// - /// This code is an optimized version of the original Umbraco method - /// The type to convert to - /// The input. - /// The + /// + /// The . + /// + /// + /// This code is an optimized version of the original Umbraco method. + /// public static Attempt TryConvertTo(this object? input) { Attempt result = TryConvertTo(input, typeof(T)); @@ -116,19 +182,23 @@ public static class ObjectExtensions { return Attempt.Succeed((T)input); } - catch (Exception e) + catch (Exception ex) { - return Attempt.Fail(e); + return Attempt.Fail(ex); } } /// - /// Attempts to convert the input object to the output type. + /// Attempts to convert the input object to the output type. /// - /// This code is an optimized version of the original Umbraco method /// The input. - /// The type to convert to - /// The + /// The type to convert to. + /// + /// The . + /// + /// + /// This code is an optimized version of the original Umbraco method. + /// public static Attempt TryConvertTo(this object? input, Type target) { if (target == null) @@ -158,7 +228,7 @@ public static class ObjectExtensions return Attempt.Succeed(input); } - // Check for string so that overloaders of ToString() can take advantage of the conversion. + // Check for string so that overloads of ToString() can take advantage of the conversion. if (target == typeof(string)) { return Attempt.Succeed(input.ToString()); @@ -225,13 +295,13 @@ public static class ObjectExtensions { if (GetCachedCanConvertToBoolean(inputType)) { - return Attempt.Succeed(CustomBooleanTypeConverter.ConvertFrom(input!)); + return Attempt.Succeed(_customBooleanTypeConverter.ConvertFrom(input!)); } } if (target == typeof(DateTime) && input is DateTimeOffset dateTimeOffset) { - // IMPORTANT: for compatability with various editors, we must discard any Offset information and assume UTC time here + // IMPORTANT: for compatibility with various editors, we must discard any Offset information and assume UTC time here return Attempt.Succeed((object?)new DateTime( new DateOnly(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day), new TimeOnly(dateTimeOffset.Hour, dateTimeOffset.Minute, dateTimeOffset.Second, dateTimeOffset.Millisecond, dateTimeOffset.Microsecond), @@ -240,7 +310,7 @@ public static class ObjectExtensions if (target == typeof(DateTimeOffset) && input is DateTime dateTime) { - // IMPORTANT: for compatability with various editors, we must discard any DateTimeKind information and assume UTC time here + // IMPORTANT: for compatibility with various editors, we must discard any DateTimeKind information and assume UTC time here return Attempt.Succeed((object?)new DateTimeOffset( new DateOnly(dateTime.Year, dateTime.Month, dateTime.Day), new TimeOnly(dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond, dateTime.Microsecond), @@ -281,102 +351,18 @@ public static class ObjectExtensions return Attempt.Fail(); } - // public enum PropertyNamesCaseType - // { - // CamelCase, - // CaseInsensitive - // } - - ///// - ///// Convert an object to a JSON string with camelCase formatting - ///// - ///// - ///// - // public static string ToJsonString(this object obj) - // { - // return obj.ToJsonString(PropertyNamesCaseType.CamelCase); - // } - - ///// - ///// Convert an object to a JSON string with the specified formatting - ///// - ///// The obj. - ///// Type of the property names case. - ///// - // public static string ToJsonString(this object obj, PropertyNamesCaseType propertyNamesCaseType) - // { - // var type = obj.GetType(); - // var dateTimeStyle = "yyyy-MM-dd HH:mm:ss"; - - // if (type.IsPrimitive || typeof(string).IsAssignableFrom(type)) - // { - // return obj.ToString(); - // } - - // if (typeof(DateTime).IsAssignableFrom(type) || typeof(DateTimeOffset).IsAssignableFrom(type)) - // { - // return Convert.ToDateTime(obj).ToString(dateTimeStyle); - // } - - // var serializer = new JsonSerializer(); - - // switch (propertyNamesCaseType) - // { - // case PropertyNamesCaseType.CamelCase: - // serializer.ContractResolver = new CamelCasePropertyNamesContractResolver(); - // break; - // } - - // var dateTimeConverter = new IsoDateTimeConverter - // { - // DateTimeStyles = System.Globalization.DateTimeStyles.None, - // DateTimeFormat = dateTimeStyle - // }; - - // if (typeof(IDictionary).IsAssignableFrom(type)) - // { - // return JObject.FromObject(obj, serializer).ToString(Formatting.None, dateTimeConverter); - // } - - // if (type.IsArray || (typeof(IEnumerable).IsAssignableFrom(type))) - // { - // return JArray.FromObject(obj, serializer).ToString(Formatting.None, dateTimeConverter); - // } - - // return JObject.FromObject(obj, serializer).ToString(Formatting.None, dateTimeConverter); - // } - - /// - /// Converts an object into a dictionary - /// - /// - /// - /// - /// - /// - /// [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static IDictionary? ToDictionary( - this T o, - params Expression>[] ignoreProperties) => o?.ToDictionary(ignoreProperties - .Select(e => o.GetPropertyInfo(e)).Select(propInfo => propInfo.Name).ToArray()); - - internal static void CheckThrowObjectDisposed(this IDisposable disposable, bool isDisposed, string objectname) - { - // TODO: Localize this exception - if (isDisposed) - { - throw new ObjectDisposedException(objectname); - } - } - /// - /// Attempts to convert the input string to the output type. + /// Attempts to convert the input string to the output type. /// - /// This code is an optimized version of the original Umbraco method /// The input. /// The type to convert to - /// The + /// + /// The + /// + /// + /// This code is an optimized version of the original Umbraco method. + /// private static Attempt? TryConvertToFromString(this string input, Type target) { // Easy @@ -529,143 +515,7 @@ public static class ObjectExtensions return null; // we can't decide... } - /// - /// Turns object into dictionary - /// - /// - /// Properties to ignore - /// - [Obsolete("Use of this can be replaced with RouteValueDictionary or HtmlHelper.AnonymousObjectToHtmlAttributes(). The method will be removed in Umbraco 17.")] - public static IDictionary ToDictionary(this object o, params string[] ignoreProperties) - { - if (o != null) - { - PropertyDescriptorCollection props = TypeDescriptor.GetProperties(o); - var d = new Dictionary(); - foreach (PropertyDescriptor prop in props.Cast() - .Where(x => ignoreProperties.Contains(x.Name) == false)) - { - var val = prop.GetValue(o); - if (val != null) - { - d.Add(prop.Name, (TVal)val); - } - } - - return d; - } - - return new Dictionary(); - } - - /// - /// Returns an XmlSerialized safe string representation for the value - /// - /// - /// The Type can only be a primitive type or Guid and byte[] otherwise an exception is thrown - /// - public static string ToXmlString(this object value, Type type) - { - if (value == null) - { - return string.Empty; - } - - if (type == typeof(string)) - { - return value.ToString().IsNullOrWhiteSpace() ? string.Empty : value.ToString()!; - } - - if (type == typeof(bool)) - { - return XmlConvert.ToString((bool)value); - } - - if (type == typeof(byte)) - { - return XmlConvert.ToString((byte)value); - } - - if (type == typeof(char)) - { - return XmlConvert.ToString((char)value); - } - - if (type == typeof(DateTime)) - { - return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Unspecified); - } - - if (type == typeof(DateTimeOffset)) - { - return XmlConvert.ToString((DateTimeOffset)value); - } - - if (type == typeof(decimal)) - { - return XmlConvert.ToString((decimal)value); - } - - if (type == typeof(double)) - { - return XmlConvert.ToString((double)value); - } - - if (type == typeof(float)) - { - return XmlConvert.ToString((float)value); - } - - if (type == typeof(Guid)) - { - return XmlConvert.ToString((Guid)value); - } - - if (type == typeof(int)) - { - return XmlConvert.ToString((int)value); - } - - if (type == typeof(long)) - { - return XmlConvert.ToString((long)value); - } - - if (type == typeof(sbyte)) - { - return XmlConvert.ToString((sbyte)value); - } - - if (type == typeof(short)) - { - return XmlConvert.ToString((short)value); - } - - if (type == typeof(TimeSpan)) - { - return XmlConvert.ToString((TimeSpan)value); - } - - if (type == typeof(uint)) - { - return XmlConvert.ToString((uint)value); - } - - if (type == typeof(ulong)) - { - return XmlConvert.ToString((ulong)value); - } - - if (type == typeof(ushort)) - { - return XmlConvert.ToString((ushort)value); - } - - throw new NotSupportedException("Cannot convert type " + type.FullName + - " to a string using ToXmlString as it is not supported by XmlConvert"); - } - - internal static string? ToDebugString(this object? obj, int levels = 0) + private static string? ToDebugString(this object? obj, int levels = 0) { if (obj == null) { @@ -738,35 +588,6 @@ public static class ObjectExtensions return null; } - /// - /// Attempts to serialize the value to an XmlString using ToXmlString - /// - /// - /// - /// - internal static Attempt TryConvertToXmlString(this object value, Type type) - { - try - { - var output = value.ToXmlString(type); - return Attempt.Succeed(output); - } - catch (NotSupportedException ex) - { - return Attempt.Fail(ex); - } - } - - /// - /// Returns an XmlSerialized safe string representation for the value and type - /// - /// - /// - /// - public static string ToXmlString(this object value) => value.ToXmlString(typeof(T)); - - public static Guid AsGuid(this object value) => value is Guid guid ? guid : Guid.Empty; - private static string? GetEnumPropertyDebugString(object enumItem, int levels) { try @@ -795,7 +616,7 @@ public static class ObjectExtensions private static string NormalizeNumberDecimalSeparator(string s) { var normalized = Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0]; - return s.ReplaceMany(NumberDecimalSeparatorsToNormalize, normalized); + return s.ReplaceMany(_numberDecimalSeparatorsToNormalize, normalized); } // gets a converter for source, that can convert to target, or null if none exists @@ -804,7 +625,7 @@ public static class ObjectExtensions { var key = new CompositeTypeTypeKey(source, target); - if (InputTypeConverterCache.TryGetValue(key, out TypeConverter? typeConverter)) + if (_inputTypeConverterCache.TryGetValue(key, out TypeConverter? typeConverter)) { return typeConverter; } @@ -812,10 +633,10 @@ public static class ObjectExtensions TypeConverter converter = TypeDescriptor.GetConverter(source); if (converter.CanConvertTo(target)) { - return InputTypeConverterCache[key] = converter; + return _inputTypeConverterCache[key] = converter; } - InputTypeConverterCache[key] = null; + _inputTypeConverterCache[key] = null; return null; } @@ -825,7 +646,7 @@ public static class ObjectExtensions { var key = new CompositeTypeTypeKey(source, target); - if (DestinationTypeConverterCache.TryGetValue(key, out TypeConverter? typeConverter)) + if (_destinationTypeConverterCache.TryGetValue(key, out TypeConverter? typeConverter)) { return typeConverter; } @@ -833,10 +654,10 @@ public static class ObjectExtensions TypeConverter converter = TypeDescriptor.GetConverter(target); if (converter.CanConvertFrom(source)) { - return DestinationTypeConverterCache[key] = converter; + return _destinationTypeConverterCache[key] = converter; } - DestinationTypeConverterCache[key] = null; + _destinationTypeConverterCache[key] = null; return null; } @@ -844,7 +665,7 @@ public static class ObjectExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Type? GetCachedGenericNullableType(Type type) { - if (NullableGenericCache.TryGetValue(type, out Type? underlyingType)) + if (_nullableGenericCache.TryGetValue(type, out Type? underlyingType)) { return underlyingType; } @@ -852,10 +673,10 @@ public static class ObjectExtensions if (type.GetGenericTypeDefinition() == typeof(Nullable<>)) { Type? underlying = Nullable.GetUnderlyingType(type); - return NullableGenericCache[type] = underlying; + return _nullableGenericCache[type] = underlying; } - NullableGenericCache[type] = null; + _nullableGenericCache[type] = null; return null; } @@ -864,7 +685,7 @@ public static class ObjectExtensions private static bool GetCachedCanAssign(object input, Type source, Type target) { var key = new CompositeTypeTypeKey(source, target); - if (AssignableTypeCache.TryGetValue(key, out var canConvert)) + if (_assignableTypeCache.TryGetValue(key, out var canConvert)) { return canConvert; } @@ -873,26 +694,26 @@ public static class ObjectExtensions // We can use it to very quickly determine whether true/false if (input is IConvertible && target.IsAssignableFrom(source)) { - return AssignableTypeCache[key] = true; + return _assignableTypeCache[key] = true; } - return AssignableTypeCache[key] = false; + return _assignableTypeCache[key] = false; } // determines whether a type can be converted to boolean [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool GetCachedCanConvertToBoolean(Type type) { - if (BoolConvertCache.TryGetValue(type, out var result)) + if (_boolConvertCache.TryGetValue(type, out var result)) { return result; } - if (CustomBooleanTypeConverter.CanConvertFrom(type)) + if (_customBooleanTypeConverter.CanConvertFrom(type)) { - return BoolConvertCache[type] = true; + return _boolConvertCache[type] = true; } - return BoolConvertCache[type] = false; + return _boolConvertCache[type] = false; } } diff --git a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs index f8ef83c350..88ed9b44a9 100644 --- a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs @@ -2832,137 +2832,6 @@ public static class PublishedContentExtensions #endregion - #region Axes: children - - /// - /// Gets the children of the content in a DataTable. - /// - /// The content. - /// - /// - /// The content type service. - /// The media type service. - /// The member type service. - /// The published url provider. - /// An optional content type alias. - /// - /// The specific culture to filter for. If null is used the current culture is used. (Default is - /// null) - /// - /// The children of the content. - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static DataTable ChildrenAsTable( - this IPublishedContent content, - INavigationQueryService navigationQueryService, - IPublishedStatusFilteringService publishedStatusFilteringService, - IContentTypeService contentTypeService, - IMediaTypeService mediaTypeService, - IMemberTypeService memberTypeService, - IPublishedUrlProvider publishedUrlProvider, - string contentTypeAliasFilter = "", - string? culture = null) - => content.GenerateDataTable(navigationQueryService, publishedStatusFilteringService, contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); - - [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] - public static DataTable ChildrenAsTable( - this IPublishedContent content, - IVariationContextAccessor variationContextAccessor, - IPublishedCache publishedCache, - INavigationQueryService navigationQueryService, - IContentTypeService contentTypeService, - IMediaTypeService mediaTypeService, - IMemberTypeService memberTypeService, - IPublishedUrlProvider publishedUrlProvider, - string contentTypeAliasFilter = "", - string? culture = null) - => content.GenerateDataTable(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); - - private static DataTable GenerateDataTable( - this IPublishedContent content, - INavigationQueryService navigationQueryService, - IPublishedStatusFilteringService publishedStatusFilteringService, - IContentTypeService contentTypeService, - IMediaTypeService mediaTypeService, - IMemberTypeService memberTypeService, - IPublishedUrlProvider publishedUrlProvider, - string contentTypeAliasFilter = "", - string? culture = null) - { - IPublishedContent[] children = content.Children(navigationQueryService, publishedStatusFilteringService, culture).ToArray(); - IPublishedContent? firstNode = contentTypeAliasFilter.IsNullOrWhiteSpace() - ? children.Length > 0 - ? children.ElementAt(0) - : null - : children.FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAliasFilter)); - if (firstNode == null) - { - // No children found - return new DataTable(); - } - - // use new utility class to create table so that we don't have to maintain code in many places, just one - DataTable dt = DataTableExtensions.GenerateDataTable( - - // pass in the alias of the first child node since this is the node type we're rendering headers for - firstNode.ContentType.Alias, - - // pass in the callback to extract the Dictionary of all defined aliases to their names - alias => GetPropertyAliasesAndNames(contentTypeService, mediaTypeService, memberTypeService, alias), - () => - { - // here we pass in a callback to populate the datatable, yup its a bit ugly but it's already legacy and we just want to maintain code in one place. - // create all row data - List>, IEnumerable>>> - tableData = DataTableExtensions.CreateTableData(); - IOrderedEnumerable? children = - content.Children(navigationQueryService, publishedStatusFilteringService).OrderBy(x => x.SortOrder); - if (children is not null) - { - // loop through each child and create row data for it - foreach (IPublishedContent n in children) - { - if (contentTypeAliasFilter.IsNullOrWhiteSpace() == false) - { - if (n.ContentType.Alias.InvariantEquals(contentTypeAliasFilter) == false) - { - continue; // skip this one, it doesn't match the filter - } - } - - var standardVals = new Dictionary - { - { "Id", n.Id }, - { "NodeName", n.Name(null, culture) }, - { "NodeTypeAlias", n.ContentType.Alias }, - { "CreateDate", n.CreateDate }, - { "UpdateDate", n.UpdateDate }, - { "CreatorId", n.CreatorId }, - { "WriterId", n.WriterId }, - { "Url", n.Url(publishedUrlProvider) }, - }; - - var userVals = new Dictionary(); - IEnumerable properties = - n.Properties?.Where(p => p.GetSourceValue() is not null) ?? - Array.Empty(); - foreach (IPublishedProperty p in properties) - { - // probably want the "object value" of the property here... - userVals[p.Alias] = p.GetValue(); - } - - // Add the row data - DataTableExtensions.AddRowData(tableData, standardVals, userVals); - } - } - - return tableData; - }); - return dt; - } - - #endregion - #region PropertyAliasesAndNames private static Func>? _getPropertyAliasesAndNames; @@ -3142,17 +3011,6 @@ public static class PublishedContentExtensions where T : class, IPublishedContent => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static DataTable ChildrenAsTable( - this IPublishedContent content, - IVariationContextAccessor variationContextAccessor, - IContentTypeService contentTypeService, - IMediaTypeService mediaTypeService, - IMemberTypeService memberTypeService, - IPublishedUrlProvider publishedUrlProvider, - string contentTypeAliasFilter = "", - string? culture = null) - => content.GenerateDataTable(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, diff --git a/src/Umbraco.Core/Extensions/StringExtensions.cs b/src/Umbraco.Core/Extensions/StringExtensions.cs index eab9d3fabf..8f602b4446 100644 --- a/src/Umbraco.Core/Extensions/StringExtensions.cs +++ b/src/Umbraco.Core/Extensions/StringExtensions.cs @@ -912,7 +912,8 @@ public static class StringExtensions return text; } - public static string OrIfNullOrWhiteSpace(this string input, string alternative) => + [return: NotNullIfNotNull(nameof(alternative))] + public static string? OrIfNullOrWhiteSpace(this string? input, string? alternative) => !string.IsNullOrWhiteSpace(input) ? input : alternative; diff --git a/src/Umbraco.Core/Extensions/ThreadExtensions.cs b/src/Umbraco.Core/Extensions/ThreadExtensions.cs deleted file mode 100644 index c365038071..0000000000 --- a/src/Umbraco.Core/Extensions/ThreadExtensions.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Globalization; - -namespace Umbraco.Extensions; - -public static class ThreadExtensions -{ - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static void SanitizeThreadCulture(this Thread thread) - { - // get the current culture - CultureInfo currentCulture = CultureInfo.CurrentCulture; - - // at the top of any culture should be the invariant culture - find it - // doing an .Equals comparison ensure that we *will* find it and not loop - // endlessly - CultureInfo invariantCulture = currentCulture; - while (invariantCulture.Equals(CultureInfo.InvariantCulture) == false) - { - invariantCulture = invariantCulture.Parent; - } - - // now that invariant culture should be the same object as CultureInfo.InvariantCulture - // yet for some reasons, sometimes it is not - and this breaks anything that loops on - // culture.Parent until a reference equality to CultureInfo.InvariantCulture. See, for - // example, the following code in PerformanceCounterLib.IsCustomCategory: - // - // CultureInfo culture = CultureInfo.CurrentCulture; - // while (culture != CultureInfo.InvariantCulture) - // { - // library = GetPerformanceCounterLib(machine, culture); - // if (library.IsCustomCategory(category)) - // return true; - // culture = culture.Parent; - // } - // - // The reference comparisons never succeeds, hence the loop never ends, and the - // application hangs. - // - // granted, that comparison should probably be a .Equals comparison, but who knows - // how many times the framework assumes that it can do a reference comparison? So, - // better fix the cultures. - if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture)) - { - return; - } - - // if we do not have equality, fix cultures by replacing them with a culture with - // the same name, but obtained here and now, with a proper invariant top culture - thread.CurrentCulture = CultureInfo.GetCultureInfo(thread.CurrentCulture.Name); - thread.CurrentUICulture = CultureInfo.GetCultureInfo(thread.CurrentUICulture.Name); - } -} diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index 4eb054b2a5..6f1877f321 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -26,7 +26,7 @@ public class SerilogLogger : IDisposable IConfiguration configuration) => CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration, configuration, out _); - public void Dispose() => SerilogLog.DisposeIfDisposable(); + public void Dispose() => (SerilogLog as IDisposable)?.Dispose(); /// /// Creates a logger with some pre-defined configuration and remainder from config file diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs index 60ec173ca5..b0172f9341 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs @@ -123,7 +123,7 @@ internal static class UserFactory if (entity.HasIdentity) { - dto.Id = entity.Id.SafeCast(); + dto.Id = entity.Id; } return dto; diff --git a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs index 921c815e2f..46a5c79a43 100644 --- a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs @@ -675,28 +675,6 @@ public static class FriendlyPublishedContentExtensions public static string Url(this IPublishedContent content, string? culture = null, UrlMode mode = UrlMode.Default) => content.Url(PublishedUrlProvider, culture, mode); - /// - /// Gets the children of the content in a DataTable. - /// - /// The content. - /// An optional content type alias. - /// - /// The specific culture to filter for. If null is used the current culture is used. (Default is - /// null) - /// - /// The children of the content. - [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] - public static DataTable ChildrenAsTable(this IPublishedContent content, string contentTypeAliasFilter = "", string? culture = null) - => content.ChildrenAsTable( - GetNavigationQueryService(content), - GetPublishedStatusFilteringService(content), - ContentTypeService, - MediaTypeService, - MemberTypeService, - PublishedUrlProvider, - contentTypeAliasFilter, - culture); - /// /// Gets the url for a media. /// diff --git a/src/Umbraco.Web.Common/Security/EncryptionHelper.cs b/src/Umbraco.Web.Common/Security/EncryptionHelper.cs index 1328d79e00..ee81b43a9b 100644 --- a/src/Umbraco.Web.Common/Security/EncryptionHelper.cs +++ b/src/Umbraco.Web.Common/Security/EncryptionHelper.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Net; using System.Web; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core; using Umbraco.Cms.Web.Common.Constants; @@ -65,14 +66,7 @@ public class EncryptionHelper string? additionalRouteValsAsQuery; if (additionalRouteVals != null) { - if (additionalRouteVals is Dictionary additionalRouteValsAsDictionary) - { - additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); - } - else - { - additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); - } + additionalRouteValsAsQuery = new RouteValueDictionary(additionalRouteVals).ToQueryString(); } else { diff --git a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index d8fd5f48a4..f013ece768 100644 --- a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -88,7 +88,7 @@ public abstract class UmbracoIntegrationTest : UmbracoIntegrationTestBase public void TearDownAsync() { _host.StopAsync(); - Services.DisposeIfDisposable(); + (Services as IDisposable)?.Dispose(); } /// diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/BackOfficeExamineSearcherTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/BackOfficeExamineSearcherTests.cs index bb4f099ef0..d743b51480 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/BackOfficeExamineSearcherTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/BackOfficeExamineSearcherTests.cs @@ -43,7 +43,7 @@ internal sealed class BackOfficeExamineSearcherTests : ExamineBaseTest // When disposing examine, it does a final write, which ends up locking the file if the indexing is not done yet. So we have this wait to circumvent that. Thread.Sleep(1500); // Sometimes we do not dispose all services in time and the test fails because the log file is locked. Resulting in all other tests failing as well - Services.DisposeIfDisposable(); + (Services as IDisposable)?.Dispose(); } private IDocumentUrlService DocumentUrlService => GetRequiredService(); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineExternalIndexTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineExternalIndexTests.cs index 98a81924bd..ca24ae8698 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineExternalIndexTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineExternalIndexTests.cs @@ -47,7 +47,7 @@ internal sealed class ExamineExternalIndexTests : ExamineBaseTest // When disposing examine, it does a final write, which ends up locking the file if the indexing is not done yet. So we have this wait to circumvent that. Thread.Sleep(1500); // Sometimes we do not dispose all services in time and the test fails because the log file is locked. Resulting in all other tests failing as well - Services.DisposeIfDisposable(); + (Services as IDisposable)?.Dispose(); } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/ObjectExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/ObjectExtensionsTests.cs index 7aae5e54ee..1461364d02 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/ObjectExtensionsTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/ObjectExtensionsTests.cs @@ -40,24 +40,6 @@ public class ObjectExtensionsTests Assert.AreEqual(3, result.Result.Count()); } - [Test] - public void ObjectExtensions_Object_To_Dictionary() - { - // Arrange - var obj = new { Key1 = "value1", Key2 = "value2", Key3 = "value3" }; - - // Act - var d = obj.ToDictionary(); - - // Assert - Assert.IsTrue(d.Keys.Contains("Key1")); - Assert.IsTrue(d.Keys.Contains("Key2")); - Assert.IsTrue(d.Keys.Contains("Key3")); - Assert.AreEqual(d["Key1"], "value1"); - Assert.AreEqual(d["Key2"], "value2"); - Assert.AreEqual(d["Key3"], "value3"); - } - [Test] public void CanConvertIntToNullableInt() { diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DelegateExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DelegateExtensionsTests.cs deleted file mode 100644 index 8c5ba62e0d..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DelegateExtensionsTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Lucene.Net.Index; -using NUnit.Framework; -using Umbraco.Cms.Core; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core; - -[TestFixture] -public class DelegateExtensionsTests -{ - [Test] - public void Only_Executes_Specific_Count() - { - const int maxTries = 5; - var totalTries = 0; - DelegateExtensions.RetryUntilSuccessOrMaxAttempts( - currentTry => - { - totalTries = currentTry; - return Attempt.Fail(); - }, - 5, - TimeSpan.FromMilliseconds(10)); - - Assert.AreEqual(maxTries, totalTries); - } - - [Test] - public void Quits_On_Success_Count() - { - var totalTries = 0; - DelegateExtensions.RetryUntilSuccessOrMaxAttempts( - currentTry => - { - totalTries = currentTry; - return totalTries == 2 ? Attempt.Succeed() : Attempt.Fail(); - }, - 5, - TimeSpan.FromMilliseconds(10)); - - Assert.AreEqual(2, totalTries); - } -} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/PublishedContentDataTableTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/PublishedContentDataTableTests.cs deleted file mode 100644 index 0f10dc6027..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/PublishedContentDataTableTests.cs +++ /dev/null @@ -1,196 +0,0 @@ -// using System.Collections.Generic; -// using System.Linq; -// using Moq; -// using NUnit.Framework; -// using Umbraco.Cms.Core.Models; -// using Umbraco.Cms.Core.Routing; -// using Umbraco.Cms.Core.Services; -// using Umbraco.Cms.Infrastructure.PublishedCache; -// using Umbraco.Cms.Tests.Common.Builders; -// using Umbraco.Cms.Tests.Common.Builders.Extensions; -// using Umbraco.Cms.Tests.UnitTests.TestHelpers; -// using Umbraco.Extensions; -// -// namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.PublishedCache; -// -// FIXME: Reintroduce if relevant -// /// -// /// Unit tests for IPublishedContent and extensions -// /// -// [TestFixture] -// public class PublishedContentDataTableTests : PublishedSnapshotServiceTestBase -// { -// private readonly DataType[] _dataTypes = GetDefaultDataTypes(); -// -// private static ContentType CreateContentType(string name, IDataType dataType, IReadOnlyDictionary propertyAliasesAndNames) -// { -// var contentType = new ContentType(TestHelper.ShortStringHelper, -1) -// { -// Alias = name, -// Name = name, -// Key = Guid.NewGuid(), -// Id = name.GetHashCode(), -// }; -// foreach (var prop in propertyAliasesAndNames) -// { -// contentType.AddPropertyType(new PropertyType(TestHelper.ShortStringHelper, dataType, prop.Key) -// { -// Name = prop.Value, -// }); -// } -// -// return contentType; -// } -// -// private IEnumerable CreateCache( -// bool createChildren, -// IDataType dataType, -// out ContentType[] contentTypes) -// { -// var result = new List(); -// var valueCounter = 1; -// var parentId = 3; -// -// var properties = new Dictionary { ["property1"] = "Property 1", ["property2"] = "Property 2" }; -// -// var parentContentType = CreateContentType( -// "Parent", -// dataType, -// new Dictionary(properties) { ["property3"] = "Property 3" }); -// var childContentType = CreateContentType( -// "Child", -// dataType, -// new Dictionary(properties) { ["property4"] = "Property 4" }); -// var child2ContentType = CreateContentType( -// "Child2", -// dataType, -// new Dictionary(properties) { ["property4"] = "Property 4" }); -// -// contentTypes = new[] { parentContentType, childContentType, child2ContentType }; -// -// var parentData = new ContentDataBuilder() -// .WithName("Page" + Guid.NewGuid()) -// .WithProperties(new PropertyDataBuilder() -// .WithPropertyData("property1", "value" + valueCounter) -// .WithPropertyData("property2", "value" + (valueCounter + 1)) -// .WithPropertyData("property3", "value" + (valueCounter + 2)) -// .Build()) -// .Build(); -// -// var parent = ContentNodeKitBuilder.CreateWithContent( -// parentContentType.Id, -// parentId, -// $"-1,{parentId}", -// draftData: parentData, -// publishedData: parentData); -// -// result.Add(parent); -// -// if (createChildren) -// { -// for (var i = 0; i < 3; i++) -// { -// valueCounter += 3; -// var childId = parentId + i + 1; -// -// var childData = new ContentDataBuilder() -// .WithName("Page" + Guid.NewGuid()) -// .WithProperties(new PropertyDataBuilder() -// .WithPropertyData("property1", "value" + valueCounter) -// .WithPropertyData("property2", "value" + (valueCounter + 1)) -// .WithPropertyData("property4", "value" + (valueCounter + 2)) -// .Build()) -// .Build(); -// -// var child = ContentNodeKitBuilder.CreateWithContent( -// i > 0 ? childContentType.Id : child2ContentType.Id, -// childId, -// $"-1,{parentId},{childId}", -// i, -// draftData: childData, -// publishedData: childData); -// -// result.Add(child); -// } -// } -// -// return result; -// } -// -// [Test] -// public void To_DataTable() -// { -// var cache = CreateCache(true, _dataTypes[0], out var contentTypes); -// InitializedCache(cache, contentTypes, _dataTypes); -// -// var snapshot = GetPublishedSnapshot(); -// var root = snapshot.Content.GetAtRoot().First(); -// -// var dt = root.ChildrenAsTable( -// VariationContextAccessor, -// ContentTypeService, -// MediaTypeService, -// Mock.Of(), -// Mock.Of()); -// -// Assert.AreEqual(11, dt.Columns.Count); -// Assert.AreEqual(3, dt.Rows.Count); -// Assert.AreEqual("value4", dt.Rows[0]["Property 1"]); -// Assert.AreEqual("value5", dt.Rows[0]["Property 2"]); -// Assert.AreEqual("value6", dt.Rows[0]["Property 4"]); -// Assert.AreEqual("value7", dt.Rows[1]["Property 1"]); -// Assert.AreEqual("value8", dt.Rows[1]["Property 2"]); -// Assert.AreEqual("value9", dt.Rows[1]["Property 4"]); -// Assert.AreEqual("value10", dt.Rows[2]["Property 1"]); -// Assert.AreEqual("value11", dt.Rows[2]["Property 2"]); -// Assert.AreEqual("value12", dt.Rows[2]["Property 4"]); -// } -// -// [Test] -// public void To_DataTable_With_Filter() -// { -// var cache = CreateCache(true, _dataTypes[0], out var contentTypes); -// InitializedCache(cache, contentTypes, _dataTypes); -// -// var snapshot = GetPublishedSnapshot(); -// var root = snapshot.Content.GetAtRoot().First(); -// -// var dt = root.ChildrenAsTable( -// VariationContextAccessor, -// ContentTypeService, -// MediaTypeService, -// Mock.Of(), -// Mock.Of(), -// "Child"); -// -// Assert.AreEqual(11, dt.Columns.Count); -// Assert.AreEqual(2, dt.Rows.Count); -// Assert.AreEqual("value7", dt.Rows[0]["Property 1"]); -// Assert.AreEqual("value8", dt.Rows[0]["Property 2"]); -// Assert.AreEqual("value9", dt.Rows[0]["Property 4"]); -// Assert.AreEqual("value10", dt.Rows[1]["Property 1"]); -// Assert.AreEqual("value11", dt.Rows[1]["Property 2"]); -// Assert.AreEqual("value12", dt.Rows[1]["Property 4"]); -// } -// -// [Test] -// public void To_DataTable_No_Rows() -// { -// var cache = CreateCache(false, _dataTypes[0], out var contentTypes); -// InitializedCache(cache, contentTypes, _dataTypes); -// -// var snapshot = GetPublishedSnapshot(); -// var root = snapshot.Content.GetAtRoot().First(); -// -// var dt = root.ChildrenAsTable( -// VariationContextAccessor, -// ContentTypeService, -// MediaTypeService, -// Mock.Of(), -// Mock.Of()); -// -// // will return an empty data table -// Assert.AreEqual(0, dt.Columns.Count); -// Assert.AreEqual(0, dt.Rows.Count); -// } -// }