Merge remote-tracking branch 'origin/6.2.0-membershipprovider' into 7.0.0

Conflicts:
	src/Umbraco.Tests/ObjectExtensionsTests.cs
	src/Umbraco.Web/WebBootManager.cs
This commit is contained in:
Shannon
2013-10-18 16:18:55 +11:00
8 changed files with 194 additions and 49 deletions

View File

@@ -22,8 +22,8 @@ namespace Umbraco.Core
if (value is string)
{
var str = (string)value;
if (str == null || str.Length == 0 || str == "0") return false;
if (str == "1") return true;
if (str == "0" || str == "") return false;
}
return base.ConvertFrom(context, culture, value);

View File

@@ -16,7 +16,6 @@ namespace Umbraco.Core
{
public static class ObjectExtensions
{
//private static readonly ConcurrentDictionary<Type, Func<object>> ObjectFactoryCache = new ConcurrentDictionary<Type, Func<object>>();
public static IEnumerable<T> AsEnumerableOfOne<T>(this T input)
@@ -93,8 +92,30 @@ namespace Umbraco.Core
//check for string so that overloaders of ToString() can take advantage of the conversion.
if (destinationType == typeof(string)) return Attempt<object>.Succeed(input.ToString());
if (!destinationType.IsGenericType || destinationType.GetGenericTypeDefinition() != typeof(Nullable<>))
// if we've got a nullable of something, we try to convert directly to that thing.
if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// recursively call into myself with the inner (not-nullable) type and handle the outcome
var nonNullable = input.TryConvertTo(Nullable.GetUnderlyingType(destinationType));
// and if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception
if (nonNullable.Success)
input = nonNullable.Result; // now fall on through...
else
return Attempt<object>.Fail(nonNullable.Exception);
}
// we've already dealed with nullables, so any other generic types need to fall through
if (!destinationType.IsGenericType)
{
if (input is string)
{
var result = TryConvertToFromString(input as string, destinationType);
// if we processed the string (succeed or fail), we're done
if (result.HasValue) return result.Value;
}
//TODO: Do a check for destination type being IEnumerable<T> and source type implementing IEnumerable<T> with
// the same 'T', then we'd have to find the extension method for the type AsEnumerable() and execute it.
@@ -158,7 +179,6 @@ namespace Umbraco.Core
}
}
if (TypeHelper.IsTypeAssignableFrom<IConvertible>(input))
{
try
@@ -175,6 +195,119 @@ namespace Umbraco.Core
return Attempt<object>.Fail();
}
private static Nullable<Attempt<object>> TryConvertToFromString(this string input, Type destinationType)
{
if (destinationType == typeof(string))
return Attempt<object>.Succeed(input);
if (input == null || input.Length == 0)
{
if (destinationType == typeof(Boolean))
return Attempt<object>.Succeed(false); // special case for booleans, null/empty == false
else if (destinationType == typeof(DateTime))
return Attempt<object>.Succeed(DateTime.MinValue);
}
// we have a non-empty string, look for type conversions in the expected order of frequency of use...
if (destinationType.IsPrimitive)
{
if (destinationType == typeof(Int32))
{
Int32 value;
return Int32.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Int64))
{
Int64 value;
return Int64.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Boolean))
{
Boolean value;
if (Boolean.TryParse(input, out value))
return Attempt<object>.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try
}
else if (destinationType == typeof(Int16))
{
Int16 value;
return Int16.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Double))
{
Double value;
return Double.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Single))
{
Single value;
return Single.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Char))
{
Char value;
return Char.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Byte))
{
Byte value;
return Byte.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(SByte))
{
SByte value;
return SByte.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(UInt32))
{
UInt32 value;
return UInt32.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(UInt16))
{
UInt16 value;
return UInt16.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(UInt64))
{
UInt64 value;
return UInt64.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
}
else if (destinationType == typeof(Guid))
{
Guid value;
return Guid.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(DateTime))
{
DateTime value;
return DateTime.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(DateTimeOffset))
{
DateTimeOffset value;
return DateTimeOffset.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(TimeSpan))
{
TimeSpan value;
return TimeSpan.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Decimal))
{
Decimal value;
return Decimal.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Version))
{
Version value;
return Version.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
// E_NOTIMPL IPAddress, BigInteger
return null; // we can't decide...
}
internal static void CheckThrowObjectDisposed(this IDisposable disposable, bool isDisposed, string objectname)
{
//TODO: Localise this exception
@@ -296,7 +429,7 @@ namespace Umbraco.Core
{
return "\"{0}\"".InvariantFormat(obj);
}
if (obj is int || obj is Int16 || obj is Int64 || obj is double || obj is bool || obj is int? || obj is Int16? || obj is Int64? || obj is double? || obj is bool?)
if (obj is int || obj is Int16 || obj is Int64 || obj is float || obj is double || obj is bool || obj is int? || obj is Int16? || obj is Int64? || obj is float? || obj is double? || obj is bool?)
{
return "{0}".InvariantFormat(obj);
}
@@ -435,6 +568,5 @@ namespace Umbraco.Core
return "[GetPropertyValueException]";
}
}
}
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Tests.TestHelpers;
@@ -82,8 +84,8 @@ namespace Umbraco.Tests
{
var result = testCase.Key.TryConvertTo<bool>();
Assert.IsTrue(result.Success);
Assert.AreEqual(testCase.Value, result.Result);
Assert.IsTrue(result.Success, testCase.Key);
Assert.AreEqual(testCase.Value, result.Result, testCase.Key);
}
}
@@ -95,34 +97,41 @@ namespace Umbraco.Tests
{
{"2012-11-10", true},
{"2012/11/10", true},
{"10/11/2012", true},
{"11/10/2012", false},
{"10/11/2012", true}, // assuming your culture uses DD/MM/YYYY
{"11/10/2012", false}, // assuming your culture uses DD/MM/YYYY
{"Sat 10, Nov 2012", true},
{"Saturday 10, Nov 2012", true},
{"Sat 10, November 2012", true},
{"Saturday 10, November 2012", true},
{"2012-11-10 13:14:15", true},
{"", false}
{"2012-11-10 13:14:15", true}
};
foreach (var testCase in testCases)
{
var result = testCase.Key.TryConvertTo<DateTime>();
Assert.IsTrue(result.Success);
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value);
Assert.IsTrue(result.Success, testCase.Key);
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value, testCase.Key);
}
}
[Test]
public virtual void CanConvertObjectToString_Using_ToString_Overload()
{
var result = new MyTestObject().TryConvertTo<string>();
[Test]
public virtual void CanConvertBlankStringToDateTime()
{
var result = "".TryConvertTo<DateTime>();
Assert.IsTrue(result.Success);
Assert.AreEqual(DateTime.MinValue, result.Result);
}
Assert.IsTrue(result.Success);
Assert.AreEqual("Hello world", result.Result);
}
[Test]
public virtual void CanConvertObjectToString_Using_ToString_Overload()
{
var result = new MyTestObject().TryConvertTo<string>();
[Test]
Assert.IsTrue(result.Success);
Assert.AreEqual("Hello world", result.Result);
}
[Test]
public virtual void CanConvertObjectToSameObject()
{
var obj = new MyTestObject();
@@ -130,7 +139,27 @@ namespace Umbraco.Tests
Assert.AreEqual(obj, result);
}
private CultureInfo savedCulture;
/// <summary>
/// Run once before each test in derived test fixtures.
/// </summary>
public override void TestSetup()
{
savedCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); // make sure the dates parse correctly
return;
}
/// <summary>
/// Run once after each test in derived test fixtures.
/// </summary>
public override void TestTearDown()
{
Thread.CurrentThread.CurrentCulture = savedCulture;
return;
}
private class MyTestObject
{

View File

@@ -7,6 +7,7 @@ using System.Data.SqlClient;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Cache;
using UmbracoExamine;
using UmbracoExamine.DataServices;
using umbraco;
@@ -67,7 +68,7 @@ namespace Umbraco.Tests
var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
typeof (LegacyScheduledTasks),
typeof(CacheHelperExtensions.CacheHelperApplicationEventListener));
typeof(CacheRefresherEventHandler));
Assert.IsTrue(t6.Success);
Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);

View File

@@ -111,6 +111,8 @@ namespace Umbraco.Web.Cache
{
if (payloads == null) return;
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
payloads.ForEach(payload =>
{
foreach (var idPart in payload.Path.Split(','))

View File

@@ -44,6 +44,8 @@ namespace Umbraco.Web.Cache
private void ClearCache(int id)
{
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
ApplicationContext.Current.ApplicationCache.
ClearCacheByKeySearch(string.Format("{0}_{1}", CacheKeys.MemberLibraryCacheKey, id));
ApplicationContext.Current.ApplicationCache.

View File

@@ -1,4 +1,5 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
using Umbraco.Core.Sync;
@@ -58,6 +59,7 @@ namespace Umbraco.Web.Cache
/// <param name="id">The id.</param>
public override void Refresh(int id)
{
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
content.Instance.UpdateDocumentCache(id);
DistributedCache.Instance.ClearAllMacroCacheOnCurrentServer();
DistributedCache.Instance.ClearXsltCacheOnCurrentServer();
@@ -70,6 +72,7 @@ namespace Umbraco.Web.Cache
/// <param name="id">The id.</param>
public override void Remove(int id)
{
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
content.Instance.ClearDocumentCache(id);
DistributedCache.Instance.ClearAllMacroCacheOnCurrentServer();
DistributedCache.Instance.ClearXsltCacheOnCurrentServer();
@@ -78,6 +81,7 @@ namespace Umbraco.Web.Cache
public override void Refresh(IContent instance)
{
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
content.Instance.UpdateDocumentCache(new Document(instance));
DistributedCache.Instance.ClearAllMacroCacheOnCurrentServer();
DistributedCache.Instance.ClearXsltCacheOnCurrentServer();
@@ -86,6 +90,7 @@ namespace Umbraco.Web.Cache
public override void Remove(IContent instance)
{
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
content.Instance.ClearDocumentCache(new Document(instance));
DistributedCache.Instance.ClearAllMacroCacheOnCurrentServer();
DistributedCache.Instance.ClearXsltCacheOnCurrentServer();

View File

@@ -14,32 +14,6 @@ namespace Umbraco.Web
/// </summary>
internal static class CacheHelperExtensions
{
/// <summary>
/// Application event handler to bind to events to clear the cache for the cache helper extensions
/// </summary>
internal sealed class CacheHelperApplicationEventListener : ApplicationEventHandler
{
protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
if (applicationContext != null)
{
//bind to events to clear the cache, after publish, after media save and after member save
Document.AfterPublish
+= (sender, args) =>
applicationContext.ApplicationCache.ClearPartialViewCache();
global::umbraco.cms.businesslogic.media.Media.AfterSave
+= (sender, args) =>
applicationContext.ApplicationCache.ClearPartialViewCache();
global::umbraco.cms.businesslogic.member.Member.AfterSave
+= (sender, args) =>
applicationContext.ApplicationCache.ClearPartialViewCache();
}
}
}
public const string PartialViewCacheKey = "Umbraco.Web.PartialViewCacheKey";