Files
Umbraco-CMS/src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs

98 lines
4.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using umbraco.businesslogic;
using Umbraco.Core.Services;
namespace Umbraco.Web.Trees
{
/// <summary>
/// A startup handler for putting the tree config in the config file based on attributes found
/// </summary>
/// <remarks>
/// TODO: This is really not a very ideal process but the code is found here because tree plugins are in the Web project or the legacy business logic project.
/// Moving forward we can put the base tree plugin classes in the core and then this can all just be taken care of normally within the service.
/// </remarks>
public sealed class ApplicationTreeRegistrar : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
//Call initialize on the tree service with the lazy enumerable class below, when the tree service needs to resolve,
// it will lazily do the scanning and comparing so it's not actually done on app start.
applicationContext.Services.ApplicationTreeService.Intitialize(new LazyEnumerableTrees());
}
/// <summary>
/// This class is here so that we can provide lazy access to tree scanning for when it is needed
/// </summary>
private class LazyEnumerableTrees : IEnumerable<ApplicationTree>
{
public LazyEnumerableTrees()
{
_lazyTrees = new Lazy<IEnumerable<ApplicationTree>>(() =>
{
var added = new List<string>();
// Load all Controller Trees by attribute
var types = PluginManager.Current.ResolveAttributedTreeControllers();
//convert them to ApplicationTree instances
var items = types
.Select(x =>
new Tuple<Type, TreeAttribute>(x, x.GetCustomAttributes<TreeAttribute>(false).Single()))
.Select(x => new ApplicationTree(x.Item2.Initialize, x.Item2.SortOrder, x.Item2.ApplicationAlias, x.Item2.Alias, x.Item2.Title, x.Item2.IconClosed, x.Item2.IconOpen, x.Item1.GetFullNameWithAssembly()))
.ToArray();
added.AddRange(items.Select(x => x.Alias));
//find the legacy trees
var legacyTreeTypes = PluginManager.Current.ResolveAttributedTrees();
//convert them to ApplicationTree instances
var legacyItems = legacyTreeTypes
.Select(x =>
new Tuple<Type, global::umbraco.businesslogic.TreeAttribute, ObsoleteAttribute>(
x,
x.GetCustomAttributes<global::umbraco.businesslogic.TreeAttribute>(false).SingleOrDefault(),
x.GetCustomAttributes<ObsoleteAttribute>(false).SingleOrDefault()))
//ensure that the legacy tree attribute exists
.Where(x => x.Item2 != null)
//ensure that it's not obsoleted, any obsoleted tree will not be auto added to the config
.Where(x => x.Item3 == null)
//make sure the legacy tree isn't added on top of the controller tree!
.Where(x => added.InvariantContains(x.Item2.Alias) == false)
.Select(x => new ApplicationTree(x.Item2.Initialize, x.Item2.SortOrder, x.Item2.ApplicationAlias, x.Item2.Alias, x.Item2.Title, x.Item2.IconClosed, x.Item2.IconOpen, x.Item1.GetFullNameWithAssembly()));
return items.Concat(legacyItems).ToArray();
});
}
private readonly Lazy<IEnumerable<ApplicationTree>> _lazyTrees;
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<ApplicationTree> GetEnumerator()
{
return _lazyTrees.Value.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
}