From 24111c52f2c01b919eeb2b32a47138640fc938c6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 20 Jun 2013 10:05:51 +1000 Subject: [PATCH] Obsoleted umbraco.businesslogic.ApplicationTree, have moved logic and new classes to core and proxied calls from it to the new ones. The new ApplicationTreeCollection will be the runtime colleciton of trees which can also read/write/save to the xml. --- src/Umbraco.Core/CoreBootManager.cs | 2 +- src/Umbraco.Core/ModelMapperHelper.cs | 15 + src/Umbraco.Core/Trees/ApplicationTree.cs | 83 ++++++ .../Trees/ApplicationTreeCollection.cs | 268 ++++++++++++++++++ src/Umbraco.Core/TypeFinder.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 + src/Umbraco.Core/packages.config | 1 + src/Umbraco.Tests/BusinessLogic/BaseTest.cs | 4 +- .../Cache/CacheRefresherEventHandler.cs | 8 +- .../Trees/ApplicationTreeApiController.cs | 9 +- .../Trees/ApplicationTreeExtensions.cs | 1 + .../Trees/LegacyTreeApiController.cs | 5 +- src/umbraco.businesslogic/ApplicationTree.cs | 228 ++------------- .../ApplicationTreeRegistrar.cs | 117 ++++---- src/umbraco.businesslogic/packages.config | 1 + .../umbraco.businesslogic.csproj | 3 + 16 files changed, 466 insertions(+), 287 deletions(-) create mode 100644 src/Umbraco.Core/ModelMapperHelper.cs create mode 100644 src/Umbraco.Core/Trees/ApplicationTree.cs create mode 100644 src/Umbraco.Core/Trees/ApplicationTreeCollection.cs diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index 0419fb0cd0..d4aa83e342 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -21,7 +21,7 @@ using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrad namespace Umbraco.Core { - /// + /// /// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application /// /// diff --git a/src/Umbraco.Core/ModelMapperHelper.cs b/src/Umbraco.Core/ModelMapperHelper.cs new file mode 100644 index 0000000000..efd843a059 --- /dev/null +++ b/src/Umbraco.Core/ModelMapperHelper.cs @@ -0,0 +1,15 @@ +using AutoMapper; + +namespace Umbraco.Core +{ + /// + /// Helper class for static model mapping with automapper + /// + internal static class ModelMapperHelper + { + internal static IMappingExpression SelfMap() + { + return Mapper.CreateMap(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Trees/ApplicationTree.cs b/src/Umbraco.Core/Trees/ApplicationTree.cs new file mode 100644 index 0000000000..df5e80acc1 --- /dev/null +++ b/src/Umbraco.Core/Trees/ApplicationTree.cs @@ -0,0 +1,83 @@ +namespace Umbraco.Core.Trees +{ + internal class ApplicationTree + { + /// + /// Initializes a new instance of the class. + /// + public ApplicationTree() { } + + + /// + /// Initializes a new instance of the class. + /// + /// if set to true [initialize]. + /// The sort order. + /// The application alias. + /// The tree alias. + /// The tree title. + /// The icon closed. + /// The icon opened. + /// The tree type. + public ApplicationTree(bool initialize, byte sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + { + this.Initialize = initialize; + this.SortOrder = sortOrder; + this.ApplicationAlias = applicationAlias; + this.Alias = alias; + this.Title = title; + this.IconClosed = iconClosed; + this.IconOpened = iconOpened; + this.Type = type; + } + + /// + /// Gets or sets a value indicating whether this should initialize. + /// + /// true if initialize; otherwise, false. + public bool Initialize { get; set; } + + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public byte SortOrder { get; set; } + + /// + /// Gets the application alias. + /// + /// The application alias. + public string ApplicationAlias { get; private set; } + + /// + /// Gets the tree alias. + /// + /// The alias. + public string Alias { get; private set; } + + /// + /// Gets or sets the tree title. + /// + /// The title. + public string Title { get; set; } + + /// + /// Gets or sets the icon closed. + /// + /// The icon closed. + public string IconClosed { get; set; } + + /// + /// Gets or sets the icon opened. + /// + /// The icon opened. + public string IconOpened { get; set; } + + /// + /// Gets or sets the tree type assembly name. + /// + /// The type. + public string Type { get; set; } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Trees/ApplicationTreeCollection.cs b/src/Umbraco.Core/Trees/ApplicationTreeCollection.cs new file mode 100644 index 0000000000..ecc074ce23 --- /dev/null +++ b/src/Umbraco.Core/Trees/ApplicationTreeCollection.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Umbraco.Core.Cache; +using Umbraco.Core.Events; +using Umbraco.Core.IO; + +namespace Umbraco.Core.Trees +{ + internal class ApplicationTreeCollection + { + internal const string TreeConfigFileName = "trees.config"; + private static string _treeConfig; + private static readonly object Locker = new object(); + + /// + /// gets/sets the trees.config file path + /// + /// + /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath + /// + internal static string TreeConfigFilePath + { + get + { + if (string.IsNullOrWhiteSpace(_treeConfig)) + { + _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); + } + return _treeConfig; + } + set { _treeConfig = value; } + } + + /// + /// The cache storage for all application trees + /// + private static List AppTrees + { + get + { + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.ApplicationTreeCacheKey, + () => + { + var list = new List(); + + LoadXml(doc => + { + foreach (var addElement in doc.Root.Elements("add").OrderBy(x => + { + var sortOrderAttr = x.Attribute("sortOrder"); + return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; + })) + { + + var applicationAlias = (string)addElement.Attribute("application"); + var type = (string)addElement.Attribute("type"); + var assembly = (string)addElement.Attribute("assembly"); + + //check if the tree definition (applicationAlias + type + assembly) is already in the list + + if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) + && tree.Type.InvariantEquals(type)) == false) + { + list.Add(new ApplicationTree( + addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), + addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0, + addElement.Attribute("application").Value, + addElement.Attribute("alias").Value, + addElement.Attribute("title").Value, + addElement.Attribute("iconClosed").Value, + addElement.Attribute("iconOpen").Value, + addElement.Attribute("type").Value)); + } + + + } + }, false); + + return list; + }); + } + } + + + /// + /// Creates a new application tree. + /// + /// if set to true [initialize]. + /// The sort order. + /// The application alias. + /// The alias. + /// The title. + /// The icon closed. + /// The icon opened. + /// The type. + public static void MakeNew(bool initialize, byte sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + { + LoadXml(doc => + { + var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); + + if (el == null) + { + doc.Root.Add(new XElement("add", + new XAttribute("initialize", initialize), + new XAttribute("sortOrder", sortOrder), + new XAttribute("alias", alias), + new XAttribute("application", applicationAlias), + new XAttribute("title", title), + new XAttribute("iconClosed", iconClosed), + new XAttribute("iconOpen", iconOpened), + new XAttribute("type", type))); + } + }, true); + + OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); + } + + /// + /// Saves this instance. + /// + public static void SaveTree(ApplicationTree tree) + { + LoadXml(doc => + { + var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); + + if (el != null) + { + el.RemoveAttributes(); + + el.Add(new XAttribute("initialize", tree.Initialize)); + el.Add(new XAttribute("sortOrder", tree.SortOrder)); + el.Add(new XAttribute("alias", tree.Alias)); + el.Add(new XAttribute("application", tree.ApplicationAlias)); + el.Add(new XAttribute("title", tree.Title)); + el.Add(new XAttribute("iconClosed", tree.IconClosed)); + el.Add(new XAttribute("iconOpen", tree.IconOpened)); + el.Add(new XAttribute("type", tree.Type)); + } + + }, true); + + OnUpdated(tree, new EventArgs()); + } + + /// + /// Deletes this instance. + /// + public static void DeleteTree(ApplicationTree tree) + { + LoadXml(doc => + { + doc.Root.Elements("add").Where(x => x.Attribute("application") != null && x.Attribute("application").Value == tree.ApplicationAlias && + x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); + }, true); + + OnDeleted(tree, new EventArgs()); + } + + /// + /// Gets an ApplicationTree by it's tree alias. + /// + /// The tree alias. + /// An ApplicationTree instance + public static ApplicationTree GetByAlias(string treeAlias) + { + return AppTrees.Find(t => (t.Alias == treeAlias)); + + } + + /// + /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. + /// + /// Returns a ApplicationTree Array + public static IEnumerable GetAll() + { + return AppTrees.OrderBy(x => x.SortOrder); + } + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// Returns a ApplicationTree Array + public static IEnumerable GetApplicationTree(string applicationAlias) + { + return GetApplicationTree(applicationAlias, false); + } + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// + /// Returns a ApplicationTree Array + public static IEnumerable GetApplicationTree(string applicationAlias, bool onlyInitializedApplications) + { + var list = AppTrees.FindAll( + t => + { + if (onlyInitializedApplications) + return (t.ApplicationAlias == applicationAlias && t.Initialize); + return (t.ApplicationAlias == applicationAlias); + } + ); + + return list.OrderBy(x => x.SortOrder).ToArray(); + } + + internal static void LoadXml(Action callback, bool saveAfterCallback) + { + lock (Locker) + { + var doc = File.Exists(TreeConfigFilePath) + ? XDocument.Load(TreeConfigFilePath) + : XDocument.Parse(""); + if (doc.Root != null) + { + callback.Invoke(doc); + + if (saveAfterCallback) + { + Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); + + doc.Save(TreeConfigFilePath); + + //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.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs index f74d7099d1..15315572ec 100644 --- a/src/Umbraco.Core/TypeFinder.cs +++ b/src/Umbraco.Core/TypeFinder.cs @@ -542,7 +542,7 @@ namespace Umbraco.Core foreach (var typeToSearch in subTypesToSearch) { //recursively find the types inheriting from this sub type in the other non-scanned assemblies. - var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses); + var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter); foundAssignableTypes.AddRange(foundTypes); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 6acadd06af..9f37d2e289 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -37,6 +37,9 @@ false + + ..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll + False ..\packages\log4net-mediumtrust.2.0.0\lib\log4net.dll @@ -174,6 +177,7 @@ + @@ -746,6 +750,8 @@ + + diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index ba4f62ac37..2a9de67098 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -1,5 +1,6 @@  + diff --git a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs index 9f48cd29d1..c6efefc474 100644 --- a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs +++ b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs @@ -4,10 +4,10 @@ using System.Configuration; using NUnit.Framework; using SqlCE4Umbraco; using Umbraco.Core; +using Umbraco.Core.IO; using Umbraco.Tests.TestHelpers; using umbraco.BusinessLogic; using umbraco.DataLayer; -using umbraco.IO; using GlobalSettings = umbraco.GlobalSettings; namespace Umbraco.Tests.BusinessLogic @@ -85,7 +85,7 @@ namespace Umbraco.Tests.BusinessLogic private void InitializeTreeConfigFile() { - ApplicationTree.TreeConfigFilePath = IOHelper.MapPath(SystemDirectories.Config + "/" + ApplicationTree.TreeConfigFileName, false); + Core.Trees.ApplicationTreeCollection.TreeConfigFilePath = IOHelper.MapPath(SystemDirectories.Config + "/" + Core.Trees.ApplicationTreeCollection.TreeConfigFileName, false); } } diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 435fb9c7ef..37be376381 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -4,12 +4,14 @@ using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Services; +using Umbraco.Core.Trees; using umbraco; using umbraco.BusinessLogic; using umbraco.cms.businesslogic; using umbraco.cms.businesslogic.member; using System.Linq; using umbraco.cms.businesslogic.web; +using ApplicationTree = Umbraco.Core.Trees.ApplicationTree; using Macro = umbraco.cms.businesslogic.macro.Macro; using Template = umbraco.cms.businesslogic.template.Template; @@ -23,9 +25,9 @@ namespace Umbraco.Web.Cache protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { //bind to application tree events - ApplicationTree.Deleted += ApplicationTreeDeleted; - ApplicationTree.Updated += ApplicationTreeUpdated; - ApplicationTree.New += ApplicationTreeNew; + ApplicationTreeCollection.Deleted += ApplicationTreeDeleted; + ApplicationTreeCollection.Updated += ApplicationTreeUpdated; + ApplicationTreeCollection.New += ApplicationTreeNew; //bind to application events Application.Deleted += ApplicationDeleted; diff --git a/src/Umbraco.Web/Trees/ApplicationTreeApiController.cs b/src/Umbraco.Web/Trees/ApplicationTreeApiController.cs index 7b26340356..581749dcab 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeApiController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeApiController.cs @@ -4,10 +4,10 @@ using System.Management.Instrumentation; using System.Net.Http.Formatting; using System.Web.Mvc; using Umbraco.Core; +using Umbraco.Core.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using umbraco.BusinessLogic; using umbraco.cms.presentation.Trees; namespace Umbraco.Web.Trees @@ -39,7 +39,7 @@ namespace Umbraco.Web.Trees if (application == null) throw new ArgumentNullException("application"); //find all tree definitions that have the current application alias - var appTrees = ApplicationTree.getApplicationTree(application).Where(x => x.Initialize).ToArray(); + var appTrees = ApplicationTreeCollection.GetApplicationTree(application).Where(x => x.Initialize).ToArray(); if (appTrees.Count() == 1) { //return the nodes for the one tree assigned @@ -49,9 +49,10 @@ namespace Umbraco.Web.Trees var collection = new TreeNodeCollection(); foreach (var tree in appTrees) { + var rootNodes = GetNodeCollection(tree, "-1", queryStrings); //return the root nodes for each tree in the app //collection.Add(); //GetNodeCollection(tree, "-1", queryStrings); - + } return null; } @@ -69,7 +70,7 @@ namespace Umbraco.Web.Trees if (treeType == null) throw new ArgumentNullException("treeType"); //get the configured tree - var foundConfigTree = ApplicationTree.getByAlias(treeType); + var foundConfigTree = ApplicationTreeCollection.GetByAlias(treeType); if (foundConfigTree == null) throw new InstanceNotFoundException("Could not find tree of type " + treeType + " in the trees.config"); diff --git a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs b/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs index 36a9aa0b69..a5df1bb7b1 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs @@ -12,6 +12,7 @@ using Umbraco.Core; using Umbraco.Web.WebApi; using umbraco.BusinessLogic; using umbraco.cms.presentation.Trees; +using ApplicationTree = Umbraco.Core.Trees.ApplicationTree; using UrlHelper = System.Web.Http.Routing.UrlHelper; namespace Umbraco.Web.Trees diff --git a/src/Umbraco.Web/Trees/LegacyTreeApiController.cs b/src/Umbraco.Web/Trees/LegacyTreeApiController.cs index 4e6a9f87f5..ff97b8eb0b 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeApiController.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeApiController.cs @@ -2,11 +2,10 @@ using System.Globalization; using System.Linq; using System.Net.Http.Formatting; +using Umbraco.Core.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using umbraco.BusinessLogic; -using umbraco.businesslogic; namespace Umbraco.Web.Trees { @@ -29,7 +28,7 @@ namespace Umbraco.Web.Trees //need to ensure we have a tree type var treeType = queryStrings.GetRequiredString("treeType"); //now we'll look up that tree - var tree = ApplicationTree.getByAlias(treeType); + var tree = ApplicationTreeCollection.GetByAlias(treeType); if (tree == null) throw new InvalidOperationException("No tree found with alias " + treeType); diff --git a/src/umbraco.businesslogic/ApplicationTree.cs b/src/umbraco.businesslogic/ApplicationTree.cs index e4ce027fe7..7f2eb0b7c9 100644 --- a/src/umbraco.businesslogic/ApplicationTree.cs +++ b/src/umbraco.businesslogic/ApplicationTree.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Web; using System.Xml.Linq; +using AutoMapper; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.IO; @@ -18,96 +19,10 @@ namespace umbraco.BusinessLogic /// An application tree is a collection of nodes belonging to one or more application(s). /// Through this class new application trees can be created, modified and deleted. /// + [Obsolete("This has been superceded by Umbraco.Core.Trees.ApplicationTree and Umbraco.Core.Trees.ApplicationTreeCollection")] public class ApplicationTree { - internal const string TreeConfigFileName = "trees.config"; - private static string _treeConfig; - private static readonly object Locker = new object(); - - /// - /// gets/sets the trees.config file path - /// - /// - /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - /// - internal static string TreeConfigFilePath - { - get - { - if (string.IsNullOrWhiteSpace(_treeConfig)) - { - _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); - } - return _treeConfig; - } - set { _treeConfig = value; } - } - - /// - /// The cache storage for all application trees - /// - private static List AppTrees - { - get - { - return ApplicationContext.Current.ApplicationCache.GetCacheItem( - CacheKeys.ApplicationTreeCacheKey, - () => - { - var list = new List(); - - LoadXml(doc => - { - foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - { - var sortOrderAttr = x.Attribute("sortOrder"); - return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - })) - { - - var applicationAlias = (string)addElement.Attribute("application"); - var type = (string)addElement.Attribute("type"); - var assembly = (string)addElement.Attribute("assembly"); - - //check if the tree definition (applicationAlias + type + assembly) is already in the list - - if (!list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) - && tree.Type.InvariantEquals(type) - && tree.AssemblyName.InvariantEquals(assembly))) - { - list.Add(new ApplicationTree( - addElement.Attribute("silent") != null ? Convert.ToBoolean(addElement.Attribute("silent").Value) : false, - addElement.Attribute("initialize") != null ? Convert.ToBoolean(addElement.Attribute("initialize").Value) : true, - addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0, - addElement.Attribute("application").Value, - addElement.Attribute("alias").Value, - addElement.Attribute("title").Value, - addElement.Attribute("iconClosed").Value, - addElement.Attribute("iconOpen").Value, - (string)addElement.Attribute("assembly"), //this could be empty: http://issues.umbraco.org/issue/U4-1360 - addElement.Attribute("type").Value, - addElement.Attribute("action") != null ? addElement.Attribute("action").Value : "")); - } - - - } - }, false); - - return list; - }); - } - } - - /// - /// Gets the SQL helper. - /// - /// The SQL helper. - public static ISqlHelper SqlHelper - { - get { return Application.SqlHelper; } - } - /// /// Gets or sets a value indicating whether this is silent. /// @@ -226,28 +141,8 @@ namespace umbraco.BusinessLogic /// The action. public static void MakeNew(bool silent, bool initialize, byte sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string assemblyName, string type, string action) { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); - - if (el == null) - { - doc.Root.Add(new XElement("add", - new XAttribute("silent", silent), - new XAttribute("initialize", initialize), - new XAttribute("sortOrder", sortOrder), - new XAttribute("alias", alias), - new XAttribute("application", applicationAlias), - new XAttribute("title", title), - new XAttribute("iconClosed", iconClosed), - new XAttribute("iconOpen", iconOpened), - new XAttribute("assembly", assemblyName), - new XAttribute("type", type), - new XAttribute("action", string.IsNullOrEmpty(action) ? "" : action))); - } - }, true); - - OnNew(new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action), new EventArgs()); + Umbraco.Core.Trees.ApplicationTreeCollection.MakeNew(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, + assemblyName.IsNullOrWhiteSpace() ? type : string.Format("{0}.{1},{0}", assemblyName, type)); } /// @@ -255,30 +150,8 @@ namespace umbraco.BusinessLogic /// public void Save() { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == this.Alias && x.Attribute("application").Value == this.ApplicationAlias); - - if (el != null) - { - el.RemoveAttributes(); - - el.Add(new XAttribute("silent", this.Silent)); - el.Add(new XAttribute("initialize", this.Initialize)); - el.Add(new XAttribute("sortOrder", this.SortOrder)); - el.Add(new XAttribute("alias", this.Alias)); - el.Add(new XAttribute("application", this.ApplicationAlias)); - el.Add(new XAttribute("title", this.Title)); - el.Add(new XAttribute("iconClosed", this.IconClosed)); - el.Add(new XAttribute("iconOpen", this.IconOpened)); - el.Add(new XAttribute("assembly", this.AssemblyName)); - el.Add(new XAttribute("type", this.Type)); - el.Add(new XAttribute("action", string.IsNullOrEmpty(this.Action) ? "" : this.Action)); - } - - }, true); - - OnUpdated(this, new EventArgs()); + Umbraco.Core.Trees.ApplicationTreeCollection.SaveTree( + Mapper.Map(this)); } /// @@ -286,19 +159,10 @@ namespace umbraco.BusinessLogic /// public void Delete() { - //SqlHelper.ExecuteNonQuery("delete from umbracoAppTree where appAlias = @appAlias AND treeAlias = @treeAlias", - // SqlHelper.CreateParameter("@appAlias", this.ApplicationAlias), SqlHelper.CreateParameter("@treeAlias", this.Alias)); - - LoadXml(doc => - { - 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()); + Umbraco.Core.Trees.ApplicationTreeCollection.DeleteTree( + Mapper.Map(this)); } - /// /// Gets an ApplicationTree by it's tree alias. /// @@ -306,8 +170,8 @@ namespace umbraco.BusinessLogic /// An ApplicationTree instance public static ApplicationTree getByAlias(string treeAlias) { - return AppTrees.Find(t => (t.Alias == treeAlias)); - + return Mapper.Map( + Umbraco.Core.Trees.ApplicationTreeCollection.GetByAlias(treeAlias)); } /// @@ -316,7 +180,9 @@ namespace umbraco.BusinessLogic /// Returns a ApplicationTree Array public static ApplicationTree[] getAll() { - return AppTrees.OrderBy(x => x.SortOrder).ToArray(); + return Umbraco.Core.Trees.ApplicationTreeCollection.GetAll() + .Select(Mapper.Map) + .ToArray(); } /// @@ -326,7 +192,9 @@ namespace umbraco.BusinessLogic /// Returns a ApplicationTree Array public static ApplicationTree[] getApplicationTree(string applicationAlias) { - return getApplicationTree(applicationAlias, false); + return Umbraco.Core.Trees.ApplicationTreeCollection.GetApplicationTree(applicationAlias) + .Select(Mapper.Map) + .ToArray(); } /// @@ -337,68 +205,10 @@ namespace umbraco.BusinessLogic /// Returns a ApplicationTree Array public static ApplicationTree[] getApplicationTree(string applicationAlias, bool onlyInitializedApplications) { - var list = AppTrees.FindAll( - t => - { - if (onlyInitializedApplications) - return (t.ApplicationAlias == applicationAlias && t.Initialize); - return (t.ApplicationAlias == applicationAlias); - } - ); - - return list.OrderBy(x => x.SortOrder).ToArray(); + return Umbraco.Core.Trees.ApplicationTreeCollection.GetApplicationTree(applicationAlias, onlyInitializedApplications) + .Select(Mapper.Map) + .ToArray(); } - internal static void LoadXml(Action callback, bool saveAfterCallback) - { - lock (Locker) - { - var doc = File.Exists(TreeConfigFilePath) - ? XDocument.Load(TreeConfigFilePath) - : XDocument.Parse(""); - if (doc.Root != null) - { - callback.Invoke(doc); - - if (saveAfterCallback) - { - Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); - - doc.Save(TreeConfigFilePath); - - //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.businesslogic/ApplicationTreeRegistrar.cs b/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs index e12eb2f21b..341ba12d11 100644 --- a/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs +++ b/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Xml.Linq; +using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; @@ -9,81 +10,69 @@ using umbraco.interfaces; namespace umbraco.BusinessLogic { - public class ApplicationTreeRegistrar : IApplicationStartupHandler + + //TODO: We should move this to Core but currently the legacy tree attribute exists here, perhaps we need two startup handlers + // one to register the legacy ones and one to register the new ones?? And create a new attribute + + /// + /// A startup handler for dealing with trees + /// + public class ApplicationTreeRegistrar : ApplicationEventHandler { - public ApplicationTreeRegistrar() + + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { - //don't do anything if the application or database is not configured! - if (ApplicationContext.Current == null - || !ApplicationContext.Current.IsConfigured - || !ApplicationContext.Current.DatabaseContext.IsDatabaseConfigured) - return; + ConfigureMappings(); + ScanTrees(); + } + /// + /// Configures automapper model mappings + /// + private static void ConfigureMappings() + { + Mapper.CreateMap() + .ReverseMap(); //two way + } + + /// + /// Scans for all attributed trees and ensures they exist in the tree xml + /// + private static void ScanTrees() + { // Load all Trees by attribute and add them to the XML config - var types = PluginManager.Current.ResolveAttributedTrees(); + var types = PluginManager.Current.ResolveAttributedTrees(); - var items = types - .Select(x => - new Tuple(x, x.GetCustomAttributes(false).Single())) - .Where(x => ApplicationTree.getByAlias(x.Item2.Alias) == null); + var items = types + .Select(x => + new Tuple(x, x.GetCustomAttributes(false).Single())) + .Where(x => Umbraco.Core.Trees.ApplicationTreeCollection.GetByAlias(x.Item2.Alias) == null); - var allAliases = ApplicationTree.getAll().Select(x => x.Alias).Concat(items.Select(x => x.Item2.Alias)); - var inString = "'" + string.Join("','", allAliases) + "'"; - - ApplicationTree.LoadXml(doc => - { - foreach (var tuple in items) + Umbraco.Core.Trees.ApplicationTreeCollection.LoadXml(doc => { - var type = tuple.Item1; - var attr = tuple.Item2; - - //Add the new tree that doesn't exist in the config that was found by type finding - - doc.Root.Add(new XElement("add", - new XAttribute("silent", attr.Silent), - new XAttribute("initialize", attr.Initialize), - new XAttribute("sortOrder", attr.SortOrder), - new XAttribute("alias", attr.Alias), - new XAttribute("application", attr.ApplicationAlias), - new XAttribute("title", attr.Title), - new XAttribute("iconClosed", attr.IconClosed), - new XAttribute("iconOpen", attr.IconOpen), - // don't add the assembly, we don't need this: - // http://issues.umbraco.org/issue/U4-1360 - //new XAttribute("assembly", assemblyName), - //new XAttribute("type", typeName), - // instead, store the assembly type name - new XAttribute("type", type.GetFullNameWithAssembly()), - new XAttribute("action", attr.Action))); - } - - //add any trees that were found in the database that don't exist in the config - - var db = ApplicationContext.Current.DatabaseContext.Database; - var exist = db.TableExist("umbracoAppTree"); - if (exist) - { - var appTrees = db.Fetch("WHERE treeAlias NOT IN (" + inString + ")"); - foreach (var appTree in appTrees) + foreach (var tuple in items) { - var action = appTree.Action; + var type = tuple.Item1; + var attr = tuple.Item2; + + //Add the new tree that doesn't exist in the config that was found by type finding doc.Root.Add(new XElement("add", - new XAttribute("silent", appTree.Silent), - new XAttribute("initialize", appTree.Initialize), - new XAttribute("sortOrder", appTree.SortOrder), - new XAttribute("alias", appTree.Alias), - new XAttribute("application", appTree.AppAlias), - new XAttribute("title", appTree.Title), - new XAttribute("iconClosed", appTree.IconClosed), - new XAttribute("iconOpen", appTree.IconOpen), - new XAttribute("assembly", appTree.HandlerAssembly), - new XAttribute("type", appTree.HandlerType), - new XAttribute("action", string.IsNullOrEmpty(action) ? "" : action))); + new XAttribute("silent", attr.Silent), + new XAttribute("initialize", attr.Initialize), + new XAttribute("sortOrder", attr.SortOrder), + new XAttribute("alias", attr.Alias), + new XAttribute("application", attr.ApplicationAlias), + new XAttribute("title", attr.Title), + new XAttribute("iconClosed", attr.IconClosed), + new XAttribute("iconOpen", attr.IconOpen), + new XAttribute("type", type.GetFullNameWithAssembly()), + new XAttribute("action", attr.Action))); } - } - }, true); + }, true); } + } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/src/umbraco.businesslogic/packages.config b/src/umbraco.businesslogic/packages.config index 8fb83abb39..9febdbd940 100644 --- a/src/umbraco.businesslogic/packages.config +++ b/src/umbraco.businesslogic/packages.config @@ -1,5 +1,6 @@  + diff --git a/src/umbraco.businesslogic/umbraco.businesslogic.csproj b/src/umbraco.businesslogic/umbraco.businesslogic.csproj index c4ff43ba36..32127a6b3a 100644 --- a/src/umbraco.businesslogic/umbraco.businesslogic.csproj +++ b/src/umbraco.businesslogic/umbraco.businesslogic.csproj @@ -106,6 +106,9 @@ false + + ..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll + True