Merge remote-tracking branch 'origin/v8/dev' into netcore/dev

# Conflicts:
#	src/Umbraco.Abstractions/Exceptions/ConnectionException.cs
#	src/Umbraco.Abstractions/Exceptions/DataOperationException.cs
#	src/Umbraco.Abstractions/Exceptions/InvalidCompositionException.cs
#	src/Umbraco.Abstractions/IO/MediaFileSystem.cs
#	src/Umbraco.Abstractions/IO/PhysicalFileSystem.cs
#	src/Umbraco.Abstractions/Migrations/DataLossException.cs
#	src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs
#	src/Umbraco.Abstractions/Xml/UmbracoXPathPathSyntaxParser.cs
#	src/Umbraco.Abstractions/Xml/XmlHelper.cs
#	src/Umbraco.Core/Manifest/ManifestParser.cs
#	src/Umbraco.Core/Models/ContentRepositoryExtensions.cs
#	src/Umbraco.Core/Models/PropertyType.cs
#	src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs
#	src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs
#	src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs
#	src/Umbraco.Core/StringExtensions.cs
#	src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs
#	src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs
This commit is contained in:
Bjarke Berg
2019-12-02 13:44:47 +01:00
161 changed files with 7429 additions and 6100 deletions

View File

@@ -70,7 +70,23 @@ namespace Umbraco.Core.Collections
/// The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public int Count => GetThreadSafeClone().Count;
public int Count
{
get
{
try
{
_instanceLocker.EnterReadLock();
return _innerSet.Count;
}
finally
{
if (_instanceLocker.IsReadLockHeld)
_instanceLocker.ExitReadLock();
}
}
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
@@ -105,8 +121,7 @@ namespace Umbraco.Core.Collections
/// <returns></returns>
public bool TryAdd(T item)
{
var clone = GetThreadSafeClone();
if (clone.Contains(item)) return false;
if (Contains(item)) return false;
try
{
_instanceLocker.EnterWriteLock();
@@ -150,7 +165,16 @@ namespace Umbraco.Core.Collections
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
public bool Contains(T item)
{
return GetThreadSafeClone().Contains(item);
try
{
_instanceLocker.EnterReadLock();
return _innerSet.Contains(item);
}
finally
{
if (_instanceLocker.IsReadLockHeld)
_instanceLocker.ExitReadLock();
}
}
/// <summary>
@@ -168,13 +192,13 @@ namespace Umbraco.Core.Collections
HashSet<T> clone = null;
try
{
_instanceLocker.EnterWriteLock();
_instanceLocker.EnterReadLock();
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
}
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
if (_instanceLocker.IsReadLockHeld)
_instanceLocker.ExitReadLock();
}
return clone;
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
namespace Umbraco.Core.Collections
{
@@ -26,7 +27,7 @@ namespace Umbraco.Core.Collections
/// <param name="equalityComparer">The equality comparer to use when comparing keys, or null to use the default comparer.</param>
public ObservableDictionary(Func<TValue, TKey> keySelector, IEqualityComparer<TKey> equalityComparer = null)
{
KeySelector = keySelector ?? throw new ArgumentException("keySelector");
KeySelector = keySelector ?? throw new ArgumentException(nameof(keySelector));
Indecies = new Dictionary<TKey, int>(equalityComparer);
}
@@ -36,7 +37,7 @@ namespace Umbraco.Core.Collections
{
var key = KeySelector(item);
if (Indecies.ContainsKey(key))
throw new DuplicateKeyException(key.ToString());
throw new ArgumentException($"An element with the same key '{key}' already exists in the dictionary.", nameof(item));
if (index != Count)
{
@@ -91,7 +92,7 @@ namespace Umbraco.Core.Collections
{
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
throw new InvalidOperationException("Key of new value does not match.");
if (!Indecies.ContainsKey(key))
{
@@ -118,7 +119,7 @@ namespace Umbraco.Core.Collections
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
throw new InvalidOperationException("Key of new value does not match.");
this[Indecies[key]] = value;
return true;
@@ -155,12 +156,12 @@ namespace Umbraco.Core.Collections
{
if (!Indecies.ContainsKey(currentKey))
{
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
throw new InvalidOperationException($"No item with the key '{currentKey}' was found in the dictionary.");
}
if (ContainsKey(newKey))
{
throw new DuplicateKeyException(newKey.ToString());
throw new ArgumentException($"An element with the same key '{newKey}' already exists in the dictionary.", nameof(newKey));
}
var currentIndex = Indecies[currentKey];
@@ -234,16 +235,5 @@ namespace Umbraco.Core.Collections
}
#endregion
internal class DuplicateKeyException : Exception
{
public DuplicateKeyException(string key)
: base("Attempted to insert duplicate key \"" + key + "\" in collection.")
{
Key = key;
}
public string Key { get; }
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using Umbraco.Core.Cache;
@@ -816,12 +817,45 @@ namespace Umbraco.Core.Composing
}
/// <summary>
/// Represents the error that occurs when a type was not found in the cache type
/// list with the specified TypeResolutionKind.
/// Represents the error that occurs when a type was not found in the cache type list with the specified TypeResolutionKind.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
internal class CachedTypeNotFoundInFileException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
/// </summary>
public CachedTypeNotFoundInFileException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public CachedTypeNotFoundInFileException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public CachedTypeNotFoundInFileException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected CachedTypeNotFoundInFileException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
#endregion
}
}

View File

@@ -41,5 +41,43 @@ namespace Umbraco.Core
return (num & nums) > 0;
}
/// <summary>
/// Sets a flag of the given input enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input">Enum to set flag of</param>
/// <param name="flag">Flag to set</param>
/// <returns>A new enum with the flag set</returns>
public static T SetFlag<T>(this T input, T flag)
where T : Enum
{
var i = Convert.ToUInt64(input);
var f = Convert.ToUInt64(flag);
// bitwise OR to set flag f of enum i
var result = i | f;
return (T)Enum.ToObject(typeof(T), result);
}
/// <summary>
/// Unsets a flag of the given input enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input">Enum to unset flag of</param>
/// <param name="flag">Flag to unset</param>
/// <returns>A new enum with the flag unset</returns>
public static T UnsetFlag<T>(this T input, T flag)
where T : Enum
{
var i = Convert.ToUInt64(input);
var f = Convert.ToUInt64(flag);
// bitwise AND combined with bitwise complement to unset flag f of enum i
var result = i & ~f;
return (T)Enum.ToObject(typeof(T), result);
}
}
}

View File

@@ -1,16 +1,24 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
/// The exception that is thrown when a null reference, or an empty argument,
/// is passed to a method that does not accept it as a valid argument.
/// The exception that is thrown when a null reference, or an empty argument, is passed to a method that does not accept it as a valid argument.
/// </summary>
/// <seealso cref="System.ArgumentNullException" />
[Obsolete("Throw an ArgumentNullException when the parameter is null or an ArgumentException when its empty instead.")]
[Serializable]
public class ArgumentNullOrEmptyException : ArgumentNullException
{
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException"/> class
/// with the name of the parameter that caused this exception.
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
/// </summary>
public ArgumentNullOrEmptyException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class with the name of the parameter that caused this exception.
/// </summary>
/// <param name="paramName">The named of the parameter that caused the exception.</param>
public ArgumentNullOrEmptyException(string paramName)
@@ -18,13 +26,30 @@ namespace Umbraco.Core.Exceptions
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException"/> class
/// with a specified error message and the name of the parameter that caused this exception.
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class with a specified error message and the name of the parameter that caused this exception.
/// </summary>
/// <param name="paramName">The named of the parameter that caused the exception.</param>
/// <param name="message">A message that describes the error.</param>
public ArgumentNullOrEmptyException(string paramName, string message)
: base(paramName, message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for this exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public ArgumentNullOrEmptyException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
/// </summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">An object that describes the source or destination of the serialized data.</param>
protected ArgumentNullOrEmptyException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -1,14 +1,45 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
/// The exception that is thrown when authorization failed.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public class AuthorizationException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
/// </summary>
public AuthorizationException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public AuthorizationException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public AuthorizationException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected AuthorizationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;
using System.Text;
namespace Umbraco.Core.Exceptions
@@ -6,6 +7,8 @@ namespace Umbraco.Core.Exceptions
/// <summary>
/// An exception that is thrown if the Umbraco application cannot boot.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public class BootFailedException : Exception
{
/// <summary>
@@ -13,6 +16,12 @@ namespace Umbraco.Core.Exceptions
/// </summary>
public const string DefaultMessage = "Boot failed: Umbraco cannot run. See Umbraco's log file for more details.";
/// <summary>
/// Initializes a new instance of the <see cref="BootFailedException" /> class.
/// </summary>
public BootFailedException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="Exception" /> class with a specified error message.
/// </summary>
@@ -26,15 +35,29 @@ namespace Umbraco.Core.Exceptions
/// and a reference to the inner exception which is the cause of this exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="inner">The inner exception, or null.</param>
public BootFailedException(string message, Exception inner)
: base(message, inner)
/// <param name="innerException">The inner exception, or null.</param>
public BootFailedException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="BootFailedException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected BootFailedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// Rethrows a captured <see cref="BootFailedException" />.
/// </summary>
/// <remarks>The exception can be null, in which case a default message is used.</remarks>
/// <param name="bootFailedException">The boot failed exception.</param>
/// <exception cref="Umbraco.Core.Exceptions.BootFailedException">
/// </exception>
/// <remarks>
/// The exception can be null, in which case a default message is used.
/// </remarks>
public static void Rethrow(BootFailedException bootFailedException)
{
if (bootFailedException == null)

View File

@@ -1,12 +0,0 @@
using System;
namespace Umbraco.Core.Exceptions
{
public class ConnectionException : Exception
{
public ConnectionException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

View File

@@ -1,21 +1,98 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="System.Exception" />
[Serializable]
public class DataOperationException<T> : Exception
where T : Enum
{
/// <summary>
/// Gets the operation.
/// </summary>
/// <value>
/// The operation.
/// </value>
/// <remarks>
/// This object should be serializable to prevent a <see cref="SerializationException" /> to be thrown.
/// </remarks>
public T Operation { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
public DataOperationException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public DataOperationException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public DataOperationException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
/// <param name="operation">The operation.</param>
public DataOperationException(T operation)
: this(operation, "Data operation exception: " + operation)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
/// <param name="operation">The operation.</param>
/// <param name="message">The message.</param>
public DataOperationException(T operation, string message)
: base(message)
{
Operation = operation;
}
public DataOperationException(T operation)
: base("Data operation exception: " + operation)
/// <summary>
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">info</exception>
protected DataOperationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
Operation = operation;
Operation = (T)Enum.Parse(typeof(T), info.GetString(nameof(Operation)));
}
/// <summary>
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">info</exception>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException(nameof(info));
}
info.AddValue(nameof(Operation), Enum.GetName(typeof(T), Operation));
base.GetObjectData(info, context);
}
}
}

View File

@@ -1,44 +1,126 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
/// The exception that is thrown when a composition is invalid.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public class InvalidCompositionException : Exception
{
public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliass)
{
ContentTypeAlias = contentTypeAlias;
AddedCompositionAlias = addedCompositionAlias;
PropertyTypeAliases = propertyTypeAliass;
}
/// <summary>
/// Gets the content type alias.
/// </summary>
/// <value>
/// The content type alias.
/// </value>
public string ContentTypeAlias { get; }
public InvalidCompositionException(string contentTypeAlias, string[] propertyTypeAliass)
{
ContentTypeAlias = contentTypeAlias;
PropertyTypeAliases = propertyTypeAliass;
}
/// <summary>
/// Gets the added composition alias.
/// </summary>
/// <value>
/// The added composition alias.
/// </value>
public string AddedCompositionAlias { get; }
public string ContentTypeAlias { get; private set; }
/// <summary>
/// Gets the property type aliases.
/// </summary>
/// <value>
/// The property type aliases.
/// </value>
public string[] PropertyTypeAliases { get; }
public string AddedCompositionAlias { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
public InvalidCompositionException()
{ }
public string[] PropertyTypeAliases { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
/// <param name="contentTypeAlias">The content type alias.</param>
/// <param name="propertyTypeAliases">The property type aliases.</param>
public InvalidCompositionException(string contentTypeAlias, string[] propertyTypeAliases)
: this(contentTypeAlias, null, propertyTypeAliases)
{ }
public override string Message
{
get
{
return string.IsNullOrWhiteSpace(AddedCompositionAlias)
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
/// <param name="contentTypeAlias">The content type alias.</param>
/// <param name="addedCompositionAlias">The added composition alias.</param>
/// <param name="propertyTypeAliases">The property type aliases.</param>
public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliases)
: this(addedCompositionAlias.IsNullOrWhiteSpace()
? string.Format(
"ContentType with alias '{0}' has an invalid composition " +
"and there was a conflict on the following PropertyTypes: '{1}'. " +
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
ContentTypeAlias, string.Join(", ", PropertyTypeAliases))
contentTypeAlias, string.Join(", ", propertyTypeAliases))
: string.Format(
"ContentType with alias '{0}' was added as a Composition to ContentType with alias '{1}', " +
"but there was a conflict on the following PropertyTypes: '{2}'. " +
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
AddedCompositionAlias, ContentTypeAlias, string.Join(", ", PropertyTypeAliases));
}
addedCompositionAlias, contentTypeAlias, string.Join(", ", propertyTypeAliases)))
{
ContentTypeAlias = contentTypeAlias;
AddedCompositionAlias = addedCompositionAlias;
PropertyTypeAliases = propertyTypeAliases;
}
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public InvalidCompositionException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public InvalidCompositionException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected InvalidCompositionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
ContentTypeAlias = info.GetString(nameof(ContentTypeAlias));
AddedCompositionAlias = info.GetString(nameof(AddedCompositionAlias));
PropertyTypeAliases = (string[])info.GetValue(nameof(PropertyTypeAliases), typeof(string[]));
}
/// <summary>
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">info</exception>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException(nameof(info));
}
info.AddValue(nameof(ContentTypeAlias), ContentTypeAlias);
info.AddValue(nameof(AddedCompositionAlias), AddedCompositionAlias);
info.AddValue(nameof(PropertyTypeAliases), PropertyTypeAliases);
base.GetObjectData(info, context);
}
}
}

View File

@@ -4,25 +4,42 @@ using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
/// Internal exception that in theory should never ben thrown, it is only thrown in circumstances that should never happen
/// Represents an internal exception that in theory should never been thrown, it is only thrown in circumstances that should never happen.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public class PanicException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="PanicException" /> class.
/// </summary>
public PanicException()
{
}
{ }
public PanicException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PanicException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public PanicException(string message)
: base(message)
{ }
public PanicException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PanicException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public PanicException(string message, Exception innerException)
: base(message, innerException)
{ }
protected PanicException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PanicException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected PanicException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -1,14 +1,20 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Exceptions
{
/// <summary>
/// The exception that is thrown when a requested method or operation is not, and will not be, implemented.
/// </summary>
/// <remarks>The <see cref="NotImplementedException"/> is to be used when some code is not implemented,
/// <remarks>
/// The <see cref="NotImplementedException" /> is to be used when some code is not implemented,
/// but should eventually be implemented (i.e. work in progress) and is reported by tools such as ReSharper.
/// This exception is to be used when some code is not implemented, and is not meant to be, for whatever
/// reason.</remarks>
/// reason.
/// </remarks>
/// <seealso cref="System.NotImplementedException" />
[Serializable]
[Obsolete("If a method or operation is not, and will not be, implemented, it is invalid or not supported, so we should throw either an InvalidOperationException or NotSupportedException instead.")]
public class WontImplementException : NotImplementedException
{
/// <summary>
@@ -20,8 +26,27 @@ namespace Umbraco.Core.Exceptions
/// <summary>
/// Initializes a new instance of the <see cref="WontImplementException" /> class with a specified reason message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public WontImplementException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="WontImplementException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="inner">The exception that is the cause of the current exception. If the <paramref name="inner" /> parameter is not <see langword="null" />, the current exception is raised in a <see langword="catch" /> block that handles the inner exception.</param>
public WontImplementException(string message, Exception inner)
: base(message, inner)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="WontImplementException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected WontImplementException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -1,20 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace Umbraco.Core.IO
{
/// <summary>
/// The exception that is thrown when the caller does not have the required permission to access a file.
/// </summary>
/// <seealso cref="System.Exception" />
[Obsolete("Throw an UnauthorizedAccessException instead.")]
[Serializable]
public class FileSecurityException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
/// </summary>
public FileSecurityException()
{
{ }
}
/// <summary>
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public FileSecurityException(string message)
: base(message)
{ }
public FileSecurityException(string message) : base(message)
{
/// <summary>
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public FileSecurityException(string message, Exception innerException)
: base(message, innerException)
{ }
}
/// <summary>
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected FileSecurityException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -3,9 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
@@ -91,7 +89,8 @@ namespace Umbraco.Core.IO
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentNullOrEmptyException(nameof(filename));
if (filename == null) throw new ArgumentNullException(nameof(filename));
if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(filename));
if (filestream == null) throw new ArgumentNullException(nameof(filestream));
// clear the old file, if any
@@ -110,7 +109,8 @@ namespace Umbraco.Core.IO
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
if (string.IsNullOrWhiteSpace(sourcepath)) throw new ArgumentNullOrEmptyException(nameof(sourcepath));
if (sourcepath == null) throw new ArgumentNullException(nameof(sourcepath));
if (string.IsNullOrWhiteSpace(sourcepath)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(sourcepath));
// ensure we have a file to copy
if (FileExists(sourcepath) == false) return null;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Composing;
using System.Threading;
using Umbraco.Core.Logging;
@@ -47,9 +48,11 @@ namespace Umbraco.Core.IO
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
if (string.IsNullOrEmpty(rootPath)) throw new ArgumentNullOrEmptyException(nameof(rootPath));
if (string.IsNullOrEmpty(rootUrl)) throw new ArgumentNullOrEmptyException(nameof(rootUrl));
if (rootPath.StartsWith("~/")) throw new ArgumentException("The rootPath argument cannot be a virtual path and cannot start with '~/'");
if (rootPath == null) throw new ArgumentNullException(nameof(rootPath));
if (string.IsNullOrEmpty(rootPath)) throw new ArgumentException("Value can't be empty.", nameof(rootPath));
if (rootUrl == null) throw new ArgumentNullException(nameof(rootUrl));
if (string.IsNullOrEmpty(rootUrl)) throw new ArgumentException("Value can't be empty.", nameof(rootUrl));
if (rootPath.StartsWith("~/")) throw new ArgumentException("Value can't be a virtual path and start with '~/'.", nameof(rootPath));
// rootPath should be... rooted, as in, it's a root path!
@@ -323,7 +326,7 @@ namespace Umbraco.Core.IO
// nothing prevents us to reach the file, security-wise, yet it is outside
// this filesystem's root - throw
throw new FileSecurityException("File '" + opath + "' is outside this filesystem's root.");
throw new UnauthorizedAccessException("File '" + opath + "' is outside this filesystem's root.");
}
/// <summary>

View File

@@ -1,22 +0,0 @@
using System;
namespace Umbraco.Core.Migrations
{
/// <summary>
/// Used if a migration has executed but the whole process has failed and cannot be rolled back
/// </summary>
internal class DataLossException : Exception
{
public DataLossException(string msg)
: base(msg)
{
}
public DataLossException(string msg, Exception inner)
: base(msg, inner)
{
}
}
}

View File

@@ -1,15 +1,17 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Migrations
{
/// <summary>
/// Represents errors that occurs when a migration exception is not executed.
/// The exception that is thrown when a migration expression is not executed.
/// </summary>
/// <remarks>
/// <para>Migration expression such as Alter.Table(...).Do() *must* end with Do() else they are
/// not executed. When a non-executed expression is detected, an IncompleteMigrationExpressionException
/// is thrown.</para>
/// Migration expressions such as Alter.Table(...).Do() must end with Do(), else they are not executed.
/// When a non-executed expression is detected, an IncompleteMigrationExpressionException is thrown.
/// </remarks>
/// <seealso cref="System.Exception" />
[Serializable]
public class IncompleteMigrationExpressionException : Exception
{
/// <summary>
@@ -21,8 +23,27 @@ namespace Umbraco.Core.Migrations
/// <summary>
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class with a message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public IncompleteMigrationExpressionException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public IncompleteMigrationExpressionException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected IncompleteMigrationExpressionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

View File

@@ -4,8 +4,6 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
@@ -229,8 +227,8 @@ namespace Umbraco.Core.Models
private void ClearCultureInfo(string culture)
{
if (culture.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
if (_cultureInfos == null) return;
_cultureInfos.Remove(culture);

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
@@ -18,7 +17,9 @@ namespace Umbraco.Core.Models
/// </summary>
public ContentCultureInfos(string culture)
{
if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
Culture = culture;
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Specialized;
using Umbraco.Core.Collections;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models
{
@@ -22,7 +21,9 @@ namespace Umbraco.Core.Models
/// </summary>
public void AddOrUpdate(string culture, string name, DateTime date)
{
if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
culture = culture.ToLowerInvariant();
if (TryGetValue(culture, out var item))

View File

@@ -1,6 +1,5 @@
using System;
using System.Linq;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models
{
@@ -8,11 +7,11 @@ namespace Umbraco.Core.Models
{
public static void SetCultureInfo(this IContentBase content, string culture, string name, DateTime date)
{
if (name.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (culture.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
content.CultureInfos.AddOrUpdate(culture, name, date);
}

View File

@@ -67,7 +67,7 @@ namespace Umbraco.Core.Models.Entities
public int ParentId { get; set; }
/// <inheritdoc />
public void SetParent(ITreeEntity parent) => throw new WontImplementException();
public void SetParent(ITreeEntity parent) => throw new InvalidOperationException("This property won't be implemented.");
/// <inheritdoc />
[DataMember]
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Models.Entities
/// <inheritdoc />
public object DeepClone()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
#endregion
@@ -127,5 +127,58 @@ namespace Umbraco.Core.Models.Entities
Id = default;
Key = Guid.Empty;
}
#region IRememberBeingDirty
// IEntitySlim does *not* track changes, but since it indirectly implements IUmbracoEntity,
// and therefore IRememberBeingDirty, we have to have those methods - which all throw.
public bool IsDirty()
{
throw new InvalidOperationException("This method won't be implemented.");
}
public bool IsPropertyDirty(string propName)
{
throw new InvalidOperationException("This method won't be implemented.");
}
public IEnumerable<string> GetDirtyProperties()
{
throw new InvalidOperationException("This method won't be implemented.");
}
public void ResetDirtyProperties()
{
throw new InvalidOperationException("This method won't be implemented.");
}
public bool WasDirty()
{
throw new InvalidOperationException("This method won't be implemented.");
}
public bool WasPropertyDirty(string propertyName)
{
throw new InvalidOperationException("This method won't be implemented.");
}
public void ResetWereDirtyProperties()
{
throw new InvalidOperationException("This method won't be implemented.");
}
public void ResetDirtyProperties(bool rememberDirty)
{
throw new InvalidOperationException("This method won't be implemented.");
}
public IEnumerable<string> GetWereDirtyProperties()
{
throw new InvalidOperationException("This method won't be implemented.");
}
#endregion
}
}

View File

@@ -75,5 +75,14 @@ namespace Umbraco.Core.Models
/// <param name="wildcards">A value indicating whether wildcards are valid.</param>
bool SupportsVariation(string culture, string segment, bool wildcards = false);
/// <summary>
/// Gets or sets the custom validation message used when a value for this PropertyType is required
/// </summary>
string MandatoryMessage { get; set; }
/// <summary>
/// Gets or sets the custom validation message used when a pattern for this PropertyType must be matched
/// </summary>
string ValidationRegExpMessage { get; set; }
}
}

View File

@@ -20,7 +20,9 @@ namespace Umbraco.Core.Models.PublishedContent
{
private ModelType(string contentTypeAlias)
{
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias));
if (contentTypeAlias == null) throw new ArgumentNullException(nameof(contentTypeAlias));
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(contentTypeAlias));
ContentTypeAlias = contentTypeAlias;
Name = "{" + ContentTypeAlias + "}";
}

View File

@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models.PublishedContent
{
@@ -13,7 +12,8 @@ namespace Umbraco.Core.Models.PublishedContent
/// </summary>
public PublishedCultureInfo(string culture, string name, string urlSegment, DateTime date)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
Culture = culture ?? throw new ArgumentNullException(nameof(culture));
Name = name;

View File

@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models.PublishedContent
{
@@ -19,7 +18,9 @@ namespace Umbraco.Core.Models.PublishedContent
/// <param name="contentTypeAlias">The content type alias.</param>
public PublishedModelAttribute(string contentTypeAlias)
{
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias));
if (contentTypeAlias == null) throw new ArgumentNullException(nameof(contentTypeAlias));
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(contentTypeAlias));
ContentTypeAlias = contentTypeAlias;
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
@@ -20,7 +19,9 @@ namespace Umbraco.Core.Models
public RelationType(Guid childObjectType, Guid parentObjectType, string alias)
{
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentNullOrEmptyException(nameof(alias));
if (alias == null) throw new ArgumentNullException(nameof(alias));
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(alias));
_childObjectType = childObjectType;
_parentObjectType = parentObjectType;
_alias = alias;
@@ -30,7 +31,9 @@ namespace Umbraco.Core.Models
public RelationType(Guid childObjectType, Guid parentObjectType, string alias, string name)
: this(childObjectType, parentObjectType, alias)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
Name = name;
}

View File

@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.PropertyEditors
{
@@ -28,13 +27,15 @@ namespace Umbraco.Core.PropertyEditors
/// <param name="view">The view to use to render the field editor.</param>
public ConfigurationFieldAttribute(string key, string name, string view)
{
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullOrEmptyException(nameof(key));
if (key == null) throw new ArgumentNullException(nameof(key));
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(key));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (view == null) throw new ArgumentNullException(nameof(view));
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(view));
Key = key;
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
Name = name;
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentNullOrEmptyException(nameof(view));
View = view;
}
@@ -47,10 +48,12 @@ namespace Umbraco.Core.PropertyEditors
/// from the name of the property marked with this attribute.</remarks>
public ConfigurationFieldAttribute(string name, string view)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
Name = name;
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (view == null) throw new ArgumentNullException(nameof(view));
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(view));
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentNullOrEmptyException(nameof(view));
Name = name;
View = view;
}

View File

@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.PropertyEditors
{
@@ -53,17 +52,17 @@ namespace Umbraco.Core.PropertyEditors
/// </remarks>
public DataEditorAttribute(string alias, EditorType type, string name, string view)
{
if ((type & ~(EditorType.PropertyValue | EditorType.MacroParameter)) > 0)
throw new ArgumentOutOfRangeException(nameof(type), $"Not a valid {typeof(EditorType)} value.");
if (alias == null) throw new ArgumentNullException(nameof(alias));
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(alias));
if ((type & ~(EditorType.PropertyValue | EditorType.MacroParameter)) > 0) throw new ArgumentOutOfRangeException(nameof(type), type, $"Not a valid {typeof(EditorType)} value.");
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (view == null) throw new ArgumentNullException(nameof(view));
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(view));
Type = type;
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentNullOrEmptyException(nameof(alias));
Alias = alias;
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
Name = name;
if (string.IsNullOrWhiteSpace(view)) throw new ArgumentNullOrEmptyException(nameof(view));
View = view == NullView ? null : view;
}
@@ -100,8 +99,10 @@ namespace Umbraco.Core.PropertyEditors
get => _valueType;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullOrEmptyException(nameof(value));
if (!ValueTypes.IsValue(value)) throw new ArgumentOutOfRangeException(nameof(value), $"Not a valid {typeof(ValueTypes)} value.");
if (value == null) throw new ArgumentNullException(nameof(value));
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(value));
if (!ValueTypes.IsValue(value)) throw new ArgumentOutOfRangeException(nameof(value), value, $"Not a valid {typeof(ValueTypes)} value.");
_valueType = value;
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Xml
{
@@ -35,7 +34,8 @@ namespace Umbraco.Core.Xml
// allowed 'inline', not just at the beginning... whether or not we want to support that is up
// for discussion.
if (string.IsNullOrWhiteSpace(xpathExpression)) throw new ArgumentNullOrEmptyException(nameof(xpathExpression));
if (xpathExpression == null) throw new ArgumentNullException(nameof(xpathExpression));
if (string.IsNullOrWhiteSpace(xpathExpression)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(xpathExpression));
if (getPath == null) throw new ArgumentNullException(nameof(getPath));
if (publishedContentExists == null) throw new ArgumentNullException(nameof(publishedContentExists));

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.XPath;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
namespace Umbraco.Core.Xml
{
@@ -14,6 +14,35 @@ namespace Umbraco.Core.Xml
/// </summary>
public class XmlHelper
{
/// <summary>
/// Creates or sets an attribute on the XmlNode if an Attributes collection is available
/// </summary>
/// <param name="xml"></param>
/// <param name="n"></param>
/// <param name="name"></param>
/// <param name="value"></param>
public static void SetAttribute(XmlDocument xml, XmlNode n, string name, string value)
{
if (xml == null) throw new ArgumentNullException(nameof(xml));
if (n == null) throw new ArgumentNullException(nameof(n));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (n.Attributes == null)
{
return;
}
if (n.Attributes[name] == null)
{
var a = xml.CreateAttribute(name);
a.Value = value;
n.Attributes.Append(a);
}
else
{
n.Attributes[name].Value = value;
}
}
/// <summary>
/// Gets a value indicating whether a specified string contains only xml whitespace characters.
@@ -173,6 +202,145 @@ namespace Umbraco.Core.Xml
}
/// <summary>
/// Opens a file as a XmlDocument.
/// </summary>
/// <param name="filePath">The relative file path. ie. /config/umbraco.config</param>
/// <param name="ioHelper"></param>
/// <returns>Returns a XmlDocument class</returns>
public static XmlDocument OpenAsXmlDocument(string filePath, IIOHelper ioHelper)
{
using (var reader = new XmlTextReader(ioHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All})
{
var xmlDoc = new XmlDocument();
//Load the file into the XmlDocument
xmlDoc.Load(reader);
return xmlDoc;
}
}
/// <summary>
/// creates a XmlAttribute with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The name of the attribute.</param>
/// <param name="value">The value of the attribute.</param>
/// <returns>a XmlAttribute</returns>
public static XmlAttribute AddAttribute(XmlDocument xd, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var temp = xd.CreateAttribute(name);
temp.Value = value;
return temp;
}
/// <summary>
/// Creates a text XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>a XmlNode</returns>
public static XmlNode AddTextNode(XmlDocument xd, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateTextNode(value));
return temp;
}
/// <summary>
/// Sets or Creates a text XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="parent">The node to set or create the child text node on</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>a XmlNode</returns>
public static XmlNode SetTextNode(XmlDocument xd, XmlNode parent, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (parent == null) throw new ArgumentNullException(nameof(parent));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var child = parent.SelectSingleNode(name);
if (child != null)
{
child.InnerText = value;
return child;
}
return AddTextNode(xd, name, value);
}
/// <summary>
/// Sets or creates an Xml node from its inner Xml.
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="parent">The node to set or create the child text node on</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node inner Xml.</param>
/// <returns>a XmlNode</returns>
public static XmlNode SetInnerXmlNode(XmlDocument xd, XmlNode parent, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (parent == null) throw new ArgumentNullException(nameof(parent));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var child = parent.SelectSingleNode(name) ?? xd.CreateNode(XmlNodeType.Element, name, "");
child.InnerXml = value;
return child;
}
/// <summary>
/// Creates a cdata XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>A XmlNode</returns>
public static XmlNode AddCDataNode(XmlDocument xd, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateCDataSection(value));
return temp;
}
/// <summary>
/// Sets or Creates a cdata XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="parent">The node to set or create the child text node on</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>a XmlNode</returns>
public static XmlNode SetCDataNode(XmlDocument xd, XmlNode parent, string name, string value)
{
if (xd == null) throw new ArgumentNullException(nameof(xd));
if (parent == null) throw new ArgumentNullException(nameof(parent));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
var child = parent.SelectSingleNode(name);
if (child != null)
{
child.InnerXml = "<![CDATA[" + value + "]]>"; ;
return child;
}
return AddCDataNode(xd, name, value);
}
/// <summary>
/// Gets the value of a XmlNode

View File

@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;
using System.Text;
namespace Umbraco.Core.Composing.LightInject
@@ -6,20 +7,51 @@ namespace Umbraco.Core.Composing.LightInject
/// <summary>
/// Represents errors that occur due to LightInject.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public class LightInjectException : Exception
{
public LightInjectException(string message)
: base(message)
{ }
public LightInjectException(string message, Exception innerException)
: base(message, innerException)
{ }
private const string LightInjectUnableToResolveType = "Unable to resolve type:";
private const string LightInjectUnresolvedDependency = "Unresolved dependency ";
private const string LightInjectRequestedDependency = "[Requested dependency:";
/// <summary>
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
/// </summary>
public LightInjectException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public LightInjectException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public LightInjectException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="LightInjectException"/> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected LightInjectException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// Tries to throw the exception with additional details.
/// </summary>
/// <param name="e">The exception.</param>
/// <exception cref="Umbraco.Core.Composing.LightInject.LightInjectException"></exception>
public static void TryThrow(Exception e)
{
var ex = e as InvalidOperationException;
@@ -32,6 +64,12 @@ namespace Umbraco.Core.Composing.LightInject
throw new LightInjectException(sb.ToString(), e);
}
/// <summary>
/// Tries to throw the exception with additional details.
/// </summary>
/// <param name="e">The exception.</param>
/// <param name="implementingType">The implementing type.</param>
/// <exception cref="Umbraco.Core.Composing.LightInject.LightInjectException"></exception>
public static void TryThrow(Exception e, Type implementingType)
{
var ex = e as InvalidOperationException;
@@ -45,6 +83,11 @@ namespace Umbraco.Core.Composing.LightInject
throw new LightInjectException(sb.ToString(), e);
}
/// <summary>
/// Writes the details.
/// </summary>
/// <param name="ex">The exception.</param>
/// <param name="sb">The <see cref="StringBuilder" /> to write the details to.</param>
private static void WriteDetails(InvalidOperationException ex, StringBuilder sb)
{
ex = ex.InnerException as InvalidOperationException;

View File

@@ -5,7 +5,6 @@ using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Umbraco.Core.Cache;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
@@ -53,12 +52,13 @@ namespace Umbraco.Core.Manifest
_localizationService = localizationService;
_validators = validators ?? throw new ArgumentNullException(nameof(validators));
_filters = filters ?? throw new ArgumentNullException(nameof(filters));
if (path == null) throw new ArgumentNullException(nameof(path));
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(path));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_ioHelper = ioHelper;
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullOrEmptyException(nameof(path));
Path = path;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
@@ -170,8 +170,8 @@ namespace Umbraco.Core.Manifest
/// </summary>
public PackageManifest ParseManifest(string text)
{
if (string.IsNullOrWhiteSpace(text))
throw new ArgumentNullOrEmptyException(nameof(text));
if (text == null) throw new ArgumentNullException(nameof(text));
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text));
var manifest = JsonConvert.DeserializeObject<PackageManifest>(text,
new DataEditorConverter(_logger, _ioHelper, _dataTypeService, _localizationService),

View File

@@ -1,4 +1,4 @@
using Umbraco.Core.Exceptions;
using System;
using Umbraco.Core.Migrations.Expressions.Common;
using Umbraco.Core.Migrations.Expressions.Delete.Column;
using Umbraco.Core.Migrations.Expressions.Delete.Constraint;
@@ -39,8 +39,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
/// <inheritdoc />
public IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true)
{
if (tableName.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(tableName));
if (tableName == null) throw new ArgumentNullException(nameof(tableName));
if (string.IsNullOrWhiteSpace(tableName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(tableName));
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName, DeleteLocal = local, DeleteForeign = foreign };
}

View File

@@ -5,7 +5,6 @@ using System.Linq;
using System.Xml.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Upgrade;
@@ -291,8 +290,10 @@ namespace Umbraco.Core.Migrations.Install
/// <param name="logger">A logger.</param>
private static void SaveConnectionString(string connectionString, string providerName, IIOHelper ioHelper, ILogger logger)
{
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentNullOrEmptyException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentNullOrEmptyException(nameof(providerName));
if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionString));
if (providerName == null) throw new ArgumentNullException(nameof(providerName));
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(providerName));
var fileSource = "web.config";
var fileName = ioHelper.MapPath(ioHelper.Root +"/" + fileSource);

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
using Type = System.Type;
@@ -25,7 +24,9 @@ namespace Umbraco.Core.Migrations
/// <param name="name">The name of the plan.</param>
public MigrationPlan(string name)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
Name = name;
}
@@ -43,7 +44,8 @@ namespace Umbraco.Core.Migrations
private MigrationPlan Add(string sourceState, string targetState, Type migration)
{
if (sourceState == null) throw new ArgumentNullException(nameof(sourceState));
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState));
if (targetState == null) throw new ArgumentNullException(nameof(targetState));
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(targetState));
if (sourceState == targetState) throw new ArgumentException("Source and target state cannot be identical.");
if (migration == null) throw new ArgumentNullException(nameof(migration));
if (!migration.Implements<IMigration>()) throw new ArgumentException($"Type {migration.Name} does not implement IMigration.", nameof(migration));
@@ -135,10 +137,12 @@ namespace Umbraco.Core.Migrations
/// </summary>
public MigrationPlan ToWithClone(string startState, string endState, string targetState)
{
if (string.IsNullOrWhiteSpace(startState)) throw new ArgumentNullOrEmptyException(nameof(startState));
if (string.IsNullOrWhiteSpace(endState)) throw new ArgumentNullOrEmptyException(nameof(endState));
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState));
if (startState == null) throw new ArgumentNullException(nameof(startState));
if (string.IsNullOrWhiteSpace(startState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(startState));
if (endState == null) throw new ArgumentNullException(nameof(endState));
if (string.IsNullOrWhiteSpace(endState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(endState));
if (targetState == null) throw new ArgumentNullException(nameof(targetState));
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(targetState));
if (startState == endState) throw new ArgumentException("Start and end states cannot be identical.");
startState = startState.Trim();
@@ -317,7 +321,7 @@ namespace Umbraco.Core.Migrations
// throw a raw exception here: this should never happen as the plan has
// been validated - this is just a paranoid safety test
if (!_transitions.TryGetValue(origState, out transition))
throw new Exception($"Unknown state \"{origState}\".");
throw new InvalidOperationException($"Unknown state \"{origState}\".");
}
// prepare and de-duplicate post-migrations, only keeping the 1st occurence
@@ -339,7 +343,7 @@ namespace Umbraco.Core.Migrations
// safety check - again, this should never happen as the plan has been validated,
// and this is just a paranoid safety test
if (origState != _finalState)
throw new Exception($"Internal error, reached state {origState} which is not final state {_finalState}");
throw new InvalidOperationException($"Internal error, reached state {origState} which is not final state {_finalState}");
return origState;
}
@@ -358,7 +362,7 @@ namespace Umbraco.Core.Migrations
var states = new List<string> { origState };
if (!_transitions.TryGetValue(origState, out var transition))
throw new Exception($"Unknown state \"{origState}\".");
throw new InvalidOperationException($"Unknown state \"{origState}\".");
while (transition != null)
{
@@ -373,12 +377,12 @@ namespace Umbraco.Core.Migrations
}
if (!_transitions.TryGetValue(origState, out transition))
throw new Exception($"Unknown state \"{origState}\".");
throw new InvalidOperationException($"Unknown state \"{origState}\".");
}
// safety check
if (origState != (toState ?? _finalState))
throw new Exception($"Internal error, reached state {origState} which is not state {toState ?? _finalState}");
throw new InvalidOperationException($"Internal error, reached state {origState} which is not state {toState ?? _finalState}");
return states;
}
@@ -417,7 +421,7 @@ namespace Umbraco.Core.Migrations
public override string ToString()
{
return MigrationType == typeof(NoopMigration)
? $"{(SourceState == "" ? "<empty>" : SourceState)} --> {TargetState}"
? $"{(SourceState == string.Empty ? "<empty>" : SourceState)} --> {TargetState}"
: $"{SourceState} -- ({MigrationType.FullName}) --> {TargetState}";
}
}

View File

@@ -6,6 +6,7 @@ using Umbraco.Core.Migrations.Upgrade.Common;
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
using Umbraco.Core.Migrations.Upgrade.V_8_0_1;
using Umbraco.Core.Migrations.Upgrade.V_8_1_0;
using Umbraco.Core.Migrations.Upgrade.V_8_6_0;
namespace Umbraco.Core.Migrations.Upgrade
{
@@ -183,6 +184,9 @@ namespace Umbraco.Core.Migrations.Upgrade
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");
// to 8.6.0
To<AddPropertyTypeValidationMessageColumns>("{3D67D2C8-5E65-47D0-A9E1-DC2EE0779D6B}");
//FINAL
}
}

View File

@@ -0,0 +1,20 @@
using System.Linq;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
{
public class AddPropertyTypeValidationMessageColumns : MigrationBase
{
public AddPropertyTypeValidationMessageColumns(IMigrationContext context)
: base(context)
{ }
public override void Migrate()
{
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToList();
AddColumnIfNotExists<PropertyTypeDto>(columns, "mandatoryMessage");
AddColumnIfNotExists<PropertyTypeDto>(columns, "validationRegExpMessage");
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models
{
@@ -103,11 +102,11 @@ namespace Umbraco.Core.Models
public static void SetPublishInfo(this IContent content, string culture, string name, DateTime date)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (culture.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
content.PublishCultureInfos.AddOrUpdate(culture, name, date);
}
@@ -240,8 +239,8 @@ namespace Umbraco.Core.Models
/// <returns></returns>
public static bool ClearPublishInfo(this IContent content, string culture)
{
if (culture.IsNullOrWhiteSpace())
throw new ArgumentNullOrEmptyException(nameof(culture));
if (culture == null) throw new ArgumentNullException(nameof(culture));
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
var removed = content.PublishCultureInfos.Remove(culture);
if (removed)

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Models
@@ -42,7 +41,8 @@ namespace Umbraco.Core.Models
public Member(string name, IMemberType contentType)
: base(name, -1, contentType, new PropertyCollection())
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
IsApproved = true;
@@ -62,9 +62,12 @@ namespace Umbraco.Core.Models
public Member(string name, string email, string username, IMemberType contentType, bool isApproved = true)
: base(name, -1, contentType, new PropertyCollection())
{
if (string.IsNullOrWhiteSpace(email)) throw new ArgumentNullOrEmptyException(nameof(email));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentNullOrEmptyException(nameof(username));
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (email == null) throw new ArgumentNullException(nameof(email));
if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(email));
if (username == null) throw new ArgumentNullException(nameof(username));
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(username));
_email = email;
_username = username;

View File

@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
@@ -25,8 +26,10 @@ namespace Umbraco.Core.Models
private string _propertyEditorAlias;
private ValueStorageType _valueStorageType;
private bool _mandatory;
private string _mandatoryMessage;
private int _sortOrder;
private string _validationRegExp;
private string _validationRegExpMessage;
private ContentVariation _variations;
/// <summary>
@@ -168,7 +171,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _propertyGroupId, nameof(PropertyGroupId));
}
/// <inheritdoc />
[DataMember]
public bool Mandatory
@@ -178,6 +180,14 @@ namespace Umbraco.Core.Models
}
/// <inheritdoc />
[DataMember]
public string MandatoryMessage
{
get => _mandatoryMessage;
set => SetPropertyValueAndDetectChanges(value, ref _mandatoryMessage, nameof(MandatoryMessage));
}
/// <inheritdoc />
[DataMember]
public int SortOrder
@@ -194,6 +204,17 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExp, nameof(ValidationRegExp));
}
/// <summary>
/// Gets or sets the custom validation message used when a pattern for this PropertyType must be matched
/// </summary>
[DataMember]
public string ValidationRegExpMessage
{
get => _validationRegExpMessage;
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExpMessage, nameof(ValidationRegExpMessage));
}
/// <inheritdoc />
public ContentVariation Variations
{

View File

@@ -785,7 +785,14 @@ namespace Umbraco.Core.Packaging
Mandatory = property.Element("Mandatory") != null
? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true")
: false,
MandatoryMessage = property.Element("MandatoryMessage") != null
? (string)property.Element("MandatoryMessage")
: string.Empty,
ValidationRegExp = (string)property.Element("Validation"),
ValidationRegExpMessage = property.Element("ValidationRegExpMessage") != null
? (string)property.Element("ValidationRegExpMessage")
: string.Empty,
SortOrder = sortOrder,
Variations = property.Element("Variations") != null
? (ContentVariation)Enum.Parse(typeof(ContentVariation), property.Element("Variations").Value)

View File

@@ -43,10 +43,20 @@ namespace Umbraco.Core.Persistence.Dtos
[Constraint(Default = "0")]
public bool Mandatory { get; set; }
[Column("mandatoryMessage")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(500)]
public string MandatoryMessage { get; set; }
[Column("validationRegExp")]
[NullSetting(NullSetting = NullSettings.Null)]
public string ValidationRegExp { get; set; }
[Column("validationRegExpMessage")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(500)]
public string ValidationRegExpMessage { get; set; }
[Column("Description")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(2000)]

View File

@@ -32,9 +32,15 @@ namespace Umbraco.Core.Persistence.Dtos
[Column("mandatory")]
public bool Mandatory { get; set; }
[Column("mandatoryMessage")]
public string MandatoryMessage { get; set; }
[Column("validationRegExp")]
public string ValidationRegExp { get; set; }
[Column("validationRegExpMessage")]
public string ValidationRegExpMessage { get; set; }
[Column("Description")]
public string Description { get; set; }

View File

@@ -1,38 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace Umbraco.Core.Persistence
{
// TODO: Would be good to use this exception type anytime we cannot find an entity
/// <summary>
/// An exception used to indicate that an umbraco entity could not be found
/// An exception used to indicate that an Umbraco entity could not be found.
/// </summary>
/// <seealso cref="System.Exception" />
[Obsolete("Instead of throwing an exception, return null or an HTTP 404 status code instead.")]
[Serializable]
public class EntityNotFoundException : Exception
{
/// <summary>
/// Gets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
/// <remarks>
/// This object should be serializable to prevent a <see cref="SerializationException" /> to be thrown.
/// </remarks>
public object Id { get; private set; }
private readonly string _msg;
public EntityNotFoundException(object id, string msg)
/// <summary>
/// Initializes a new instance of the <see cref="EntityNotFoundException" /> class.
/// </summary>
public EntityNotFoundException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="EntityNotFoundException" /> class.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="message">The message.</param>
public EntityNotFoundException(object id, string message)
: base(message)
{
Id = id;
_msg = msg;
}
public EntityNotFoundException(string msg)
/// <summary>
/// Initializes a new instance of the <see cref="EntityNotFoundException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public EntityNotFoundException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="EntityNotFoundException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
public EntityNotFoundException(string message, Exception innerException)
: base(message, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="EntityNotFoundException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected EntityNotFoundException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
_msg = msg;
Id = info.GetValue(nameof(Id), typeof(object));
}
public override string Message
/// <summary>
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">info</exception>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
get { return _msg; }
if (info == null)
{
throw new ArgumentNullException(nameof(info));
}
info.AddValue(nameof(Id), Id);
base.GetObjectData(info, context);
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var result = base.ToString();

View File

@@ -60,8 +60,10 @@ namespace Umbraco.Core.Persistence.Factories
propertyType.Key = typeDto.UniqueId;
propertyType.Name = typeDto.Name;
propertyType.Mandatory = typeDto.Mandatory;
propertyType.MandatoryMessage = typeDto.MandatoryMessage;
propertyType.SortOrder = typeDto.SortOrder;
propertyType.ValidationRegExp = typeDto.ValidationRegExp;
propertyType.ValidationRegExpMessage = typeDto.ValidationRegExpMessage;
propertyType.PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id);
propertyType.CreateDate = createDate;
propertyType.UpdateDate = updateDate;
@@ -124,9 +126,11 @@ namespace Umbraco.Core.Persistence.Factories
DataTypeId = propertyType.DataTypeId,
Description = propertyType.Description,
Mandatory = propertyType.Mandatory,
MandatoryMessage = propertyType.MandatoryMessage,
Name = propertyType.Name,
SortOrder = propertyType.SortOrder,
ValidationRegExp = propertyType.ValidationRegExp,
ValidationRegExpMessage = propertyType.ValidationRegExpMessage,
UniqueId = propertyType.Key,
Variations = (byte)propertyType.Variations
};

View File

@@ -4,9 +4,9 @@ using System.Runtime.Serialization;
namespace Umbraco.Core.Persistence.FaultHandling
{
/// <summary>
/// The special type of exception that provides managed exit from a retry loop. The user code can use this
/// exception to notify the retry policy that no further retry attempts are required.
/// The special type of exception that provides managed exit from a retry loop. The user code can use this exception to notify the retry policy that no further retry attempts are required.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
public sealed class RetryLimitExceededException : Exception
{
@@ -14,9 +14,8 @@ namespace Umbraco.Core.Persistence.FaultHandling
/// Initializes a new instance of the <see cref="RetryLimitExceededException" /> class with a default error message.
/// </summary>
public RetryLimitExceededException()
: this("RetryLimitExceeded")
{
}
: base()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="RetryLimitExceededException" /> class with a specified error message.
@@ -24,18 +23,15 @@ namespace Umbraco.Core.Persistence.FaultHandling
/// <param name="message">The message that describes the error.</param>
public RetryLimitExceededException(string message)
: base(message)
{
}
{ }
/// <summary>
/// Initializes a new instance of the <see cref="RetryLimitExceededException"/> class with a reference to the inner exception
/// that is the cause of this exception.
/// Initializes a new instance of the <see cref="RetryLimitExceededException" /> class with a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
public RetryLimitExceededException(Exception innerException)
: base(innerException != null ? innerException.Message : "RetryLimitExceeded", innerException)
{
}
: base(null, innerException)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="RetryLimitExceededException" /> class.
@@ -44,19 +40,15 @@ namespace Umbraco.Core.Persistence.FaultHandling
/// <param name="innerException">The exception that is the cause of the current exception.</param>
public RetryLimitExceededException(string message, Exception innerException)
: base(message, innerException)
{
}
{ }
/// <summary>
/// Initializes a new instance of the <see cref="RetryLimitExceededException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null.</exception>
/// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0).</exception>
private RetryLimitExceededException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
{ }
}
}

View File

@@ -24,9 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.DataTypeId), nameof(PropertyTypeDto.DataTypeId));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Description), nameof(PropertyTypeDto.Description));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Mandatory), nameof(PropertyTypeDto.Mandatory));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.MandatoryMessage), nameof(PropertyTypeDto.MandatoryMessage));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Name), nameof(PropertyTypeDto.Name));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.SortOrder), nameof(PropertyTypeDto.SortOrder));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.ValidationRegExp), nameof(PropertyTypeDto.ValidationRegExp));
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.ValidationRegExpMessage), nameof(PropertyTypeDto.ValidationRegExpMessage));
DefineMap<PropertyType, DataTypeDto>(nameof(PropertyType.PropertyEditorAlias), nameof(DataTypeDto.EditorAlias));
DefineMap<PropertyType, DataTypeDto>(nameof(PropertyType.ValueStorageType), nameof(DataTypeDto.DbType));
}

View File

@@ -296,10 +296,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
Id = dto.Id,
Key = dto.UniqueId,
Mandatory = dto.Mandatory,
MandatoryMessage = dto.MandatoryMessage,
Name = dto.Name,
PropertyGroupId = groupId.HasValue ? new Lazy<int>(() => groupId.Value) : null,
SortOrder = dto.SortOrder,
ValidationRegExp = dto.ValidationRegExp,
ValidationRegExpMessage = dto.ValidationRegExpMessage,
Variations = (ContentVariation)dto.Variations
};
}

View File

@@ -924,32 +924,32 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override IEnumerable<IContent> PerformGetByQuery(IQuery<IContent> query)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override void PersistNewItem(IContent entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override void PersistUpdatedItem(IContent entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override string GetBaseWhereClause()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Dtos;
@@ -129,6 +128,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistDeletedItem(EntityContainer entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
EnsureContainerType(entity);
var nodeDto = Database.FirstOrDefault<NodeDto>(Sql().SelectAll()
@@ -162,9 +162,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(EntityContainer entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
EnsureContainerType(entity);
if (string.IsNullOrWhiteSpace(entity.Name)) throw new ArgumentNullOrEmptyException("entity.Name");
if (entity.Name == null) throw new InvalidOperationException("Entity name can't be null.");
if (string.IsNullOrWhiteSpace(entity.Name)) throw new InvalidOperationException("Entity name can't be empty or consist only of white-space characters.");
entity.Name = entity.Name.Trim();
// guard against duplicates
@@ -184,7 +186,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
.Where<NodeDto>(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType));
if (parentDto == null)
throw new NullReferenceException("Could not find parent container with id " + entity.ParentId);
throw new InvalidOperationException("Could not find parent container with id " + entity.ParentId);
level = parentDto.Level;
path = parentDto.Path;
@@ -223,10 +225,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
//
protected override void PersistUpdatedItem(EntityContainer entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
EnsureContainerType(entity);
if (entity.Name == null) throw new InvalidOperationException("Entity name can't be null.");
if (string.IsNullOrWhiteSpace(entity.Name)) throw new InvalidOperationException("Entity name can't be empty or consist only of white-space characters.");
entity.Name = entity.Name.Trim();
if (string.IsNullOrWhiteSpace(entity.Name)) throw new ArgumentNullOrEmptyException("entity.Name");
// find container to update
var nodeDto = Database.FirstOrDefault<NodeDto>(Sql().SelectAll()
@@ -255,7 +259,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
.Where<NodeDto>(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType));
if (parent == null)
throw new NullReferenceException("Could not find parent container with id " + entity.ParentId);
throw new InvalidOperationException("Could not find parent container with id " + entity.ParentId);
nodeDto.Level = Convert.ToInt16(parent.Level + 1);
nodeDto.Path = parent.Path + "," + nodeDto.NodeId;

View File

@@ -424,32 +424,32 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override IEnumerable<IMedia> PerformGetByQuery(IQuery<IMedia> query)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override void PersistNewItem(IMedia entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override void PersistUpdatedItem(IMedia entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override string GetBaseWhereClause()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
}

View File

@@ -252,27 +252,27 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override ContentPermissionSet PerformGet(int id)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<ContentPermissionSet> PerformGetAll(params int[] ids)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<ContentPermissionSet> PerformGetByQuery(IQuery<ContentPermissionSet> query)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override string GetBaseWhereClause()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<string> GetDeleteClauses()
@@ -280,11 +280,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
return new List<string>();
}
protected override Guid NodeObjectTypeId => throw new WontImplementException();
protected override Guid NodeObjectTypeId => throw new InvalidOperationException("This property won't be implemented.");
protected override void PersistDeletedItem(ContentPermissionSet entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
#endregion

View File

@@ -75,19 +75,19 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected sealed override IEnumerable<string> GetDeleteClauses()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected sealed override Guid NodeObjectTypeId => throw new WontImplementException();
protected sealed override Guid NodeObjectTypeId => throw new InvalidOperationException("This property won't be implemented.");
protected sealed override void PersistNewItem(TEntity entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected sealed override void PersistUpdatedItem(TEntity entity)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
#endregion

View File

@@ -286,7 +286,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
return list;
}
protected override Guid NodeObjectTypeId => throw new WontImplementException();
protected override Guid NodeObjectTypeId => throw new InvalidOperationException("This property won't be implemented.");
protected override void PersistNewItem(IUserGroup entity)
{
@@ -370,35 +370,35 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override UserGroupWithUsers PerformGet(int id)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<UserGroupWithUsers> PerformGetAll(params int[] ids)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<UserGroupWithUsers> PerformGetByQuery(IQuery<UserGroupWithUsers> query)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override string GetBaseWhereClause()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new WontImplementException();
throw new InvalidOperationException("This method won't be implemented.");
}
protected override Guid NodeObjectTypeId => throw new WontImplementException();
protected override Guid NodeObjectTypeId => throw new InvalidOperationException("This property won't be implemented.");
#endregion

View File

@@ -5,7 +5,6 @@ using NPoco;
using NPoco.FluentMappings;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.FaultHandling;
using Umbraco.Core.Persistence.Mappers;
@@ -62,8 +61,8 @@ namespace Umbraco.Core.Persistence
/// <remarks>Used by the other ctor and in tests.</remarks>
public UmbracoDatabaseFactory(string connectionStringName, ILogger logger, Lazy<IMapperCollection> mappers, Configs configs)
{
if (string.IsNullOrWhiteSpace(connectionStringName))
throw new ArgumentNullOrEmptyException(nameof(connectionStringName));
if (connectionStringName == null) throw new ArgumentNullException(nameof(connectionStringName));
if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionStringName));
_mappers = mappers ?? throw new ArgumentNullException(nameof(mappers));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Services;
namespace Umbraco.Core.PropertyEditors.Validators
@@ -50,8 +49,9 @@ namespace Umbraco.Core.PropertyEditors.Validators
get => _regex;
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullOrEmptyException(nameof(value));
if (value == null) throw new ArgumentNullException(nameof(value));
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(value));
_regex = value;
}
}
@@ -60,7 +60,9 @@ namespace Umbraco.Core.PropertyEditors.Validators
public IEnumerable<ValidationResult> Validate(object value, string valueType, object dataTypeConfiguration)
{
if (_regex == null)
{
throw new InvalidOperationException("The validator has not been configured.");
}
return ValidateFormat(value, valueType, _regex);
}
@@ -68,7 +70,8 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <inheritdoc cref="IValueFormatValidator.ValidateFormat"/>
public IEnumerable<ValidationResult> ValidateFormat(object value, string valueType, string format)
{
if (string.IsNullOrWhiteSpace(format)) throw new ArgumentNullOrEmptyException(nameof(format));
if (format == null) throw new ArgumentNullException(nameof(format));
if (string.IsNullOrWhiteSpace(format)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(format));
if (value == null || !new Regex(format).IsMatch(value.ToString()))
{
yield return new ValidationResult(_textService?.Localize("validation", "invalidPattern") ?? ValueIsInvalid, new[] { "value" });

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core
{
@@ -29,10 +28,14 @@ namespace Umbraco.Core
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
/// <typeparam name="TValue">The field type.</typeparam>
/// <param name="fieldName">The name of the field.</param>
/// <returns>A field getter function.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
/// <returns>
/// A field getter function.
/// </returns>
/// <exception cref="ArgumentNullException">fieldName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="fieldName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match field <typeparamref name="TDeclaring" />.<paramref name="fieldName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find field <typeparamref name="TDeclaring" />.<paramref name="fieldName" />.</exception>
public static Func<TDeclaring, TValue> EmitFieldGetter<TDeclaring, TValue>(string fieldName)
{
var field = GetField<TDeclaring, TValue>(fieldName);
@@ -45,10 +48,14 @@ namespace Umbraco.Core
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
/// <typeparam name="TValue">The field type.</typeparam>
/// <param name="fieldName">The name of the field.</param>
/// <returns>A field setter action.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
/// <returns>
/// A field setter action.
/// </returns>
/// <exception cref="ArgumentNullException">fieldName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="fieldName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match field <typeparamref name="TDeclaring" />.<paramref name="fieldName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find field <typeparamref name="TDeclaring" />.<paramref name="fieldName" />.</exception>
public static Action<TDeclaring, TValue> EmitFieldSetter<TDeclaring, TValue>(string fieldName)
{
var field = GetField<TDeclaring, TValue>(fieldName);
@@ -61,19 +68,36 @@ namespace Umbraco.Core
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
/// <typeparam name="TValue">The field type.</typeparam>
/// <param name="fieldName">The name of the field.</param>
/// <returns>A field getter and setter functions.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
/// <returns>
/// A field getter and setter functions.
/// </returns>
/// <exception cref="ArgumentNullException">fieldName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="fieldName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match field <typeparamref name="TDeclaring" />.<paramref name="fieldName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find field <typeparamref name="TDeclaring" />.<paramref name="fieldName" />.</exception>
public static (Func<TDeclaring, TValue>, Action<TDeclaring, TValue>) EmitFieldGetterAndSetter<TDeclaring, TValue>(string fieldName)
{
var field = GetField<TDeclaring, TValue>(fieldName);
return (EmitFieldGetter<TDeclaring, TValue>(field), EmitFieldSetter<TDeclaring, TValue>(field));
}
/// <summary>
/// Gets the field.
/// </summary>
/// <typeparam name="TDeclaring">The type of the declaring.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="fieldName">Name of the field.</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException">fieldName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="fieldName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match field <typeparamref name="TDeclaring" />.<paramref name="fieldName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find field <typeparamref name="TDeclaring" />.<paramref name="fieldName" />.</exception>
private static FieldInfo GetField<TDeclaring, TValue>(string fieldName)
{
if (string.IsNullOrWhiteSpace(fieldName)) throw new ArgumentNullOrEmptyException(nameof(fieldName));
if (fieldName == null) throw new ArgumentNullException(nameof(fieldName));
if (string.IsNullOrWhiteSpace(fieldName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(fieldName));
// get the field
var field = typeof(TDeclaring).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
@@ -120,13 +144,18 @@ namespace Umbraco.Core
/// <typeparam name="TValue">The property type.</typeparam>
/// <param name="propertyName">The name of the property.</param>
/// <param name="mustExist">A value indicating whether the property and its getter must exist.</param>
/// <returns>A property getter function. If <paramref name="mustExist"/> is <c>false</c>, returns null when the property or its getter does not exist.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="propertyName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the property or its getter does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the property.</exception>
/// <returns>
/// A property getter function. If <paramref name="mustExist" /> is <c>false</c>, returns null when the property or its getter does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">propertyName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="propertyName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match property <typeparamref name="TDeclaring" />.<paramref name="propertyName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find property getter for <typeparamref name="TDeclaring" />.<paramref name="propertyName" />.</exception>
public static Func<TDeclaring, TValue> EmitPropertyGetter<TDeclaring, TValue>(string propertyName, bool mustExist = true)
{
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentNullOrEmptyException(nameof(propertyName));
if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyName));
var property = typeof(TDeclaring).GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
@@ -146,13 +175,18 @@ namespace Umbraco.Core
/// <typeparam name="TValue">The property type.</typeparam>
/// <param name="propertyName">The name of the property.</param>
/// <param name="mustExist">A value indicating whether the property and its setter must exist.</param>
/// <returns>A property setter function. If <paramref name="mustExist"/> is <c>false</c>, returns null when the property or its setter does not exist.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="propertyName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the property or its setter does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the property.</exception>
/// <returns>
/// A property setter function. If <paramref name="mustExist" /> is <c>false</c>, returns null when the property or its setter does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">propertyName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="propertyName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match property <typeparamref name="TDeclaring" />.<paramref name="propertyName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find property setter for <typeparamref name="TDeclaring" />.<paramref name="propertyName" />.</exception>
public static Action<TDeclaring, TValue> EmitPropertySetter<TDeclaring, TValue>(string propertyName, bool mustExist = true)
{
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentNullOrEmptyException(nameof(propertyName));
if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyName));
var property = typeof(TDeclaring).GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
@@ -172,13 +206,18 @@ namespace Umbraco.Core
/// <typeparam name="TValue">The property type.</typeparam>
/// <param name="propertyName">The name of the property.</param>
/// <param name="mustExist">A value indicating whether the property and its getter and setter must exist.</param>
/// <returns>A property getter and setter functions. If <paramref name="mustExist"/> is <c>false</c>, returns null when the property or its getter or setter does not exist.</returns>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="propertyName"/> is null or empty.</exception>
/// <exception cref="InvalidOperationException">Occurs when the property or its getter or setter does not exist.</exception>
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the property.</exception>
/// <returns>
/// A property getter and setter functions. If <paramref name="mustExist" /> is <c>false</c>, returns null when the property or its getter or setter does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">propertyName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="propertyName" />
/// or
/// Value type <typeparamref name="TValue" /> does not match property <typeparamref name="TDeclaring" />.<paramref name="propertyName" /> type.</exception>
/// <exception cref="InvalidOperationException">Could not find property getter and setter for <typeparamref name="TDeclaring" />.<paramref name="propertyName" />.</exception>
public static (Func<TDeclaring, TValue>, Action<TDeclaring, TValue>) EmitPropertyGetterAndSetter<TDeclaring, TValue>(string propertyName, bool mustExist = true)
{
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentNullOrEmptyException(nameof(propertyName));
if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyName));
var property = typeof(TDeclaring).GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
@@ -402,13 +441,17 @@ namespace Umbraco.Core
/// <typeparam name="TLambda">A lambda representing the method.</typeparam>
/// <param name="methodName">The name of the method.</param>
/// <param name="mustExist">A value indicating whether the constructor must exist.</param>
/// <returns>The method. If <paramref name="mustExist"/> is <c>false</c>, returns null when the method does not exist.</returns>
/// <remarks>
/// <para>The method arguments are determined by <typeparamref name="TLambda"/> generic arguments.</para>
/// </remarks>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="methodName"/> is null or empty.</exception>
/// <returns>
/// The method. If <paramref name="mustExist" /> is <c>false</c>, returns null when the method does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">methodName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="methodName" />
/// or
/// Occurs when <typeparamref name="TLambda" /> does not match the method signature..</exception>
/// <exception cref="InvalidOperationException">Occurs when no proper method with name <paramref name="methodName" /> could be found.</exception>
/// <exception cref="ArgumentException">Occurs when Occurs when <typeparamref name="TLambda"/> does not match the method signature.</exception>
/// <remarks>
/// The method arguments are determined by <typeparamref name="TLambda" /> generic arguments.
/// </remarks>
public static TLambda EmitMethod<TDeclaring, TLambda>(string methodName, bool mustExist = true)
{
return EmitMethod<TLambda>(typeof(TDeclaring), methodName, mustExist);
@@ -421,16 +464,21 @@ namespace Umbraco.Core
/// <param name="declaring">The declaring type.</param>
/// <param name="methodName">The name of the method.</param>
/// <param name="mustExist">A value indicating whether the constructor must exist.</param>
/// <returns>The method. If <paramref name="mustExist"/> is <c>false</c>, returns null when the method does not exist.</returns>
/// <remarks>
/// <para>The method arguments are determined by <typeparamref name="TLambda"/> generic arguments.</para>
/// </remarks>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="methodName"/> is null or empty.</exception>
/// <returns>
/// The method. If <paramref name="mustExist" /> is <c>false</c>, returns null when the method does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">methodName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="methodName" />
/// or
/// Occurs when <typeparamref name="TLambda" /> does not match the method signature..</exception>
/// <exception cref="InvalidOperationException">Occurs when no proper method with name <paramref name="methodName" /> could be found.</exception>
/// <exception cref="ArgumentException">Occurs when Occurs when <typeparamref name="TLambda"/> does not match the method signature.</exception>
/// <remarks>
/// The method arguments are determined by <typeparamref name="TLambda" /> generic arguments.
/// </remarks>
public static TLambda EmitMethod<TLambda>(Type declaring, string methodName, bool mustExist = true)
{
if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentNullOrEmptyException(nameof(methodName));
if (methodName == null) throw new ArgumentNullException(nameof(methodName));
if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(methodName));
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(true, out var isFunction);
@@ -510,17 +558,21 @@ namespace Umbraco.Core
/// <typeparam name="TLambda">A lambda representing the method.</typeparam>
/// <param name="methodName">The name of the method.</param>
/// <param name="mustExist">A value indicating whether the constructor must exist.</param>
/// <returns>The method. If <paramref name="mustExist"/> is <c>false</c>, returns null when the method does not exist.</returns>
/// <remarks>
/// <para>The method arguments are determined by <typeparamref name="TLambda"/> generic arguments.</para>
/// </remarks>
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="methodName"/> is null or empty.</exception>
/// <returns>
/// The method. If <paramref name="mustExist" /> is <c>false</c>, returns null when the method does not exist.
/// </returns>
/// <exception cref="ArgumentNullException">methodName</exception>
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - <paramref name="methodName" />
/// or
/// Occurs when <typeparamref name="TLambda" /> does not match the method signature..</exception>
/// <exception cref="InvalidOperationException">Occurs when no proper method with name <paramref name="methodName" /> could be found.</exception>
/// <exception cref="ArgumentException">Occurs when Occurs when <typeparamref name="TLambda"/> does not match the method signature.</exception>
/// <remarks>
/// The method arguments are determined by <typeparamref name="TLambda" /> generic arguments.
/// </remarks>
public static TLambda EmitMethod<TLambda>(string methodName, bool mustExist = true)
{
if (string.IsNullOrWhiteSpace(methodName))
throw new ArgumentNullOrEmptyException(nameof(methodName));
if (methodName == null) throw new ArgumentNullException(nameof(methodName));
if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(methodName));
// validate lambda type
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(false, out var isFunction);

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Web;
using Semver;
using Umbraco.Core.Collections;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Exceptions;
@@ -22,7 +22,7 @@ namespace Umbraco.Core
private readonly ILogger _logger;
private readonly IUmbracoSettingsSection _settings;
private readonly IGlobalSettings _globalSettings;
private readonly HashSet<string> _applicationUrls = new HashSet<string>();
private readonly ConcurrentHashSet<string> _applicationUrls = new ConcurrentHashSet<string>();
private readonly Lazy<IMainDom> _mainDom;
private readonly Lazy<IServerRegistrar> _serverRegistrar;
private readonly IUmbracoVersion _umbracoVersion;

View File

@@ -5,7 +5,6 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Umbraco.Core.Configuration;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Identity;
@@ -208,7 +207,8 @@ namespace Umbraco.Core.Security
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException(nameof(user));
if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentNullOrEmptyException(nameof(passwordHash));
if (passwordHash == null) throw new ArgumentNullException(nameof(passwordHash));
if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentException("Value can't be empty.", nameof(passwordHash));
user.PasswordHash = passwordHash;
@@ -320,7 +320,7 @@ namespace Umbraco.Core.Security
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException(nameof(user));
if (login == null) throw new ArgumentNullException("login");
if (login == null) throw new ArgumentNullException(nameof(login));
var logins = user.Logins;
var instance = new IdentityUserLogin(login.LoginProvider, login.ProviderKey, user.Id);
@@ -339,7 +339,7 @@ namespace Umbraco.Core.Security
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException(nameof(user));
if (login == null) throw new ArgumentNullException("login");
if (login == null) throw new ArgumentNullException(nameof(login));
var provider = login.LoginProvider;
var key = login.ProviderKey;
@@ -370,7 +370,7 @@ namespace Umbraco.Core.Security
public Task<BackOfficeIdentityUser> FindAsync(UserLoginInfo login)
{
ThrowIfDisposed();
if (login == null) throw new ArgumentNullException("login");
if (login == null) throw new ArgumentNullException(nameof(login));
//get all logins associated with the login id
var result = _externalLoginService.Find(UserLoginInfoWrapper.Wrap(login)).ToArray();
@@ -404,7 +404,8 @@ namespace Umbraco.Core.Security
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleName)) throw new ArgumentException("Value cannot be null or whitespace.", "roleName");
if (roleName == null) throw new ArgumentNullException(nameof(roleName));
if (string.IsNullOrWhiteSpace(roleName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(roleName));
var userRole = user.Roles.SingleOrDefault(r => r.RoleId == roleName);
@@ -425,7 +426,8 @@ namespace Umbraco.Core.Security
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleName)) throw new ArgumentException("Value cannot be null or whitespace.", "roleName");
if (roleName == null) throw new ArgumentNullException(nameof(roleName));
if (string.IsNullOrWhiteSpace(roleName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(roleName));
var userRole = user.Roles.SingleOrDefault(r => r.RoleId == roleName);

View File

@@ -2884,7 +2884,8 @@ namespace Umbraco.Core.Services.Implement
private IContentType GetContentType(IScope scope, string contentTypeAlias)
{
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias));
if (contentTypeAlias == null) throw new ArgumentNullException(nameof(contentTypeAlias));
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(contentTypeAlias));
scope.ReadLock(Constants.Locks.ContentTypes);
@@ -2899,7 +2900,8 @@ namespace Umbraco.Core.Services.Implement
private IContentType GetContentType(string contentTypeAlias)
{
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias));
if (contentTypeAlias == null) throw new ArgumentNullException(nameof(contentTypeAlias));
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(contentTypeAlias));
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
{

View File

@@ -592,10 +592,9 @@ namespace Umbraco.Core.Services.Implement
public TItem Copy(TItem original, string alias, string name, TItem parent)
{
if (original == null) throw new ArgumentNullException(nameof(original));
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentNullOrEmptyException(nameof(alias));
if (parent != null && parent.HasIdentity == false)
throw new InvalidOperationException("Parent must have an identity.");
if (alias == null) throw new ArgumentNullException(nameof(alias));
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(alias));
if (parent != null && parent.HasIdentity == false) throw new InvalidOperationException("Parent must have an identity.");
// this is illegal
//var originalb = (ContentTypeCompositionBase)original;

View File

@@ -360,7 +360,9 @@ namespace Umbraco.Core.Services.Implement
new XElement("Definition", definition.Key),
new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name),
new XElement("Mandatory", propertyType.Mandatory.ToString()),
new XElement("MandatoryMessage", propertyType.MandatoryMessage),
new XElement("Validation", propertyType.ValidationRegExp),
new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage),
new XElement("Description", new XCData(propertyType.Description)));
genericProperties.Add(genericProperty);
}
@@ -487,7 +489,9 @@ namespace Umbraco.Core.Services.Implement
new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name),
new XElement("SortOrder", propertyType.SortOrder),
new XElement("Mandatory", propertyType.Mandatory.ToString()),
propertyType.MandatoryMessage != null ? new XElement("MandatoryMessage", propertyType.MandatoryMessage) : null,
propertyType.ValidationRegExp != null ? new XElement("Validation", propertyType.ValidationRegExp) : null,
propertyType.ValidationRegExpMessage != null ? new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage) : null,
propertyType.Description != null ? new XElement("Description", new XCData(propertyType.Description)) : null,
new XElement("Variations", propertyType.Variations.ToString()));

View File

@@ -5,7 +5,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
@@ -1340,7 +1339,8 @@ namespace Umbraco.Core.Services.Implement
private IMediaType GetMediaType(string mediaTypeAlias)
{
if (string.IsNullOrWhiteSpace(mediaTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(mediaTypeAlias));
if (mediaTypeAlias == null) throw new ArgumentNullException(nameof(mediaTypeAlias));
if (string.IsNullOrWhiteSpace(mediaTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(mediaTypeAlias));
using (var scope = ScopeProvider.CreateScope())
{
@@ -1350,7 +1350,7 @@ namespace Umbraco.Core.Services.Implement
var mediaType = _mediaTypeRepository.Get(query).FirstOrDefault();
if (mediaType == null)
throw new Exception($"No MediaType matching the passed in Alias: '{mediaTypeAlias}' was found"); // causes rollback // causes rollback
throw new InvalidOperationException($"No media type matched the specified alias '{mediaTypeAlias}'.");
scope.Complete();
return mediaType;

View File

@@ -1291,7 +1291,8 @@ namespace Umbraco.Core.Services.Implement
private IMemberType GetMemberType(IScope scope, string memberTypeAlias)
{
if (string.IsNullOrWhiteSpace(memberTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(memberTypeAlias));
if (memberTypeAlias == null) throw new ArgumentNullException(nameof(memberTypeAlias));
if (string.IsNullOrWhiteSpace(memberTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(memberTypeAlias));
scope.ReadLock(Constants.Locks.MemberTypes);
@@ -1305,7 +1306,8 @@ namespace Umbraco.Core.Services.Implement
private IMemberType GetMemberType(string memberTypeAlias)
{
if (string.IsNullOrWhiteSpace(memberTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(memberTypeAlias));
if (memberTypeAlias == null) throw new ArgumentNullException(nameof(memberTypeAlias));
if (string.IsNullOrWhiteSpace(memberTypeAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(memberTypeAlias));
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
{

View File

@@ -61,7 +61,7 @@ namespace Umbraco.Core.Services.Implement
}
catch (HttpRequestException ex)
{
throw new ConnectionException("An error occurring downloading the package from " + url, ex);
throw new HttpRequestException("An error occurring downloading the package from " + url, ex);
}
//successful

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Linq.Expressions;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Querying;
@@ -102,7 +101,8 @@ namespace Umbraco.Core.Services.Implement
/// <returns><see cref="IUser"/></returns>
private IUser CreateUserWithIdentity(string username, string email, string passwordValue, bool isApproved = true)
{
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentNullOrEmptyException(nameof(username));
if (username == null) throw new ArgumentNullException(nameof(username));
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(username));
// TODO: PUT lock here!!

View File

@@ -3,7 +3,6 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Strings;
@@ -106,7 +105,8 @@ namespace Umbraco.Core
/// <returns>The safe url segment.</returns>
public static string ToUrlSegment(this string text)
{
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullOrEmptyException(nameof(text));
if (text == null) throw new ArgumentNullException(nameof(text));
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text));
return Current.ShortStringHelper.CleanStringForUrlSegment(text);
}
@@ -119,7 +119,8 @@ namespace Umbraco.Core
/// <returns>The safe url segment.</returns>
public static string ToUrlSegment(this string text, string culture)
{
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullOrEmptyException(nameof(text));
if (text == null) throw new ArgumentNullException(nameof(text));
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text));
return Current.ShortStringHelper.CleanStringForUrlSegment(text, culture);
}

View File

@@ -188,6 +188,7 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameMediaVersionTable.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\ValueListPreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\UmbracoSliderPreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_6_0\AddPropertyTypeValidationMessageColumns.cs" />
<Compile Include="Migrations\Upgrade\V_8_1_0\FixContentNuCascade.cs" />
<Compile Include="Migrations\Upgrade\V_8_1_0\RenameUserLoginDtoDateIndex.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_1\ChangeNuCacheJsonFormat.cs" />

View File

@@ -51,5 +51,47 @@ namespace Umbraco.Tests.CoreThings
else
Assert.IsFalse(value.HasFlagAny(test));
}
[TestCase(TreeUse.None, TreeUse.None, TreeUse.None)]
[TestCase(TreeUse.None, TreeUse.Main, TreeUse.Main)]
[TestCase(TreeUse.None, TreeUse.Dialog, TreeUse.Dialog)]
[TestCase(TreeUse.None, TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main, TreeUse.None, TreeUse.Main)]
[TestCase(TreeUse.Main, TreeUse.Main, TreeUse.Main)]
[TestCase(TreeUse.Main, TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main, TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.None, TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.Main, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.Dialog, TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.None, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Main, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog)]
public void SetFlagTests(TreeUse value, TreeUse flag, TreeUse expected)
{
Assert.AreEqual(expected, value.SetFlag(flag));
}
[TestCase(TreeUse.None, TreeUse.None, TreeUse.None)]
[TestCase(TreeUse.None, TreeUse.Main, TreeUse.None)]
[TestCase(TreeUse.None, TreeUse.Dialog, TreeUse.None)]
[TestCase(TreeUse.None, TreeUse.Main | TreeUse.Dialog, TreeUse.None)]
[TestCase(TreeUse.Main, TreeUse.None, TreeUse.Main)]
[TestCase(TreeUse.Main, TreeUse.Main, TreeUse.None)]
[TestCase(TreeUse.Main, TreeUse.Dialog, TreeUse.Main)]
[TestCase(TreeUse.Main, TreeUse.Main | TreeUse.Dialog, TreeUse.None)]
[TestCase(TreeUse.Dialog, TreeUse.None, TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.Main, TreeUse.Dialog)]
[TestCase(TreeUse.Dialog, TreeUse.Dialog, TreeUse.None)]
[TestCase(TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog, TreeUse.None)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.None, TreeUse.Main | TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Main, TreeUse.Dialog)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Dialog, TreeUse.Main)]
[TestCase(TreeUse.Main | TreeUse.Dialog, TreeUse.Main | TreeUse.Dialog, TreeUse.None)]
public void UnsetFlagTests(TreeUse value, TreeUse flag, TreeUse expected)
{
Assert.AreEqual(expected, value.UnsetFlag(flag));
}
}
}

View File

@@ -103,7 +103,7 @@ namespace Umbraco.Tests.IO
Assert.AreEqual(Path.Combine(basePath, @"foo\bar.tmp"), path);
// that path is invalid as it would be outside the root directory
Assert.Throws<FileSecurityException>(() => _fileSystem.GetFullPath("../../foo.tmp"));
Assert.Throws<UnauthorizedAccessException>(() => _fileSystem.GetFullPath("../../foo.tmp"));
// a very long path, which ends up being very long, works
path = Repeat("bah/bah/", 50);

View File

@@ -250,7 +250,7 @@ namespace Umbraco.Tests.IO
var sfs = new PhysicalFileSystem(ioHelper, Current.Logger, path + "/ShadowSystem/", "ignore");
var ss = new ShadowFileSystem(fs, sfs);
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
ss.AddFile("../../f1.txt", ms);

View File

@@ -622,7 +622,9 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation()
{
Mandatory = true,
Pattern = "xyz"
MandatoryMessage = "Please enter a value",
Pattern = "xyz",
PatternMessage = "Please match the pattern",
}
};
@@ -635,7 +637,9 @@ namespace Umbraco.Tests.Models.Mapping
Assert.AreEqual(basic.DataTypeId, result.DataTypeId);
Assert.AreEqual(basic.Label, result.Name);
Assert.AreEqual(basic.Validation.Mandatory, result.Mandatory);
Assert.AreEqual(basic.Validation.MandatoryMessage, result.MandatoryMessage);
Assert.AreEqual(basic.Validation.Pattern, result.ValidationRegExp);
Assert.AreEqual(basic.Validation.PatternMessage, result.ValidationRegExpMessage);
}
[Test]
@@ -656,7 +660,9 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation()
{
Mandatory = true,
Pattern = "xyz"
MandatoryMessage = "Please enter a value",
Pattern = "xyz",
PatternMessage = "Please match the pattern",
}
};
@@ -669,7 +675,9 @@ namespace Umbraco.Tests.Models.Mapping
Assert.AreEqual(basic.DataTypeId, result.DataTypeId);
Assert.AreEqual(basic.Label, result.Name);
Assert.AreEqual(basic.Validation.Mandatory, result.Mandatory);
Assert.AreEqual(basic.Validation.MandatoryMessage, result.MandatoryMessage);
Assert.AreEqual(basic.Validation.Pattern, result.ValidationRegExp);
Assert.AreEqual(basic.Validation.PatternMessage, result.ValidationRegExpMessage);
}
[Test]
@@ -966,7 +974,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1012,7 +1020,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1064,7 +1072,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1110,7 +1118,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1134,7 +1142,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1188,7 +1196,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555
@@ -1212,7 +1220,7 @@ namespace Umbraco.Tests.Models.Mapping
Validation = new PropertyTypeValidation
{
Mandatory = false,
Pattern = ""
Pattern = string.Empty
},
SortOrder = 0,
DataTypeId = 555

View File

@@ -9,6 +9,7 @@ using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using System;
namespace Umbraco.Tests.Persistence.Repositories
{
@@ -79,7 +80,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath);
partialView = new PartialView(PartialViewType.PartialView, "\\test-path-4.cshtml") { Content = "// partialView" };
Assert.Throws<FileSecurityException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
Assert.Throws<UnauthorizedAccessException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
{
repository.Save(partialView);
});
@@ -88,11 +89,11 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.IsNull(partialView);
// fixed in 7.3 - 7.2.8 used to...
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
partialView = (PartialView) repository.Get("\\test-path-4.cshtml"); // outside the filesystem, does not exist
});
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
partialView = (PartialView) repository.Get("../../packages.config"); // outside the filesystem, exists
});

View File

@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using System.Linq;
using System.Text;
using Moq;
@@ -310,7 +311,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("/scripts/path-2/test-path-3.js", script.VirtualPath);
script = new Script("\\test-path-4.js") { Content = "// script" };
Assert.Throws<FileSecurityException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
Assert.Throws<UnauthorizedAccessException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
{
repository.Save(script);
});
@@ -319,11 +320,11 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.IsNull(script);
// fixed in 7.3 - 7.2.8 used to...
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
script = repository.Get("\\test-path-4.js"); // outside the filesystem, does not exist
});
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
script = repository.Get("../packages.config"); // outside the filesystem, exists
});

View File

@@ -1,4 +1,5 @@
using System.Data;
using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
@@ -293,7 +294,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath);
stylesheet = new Stylesheet("\\test-path-4.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
Assert.Throws<FileSecurityException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
Assert.Throws<UnauthorizedAccessException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
{
repository.Save(stylesheet);
});
@@ -303,11 +304,11 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.IsNull(stylesheet);
// fixed in 7.3 - 7.2.8 used to...
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
stylesheet = repository.Get("\\test-path-4.css"); // outside the filesystem, does not exist
});
Assert.Throws<FileSecurityException>(() =>
Assert.Throws<UnauthorizedAccessException>(() =>
{
stylesheet = repository.Get("../packages.config"); // outside the filesystem, exists
});

View File

@@ -266,7 +266,7 @@ namespace Umbraco.Tests.Published
public override bool HasValue(string culture = null, string segment = null) => _hasValue;
public override object GetSourceValue(string culture = null, string segment = null) => _sourceValue;
public override object GetValue(string culture = null, string segment = null) => PropertyType.ConvertInterToObject(_owner, ReferenceCacheLevel, InterValue, _preview);
public override object GetXPathValue(string culture = null, string segment = null) => throw new WontImplementException();
public override object GetXPathValue(string culture = null, string segment = null) => throw new InvalidOperationException("This method won't be implemented.");
}
}
}

View File

@@ -865,7 +865,7 @@ namespace Umbraco.Tests.Services
var userService = ServiceContext.UserService;
// Act & Assert
Assert.Throws<ArgumentNullOrEmptyException>(() => userService.CreateUserWithIdentity(string.Empty, "john@umbraco.io"));
Assert.Throws<ArgumentException>(() => userService.CreateUserWithIdentity(string.Empty, "john@umbraco.io"));
}
[Test]

View File

@@ -4,7 +4,7 @@
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbProperty', function (umbPropEditorHelper, userService) {
.directive('umbProperty', function (userService) {
return {
scope: {
property: "=",
@@ -17,7 +17,7 @@ angular.module("umbraco.directives")
templateUrl: 'views/components/property/umb-property.html',
link: function (scope) {
scope.propertyEditorAPI = {};
scope.propertyActions = [];
userService.getCurrentUser().then(function (u) {
var isAdmin = u.userGroups.indexOf('admin') !== -1;
@@ -25,7 +25,7 @@ angular.module("umbraco.directives")
});
},
//Define a controller for this directive to expose APIs to other directives
controller: function ($scope, $timeout) {
controller: function ($scope) {
var self = this;
@@ -36,17 +36,9 @@ angular.module("umbraco.directives")
$scope.property.propertyErrorMessage = errorMsg;
};
var unsubscribe = $scope.$on("ExposePropertyEditorAPI", function(event, api) {
//avoid eventual parent properties to capture this.
event.stopPropagation();
$scope.propertyEditorAPI = api;
});
$scope.$on("$destroy", function () {
unsubscribe();
});
self.setPropertyActions = function(actions) {
$scope.propertyActions = actions;
};
}
};

View File

@@ -65,6 +65,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
vm.reloadNode = reloadNode;
vm.syncTree = syncTree;
vm.loadChildren = loadChildren;
vm.hasTree = hasTree;
//wire up the exposed api object for hosting controllers
if ($scope.api) {
@@ -72,6 +73,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
$scope.api.load = vm.load;
$scope.api.reloadNode = vm.reloadNode;
$scope.api.syncTree = vm.syncTree;
$scope.api.hasTree = vm.hasTree;
}
//flag to track the last loaded section when the tree 'un-loads'. We use this to determine if we should
@@ -203,6 +205,25 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
});
}
//given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node
function hasTree(treeAlias) {
if (!$scope.tree) {
throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null";
}
if (!treeAlias) {
return false;
}
var treeRoots = getTreeRootNodes();
var foundTree = _.find(treeRoots, function (node) {
return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase();
});
return foundTree !== undefined;
}
//given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node
function loadActiveTree(treeAlias) {

View File

@@ -549,7 +549,9 @@
property.dataTypeIcon = propertyModel.dataTypeIcon;
property.dataTypeName = propertyModel.dataTypeName;
property.validation.mandatory = propertyModel.validation.mandatory;
property.validation.mandatoryMessage = propertyModel.validation.mandatoryMessage;
property.validation.pattern = propertyModel.validation.pattern;
property.validation.patternMessage = propertyModel.validation.patternMessage;
property.showOnMemberProfile = propertyModel.showOnMemberProfile;
property.memberCanEdit = propertyModel.memberCanEdit;
property.isSensitiveValue = propertyModel.isSensitiveValue;
@@ -632,7 +634,9 @@
propertyState: "init",
validation: {
mandatory: false,
pattern: null
mandatoryMessage: null,
pattern: null,
patternMessage: null
}
};

View File

@@ -338,6 +338,22 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
});
},
/**
* @ngdoc method
* @name umbraco.services.navigationService#hasTree
* @methodOf umbraco.services.navigationService
*
* @description
* Checks if a tree with the given alias exists.
*
* @param {String} treeAlias the tree alias to check
*/
hasTree: function (treeAlias) {
return navReadyPromise.promise.then(function () {
return mainTreeApi.hasTree(treeAlias);
});
},
/**
Internal method that should ONLY be used by the legacy API wrapper, the legacy API used to
have to set an active tree and then sync, the new API does this in one method by using syncTree

View File

@@ -89,6 +89,7 @@
}
function confirmDelete(overlay) {
overlay.confirmType = "delete";
confirm(overlay);
}

View File

@@ -1,29 +0,0 @@
(function() {
'use strict';
function propertyEditorService() {
/**
* @ngdoc function
* @name umbraco.services.propertyEditorService#expose
* @methodOf umbraco.services.propertyEditorService
* @function
*
* @param {object} scope An object containing API for the PropertyEditor
*/
function exposeAPI(scope, api) {
if (!scope) {
throw "scope cannot be null";
}
if (!api) {
throw "api cannot be null";
}
scope.$emit("ExposePropertyEditorAPI", api);
}
return {
exposeAPI: exposeAPI
};
}
angular.module('umbraco.services').factory('propertyEditorService', propertyEditorService);
})();

View File

@@ -184,7 +184,13 @@
});
if (cached) return cached[1];
nodeComputedStyle = nodeComputedStyle || this.doc.defaultView.getComputedStyle(node);
if (!nodeComputedStyle) {
if (node instanceof DocumentFragment) {
return true;// though DocumentFragment doesn't directly have display 'none', we know that it will never be visible, and therefore we return true. (and do not cache this, cause it will change if appended to the DOM)
} else {
nodeComputedStyle = this.doc.defaultView.getComputedStyle(node);
}
}
var result = false;

View File

@@ -0,0 +1,34 @@
(function () {
'use strict';
function validationMessageService($q, localizationService) {
// Gets the message to use for when a mandatory field isn't completed.
// Will either use the one provided on the property type's validation object
// or a localised default.
function getMandatoryMessage(validation) {
if (!validation) {
return $q.when("");
}
if (validation.mandatoryMessage) {
return $q.when(validation.mandatoryMessage);
} else {
return localizationService.localize("general_required").then(function (value) {
return $q.when(value);
});
}
}
var service = {
getMandatoryMessage: getMandatoryMessage
};
return service;
}
angular.module('umbraco.services').factory('validationMessageService', validationMessageService);
})();

View File

@@ -554,6 +554,12 @@ input.umb-group-builder__group-sort-value {
overflow: hidden;
}
.editor-validation-message {
min-width: 100%;
min-height: 25px;
margin-top: 4px;
}
.editor-validation-pattern {
border: 1px solid @gray-7;
margin: 10px 0 0;

View File

@@ -14,6 +14,17 @@
pointer-events: none;
}
.umb-nested-content--mandatory {
/*
yeah so this is a pain, but we must be super specific in targeting the mandatory property labels,
otherwise all properties within a reqired, nested, nested content property will all appear mandatory
*/
> ng-form > .control-group > .umb-el-wrap > .control-header label:after {
content: '*';
color: @red;
}
}
.umb-nested-content-overlay {
position: absolute;
top: 0;
@@ -134,6 +145,8 @@
.umb-nested-content__icon {
background: transparent;
border: 0 none;
display: inline-block;
padding: 4px;
margin: 2px;
@@ -235,7 +248,6 @@
}
.umb-nested-content__placeholder {
height: 22px;
padding: 4px 6px;
border: 1px dashed #d8d7d9;
background: 0 0;
@@ -246,33 +258,18 @@
text-align: center;
&--selected {
border: 1px solid #d8d7d9;
border: none;
text-align: left;
padding: 0;
}
}
.umb-nested-content__placeholder-name{
font-size: 15px;
}
.umb-nested-content__placeholder:hover {
color: #2152a3;
border-color: #2152a3;
text-decoration: none;
}
.umb-nested-content__placeholder-icon-holder {
width: 20px;
text-align: center;
display: inline-block;
}
.umb-nested-content__placeholder-icon {
font-size: 18px;
vertical-align: middle;
}
.form-horizontal .umb-nested-content--narrow .controls-row {
margin-left: 40% !important;
}

View File

@@ -528,7 +528,8 @@ input[type="checkbox"][readonly] {
.help-inline {
display: inline-block;
vertical-align: middle;
padding-left: 5px;
padding-top: 4px;
padding-left: 2px;
}
div.help {

View File

@@ -97,7 +97,8 @@
.history-line {
width: 2px;
height: 100%;
top: 10px;
bottom: 10px;
margin: 0 0 0 14px;
background-color: @gray-8;
position: absolute;

View File

@@ -90,11 +90,19 @@
<umb-toggle data-element="validation_mandatory"
checked="model.property.validation.mandatory"
on-click="vm.toggleValidation()"
on-click="vm.toggleValidation()">
focus-when="{{vm.focusOnMandatoryField}}"
>
</umb-toggle>
<input type="text"
class="editor-validation-message"
localize="placeholder"
placeholder="@validation_mandatoryMessage"
ng-model="model.property.validation.mandatoryMessage"
ng-if="model.property.validation.mandatory"
ng-keypress="vm.submitOnEnter($event)">
</input>
<label class="mt3">
<localize key="validation_customValidation"></localize>
</label>
@@ -114,6 +122,14 @@
ng-keypress="vm.submitOnEnter($event)">
</textarea>
<input type="text"
class="editor-validation-message"
localize="placeholder"
placeholder="@validation_validationRegExpMessage"
ng-model="model.property.validation.patternMessage"
ng-if="vm.showValidationPattern"
ng-keypress="vm.submitOnEnter($event)" />
</div>
<div class="umb-control-group clearfix" ng-if="model.contentType === 'documentType' && model.contentTypeAllowCultureVariant">

View File

@@ -21,7 +21,7 @@
</label>
<umb-property-actions actions="propertyEditorAPI.propertyActions"></umb-property-actions>
<umb-property-actions actions="propertyActions"></umb-property-actions>
<small class="control-description" ng-bind-html="property.description | preserveNewLineInHtml"></small>
</div>

View File

@@ -24,10 +24,6 @@ function DataTypeEditController($scope, $routeParams, appState, navigationServic
alias: "selectedEditor",
description: "Select a property editor",
label: "Property editor"
},
selectedEditorId: {
alias: "selectedEditorId",
label: "Property editor alias"
}
};
@@ -205,7 +201,7 @@ function DataTypeEditController($scope, $routeParams, appState, navigationServic
var labelKeys = [
"general_settings",
"references_tabName"
"general_info"
];
localizationService.localizeMany(labelKeys).then(function (values) {
@@ -220,9 +216,9 @@ function DataTypeEditController($scope, $routeParams, appState, navigationServic
},
{
"name": values[1],
"alias": "references",
"icon": "icon-molecular-network",
"view": "views/datatypes/views/datatype.references.html"
"alias": "info",
"icon": "icon-info",
"view": "views/datatypes/views/datatype.info.html"
}
];
});

View File

@@ -1,12 +1,12 @@
/**
* @ngdoc controller
* @name Umbraco.Editors.DataType.ReferencesController
* @name Umbraco.Editors.DataType.InfoController
* @function
*
* @description
* The controller for the references view of the datatype editor
* The controller for the info view of the datatype editor
*/
function DataTypeReferencesController($scope, $routeParams, dataTypeResource, eventsService, $timeout) {
function DataTypeInfoController($scope, $routeParams, dataTypeResource, eventsService, $timeout) {
var vm = this;
var evts = [];
@@ -34,7 +34,7 @@ function DataTypeReferencesController($scope, $routeParams, dataTypeResource, ev
// load data type references when the references tab is activated
evts.push(eventsService.on("app.tabChange", function (event, args) {
$timeout(function () {
if (args.alias === "references") {
if (args.alias === "info") {
loadRelations();
}
});
@@ -52,4 +52,4 @@ function DataTypeReferencesController($scope, $routeParams, dataTypeResource, ev
}
angular.module("umbraco").controller("Umbraco.Editors.DataType.ReferencesController", DataTypeReferencesController);
angular.module("umbraco").controller("Umbraco.Editors.DataType.InfoController", DataTypeInfoController);

View File

@@ -0,0 +1,140 @@
<div ng-controller="Umbraco.Editors.DataType.InfoController as vm">
<div class="umb-package-details">
<div class="umb-package-details__main-content">
<umb-load-indicator ng-if="vm.view.loading === true"></umb-load-indicator>
<umb-box ng-if="vm.view.loading === false && vm.hasReferences === false">
<umb-box-header title-key="references_tabName"></umb-box-header>
<umb-box-content>
<umb-empty-state size="small">
<localize key="references_DataTypeNoReferences">This Data Type has no references.</localize>
</umb-empty-state>
</umb-box-content>
</umb-box>
<div ng-if="vm.view.loading === false && vm.hasReferences === true">
<!-- Document Types -->
<div ng-if="vm.references.documentTypes.length > 0" class="mb4">
<h5 class="mt0" style="margin-bottom: 20px;">
<localize key="references_labelUsedByDocumentTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.documentTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/documentTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
<!-- Media Types -->
<div ng-if="vm.references.mediaTypes.length > 0" class="mb4">
<h5 class="mt0" style="margin-bottom: 20px;">
<localize key="references_labelUsedByMediaTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.mediaTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/mediaTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
<!-- Member Types -->
<div ng-if="vm.references.memberTypes.length > 0" class="mb4">
<h5 class="mt0" style="margin-bottom: 20px;">
<localize key="references_labelUsedByMemberTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.memberTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/memberTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="umb-package-details__sidebar">
<umb-box data-element="node-info-general">
<umb-box-header title-key="general_general"></umb-box-header>
<umb-box-content class="block-form">
<umb-control-group label="Id" ng-if="model.showIdentifier">
<div>{{model.content.id}}</div>
<small>{{model.content.key}}</small>
</umb-control-group>
<umb-control-group label="Property Editor Alias" ng-if="model.content.selectedEditor">
<div>{{model.content.selectedEditor}}</div>
</umb-control-group>
</umb-box-content>
</umb-box>
</div>
</div>
</div>

View File

@@ -1,112 +0,0 @@
<div ng-controller="Umbraco.Editors.DataType.ReferencesController as vm">
<umb-load-indicator ng-if="vm.view.loading === true"></umb-load-indicator>
<umb-box ng-if="vm.view.loading === false && vm.hasReferences === false">
<umb-box-header title-key="references_tabName"></umb-box-header>
<umb-box-content>
<umb-empty-state size="small">
<localize key="references_DataTypeNoReferences">This Data Type has no references.</localize>
</umb-empty-state>
</umb-box-content>
</umb-box>
<div ng-if="vm.view.loading === false && vm.hasReferences === true">
<!-- Document Types -->
<div ng-if="vm.references.documentTypes.length > 0">
<h5 class="mt4" style="margin-bottom: 20px;">
<localize key="references_labelUsedByDocumentTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.documentTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/documentTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
<!-- Media Types -->
<div ng-if="vm.references.mediaTypes.length > 0">
<h5 class="mt4" style="margin-bottom: 20px;">
<localize key="references_labelUsedByMediaTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.mediaTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/mediaTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
<!-- Member Types -->
<div ng-if="vm.references.memberTypes.length > 0">
<h5 class="mt4" style="margin-bottom: 20px;">
<localize key="references_labelUsedByMemberTypes"></localize>
</h5>
<div class="umb-table">
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell"></div>
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
<div class="umb-table-cell"><localize key="references_usedByProperties">Used in</localize></div>
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
</div>
</div>
<div class="umb-table-body">
<div class="umb-table-row" ng-repeat="reference in vm.references.memberTypes">
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></div>
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/memberTypes/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -2,11 +2,6 @@
<umb-box-content>
<umb-control-group label="Id" ng-if="model.showIdentifier">
<div>{{model.content.id}}</div>
<small>{{model.content.key}}</small>
</umb-control-group>
<umb-property property="model.properties.selectedEditor">
<div>
<select name="selectedEditor"
@@ -20,10 +15,6 @@
</umb-property>
<umb-property property="model.properties.selectedEditorId">
<div>{{model.content.selectedEditor}}</div>
</umb-property>
<umb-property property="preValue"
ng-repeat="preValue in model.preValues">
<umb-property-editor model="preValue" is-pre-value="true"></umb-property-editor>

View File

@@ -520,9 +520,14 @@
evts.push(eventsService.on("editors.documentType.saved", function(name, args) {
if(args.documentType.allowedTemplates.length > 0) {
navigationService.hasTree("templates").then(function (treeExists) {
if (treeExists) {
navigationService.syncTree({ tree: "templates", path: [], forceReload: true })
.then(function (syncArgs) {
navigationService.reloadNode(syncArgs.node)
}
);
}
});
}
}));

View File

@@ -71,7 +71,7 @@ function ColorPickerController($scope, $timeout) {
);
return {
isValid: isValid,
errorMsg: "Value cannot be empty",
errorMsg: $scope.model.validation.mandatoryMessage || "Value cannot be empty",
errorKey: "required"
};
}

View File

@@ -1,4 +1,4 @@
function dateTimePickerController($scope, notificationsService, assetsService, angularHelper, userService, $element, dateHelper) {
function dateTimePickerController($scope, angularHelper, dateHelper, validationMessageService) {
let flatPickr = null;
@@ -62,6 +62,11 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
setDatePickerVal();
// Set the message to use for when a mandatory field isn't completed.
// Will either use the one provided on the property type or a localised default.
validationMessageService.getMandatoryMessage($scope.model.validation).then(function (value) {
$scope.mandatoryMessage = value;
});
}
$scope.clearDate = function() {

Some files were not shown because too many files have changed in this diff Show More