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.

This commit is contained in:
Shannon
2013-06-20 10:05:51 +10:00
parent 2650740fa7
commit 24111c52f2
16 changed files with 466 additions and 287 deletions

View File

@@ -21,7 +21,7 @@ using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrad
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// </summary>
/// <remarks>

View File

@@ -0,0 +1,15 @@
using AutoMapper;
namespace Umbraco.Core
{
/// <summary>
/// Helper class for static model mapping with automapper
/// </summary>
internal static class ModelMapperHelper
{
internal static IMappingExpression<TSource, TSource> SelfMap<TSource>()
{
return Mapper.CreateMap<TSource, TSource>();
}
}
}

View File

@@ -0,0 +1,83 @@
namespace Umbraco.Core.Trees
{
internal class ApplicationTree
{
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationTree"/> class.
/// </summary>
public ApplicationTree() { }
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationTree"/> class.
/// </summary>
/// <param name="initialize">if set to <c>true</c> [initialize].</param>
/// <param name="sortOrder">The sort order.</param>
/// <param name="applicationAlias">The application alias.</param>
/// <param name="alias">The tree alias.</param>
/// <param name="title">The tree title.</param>
/// <param name="iconClosed">The icon closed.</param>
/// <param name="iconOpened">The icon opened.</param>
/// <param name="type">The tree type.</param>
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;
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ApplicationTree"/> should initialize.
/// </summary>
/// <value><c>true</c> if initialize; otherwise, <c>false</c>.</value>
public bool Initialize { get; set; }
/// <summary>
/// Gets or sets the sort order.
/// </summary>
/// <value>The sort order.</value>
public byte SortOrder { get; set; }
/// <summary>
/// Gets the application alias.
/// </summary>
/// <value>The application alias.</value>
public string ApplicationAlias { get; private set; }
/// <summary>
/// Gets the tree alias.
/// </summary>
/// <value>The alias.</value>
public string Alias { get; private set; }
/// <summary>
/// Gets or sets the tree title.
/// </summary>
/// <value>The title.</value>
public string Title { get; set; }
/// <summary>
/// Gets or sets the icon closed.
/// </summary>
/// <value>The icon closed.</value>
public string IconClosed { get; set; }
/// <summary>
/// Gets or sets the icon opened.
/// </summary>
/// <value>The icon opened.</value>
public string IconOpened { get; set; }
/// <summary>
/// Gets or sets the tree type assembly name.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
}
}

View File

@@ -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();
/// <summary>
/// gets/sets the trees.config file path
/// </summary>
/// <remarks>
/// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath
/// </remarks>
internal static string TreeConfigFilePath
{
get
{
if (string.IsNullOrWhiteSpace(_treeConfig))
{
_treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName);
}
return _treeConfig;
}
set { _treeConfig = value; }
}
/// <summary>
/// The cache storage for all application trees
/// </summary>
private static List<ApplicationTree> AppTrees
{
get
{
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
CacheKeys.ApplicationTreeCacheKey,
() =>
{
var list = new List<ApplicationTree>();
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;
});
}
}
/// <summary>
/// Creates a new application tree.
/// </summary>
/// <param name="initialize">if set to <c>true</c> [initialize].</param>
/// <param name="sortOrder">The sort order.</param>
/// <param name="applicationAlias">The application alias.</param>
/// <param name="alias">The alias.</param>
/// <param name="title">The title.</param>
/// <param name="iconClosed">The icon closed.</param>
/// <param name="iconOpened">The icon opened.</param>
/// <param name="type">The type.</param>
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());
}
/// <summary>
/// Saves this instance.
/// </summary>
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());
}
/// <summary>
/// Deletes this instance.
/// </summary>
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());
}
/// <summary>
/// Gets an ApplicationTree by it's tree alias.
/// </summary>
/// <param name="treeAlias">The tree alias.</param>
/// <returns>An ApplicationTree instance</returns>
public static ApplicationTree GetByAlias(string treeAlias)
{
return AppTrees.Find(t => (t.Alias == treeAlias));
}
/// <summary>
/// Gets all applicationTrees registered in umbraco from the umbracoAppTree table..
/// </summary>
/// <returns>Returns a ApplicationTree Array</returns>
public static IEnumerable<ApplicationTree> GetAll()
{
return AppTrees.OrderBy(x => x.SortOrder);
}
/// <summary>
/// Gets the application tree for the applcation with the specified alias
/// </summary>
/// <param name="applicationAlias">The application alias.</param>
/// <returns>Returns a ApplicationTree Array</returns>
public static IEnumerable<ApplicationTree> GetApplicationTree(string applicationAlias)
{
return GetApplicationTree(applicationAlias, false);
}
/// <summary>
/// Gets the application tree for the applcation with the specified alias
/// </summary>
/// <param name="applicationAlias">The application alias.</param>
/// <param name="onlyInitializedApplications"></param>
/// <returns>Returns a ApplicationTree Array</returns>
public static IEnumerable<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();
}
internal static void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
{
lock (Locker)
{
var doc = File.Exists(TreeConfigFilePath)
? XDocument.Load(TreeConfigFilePath)
: XDocument.Parse("<?xml version=\"1.0\"?><trees />");
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<ApplicationTree, EventArgs> Deleted;
private static void OnDeleted(ApplicationTree app, EventArgs args)
{
if (Deleted != null)
{
Deleted(app, args);
}
}
internal static event TypedEventHandler<ApplicationTree, EventArgs> New;
private static void OnNew(ApplicationTree app, EventArgs args)
{
if (New != null)
{
New(app, args);
}
}
internal static event TypedEventHandler<ApplicationTree, EventArgs> Updated;
private static void OnUpdated(ApplicationTree app, EventArgs args)
{
if (Updated != null)
{
Updated(app, args);
}
}
}
}

View File

@@ -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);
}

View File

@@ -37,6 +37,9 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\log4net-mediumtrust.2.0.0\lib\log4net.dll</HintPath>
@@ -174,6 +177,7 @@
<Compile Include="Manifest\PackageManifest.cs" />
<Compile Include="Manifest\PropertyEditorConverter.cs" />
<Compile Include="Media\MediaSubfolderCounter.cs" />
<Compile Include="ModelMapperHelper.cs" />
<Compile Include="Models\ContentBase.cs" />
<Compile Include="Models\ContentExtensions.cs" />
<Compile Include="Enum.cs" />
@@ -746,6 +750,8 @@
<Compile Include="Strings\LegacyShortStringHelper.cs" />
<Compile Include="Strings\StringAliasCaseTypeExtensions.cs" />
<Compile Include="Strings\DefaultShortStringHelper.cs" />
<Compile Include="Trees\ApplicationTree.cs" />
<Compile Include="Trees\ApplicationTreeCollection.cs" />
<Compile Include="TypeExtensions.cs" />
<Compile Include="ReadLock.cs" />
<Compile Include="TypeFinder.cs" />

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="2.2.1" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.20710.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net40" />

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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");

View File

@@ -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

View File

@@ -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);

View File

@@ -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.
/// </summary>
[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();
/// <summary>
/// gets/sets the trees.config file path
/// </summary>
/// <remarks>
/// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath
/// </remarks>
internal static string TreeConfigFilePath
{
get
{
if (string.IsNullOrWhiteSpace(_treeConfig))
{
_treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName);
}
return _treeConfig;
}
set { _treeConfig = value; }
}
/// <summary>
/// The cache storage for all application trees
/// </summary>
private static List<ApplicationTree> AppTrees
{
get
{
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
CacheKeys.ApplicationTreeCacheKey,
() =>
{
var list = new List<ApplicationTree>();
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;
});
}
}
/// <summary>
/// Gets the SQL helper.
/// </summary>
/// <value>The SQL helper.</value>
public static ISqlHelper SqlHelper
{
get { return Application.SqlHelper; }
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ApplicationTree"/> is silent.
/// </summary>
@@ -226,28 +141,8 @@ namespace umbraco.BusinessLogic
/// <param name="action">The action.</param>
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));
}
/// <summary>
@@ -255,30 +150,8 @@ namespace umbraco.BusinessLogic
/// </summary>
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<ApplicationTree, Umbraco.Core.Trees.ApplicationTree>(this));
}
/// <summary>
@@ -286,19 +159,10 @@ namespace umbraco.BusinessLogic
/// </summary>
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<ApplicationTree, Umbraco.Core.Trees.ApplicationTree>(this));
}
/// <summary>
/// Gets an ApplicationTree by it's tree alias.
/// </summary>
@@ -306,8 +170,8 @@ namespace umbraco.BusinessLogic
/// <returns>An ApplicationTree instance</returns>
public static ApplicationTree getByAlias(string treeAlias)
{
return AppTrees.Find(t => (t.Alias == treeAlias));
return Mapper.Map<Umbraco.Core.Trees.ApplicationTree, ApplicationTree>(
Umbraco.Core.Trees.ApplicationTreeCollection.GetByAlias(treeAlias));
}
/// <summary>
@@ -316,7 +180,9 @@ namespace umbraco.BusinessLogic
/// <returns>Returns a ApplicationTree Array</returns>
public static ApplicationTree[] getAll()
{
return AppTrees.OrderBy(x => x.SortOrder).ToArray();
return Umbraco.Core.Trees.ApplicationTreeCollection.GetAll()
.Select(Mapper.Map<Umbraco.Core.Trees.ApplicationTree, ApplicationTree>)
.ToArray();
}
/// <summary>
@@ -326,7 +192,9 @@ namespace umbraco.BusinessLogic
/// <returns>Returns a ApplicationTree Array</returns>
public static ApplicationTree[] getApplicationTree(string applicationAlias)
{
return getApplicationTree(applicationAlias, false);
return Umbraco.Core.Trees.ApplicationTreeCollection.GetApplicationTree(applicationAlias)
.Select(Mapper.Map<Umbraco.Core.Trees.ApplicationTree, ApplicationTree>)
.ToArray();
}
/// <summary>
@@ -337,68 +205,10 @@ namespace umbraco.BusinessLogic
/// <returns>Returns a ApplicationTree Array</returns>
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<Umbraco.Core.Trees.ApplicationTree, ApplicationTree>)
.ToArray();
}
internal static void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
{
lock (Locker)
{
var doc = File.Exists(TreeConfigFilePath)
? XDocument.Load(TreeConfigFilePath)
: XDocument.Parse("<?xml version=\"1.0\"?><trees />");
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<ApplicationTree, EventArgs> Deleted;
private static void OnDeleted(ApplicationTree app, EventArgs args)
{
if (Deleted != null)
{
Deleted(app, args);
}
}
internal static event TypedEventHandler<ApplicationTree, EventArgs> New;
private static void OnNew(ApplicationTree app, EventArgs args)
{
if (New != null)
{
New(app, args);
}
}
internal static event TypedEventHandler<ApplicationTree, EventArgs> Updated;
private static void OnUpdated(ApplicationTree app, EventArgs args)
{
if (Updated != null)
{
Updated(app, args);
}
}
}
}

View File

@@ -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
/// <summary>
/// A startup handler for dealing with trees
/// </summary>
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();
}
/// <summary>
/// Configures automapper model mappings
/// </summary>
private static void ConfigureMappings()
{
Mapper.CreateMap<Umbraco.Core.Trees.ApplicationTree, ApplicationTree>()
.ReverseMap(); //two way
}
/// <summary>
/// Scans for all attributed trees and ensures they exist in the tree xml
/// </summary>
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<Type, TreeAttribute>(x, x.GetCustomAttributes<TreeAttribute>(false).Single()))
.Where(x => ApplicationTree.getByAlias(x.Item2.Alias) == null);
var items = types
.Select(x =>
new Tuple<Type, TreeAttribute>(x, x.GetCustomAttributes<TreeAttribute>(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<AppTreeDto>("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);
}
}
}
}

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="2.2.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.20710.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net40" />

View File

@@ -106,6 +106,9 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
</Reference>