Further incremental work establishing a per-request theme-aware engine stack

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4044110
This commit is contained in:
loudej 2009-12-15 19:50:37 +00:00
parent 341bb208b0
commit 7b777ef4f6
14 changed files with 201 additions and 20 deletions

View File

@ -91,6 +91,7 @@
<Compile Include="Themes\Permissions.cs" />
<Compile Include="Themes\Records\ThemeRecord.cs" />
<Compile Include="Themes\Records\ThemeSiteSettingsRecord.cs" />
<Compile Include="Themes\Services\SiteThemeSelector.cs" />
<Compile Include="Themes\Services\ThemeService.cs" />
<Compile Include="Themes\ViewModels\ThemesIndexViewModel.cs" />
<Compile Include="XmlRpc\Controllers\HomeController.cs" />

View File

@ -28,7 +28,7 @@ namespace Orchard.Core.Themes.Controllers {
public ActionResult Index() {
try {
var themes = _themeService.GetInstalledThemes();
var currentTheme = _themeService.GetCurrentTheme();
var currentTheme = _themeService.GetSiteTheme();
var model = new ThemesIndexViewModel { CurrentTheme = currentTheme, Themes = themes };
return View(model);
}
@ -40,9 +40,9 @@ namespace Orchard.Core.Themes.Controllers {
public ActionResult Activate(string themeName) {
try {
if (!_authorizer.Authorize(Permissions.SetCurrentTheme, T("Couldn't set the current theme")))
if (!_authorizer.Authorize(Permissions.SetSiteTheme, T("Couldn't set the current theme")))
return new HttpUnauthorizedResult();
_themeService.SetCurrentTheme(themeName);
_themeService.SetSiteTheme(themeName);
return RedirectToAction("Index");
}
catch (Exception exception) {

View File

@ -4,7 +4,7 @@ using Orchard.Security.Permissions;
namespace Orchard.Core.Themes {
public class Permissions : IPermissionProvider {
public static readonly Permission InstallUninstallTheme = new Permission { Description = "Installing or Uninstalling Themes", Name = "InstallUninstallTheme" };
public static readonly Permission SetCurrentTheme = new Permission { Description = "Setting the Current Theme", Name = "SetCurrentTheme" };
public static readonly Permission SetSiteTheme = new Permission { Description = "Setting the Current Theme", Name = "SetSiteTheme" };
public string PackageName {
get {
@ -14,7 +14,7 @@ namespace Orchard.Core.Themes {
public IEnumerable<Permission> GetPermissions() {
return new List<Permission> {
SetCurrentTheme,
SetSiteTheme,
InstallUninstallTheme
};
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using Orchard.Core.Themes.Models;
using Orchard.Models;
using Orchard.Settings;
using Orchard.Themes;
namespace Orchard.Core.Themes.Services {
public class SiteThemeSelector : IThemeSelector {
private readonly IThemeService _themeService;
public SiteThemeSelector (IThemeService themeService) {
_themeService = themeService;
}
public ThemeSelectorResult GetTheme(RequestContext context) {
var theme = _themeService.GetSiteTheme();
if (theme == null) {
return null;
}
return new ThemeSelectorResult {Priority = -5, ThemeName = theme.ThemeName};
}
}
}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using Orchard.Extensions;
using Orchard.Logging;
using Orchard.Models;
@ -11,9 +13,13 @@ using Orchard.Core.Themes.Models;
namespace Orchard.Core.Themes.Services {
public class ThemeService : IThemeService {
private readonly IExtensionManager _extensionManager;
private readonly IEnumerable<IThemeSelector> _themeSelectors;
public ThemeService(IExtensionManager extensionManager) {
public ThemeService(
IExtensionManager extensionManager,
IEnumerable<IThemeSelector> themeSelectors) {
_extensionManager = extensionManager;
_themeSelectors = themeSelectors;
Logger = NullLogger.Instance;
}
@ -22,7 +28,7 @@ namespace Orchard.Core.Themes.Services {
#region Implementation of IThemeService
public ITheme GetCurrentTheme() {
public ITheme GetSiteTheme() {
string currentThemeName = CurrentSite.As<ThemeSiteSettings>().Record.CurrentThemeName;
if (String.IsNullOrEmpty(currentThemeName)) {
@ -32,6 +38,27 @@ namespace Orchard.Core.Themes.Services {
return GetThemeByName(currentThemeName);
}
public void SetSiteTheme(string themeName) {
if (GetThemeByName(themeName) != null) {
CurrentSite.As<ThemeSiteSettings>().Record.CurrentThemeName = themeName;
}
}
public ITheme GetRequestTheme(RequestContext requestContext) {
var requestTheme = _themeSelectors
.Select(x => x.GetTheme(requestContext))
.Where(x => x != null)
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (requestTheme == null) {
return null;
}
return GetThemeByName(requestTheme.ThemeName);
}
public ITheme GetThemeByName(string name) {
foreach (var descriptor in _extensionManager.AvailableExtensions()) {
if (String.Equals(descriptor.Name, name, StringComparison.OrdinalIgnoreCase)) {
@ -66,11 +93,6 @@ namespace Orchard.Core.Themes.Services {
return themes;
}
public void SetCurrentTheme(string themeName) {
if (GetThemeByName(themeName) != null) {
CurrentSite.As<ThemeSiteSettings>().Record.CurrentThemeName = themeName;
}
}
public void InstallTheme(HttpPostedFileBase file) {
_extensionManager.InstallExtension("Theme", file);

View File

@ -1,7 +1,18 @@
namespace Orchard.Extensions {
public class ExtensionDescriptor {
/// <summary>
/// Virtual path base, "~/Themes", "~/Packages", or "~/Core"
/// </summary>
public string Location { get; set; }
/// <summary>
/// Folder name under virtual path base
/// </summary>
public string Name { get; set; }
/// <summary>
/// "Theme" or "Package"
/// </summary>
public string ExtensionType { get; set; }
// extension metadata

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc;
using Orchard.Mvc.ViewEngines;
namespace Orchard.Mvc.Html {

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Web.Mvc;
namespace Orchard.Mvc.ViewEngines {
public class CreateThemeViewEngineParams {
public string VirtualPath { get; set; }
}
public class CreatePackagesViewEngineParams {
public IEnumerable<string> VirtualPaths { get; set; }
}
public interface IViewEngineProvider : IDependency {
IViewEngine CreateThemeViewEngine(CreateThemeViewEngineParams parameters);
IViewEngine CreatePackagesViewEngine(CreatePackagesViewEngineParams parameters);
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using Orchard.Extensions;
using Orchard.Mvc.Filters;
using Orchard.Themes;
namespace Orchard.Mvc.ViewEngines {
//TEMP: abstract only because it's not functional yet
public abstract class ViewEngineFilter : FilterProvider, IResultFilter {
private readonly ViewEngineCollection _viewEngines;
private readonly IThemeService _themeService;
private readonly IExtensionManager _extensionManager;
private readonly IEnumerable<IViewEngineProvider> _viewEngineProviders;
public ViewEngineFilter(
ViewEngineCollection viewEngines,
IThemeService themeService,
IExtensionManager extensionManager,
IEnumerable<IViewEngineProvider> viewEngineProviders) {
_viewEngines = viewEngines;
_themeService = themeService;
_extensionManager = extensionManager;
_viewEngineProviders = viewEngineProviders;
}
public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewResultBase = filterContext.Result as ViewResultBase;
if (viewResultBase == null) {
return;
}
//TODO: factor out into a service apart from the filter
var requestTheme = _themeService.GetRequestTheme(filterContext.RequestContext);
var theme = _extensionManager.ActiveExtensions()
.Single(x => x.Descriptor.ExtensionType == "Theme" && x.Descriptor.Name == requestTheme.ThemeName);
var themeLocation = Path.Combine(theme.Descriptor.Location, theme.Descriptor.Name);
var themeViewEngines = _viewEngineProviders
.Select(x => x.CreateThemeViewEngine(new CreateThemeViewEngineParams{VirtualPath = themeLocation}));
var packages = _extensionManager.ActiveExtensions()
.Where(x => x.Descriptor.ExtensionType == "Package");
var packageLocations = packages.Select(x => Path.Combine(x.Descriptor.Location, x.Descriptor.Name));
var packageViewEngines = _viewEngineProviders
.Select(x => x.CreatePackagesViewEngine(new CreatePackagesViewEngineParams {VirtualPaths = packageLocations}));
viewResultBase.ViewEngineCollection = new ViewEngineCollection(
themeViewEngines
.Concat(packageViewEngines)
.Concat(_viewEngines)
.ToList());
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace Orchard.Mvc.ViewEngines {
public class WebFormsViewEngineProvider : IViewEngineProvider {
public IViewEngine CreateThemeViewEngine(CreateThemeViewEngineParams parameters) {
//var viewEngine = new WebFormViewEngine();
//viewEngine.PartialViewLocationFormats
return null;
}
public IViewEngine CreatePackagesViewEngine(CreatePackagesViewEngineParams parameters) {
return null;
}
}
}

View File

@ -214,9 +214,12 @@
<Compile Include="Mvc\Results\NotFoundResult.cs" />
<Compile Include="Mvc\OrchardControllerIdentificationStrategy.cs" />
<Compile Include="Mvc\Routes\RouteExtensions.cs" />
<Compile Include="Mvc\ViewEngines\IViewEngineProvider.cs" />
<Compile Include="Mvc\ViewEngines\LayoutView.cs" />
<Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" />
<Compile Include="Mvc\ViewEngines\OrchardLayoutContext.cs" />
<Compile Include="Mvc\ViewEngines\ViewEngineFilter.cs" />
<Compile Include="Mvc\ViewEngines\WebFormsViewEngineProvider.cs" />
<Compile Include="Mvc\ViewModels\AdminViewModel.cs" />
<Compile Include="Mvc\ViewModels\BaseViewModel.cs" />
<Compile Include="Mvc\ViewPage.cs">
@ -234,6 +237,7 @@
<Compile Include="Tasks\IBackgroundTask.cs" />
<Compile Include="Tasks\SweepGenerator.cs" />
<Compile Include="Themes\ITheme.cs" />
<Compile Include="Themes\IThemeSelector.cs" />
<Compile Include="Themes\IThemeService.cs" />
<Compile Include="Themes\ThemesModule.cs" />
<Compile Include="UI\Menus\AdminMenuFilter.cs" />

View File

@ -0,0 +1,13 @@
using System.Web.Routing;
namespace Orchard.Themes {
public class ThemeSelectorResult {
public int Priority { get; set; }
public string ThemeName { get; set; }
}
public interface IThemeSelector : IDependency {
ThemeSelectorResult GetTheme(RequestContext context);
}
}

View File

@ -1,12 +1,16 @@
using System.Collections.Generic;
using System.Web;
using System.Web.Routing;
namespace Orchard.Themes {
public interface IThemeService : IDependency {
ITheme GetCurrentTheme();
ITheme GetThemeByName(string themeName);
ITheme GetSiteTheme();
void SetSiteTheme(string themeName);
ITheme GetRequestTheme(RequestContext requestContext);
IEnumerable<ITheme> GetInstalledThemes();
void SetCurrentTheme(string themeName);
void InstallTheme(HttpPostedFileBase file);
void UninstallTheme(string themeName);
}

View File

@ -11,7 +11,7 @@ namespace Orchard.Themes {
if (themeProperty != null) {
registration.Activated += (sender, e) => {
var themeService = e.Context.Resolve<IThemeService>();
var currentTheme = themeService.GetCurrentTheme();
var currentTheme = themeService.GetSiteTheme();
themeProperty.SetValue(e.Instance, currentTheme, null);
};
}