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