diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec
index 6067cade4a..4fe812dbeb 100644
--- a/build/NuSpecs/UmbracoCms.Core.nuspec
+++ b/build/NuSpecs/UmbracoCms.Core.nuspec
@@ -30,7 +30,7 @@
-
+
diff --git a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs
index 1e59c8e920..52499bee7d 100644
--- a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs
@@ -48,7 +48,6 @@ namespace Umbraco.Core.Persistence.Factories
template.IsMasterTemplate = true;
}
- //TODO: Change this to ParentId: http://issues.umbraco.org/issue/U4-5846
if(dto.NodeDto.ParentId > 0)
template.MasterTemplateId = new Lazy(() => dto.NodeDto.ParentId);
diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs
index 4366aaa4a6..14957ac49f 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Persistence.Repositories
@@ -10,12 +11,17 @@ namespace Umbraco.Core.Persistence.Repositories
IEnumerable GetAll(params string[] aliases);
IEnumerable GetChildren(int masterTemplateId);
+ IEnumerable GetChildren(string alias);
+
+ IEnumerable GetDescendants(int masterTemplateId);
+ IEnumerable GetDescendants(string alias);
///
/// Returns a template as a template node which can be traversed (parent, children)
///
///
///
+ [Obsolete("Use GetDescendants instead")]
TemplateNode GetTemplateNode(string alias);
///
@@ -24,6 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
///
+ [Obsolete("Use GetDescendants instead")]
TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias);
///
diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs
index 235c18a7a8..53e9954fd0 100644
--- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs
@@ -67,7 +67,15 @@ namespace Umbraco.Core.Persistence.Repositories
protected override ITemplate PerformGet(int id)
{
- return GetAll(new[] { id }).FirstOrDefault();
+ var sql = GetBaseQuery(false).Where(x => x.NodeId == id);
+ var result = Database.Fetch(sql).FirstOrDefault();
+ if (result == null) return null;
+
+ //look up the simple template definitions that have a master template assigned, this is used
+ // later to populate the template item's properties
+ var childIds = GetAxisDefinitions(result).ToArray();
+
+ return MapFromDto(result, childIds);
}
protected override IEnumerable PerformGetAll(params int[] ids)
@@ -89,20 +97,15 @@ namespace Umbraco.Core.Persistence.Repositories
//look up the simple template definitions that have a master template assigned, this is used
// later to populate the template item's properties
- var childIdsSql = new Sql()
- .Select("nodeId,alias,parentID")
- .From()
- .InnerJoin()
- .On(dto => dto.NodeId, dto => dto.NodeId)
- .Where(t => t.ParentId > 0);
- var childIds = Database.Fetch(childIdsSql)
- .Select(x => new UmbracoEntity
+ var childIds = (ids.Any()
+ ? GetAxisDefinitions(dtos.ToArray())
+ : dtos.Select(x => new UmbracoEntity
{
- Id = x.nodeId,
- ParentId = x.parentID,
- Name = x.alias
- });
-
+ Id = x.NodeId,
+ ParentId = x.NodeDto.ParentId,
+ Name = x.Alias
+ })).ToArray();
+
return dtos.Select(d => MapFromDto(d, childIds));
}
@@ -118,19 +121,7 @@ namespace Umbraco.Core.Persistence.Repositories
//look up the simple template definitions that have a master template assigned, this is used
// later to populate the template item's properties
- var childIdsSql = new Sql()
- .Select("nodeId,alias,parentID")
- .From()
- .InnerJoin()
- .On(dto => dto.NodeId, dto => dto.NodeId)
- .Where(t => t.ParentId > 0);
- var childIds = Database.Fetch(childIdsSql)
- .Select(x => new UmbracoEntity
- {
- Id = x.nodeId,
- ParentId = x.parentID,
- Name = x.alias
- });
+ var childIds = GetAxisDefinitions(dtos.ToArray()).ToArray();
return dtos.Select(d => MapFromDto(d, childIds));
}
@@ -143,9 +134,9 @@ namespace Umbraco.Core.Persistence.Repositories
{
var sql = new Sql();
sql.Select(isCount ? "COUNT(*)" : "*")
- .From()
- .InnerJoin()
- .On(left => left.NodeId, right => right.NodeId)
+ .From(SqlSyntax)
+ .InnerJoin(SqlSyntax)
+ .On(SqlSyntax, left => left.NodeId, right => right.NodeId)
.Where(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
}
@@ -348,22 +339,52 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
- private ITemplate MapFromDto(TemplateDto dto, IEnumerable childDefinitions)
+ private IEnumerable GetAxisDefinitions(params TemplateDto[] templates)
+ {
+ //look up the simple template definitions that have a master template assigned, this is used
+ // later to populate the template item's properties
+ var childIdsSql = new Sql()
+ .Select("nodeId,alias,parentID")
+ .From(SqlSyntax)
+ .InnerJoin(SqlSyntax)
+ .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId)
+ //lookup axis's
+ .Where("umbracoNode." + SqlSyntax.GetQuotedColumnName("id") + " IN (@parentIds) OR umbracoNode.parentID IN (@childIds)",
+ new {parentIds = templates.Select(x => x.NodeDto.ParentId), childIds = templates.Select(x => x.NodeId)});
+
+ var childIds = Database.Fetch(childIdsSql)
+ .Select(x => new UmbracoEntity
+ {
+ Id = x.nodeId,
+ ParentId = x.parentID,
+ Name = x.alias
+ });
+ return childIds;
+ }
+
+ ///
+ /// Maps from a dto to an ITemplate
+ ///
+ ///
+ ///
+ /// This is a collection of template definitions ... either all templates, or the collection of child templates and it's parent template
+ ///
+ ///
+ private ITemplate MapFromDto(TemplateDto dto, IUmbracoEntity[] axisDefinitions)
{
string csViewName = string.Concat(dto.Alias, ".cshtml");
string vbViewName = string.Concat(dto.Alias, ".vbhtml");
string masterpageName = string.Concat(dto.Alias, ".master");
var factory = new TemplateFactory();
- var template = factory.BuildEntity(dto, childDefinitions);
+ var template = factory.BuildEntity(dto, axisDefinitions);
if (dto.NodeDto.ParentId > 0)
{
- //TODO: Fix this n+1 query!
- var masterTemplate = Get(dto.NodeDto.ParentId);
+ var masterTemplate = axisDefinitions.FirstOrDefault(x => x.Id == dto.NodeDto.ParentId);
if (masterTemplate != null)
{
- template.MasterTemplateAlias = masterTemplate.Alias;
+ template.MasterTemplateAlias = masterTemplate.Name;
template.MasterTemplateId = new Lazy(() => dto.NodeDto.ParentId);
}
}
@@ -460,49 +481,105 @@ namespace Umbraco.Core.Persistence.Repositories
if (dto == null)
return null;
- return Get(dto.NodeId);
+ return MapFromDto(dto, GetAxisDefinitions(dto).ToArray());
}
public IEnumerable GetAll(params string[] aliases)
{
+ var sql = GetBaseQuery(false);
+
if (aliases.Any())
{
- foreach (var id in aliases)
- {
- yield return Get(id);
- }
- }
- else
- {
- var nodeDtos = Database.Fetch("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
- foreach (var nodeDto in nodeDtos)
- {
- yield return Get(nodeDto.NodeId);
- }
+ sql.Where("cmsTemplate.alias IN (@aliases)", new {aliases = aliases});
}
+ var dtos = Database.Fetch(sql).ToArray();
+ var axisDefos = GetAxisDefinitions(dtos).ToArray();
+ return dtos.Select(x => MapFromDto(x, axisDefos));
}
public IEnumerable GetChildren(int masterTemplateId)
{
- //TODO: Fix this N+1!
-
- List found;
- if (masterTemplateId == -1)
+ var sql = GetBaseQuery(false);
+ if (masterTemplateId <= 0)
{
- var sql = GetBaseQuery(false).Where(x => x.ParentId <= 0);
- found = Database.Fetch(sql);
+ sql.Where(x => x.ParentId <= 0);
}
else
{
- var sql = GetBaseQuery(false).Where(x => x.ParentId == masterTemplateId);
- found = Database.Fetch(sql);
+ sql.Where(x => x.ParentId == masterTemplateId);
}
- foreach (var templateDto in found)
+ var dtos = Database.Fetch(sql).ToArray();
+ var axisDefos = GetAxisDefinitions(dtos).ToArray();
+ return dtos.Select(x => MapFromDto(x, axisDefos));
+ }
+
+ public IEnumerable GetChildren(string alias)
+ {
+ var sql = GetBaseQuery(false);
+ if (alias.IsNullOrWhiteSpace())
{
- yield return Get(templateDto.NodeId);
+ sql.Where(x => x.ParentId <= 0);
}
+ else
+ {
+ //unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
+ // in a single query, now we have to lookup the path to acheive the same thing
+ var parent = Database.ExecuteScalar(new Sql().Select("nodeId").From(SqlSyntax).Where(dto => dto.Alias == alias));
+ if (parent.HasValue == false) return Enumerable.Empty();
+
+ sql.Where(x => x.ParentId == parent.Value);
+ }
+
+ var dtos = Database.Fetch(sql).ToArray();
+ var axisDefos = GetAxisDefinitions(dtos).ToArray();
+ return dtos.Select(x => MapFromDto(x, axisDefos));
+ }
+
+ public IEnumerable GetDescendants(int masterTemplateId)
+ {
+ var sql = GetBaseQuery(false);
+ if (masterTemplateId > 0)
+ {
+ //unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
+ // in a single query, now we have to lookup the path to acheive the same thing
+ var path = Database.ExecuteScalar(
+ new Sql().Select(SqlSyntax.GetQuotedColumnName("path"))
+ .From(SqlSyntax)
+ .InnerJoin(SqlSyntax)
+ .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId)
+ .Where(dto => dto.NodeId == masterTemplateId));
+
+ if (path.IsNullOrWhiteSpace()) return Enumerable.Empty();
+
+ sql.Where(@"(umbracoNode." + SqlSyntax.GetQuotedColumnName("path") + @" LIKE @query)", new { query = path + ",%" });
+ }
+
+ var dtos = Database.Fetch(sql).ToArray();
+ var axisDefos = GetAxisDefinitions(dtos).ToArray();
+ return dtos.Select(x => MapFromDto(x, axisDefos));
+
+ }
+
+ public IEnumerable GetDescendants(string alias)
+ {
+ var sql = GetBaseQuery(false);
+ if (alias.IsNullOrWhiteSpace() == false)
+ {
+ //unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
+ // in a single query, now we have to lookup the path to acheive the same thing
+ var path = Database.ExecuteScalar(
+ "SELECT umbracoNode.path FROM cmsTemplate INNER JOIN umbracoNode ON cmsTemplate.nodeId = umbracoNode.id WHERE cmsTemplate.alias = @alias", new { alias = alias });
+
+ if (path.IsNullOrWhiteSpace()) return Enumerable.Empty();
+
+ sql.Where(@"(umbracoNode." + SqlSyntax.GetQuotedColumnName("path") + @" LIKE @query)", new {query = path + ",%" });
+ }
+
+ var dtos = Database.Fetch(sql).ToArray();
+ var axisDefos = GetAxisDefinitions(dtos).ToArray();
+ return dtos.Select(x => MapFromDto(x, axisDefos));
}
///
@@ -510,13 +587,9 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
///
+ [Obsolete("Use GetDescendants instead")]
public TemplateNode GetTemplateNode(string alias)
- {
- //in order to do this we need to get all of the templates and then organize,
- // TODO: unfortunately our db structure does not use the path correctly for templates so we cannot just look
- // up a template tree easily.
- //TODO: We do use the 'path' now, so this might be able to be fixed up
-
+ {
//first get all template objects
var allTemplates = GetAll().ToArray();
@@ -525,23 +598,17 @@ namespace Umbraco.Core.Persistence.Repositories
{
return null;
}
-
- //then we need to get all template Dto's because those contain the master property
- var sql = GetBaseQuery(false);
- var allDtos = Database.Fetch(sql).ToArray();
- var selfDto = allDtos.Single(x => x.NodeId == selfTemplate.Id);
-
- //need to get the top-most node of the current tree
- var top = selfDto;
- while (top.NodeDto.ParentId > 0)
+
+ var top = selfTemplate;
+ while (top.MasterTemplateAlias.IsNullOrWhiteSpace() == false)
{
- top = allDtos.Single(x => x.NodeId == top.NodeDto.ParentId);
+ top = allTemplates.Single(x => x.Alias == top.MasterTemplateAlias);
}
- var topNode = new TemplateNode(allTemplates.Single(x => x.Id == top.NodeId));
- var childIds = allDtos.Where(x => x.NodeDto.ParentId == top.NodeId).Select(x => x.NodeId);
+ var topNode = new TemplateNode(allTemplates.Single(x => x.Id == top.Id));
+ var childTemplates = allTemplates.Where(x => x.MasterTemplateAlias == top.Alias);
//This now creates the hierarchy recursively
- topNode.Children = CreateChildren(topNode, childIds, allTemplates, allDtos);
+ topNode.Children = CreateChildren(topNode, childTemplates, allTemplates);
//now we'll return the TemplateNode requested
return FindTemplateInTree(topNode, alias);
@@ -568,6 +635,7 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
///
+ [Obsolete("Use GetDescendants instead")]
public TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias)
{
//first get the root
@@ -658,12 +726,12 @@ namespace Umbraco.Core.Persistence.Repositories
return validFile && validExtension;
}
- private static IEnumerable CreateChildren(TemplateNode parent, IEnumerable childIds, ITemplate[] allTemplates, TemplateDto[] allDtos)
+ private static IEnumerable CreateChildren(TemplateNode parent, IEnumerable childTemplates, ITemplate[] allTemplates)
{
var children = new List();
- foreach (var i in childIds)
+ foreach (var childTemplate in childTemplates)
{
- var template = allTemplates.Single(x => x.Id == i);
+ var template = allTemplates.Single(x => x.Id == childTemplate.Id);
var child = new TemplateNode(template)
{
Parent = parent
@@ -673,10 +741,11 @@ namespace Umbraco.Core.Persistence.Repositories
children.Add(child);
//get this node's children
- var kids = allDtos.Where(x => x.NodeDto.ParentId == i).Select(x => x.NodeId).ToArray();
+ var local = childTemplate;
+ var kids = allTemplates.Where(x => x.MasterTemplateAlias == local.Alias);
//recurse
- child.Children = CreateChildren(child, kids, allTemplates, allDtos);
+ child.Children = CreateChildren(child, kids, allTemplates);
}
return children;
}
diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs
index 29ccfbf6bf..4dcbd5bdc8 100644
--- a/src/Umbraco.Core/Services/FileService.cs
+++ b/src/Umbraco.Core/Services/FileService.cs
@@ -319,6 +319,53 @@ namespace Umbraco.Core.Services
}
}
+ public IEnumerable GetTemplateDescendants(string alias)
+ {
+ using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
+ {
+ return repository.GetDescendants(alias);
+ }
+ }
+
+ ///
+ /// Gets the template descendants
+ ///
+ ///
+ ///
+ public IEnumerable GetTemplateDescendants(int masterTemplateId)
+ {
+ using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
+ {
+ return repository.GetDescendants(masterTemplateId);
+ }
+ }
+
+ ///
+ /// Gets the template children
+ ///
+ ///
+ ///
+ public IEnumerable GetTemplateChildren(string alias)
+ {
+ using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
+ {
+ return repository.GetChildren(alias);
+ }
+ }
+
+ ///
+ /// Gets the template children
+ ///
+ ///
+ ///
+ public IEnumerable GetTemplateChildren(int masterTemplateId)
+ {
+ using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
+ {
+ return repository.GetChildren(masterTemplateId);
+ }
+ }
+
///
/// Returns a template as a template node which can be traversed (parent, children)
///
diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs
index 7803abe98e..e1c0f1428c 100644
--- a/src/Umbraco.Core/Services/IFileService.cs
+++ b/src/Umbraco.Core/Services/IFileService.cs
@@ -130,10 +130,38 @@ namespace Umbraco.Core.Services
ITemplate GetTemplate(int id);
///
- /// Returns a template as a template node which can be traversed (parent, children)
+ /// Gets the template descendants
///
///
///
+ IEnumerable GetTemplateDescendants(string alias);
+
+ ///
+ /// Gets the template descendants
+ ///
+ ///
+ ///
+ IEnumerable GetTemplateDescendants(int masterTemplateId);
+
+ ///
+ /// Gets the template children
+ ///
+ ///
+ ///
+ IEnumerable GetTemplateChildren(string alias);
+
+ ///
+ /// Gets the template children
+ ///
+ ///
+ ///
+ IEnumerable GetTemplateChildren(int masterTemplateId);
+
+ ///
+ /// Returns a template as a template node which can be traversed (parent, children)
+ ///
+ ///
+ ///
TemplateNode GetTemplateNode(string alias);
///
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index b13529f8ea..56935ed7f7 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -37,13 +37,13 @@
false
-
- False
- ..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll
+
+ ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll
+ True
-
- False
- ..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll
+
+ ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll
+ True
False
@@ -1387,7 +1387,6 @@
-
-
+
-
\ No newline at end of file
diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs
index 37de741007..0f6fc03b80 100644
--- a/src/Umbraco.Web/UmbracoApplication.cs
+++ b/src/Umbraco.Web/UmbracoApplication.cs
@@ -30,9 +30,13 @@ namespace Umbraco.Web
base.OnApplicationStarted(sender, e);
if (ApplicationContext.Current.IsConfigured && GlobalSettings.DebugMode)
- {
- _mw = new ManifestWatcher(LoggerResolver.Current.Logger);
- _mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/")));
+ {
+ var appPluginFolder = IOHelper.MapPath("~/App_Plugins/");
+ if (Directory.Exists(appPluginFolder))
+ {
+ _mw = new ManifestWatcher(LoggerResolver.Current.Logger);
+ _mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/")));
+ }
}
}
diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config
index 6cdd67fe04..f3ecf6b064 100644
--- a/src/Umbraco.Web/packages.config
+++ b/src/Umbraco.Web/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs b/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs
index 6854bb9a4d..27e62888d4 100644
--- a/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs
+++ b/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs
@@ -326,8 +326,7 @@ namespace umbraco {
HttpContext.Current.Request.ServerVariables["SERVER_NAME"],
ApplicationContext.Current.Services.EntityService,
new PublishedContentQuery(UmbracoContext.Current.ContentCache, UmbracoContext.Current.MediaCache),
- ApplicationContext.Current.Services.DomainService,
- ApplicationContext.Current.Services.LocalizationService);
+ ApplicationContext.Current.Services.DomainService);
if (error404.HasValue)
{
diff --git a/src/umbraco.businesslogic/packages.config b/src/umbraco.businesslogic/packages.config
index 65ef682839..4a0a1d249b 100644
--- a/src/umbraco.businesslogic/packages.config
+++ b/src/umbraco.businesslogic/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/src/umbraco.businesslogic/umbraco.businesslogic.csproj b/src/umbraco.businesslogic/umbraco.businesslogic.csproj
index c34a55d08b..e134c33eab 100644
--- a/src/umbraco.businesslogic/umbraco.businesslogic.csproj
+++ b/src/umbraco.businesslogic/umbraco.businesslogic.csproj
@@ -106,13 +106,13 @@
false
-
- False
- ..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll
+
+ ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll
+ True
-
- False
- ..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll
+
+ ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll
+ True
False
@@ -295,5 +295,4 @@
-
\ No newline at end of file