From 39cbf42c5a552ccdfb9413921f41c058df2979a6 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Fri, 3 Sep 2010 18:58:24 -0700 Subject: [PATCH] Less broken than ever Layout component injected by themed result filter Composes three stage rendering Obsoletes additional rendering placeholder components Additional csproj files renamed to avoid broken modules from being included in view compilation A dynamic language in views would be nice --HG-- branch : theming --- .../Lucene/{Lucene.csproj => Lucene.csproj_} | 0 ...es.csproj => Orchard.ContentTypes.csproj_} | 0 ...Modules.csproj => Orchard.Modules.csproj_} | 0 ...aging.csproj => Orchard.Packaging.csproj_} | 0 .../Modules/Orchard.Setup/SetupMode.cs | 3 +- src/Orchard/Mvc/ViewEngines/LayoutView.cs | 61 ------------ .../ThemeAwareness/LayoutAwareViewEngine.cs | 98 +++++++++++++++++++ .../ThemeAwareness/ThemeAwareViewEngine.cs | 33 ++++--- .../ThemeAwareViewEngineShim.cs | 6 +- ...rentTheme.cs => ThemedViewResultFilter.cs} | 14 ++- src/Orchard/Orchard.Framework.csproj | 3 +- 11 files changed, 137 insertions(+), 81 deletions(-) rename src/Orchard.Web/Modules/Lucene/{Lucene.csproj => Lucene.csproj_} (100%) rename src/Orchard.Web/Modules/Orchard.ContentTypes/{Orchard.ContentTypes.csproj => Orchard.ContentTypes.csproj_} (100%) rename src/Orchard.Web/Modules/Orchard.Modules/{Orchard.Modules.csproj => Orchard.Modules.csproj_} (100%) rename src/Orchard.Web/Modules/Orchard.Packaging/{Orchard.Packaging.csproj => Orchard.Packaging.csproj_} (100%) delete mode 100644 src/Orchard/Mvc/ViewEngines/LayoutView.cs create mode 100644 src/Orchard/Mvc/ViewEngines/ThemeAwareness/LayoutAwareViewEngine.cs rename src/Orchard/Mvc/ViewEngines/ThemeAwareness/{CurrentTheme.cs => ThemedViewResultFilter.cs} (80%) diff --git a/src/Orchard.Web/Modules/Lucene/Lucene.csproj b/src/Orchard.Web/Modules/Lucene/Lucene.csproj_ similarity index 100% rename from src/Orchard.Web/Modules/Lucene/Lucene.csproj rename to src/Orchard.Web/Modules/Lucene/Lucene.csproj_ diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj b/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj_ similarity index 100% rename from src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj rename to src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj_ diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj b/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj_ similarity index 100% rename from src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj rename to src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj_ diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj b/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj_ similarity index 100% rename from src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj rename to src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj_ diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index e4192f255..655225e8e 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -43,7 +43,7 @@ namespace Orchard.Setup { builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); @@ -70,6 +70,7 @@ namespace Orchard.Setup { builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); } diff --git a/src/Orchard/Mvc/ViewEngines/LayoutView.cs b/src/Orchard/Mvc/ViewEngines/LayoutView.cs deleted file mode 100644 index e925e7e50..000000000 --- a/src/Orchard/Mvc/ViewEngines/LayoutView.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.IO; -using System.Web.Mvc; -using Orchard.Mvc.ViewModels; - -namespace Orchard.Mvc.ViewEngines { - public class LayoutView : IView { - private readonly LayoutViewEngine _viewEngine; - private ViewEngineResult[] _viewEngineResults; - - public LayoutView(LayoutViewEngine viewEngine, ViewEngineResult[] views) { - _viewEngine = viewEngine; - _viewEngineResults = views; - } - - public void Render(ViewContext viewContext, TextWriter writer) { - using (_viewEngine.CreateScope(viewContext)) { - var layoutViewContext = LayoutViewContext.From(viewContext); - - for (var index = 0; index != _viewEngineResults.Length; ++index) { - bool isFirst = index == 0; - bool isLast = index == _viewEngineResults.Length - 1; - - var effectiveWriter = isLast ? viewContext.Writer : new StringWriter(); - var effectiveViewData = isFirst ? viewContext.ViewData : CoerceViewData(viewContext.ViewData); - var viewEngineResult = _viewEngineResults[index]; - - var effectiveContext = new ViewContext( - viewContext, - viewEngineResult.View, - effectiveViewData, - viewContext.TempData, - effectiveWriter); - - viewEngineResult.View.Render(effectiveContext, effectiveWriter); - - if (!isLast) - layoutViewContext.BodyContent = effectiveWriter.ToString(); - } - } - } - - private static ViewDataDictionary CoerceViewData(ViewDataDictionary dictionary) { -#if REFACTORING - if (dictionary.Model is BaseViewModel) - return dictionary; - - return new ViewDataDictionary(BaseViewModel.From(dictionary)); -#else - return dictionary; -#endif - } - - - - public void ReleaseViews(ControllerContext context) { - foreach (var viewEngineResult in _viewEngineResults) { - viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View); - } - } - } -} diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/LayoutAwareViewEngine.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/LayoutAwareViewEngine.cs new file mode 100644 index 000000000..2aab9e42b --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/LayoutAwareViewEngine.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.Mvc; + +namespace Orchard.Mvc.ViewEngines.ThemeAwareness { + public interface ILayoutAwareViewEngine : IDependency, IViewEngine { + } + + public class LayoutAwareViewEngine : ILayoutAwareViewEngine { + private readonly IThemeAwareViewEngine _themeAwareViewEngine; + + public LayoutAwareViewEngine(IThemeAwareViewEngine themeAwareViewEngine) { + _themeAwareViewEngine = themeAwareViewEngine; + } + + public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { + return _themeAwareViewEngine.FindPartialView(controllerContext, partialViewName, useCache, true); + } + + public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { + var bodyView = _themeAwareViewEngine.FindPartialView(controllerContext, viewName, useCache, true); + var layoutView = _themeAwareViewEngine.FindPartialView(controllerContext, "Layout", useCache, true); + var documentView = _themeAwareViewEngine.FindPartialView(controllerContext, "Document", useCache, true); + + if (bodyView.View == null || + layoutView.View == null || + documentView.View == null) { + + var missingTemplatesResult = new ViewEngineResult( + (bodyView.SearchedLocations ?? Enumerable.Empty()) + .Concat((layoutView.SearchedLocations ?? Enumerable.Empty())) + .Concat((documentView.SearchedLocations ?? Enumerable.Empty())) + ); + + return missingTemplatesResult; + } + + var view = new LayoutView(new[] { + bodyView, + layoutView, + documentView, + }); + + return new ViewEngineResult(view, this); + } + + public void ReleaseView(ControllerContext controllerContext, IView view) { + var layoutView = (LayoutView)view; + layoutView.ReleaseViews(controllerContext); + } + + class LayoutView : IView { + private readonly ViewEngineResult[] _viewEngineResults; + + public LayoutView(ViewEngineResult[] viewEngineResults) { + _viewEngineResults = viewEngineResults; + } + + public void Render(ViewContext viewContext, TextWriter writer) { + var layoutViewContext = LayoutViewContext.From(viewContext); + + for (var index = 0; index != _viewEngineResults.Length; ++index) { + bool isFirst = index == 0; + bool isLast = index == _viewEngineResults.Length - 1; + + var effectiveWriter = isLast ? viewContext.Writer : new StringWriter(); + var effectiveViewData = isFirst ? viewContext.ViewData : CoerceViewData(viewContext.ViewData); + var viewEngineResult = _viewEngineResults[index]; + + var effectiveContext = new ViewContext( + viewContext, + viewEngineResult.View, + effectiveViewData, + viewContext.TempData, + effectiveWriter); + + viewEngineResult.View.Render(effectiveContext, effectiveWriter); + + if (!isLast) + layoutViewContext.BodyContent = effectiveWriter.ToString(); + } + } + + private static ViewDataDictionary CoerceViewData(ViewDataDictionary dictionary) { + return dictionary; + } + + public void ReleaseViews(ControllerContext context) { + foreach (var viewEngineResult in _viewEngineResults) { + viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View); + } + } + } + } +} diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs index b9e1825bb..4ba2f9c18 100644 --- a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs +++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs @@ -7,7 +7,9 @@ using Orchard.Environment.Extensions; using Orchard.Themes; namespace Orchard.Mvc.ViewEngines.ThemeAwareness { - public interface IThemeAwareViewEngine : IDependency, IViewEngine { + public interface IThemeAwareViewEngine : IDependency { + ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths); + ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache, bool useDeepPaths); } public class ThemeAwareViewEngine : IThemeAwareViewEngine { @@ -31,24 +33,33 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness { _shellDescriptor = shellDescriptor; } - public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { - IViewEngine engines = _nullEngines; + public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths) { + var engines = _nullEngines; if (partialViewName.StartsWith("/") || partialViewName.StartsWith("~")) { engines = BareEngines(); } else if (_workContext.CurrentTheme != null) { - if (controllerContext is ViewContext) { - engines = ShallowEngines(_workContext.CurrentTheme); - } - else { - engines = DeepEngines(_workContext.CurrentTheme); - } + engines = useDeepPaths ? DeepEngines(_workContext.CurrentTheme) : ShallowEngines(_workContext.CurrentTheme); } return engines.FindPartialView(controllerContext, partialViewName, useCache); } + public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache, bool useDeepPaths) { + var engines = _nullEngines; + + if (viewName.StartsWith("/") || viewName.StartsWith("~")) { + engines = BareEngines(); + } + else if (_workContext.CurrentTheme != null) { + engines = useDeepPaths ? DeepEngines(_workContext.CurrentTheme) : ShallowEngines(_workContext.CurrentTheme); + } + + return engines.FindView(controllerContext, viewName, masterName, useCache); + } + + private IViewEngine BareEngines() { return _configuredEnginesCache.BindBareEngines(() => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine()))); } @@ -75,10 +86,6 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness { }); } - public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { - return FindPartialView(controllerContext, viewName, useCache); - } - public void ReleaseView(ControllerContext controllerContext, IView view) { throw new NotImplementedException(); } diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngineShim.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngineShim.cs index 86f0b8759..018e12b6a 100644 --- a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngineShim.cs +++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngineShim.cs @@ -13,15 +13,15 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness { public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { return Forward( - controllerContext, - dve => dve.FindPartialView(controllerContext, partialViewName, useCache), + controllerContext, + dve => dve.FindPartialView(controllerContext, partialViewName, useCache, false /*useDeepPaths*/), EmptyViewEngineResult); } public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { return Forward( controllerContext, - dve => dve.FindView(controllerContext, viewName, masterName, useCache), + dve => dve.FindView(controllerContext, viewName, masterName, useCache, false /*useDeepPaths*/), EmptyViewEngineResult); } diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/CurrentTheme.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs similarity index 80% rename from src/Orchard/Mvc/ViewEngines/ThemeAwareness/CurrentTheme.cs rename to src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs index 56e42d27b..b4d617040 100644 --- a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/CurrentTheme.cs +++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs @@ -5,22 +5,32 @@ using Orchard.Themes; namespace Orchard.Mvc.ViewEngines.ThemeAwareness { - public class CurrentThemeFilter : FilterProvider, IResultFilter { + public class ThemedViewResultFilter : FilterProvider, IResultFilter { private readonly IThemeService _themeService; private readonly WorkContext _workContext; + private readonly ILayoutAwareViewEngine _layoutAwareViewEngine; - public CurrentThemeFilter(IThemeService themeService, WorkContext workContext) { + public ThemedViewResultFilter(IThemeService themeService, WorkContext workContext, ILayoutAwareViewEngine layoutAwareViewEngine) { _themeService = themeService; _workContext = workContext; + _layoutAwareViewEngine = layoutAwareViewEngine; Logger = NullLogger.Instance; } public ILogger Logger { get; set; } public void OnResultExecuting(ResultExecutingContext filterContext) { + var viewResultBase = filterContext.Result as ViewResultBase; + if (viewResultBase == null) { + return; + } + if (_workContext.CurrentTheme == null) { _workContext.CurrentTheme = _themeService.GetRequestTheme(filterContext.RequestContext); } + + viewResultBase.ViewEngineCollection = new ViewEngineCollection(new[] { _layoutAwareViewEngine }); + #if REFACTORING var viewResultBase = filterContext.Result as ViewResultBase; if (viewResultBase == null) { diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 33dd0dd5b..53a3d2326 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -140,6 +140,7 @@ + @@ -717,7 +718,7 @@ - +