mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 19:04:51 +08:00
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
This commit is contained in:
@@ -43,7 +43,7 @@ namespace Orchard.Setup {
|
||||
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<CurrentThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<ThemedViewResultFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<PageClassBuilder>().As<IPageClassBuilder>().InstancePerLifetimeScope();
|
||||
@@ -70,6 +70,7 @@ namespace Orchard.Setup {
|
||||
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
|
||||
|
||||
builder.RegisterType<ThemeAwareViewEngine>().As<IThemeAwareViewEngine>();
|
||||
builder.RegisterType<LayoutAwareViewEngine>().As<ILayoutAwareViewEngine>();
|
||||
builder.RegisterType<ConfiguredEnginesCache>().As<IConfiguredEnginesCache>();
|
||||
|
||||
}
|
||||
|
@@ -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>(BaseViewModel.From(dictionary));
|
||||
#else
|
||||
return dictionary;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ReleaseViews(ControllerContext context) {
|
||||
foreach (var viewEngineResult in _viewEngineResults) {
|
||||
viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<string>())
|
||||
.Concat((layoutView.SearchedLocations ?? Enumerable.Empty<string>()))
|
||||
.Concat((documentView.SearchedLocations ?? Enumerable.Empty<string>()))
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
@@ -140,6 +140,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ConfiguredEnginesCache.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\LayoutAwareViewEngine.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngine.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngineShim.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ViewEngineCollectionWrapper.cs" />
|
||||
@@ -717,7 +718,7 @@
|
||||
<Compile Include="Mvc\ViewEngines\LayoutView.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\CurrentTheme.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemedViewResultFilter.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineProvider.cs" />
|
||||
<Compile Include="UI\Admin\AdminThemeSelector.cs" />
|
||||
<Compile Include="UI\Navigation\INavigationManager.cs" />
|
||||
|
Reference in New Issue
Block a user