diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs
index 5b31a4f315..1c89d7662f 100644
--- a/src/Umbraco.Core/Cache/CacheKeys.cs
+++ b/src/Umbraco.Core/Cache/CacheKeys.cs
@@ -6,6 +6,9 @@ namespace Umbraco.Core.Cache
///
public static class CacheKeys
{
+ public const string ApplicationTreeCacheKey = "ApplicationTreeCache";
+ public const string ApplicationsCacheKey = "ApplicationCache";
+
public const string UserTypeCacheKey = "UserTypeCache";
public const string ContentItemCacheKey = "contentItem";
diff --git a/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs
new file mode 100644
index 0000000000..a9e52fbb2f
--- /dev/null
+++ b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs
@@ -0,0 +1,43 @@
+using System;
+using Umbraco.Core;
+using Umbraco.Core.Cache;
+
+namespace Umbraco.Web.Cache
+{
+ ///
+ /// Handles Application cache invalidation/refreshing
+ ///
+ public sealed class ApplicationCacheRefresher : CacheRefresherBase
+ {
+ protected override ApplicationCacheRefresher Instance
+ {
+ get { return this; }
+ }
+
+ public override Guid UniqueIdentifier
+ {
+ get { return Guid.Parse(DistributedCache.ApplicationCacheRefresherId); }
+ }
+
+ public override string Name
+ {
+ get { return "Applications cache refresher"; }
+ }
+
+ public override void RefreshAll()
+ {
+ ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey);
+ }
+
+ public override void Refresh(int id)
+ {
+ Remove(id);
+ }
+
+ public override void Remove(int id)
+ {
+ ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
index 6176446088..025748cf13 100644
--- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
+++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
@@ -21,7 +21,16 @@ namespace Umbraco.Web.Cache
public class CacheRefresherEventHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
- {
+ {
+ //bind to application tree events
+ ApplicationTree.Deleted += ApplicationTreeDeleted;
+ ApplicationTree.Updated += ApplicationTreeUpdated;
+ ApplicationTree.New += ApplicationTreeNew;
+
+ //bind to application events
+ Application.Deleted += ApplicationDeleted;
+ Application.New += ApplicationNew;
+
//bind to user type events
UserType.Deleted += UserTypeDeleted;
UserType.New += UserTypeNew;
@@ -116,6 +125,35 @@ namespace Umbraco.Web.Cache
MediaService.Trashing += MediaServiceTrashing;
}
+ #region ApplicationTree event handlers
+ static void ApplicationTreeNew(ApplicationTree sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+
+ static void ApplicationTreeUpdated(ApplicationTree sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+
+ static void ApplicationTreeDeleted(ApplicationTree sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+ #endregion
+
+ #region Application event handlers
+ static void ApplicationNew(Application sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationCache();
+ }
+
+ static void ApplicationDeleted(Application sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationCache();
+ }
+ #endregion
+
#region UserType event handlers
static void UserTypeUpdated(UserType sender, System.EventArgs e)
{
diff --git a/src/Umbraco.Web/Cache/DistributedCache.cs b/src/Umbraco.Web/Cache/DistributedCache.cs
index ffc43c1a73..a0ce50d4c7 100644
--- a/src/Umbraco.Web/Cache/DistributedCache.cs
+++ b/src/Umbraco.Web/Cache/DistributedCache.cs
@@ -35,6 +35,8 @@ namespace Umbraco.Web.Cache
#region Public constants/Ids
+ public const string ApplicationTreeCacheRefresherId = "0AC6C028-9860-4EA4-958D-14D39F45886E";
+ public const string ApplicationCacheRefresherId = "B15F34A1-BC1D-4F8B-8369-3222728AB4C8";
public const string TemplateRefresherId = "DD12B6A0-14B9-46e8-8800-C154F74047C8";
public const string PageCacheRefresherId = "27AB3022-3DFA-47b6-9119-5945BC88FD66";
public const string MemberCacheRefresherId = "E285DF34-ACDC-4226-AE32-C0CB5CF388DA";
diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
index 48f8bf7bdd..f9ae3b8d6e 100644
--- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
+++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
@@ -13,6 +13,20 @@ namespace Umbraco.Web.Cache
///
internal static class DistributedCacheExtensions
{
+ #region Application tree cache
+ public static void RefreshAllApplicationTreeCache(this DistributedCache dc)
+ {
+ dc.RefreshAll(new Guid(DistributedCache.ApplicationTreeCacheRefresherId));
+ }
+ #endregion
+
+ #region Application cache
+ public static void RefreshAllApplicationCache(this DistributedCache dc)
+ {
+ dc.RefreshAll(new Guid(DistributedCache.ApplicationCacheRefresherId));
+ }
+ #endregion
+
#region User type cache
public static void RemoveUserTypeCache(this DistributedCache dc, int userTypeId)
{
diff --git a/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs
new file mode 100644
index 0000000000..d4ec8a0d60
--- /dev/null
+++ b/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs
@@ -0,0 +1,43 @@
+using System;
+using Umbraco.Core;
+using Umbraco.Core.Cache;
+
+namespace Umbraco.Web.Cache
+{
+ ///
+ /// Handles User type cache invalidation/refreshing
+ ///
+ public sealed class UserTypeCacheRefresher : CacheRefresherBase
+ {
+ protected override UserTypeCacheRefresher Instance
+ {
+ get { return this; }
+ }
+
+ public override Guid UniqueIdentifier
+ {
+ get { return Guid.Parse(DistributedCache.UserTypeCacheRefresherId); }
+ }
+
+ public override string Name
+ {
+ get { return "User type cache refresher"; }
+ }
+
+ public override void RefreshAll()
+ {
+ ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserTypeCacheKey);
+ }
+
+ public override void Refresh(int id)
+ {
+ Remove(id);
+ }
+
+ public override void Remove(int id)
+ {
+ ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserTypeCacheKey);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 4cf8f78146..39f1b28bb7 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -263,6 +263,8 @@
+
+
diff --git a/src/umbraco.businesslogic/Application.cs b/src/umbraco.businesslogic/Application.cs
index 034f302895..efa7131196 100644
--- a/src/umbraco.businesslogic/Application.cs
+++ b/src/umbraco.businesslogic/Application.cs
@@ -6,6 +6,8 @@ using System.Linq;
using System.Web;
using System.Xml.Linq;
using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using umbraco.DataLayer;
@@ -21,7 +23,6 @@ namespace umbraco.BusinessLogic
{
private static ISqlHelper _sqlHelper;
- private const string CacheKey = "ApplicationCache";
internal const string AppConfigFileName = "applications.config";
private static string _appConfig;
private static readonly object Locker = new object();
@@ -45,8 +46,6 @@ namespace umbraco.BusinessLogic
set { _appConfig = value; }
}
- //private static List _testApps;
-
///
/// The cache storage for all applications
///
@@ -55,7 +54,7 @@ namespace umbraco.BusinessLogic
get
{
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
- CacheKey,
+ CacheKeys.ApplicationsCacheKey,
() =>
{
////used for unit tests
@@ -98,15 +97,6 @@ namespace umbraco.BusinessLogic
}
}
- /////
- ///// THIS IS USED ONLY FOR UNIT TESTS!
- /////
- /////
- //internal static void SetTestApps(List testApps)
- //{
- // _testApps = testApps;
- //}
-
///
/// Gets the SQL helper.
///
@@ -144,8 +134,6 @@ namespace umbraco.BusinessLogic
}
}
-
-
///
/// Initializes a new instance of the class.
///
@@ -237,6 +225,9 @@ namespace umbraco.BusinessLogic
new XAttribute("icon", icon),
new XAttribute("sortOrder", sortOrder)));
}, true);
+
+ //raise event
+ OnNew(new Application(name, alias, icon, sortOrder), new EventArgs());
}
}
@@ -269,6 +260,9 @@ namespace umbraco.BusinessLogic
{
doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == this.alias).Remove();
}, true);
+
+ //raise event
+ OnDeleted(this, new EventArgs());
}
///
@@ -308,11 +302,30 @@ namespace umbraco.BusinessLogic
doc.Save(AppConfigFilePath);
- //remove the cache so it gets re-read
- ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKey);
+ //remove the cache so it gets re-read ... SD: I'm leaving this here even though it
+ // is taken care of by events as well, I think unit tests may rely on it being cleared here.
+ ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey);
}
}
}
}
+
+ internal static event TypedEventHandler Deleted;
+ private static void OnDeleted(Application app, EventArgs args)
+ {
+ if (Deleted != null)
+ {
+ Deleted(app, args);
+ }
+ }
+
+ internal static event TypedEventHandler New;
+ private static void OnNew(Application app, EventArgs args)
+ {
+ if (New != null)
+ {
+ New(app, args);
+ }
+ }
}
}
diff --git a/src/umbraco.businesslogic/ApplicationTree.cs b/src/umbraco.businesslogic/ApplicationTree.cs
index 27c7a2d04f..968b3b86cb 100644
--- a/src/umbraco.businesslogic/ApplicationTree.cs
+++ b/src/umbraco.businesslogic/ApplicationTree.cs
@@ -5,6 +5,8 @@ using System.Linq;
using System.Web;
using System.Xml.Linq;
using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Events;
using Umbraco.Core.IO;
using umbraco.DataLayer;
@@ -18,7 +20,6 @@ namespace umbraco.BusinessLogic
public class ApplicationTree
{
- private const string CacheKey = "ApplicationTreeCache";
internal const string TreeConfigFileName = "trees.config";
private static string _treeConfig;
private static readonly object Locker = new object();
@@ -50,7 +51,7 @@ namespace umbraco.BusinessLogic
get
{
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
- CacheKey,
+ CacheKeys.ApplicationTreeCacheKey,
() =>
{
var list = new List();
@@ -244,6 +245,8 @@ namespace umbraco.BusinessLogic
new XAttribute("action", string.IsNullOrEmpty(action) ? "" : action)));
}
}, true);
+
+ OnNew(new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action), new EventArgs());
}
///
@@ -274,6 +277,7 @@ namespace umbraco.BusinessLogic
}, true);
+ OnUpdated(this, new EventArgs());
}
///
@@ -289,6 +293,8 @@ namespace umbraco.BusinessLogic
doc.Root.Elements("add").Where(x => x.Attribute("application") != null && x.Attribute("application").Value == this.ApplicationAlias &&
x.Attribute("alias") != null && x.Attribute("alias").Value == this.Alias).Remove();
}, true);
+
+ OnDeleted(this, new EventArgs());
}
@@ -359,11 +365,39 @@ namespace umbraco.BusinessLogic
doc.Save(TreeConfigFilePath);
- //remove the cache now that it has changed
- ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKey);
+ //remove the cache now that it has changed SD: I'm leaving this here even though it
+ // is taken care of by events as well, I think unit tests may rely on it being cleared here.
+ ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey);
}
}
}
}
+
+ internal static event TypedEventHandler Deleted;
+ private static void OnDeleted(ApplicationTree app, EventArgs args)
+ {
+ if (Deleted != null)
+ {
+ Deleted(app, args);
+ }
+ }
+
+ internal static event TypedEventHandler New;
+ private static void OnNew(ApplicationTree app, EventArgs args)
+ {
+ if (New != null)
+ {
+ New(app, args);
+ }
+ }
+
+ internal static event TypedEventHandler Updated;
+ private static void OnUpdated(ApplicationTree app, EventArgs args)
+ {
+ if (Updated != null)
+ {
+ Updated(app, args);
+ }
+ }
}
}
diff --git a/src/umbraco.cms/businesslogic/web/StyleSheet.cs b/src/umbraco.cms/businesslogic/web/StyleSheet.cs
index c73b3a337f..d9de01dcb5 100644
--- a/src/umbraco.cms/businesslogic/web/StyleSheet.cs
+++ b/src/umbraco.cms/businesslogic/web/StyleSheet.cs
@@ -238,9 +238,7 @@ namespace umbraco.cms.businesslogic.web
return retval;
}
-
-
-
+
public StylesheetProperty AddProperty(string Alias, BusinessLogic.User u)
{
return StylesheetProperty.MakeNew(Alias, this, u);
@@ -254,8 +252,10 @@ namespace umbraco.cms.businesslogic.web
if (!e.Cancel)
{
File.Delete(IOHelper.MapPath(String.Format("{0}/{1}.css", SystemDirectories.Css, this.Text)));
- foreach (StylesheetProperty p in this.Properties)
+ foreach (var p in Properties.Where(p => p != null))
+ {
p.delete();
+ }
SqlHelper.ExecuteNonQuery("delete from cmsStylesheet where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
base.delete();