mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 10:54:50 +08:00
Themes admin allows you to enable/disable themes separately from setting them to the default. DataMigrations for themes are done there too.
--HG-- branch : dev
This commit is contained in:
@@ -68,7 +68,7 @@ namespace Orchard.Tests.Modules.Themes.Services {
|
|||||||
var context = new DynamicProxyContext();
|
var context = new DynamicProxyContext();
|
||||||
var builder = new ContainerBuilder();
|
var builder = new ContainerBuilder();
|
||||||
builder.RegisterModule(new SettingsModule());
|
builder.RegisterModule(new SettingsModule());
|
||||||
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>(); // test
|
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||||
builder.RegisterType<ThemeService>().EnableDynamicProxy(context).As<IThemeService>();
|
builder.RegisterType<ThemeService>().EnableDynamicProxy(context).As<IThemeService>();
|
||||||
builder.RegisterType<SettingsModuleInterceptor>().As<ISettingsModuleInterceptor>();
|
builder.RegisterType<SettingsModuleInterceptor>().As<ISettingsModuleInterceptor>();
|
||||||
builder.RegisterType<SiteService>().As<ISiteService>();
|
builder.RegisterType<SiteService>().As<ISiteService>();
|
||||||
@@ -86,7 +86,7 @@ namespace Orchard.Tests.Modules.Themes.Services {
|
|||||||
builder.RegisterType<ThemeSiteSettingsPartHandler>().As<IContentHandler>();
|
builder.RegisterType<ThemeSiteSettingsPartHandler>().As<IContentHandler>();
|
||||||
builder.RegisterType<ModuleService>().As<IModuleService>();
|
builder.RegisterType<ModuleService>().As<IModuleService>();
|
||||||
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
||||||
builder.RegisterType<StubShellDescriptorManager>().As<IShellDescriptorManager>();
|
builder.RegisterType<StubShellDescriptorManager>().As<IShellDescriptorManager>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<TransactionManager>().As<ITransactionManager>();
|
builder.RegisterType<TransactionManager>().As<ITransactionManager>();
|
||||||
builder.RegisterType<Notifier>().As<INotifier>();
|
builder.RegisterType<Notifier>().As<INotifier>();
|
||||||
builder.RegisterType<StubAuthorizer>().As<IAuthorizer>();
|
builder.RegisterType<StubAuthorizer>().As<IAuthorizer>();
|
||||||
@@ -136,6 +136,34 @@ namespace Orchard.Tests.Modules.Themes.Services {
|
|||||||
Assert.That(siteTheme.ThemeName, Is.EqualTo("ThemeOne"));
|
Assert.That(siteTheme.ThemeName, Is.EqualTo("ThemeOne"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CanEnableAndDisableThemes() {
|
||||||
|
_themeService.EnableTheme("ThemeOne");
|
||||||
|
Assert.IsTrue(_themeService.GetThemeByName("ThemeOne").Enabled);
|
||||||
|
Assert.IsTrue(_container.Resolve<IShellDescriptorManager>().GetShellDescriptor().Features.Any(sf => sf.Name == "ThemeOne"));
|
||||||
|
_themeService.DisableTheme("ThemeOne");
|
||||||
|
Assert.IsFalse(_themeService.GetThemeByName("ThemeOne").Enabled);
|
||||||
|
Assert.IsFalse(_container.Resolve<IShellDescriptorManager>().GetShellDescriptor().Features.Any(sf => sf.Name == "ThemeOne"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActivatingThemeEnablesIt() {
|
||||||
|
_themeService.SetSiteTheme("ThemeOne");
|
||||||
|
Assert.IsTrue(_themeService.GetThemeByName("ThemeOne").Enabled);
|
||||||
|
Assert.IsTrue(_container.Resolve<IShellDescriptorManager>().GetShellDescriptor().Features.Any(sf => sf.Name == "ThemeOne"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActivatingThemeDoesNotDisableOldTheme() {
|
||||||
|
_themeService.SetSiteTheme("ThemeOne");
|
||||||
|
_themeService.SetSiteTheme("ThemeTwo");
|
||||||
|
Assert.IsTrue(_themeService.GetThemeByName("ThemeOne").Enabled);
|
||||||
|
Assert.IsTrue(_themeService.GetThemeByName("ThemeTwo").Enabled);
|
||||||
|
Assert.IsTrue(_container.Resolve<IShellDescriptorManager>().GetShellDescriptor().Features.Any(sf => sf.Name == "ThemeOne"));
|
||||||
|
Assert.IsTrue(_container.Resolve<IShellDescriptorManager>().GetShellDescriptor().Features.Any(sf => sf.Name == "ThemeTwo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#region Stubs
|
#region Stubs
|
||||||
|
|
||||||
public class TestSessionLocator : ISessionLocator {
|
public class TestSessionLocator : ISessionLocator {
|
||||||
|
@@ -46,6 +46,7 @@ namespace Orchard.Tests.DisplayManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Theme : ITheme {
|
public class Theme : ITheme {
|
||||||
|
public bool Enabled { get; set; }
|
||||||
public string ThemeName { get; set; }
|
public string ThemeName { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Orchard.Commands;
|
using Orchard.Commands;
|
||||||
using Orchard.Commands.Builtin;
|
using Orchard.Commands.Builtin;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
@@ -91,6 +92,7 @@ namespace Orchard.Setup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
class SafeModeText : IText {
|
class SafeModeText : IText {
|
||||||
public LocalizedString Get(string textHint, params object[] args) {
|
public LocalizedString Get(string textHint, params object[] args) {
|
||||||
if (args == null || args.Length == 0) {
|
if (args == null || args.Length == 0) {
|
||||||
@@ -100,9 +102,11 @@ namespace Orchard.Setup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
class SafeModeThemeService : IThemeService {
|
class SafeModeThemeService : IThemeService {
|
||||||
class SafeModeTheme : ITheme {
|
class SafeModeTheme : ITheme {
|
||||||
public ContentItem ContentItem { get; set; }
|
public ContentItem ContentItem { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
public string ThemeName { get; set; }
|
public string ThemeName { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
@@ -115,6 +119,7 @@ namespace Orchard.Setup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly SafeModeTheme _theme = new SafeModeTheme {
|
private readonly SafeModeTheme _theme = new SafeModeTheme {
|
||||||
|
Enabled = true,
|
||||||
ThemeName = "SafeMode",
|
ThemeName = "SafeMode",
|
||||||
DisplayName = "SafeMode",
|
DisplayName = "SafeMode",
|
||||||
};
|
};
|
||||||
@@ -126,8 +131,11 @@ namespace Orchard.Setup {
|
|||||||
public IEnumerable<ITheme> GetInstalledThemes() { return new[] { _theme }; }
|
public IEnumerable<ITheme> GetInstalledThemes() { return new[] { _theme }; }
|
||||||
public void InstallTheme(HttpPostedFileBase file) { }
|
public void InstallTheme(HttpPostedFileBase file) { }
|
||||||
public void UninstallTheme(string themeName) { }
|
public void UninstallTheme(string themeName) { }
|
||||||
|
public void EnableTheme(string themeName) { }
|
||||||
|
public void DisableTheme(string themeName) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
class SafeModeSiteWorkContextProvider : IWorkContextStateProvider {
|
class SafeModeSiteWorkContextProvider : IWorkContextStateProvider {
|
||||||
public T Get<T>(string name) {
|
public T Get<T>(string name) {
|
||||||
if (name == "CurrentSite")
|
if (name == "CurrentSite")
|
||||||
@@ -136,6 +144,7 @@ namespace Orchard.Setup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
class SafeModeSiteService : ISiteService {
|
class SafeModeSiteService : ISiteService {
|
||||||
public ISite GetSiteSettings() {
|
public ISite GetSiteSettings() {
|
||||||
var siteType = new ContentTypeDefinitionBuilder().Named("Site").Build();
|
var siteType = new ContentTypeDefinitionBuilder().Named("Site").Build();
|
||||||
|
@@ -2,8 +2,11 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using Orchard.Data.Migration;
|
||||||
using Orchard.DisplayManagement;
|
using Orchard.DisplayManagement;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
|
using Orchard.Mvc.Results;
|
||||||
|
using Orchard.Reports.Services;
|
||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
using Orchard.Themes.Preview;
|
using Orchard.Themes.Preview;
|
||||||
using Orchard.Themes.ViewModels;
|
using Orchard.Themes.ViewModels;
|
||||||
@@ -14,8 +17,12 @@ namespace Orchard.Themes.Controllers {
|
|||||||
public class AdminController : Controller {
|
public class AdminController : Controller {
|
||||||
private readonly IThemeService _themeService;
|
private readonly IThemeService _themeService;
|
||||||
private readonly IPreviewTheme _previewTheme;
|
private readonly IPreviewTheme _previewTheme;
|
||||||
|
private readonly IDataMigrationManager _dataMigrationManager;
|
||||||
|
private readonly IReportsCoordinator _reportsCoordinator;
|
||||||
|
|
||||||
public AdminController(
|
public AdminController(
|
||||||
|
IDataMigrationManager dataMigraitonManager,
|
||||||
|
IReportsCoordinator reportsCoordinator,
|
||||||
IOrchardServices services,
|
IOrchardServices services,
|
||||||
IThemeService themeService,
|
IThemeService themeService,
|
||||||
IPreviewTheme previewTheme,
|
IPreviewTheme previewTheme,
|
||||||
@@ -23,6 +30,8 @@ namespace Orchard.Themes.Controllers {
|
|||||||
INotifier notifier,
|
INotifier notifier,
|
||||||
IShapeHelperFactory shapeHelperFactory) {
|
IShapeHelperFactory shapeHelperFactory) {
|
||||||
Services = services;
|
Services = services;
|
||||||
|
_dataMigrationManager = dataMigraitonManager;
|
||||||
|
_reportsCoordinator = reportsCoordinator;
|
||||||
_themeService = themeService;
|
_themeService = themeService;
|
||||||
_previewTheme = previewTheme;
|
_previewTheme = previewTheme;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
@@ -36,7 +45,8 @@ namespace Orchard.Themes.Controllers {
|
|||||||
try {
|
try {
|
||||||
var themes = _themeService.GetInstalledThemes();
|
var themes = _themeService.GetInstalledThemes();
|
||||||
var currentTheme = _themeService.GetSiteTheme();
|
var currentTheme = _themeService.GetSiteTheme();
|
||||||
var model = new ThemesIndexViewModel { CurrentTheme = currentTheme, Themes = themes };
|
var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate();
|
||||||
|
var model = new ThemesIndexViewModel { CurrentTheme = currentTheme, Themes = themes, FeaturesThatNeedUpdate = featuresThatNeedUpdate };
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
@@ -66,12 +76,11 @@ namespace Orchard.Themes.Controllers {
|
|||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
_previewTheme.SetPreviewTheme(null);
|
_previewTheme.SetPreviewTheme(null);
|
||||||
_themeService.SetSiteTheme(themeName);
|
_themeService.SetSiteTheme(themeName);
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
Services.Notifier.Error(T("Previewing theme failed: " + exception.Message));
|
Services.Notifier.Error(T("Previewing theme failed: " + exception.Message));
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("Preview"), FormValueRequired("submit.Cancel")]
|
[HttpPost, ActionName("Preview"), FormValueRequired("submit.Cancel")]
|
||||||
@@ -80,12 +89,37 @@ namespace Orchard.Themes.Controllers {
|
|||||||
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't preview the current theme")))
|
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't preview the current theme")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
_previewTheme.SetPreviewTheme(null);
|
_previewTheme.SetPreviewTheme(null);
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
Services.Notifier.Error(T("Previewing theme failed: " + exception.Message));
|
Services.Notifier.Error(T("Previewing theme failed: " + exception.Message));
|
||||||
|
}
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult Enable(string themeName) {
|
||||||
|
try {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't enable the theme")))
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
_themeService.EnableTheme(themeName);
|
||||||
|
}
|
||||||
|
catch (Exception exception) {
|
||||||
|
Services.Notifier.Error(T("Enabling theme failed: " + exception.Message));
|
||||||
|
}
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult Disable(string themeName) {
|
||||||
|
try {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't disable the current theme")))
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
_themeService.DisableTheme(themeName);
|
||||||
|
}
|
||||||
|
catch (Exception exception) {
|
||||||
|
Services.Notifier.Error(T("Disabling theme failed: " + exception.Message));
|
||||||
|
}
|
||||||
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@@ -94,12 +128,11 @@ namespace Orchard.Themes.Controllers {
|
|||||||
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't set the current theme")))
|
if (!Services.Authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't set the current theme")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
_themeService.SetSiteTheme(themeName);
|
_themeService.SetSiteTheme(themeName);
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
Services.Notifier.Error(T("Activating theme failed: " + exception.Message));
|
Services.Notifier.Error(T("Activating theme failed: " + exception.Message));
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Install() {
|
public ActionResult Install() {
|
||||||
@@ -137,6 +170,26 @@ namespace Orchard.Themes.Controllers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult Update(string themeName) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.ManageThemes, T("Couldn't update theme")))
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(themeName))
|
||||||
|
return new NotFoundResult();
|
||||||
|
|
||||||
|
try {
|
||||||
|
_reportsCoordinator.Register("Data Migration", "Upgrade " + themeName, "Orchard installation");
|
||||||
|
_dataMigrationManager.Update(themeName);
|
||||||
|
Services.Notifier.Information(T("The theme {0} was updated succesfuly", themeName));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Services.Notifier.Error(T("An error occured while updating the theme {0}: {1}", themeName, ex.Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
|
||||||
class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
|
class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
|
||||||
private readonly string _submitButtonName;
|
private readonly string _submitButtonName;
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
namespace Orchard.Themes.Models {
|
namespace Orchard.Themes.Models {
|
||||||
public class Theme : ITheme {
|
public class Theme : ITheme {
|
||||||
|
public bool Enabled { get; set; }
|
||||||
public string ThemeName { get; set; }
|
public string ThemeName { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Orchard.Environment.Descriptor;
|
||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
@@ -19,13 +20,16 @@ namespace Orchard.Themes.Services {
|
|||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
private readonly IEnumerable<IThemeSelector> _themeSelectors;
|
private readonly IEnumerable<IThemeSelector> _themeSelectors;
|
||||||
private readonly IModuleService _moduleService;
|
private readonly IModuleService _moduleService;
|
||||||
private IWorkContextAccessor _workContextAccessor;
|
private readonly IWorkContextAccessor _workContextAccessor;
|
||||||
|
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||||
|
|
||||||
public ThemeService(
|
public ThemeService(
|
||||||
|
IShellDescriptorManager shellDescriptorManager,
|
||||||
IExtensionManager extensionManager,
|
IExtensionManager extensionManager,
|
||||||
IEnumerable<IThemeSelector> themeSelectors,
|
IEnumerable<IThemeSelector> themeSelectors,
|
||||||
IModuleService moduleService,
|
IModuleService moduleService,
|
||||||
IWorkContextAccessor workContextAccessor) {
|
IWorkContextAccessor workContextAccessor) {
|
||||||
|
_shellDescriptorManager = shellDescriptorManager;
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
_themeSelectors = themeSelectors;
|
_themeSelectors = themeSelectors;
|
||||||
_moduleService = moduleService;
|
_moduleService = moduleService;
|
||||||
@@ -49,26 +53,17 @@ namespace Orchard.Themes.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void SetSiteTheme(string themeName) {
|
public void SetSiteTheme(string themeName) {
|
||||||
if (string.IsNullOrWhiteSpace(themeName))
|
if (DoEnableTheme(themeName)) {
|
||||||
return;
|
CurrentSite.As<ThemeSiteSettingsPart>().Record.CurrentThemeName = themeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//todo: (heskew) need messages given in addition to all of these early returns so something meaningful can be presented to the user
|
public void EnableTheme(string themeName) {
|
||||||
var themeToSet = GetThemeByName(themeName);
|
DoEnableTheme(themeName);
|
||||||
if (themeToSet == null)
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
// ensure all base themes down the line are present and accounted for
|
public void DisableTheme(string themeName) {
|
||||||
//todo: (heskew) dito on the need of a meaningful message
|
DisableThemeFeatures(themeName);
|
||||||
if (!AllBaseThemesAreInstalled(themeToSet.BaseTheme))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// disable all theme features
|
|
||||||
DisableThemeFeatures(CurrentSite.As<ThemeSiteSettingsPart>().CurrentThemeName);
|
|
||||||
|
|
||||||
// enable all theme features
|
|
||||||
EnableThemeFeatures(themeToSet.ThemeName);
|
|
||||||
|
|
||||||
CurrentSite.As<ThemeSiteSettingsPart>().Record.CurrentThemeName = themeToSet.ThemeName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool AllBaseThemesAreInstalled(string baseThemeName) {
|
private bool AllBaseThemesAreInstalled(string baseThemeName) {
|
||||||
@@ -93,12 +88,15 @@ namespace Orchard.Themes.Services {
|
|||||||
while (themeName != null) {
|
while (themeName != null) {
|
||||||
if (themes.Contains(themeName))
|
if (themes.Contains(themeName))
|
||||||
throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features disabled.", themeName).Text);
|
throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features disabled.", themeName).Text);
|
||||||
|
var theme = GetThemeByName(themeName);
|
||||||
|
if (theme == null)
|
||||||
|
break;
|
||||||
themes.Enqueue(themeName);
|
themes.Enqueue(themeName);
|
||||||
|
|
||||||
var theme = GetThemeByName(themeName);
|
|
||||||
themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
|
themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
|
||||||
? theme.BaseTheme
|
? theme.BaseTheme
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (themes.Count > 0)
|
while (themes.Count > 0)
|
||||||
@@ -122,6 +120,25 @@ namespace Orchard.Themes.Services {
|
|||||||
_moduleService.EnableFeatures(new[] {themes.Pop()});
|
_moduleService.EnableFeatures(new[] {themes.Pop()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool DoEnableTheme(string themeName) {
|
||||||
|
if (string.IsNullOrWhiteSpace(themeName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//todo: (heskew) need messages given in addition to all of these early returns so something meaningful can be presented to the user
|
||||||
|
var themeToEnable = GetThemeByName(themeName);
|
||||||
|
if (themeToEnable == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// ensure all base themes down the line are present and accounted for
|
||||||
|
//todo: (heskew) dito on the need of a meaningful message
|
||||||
|
if (!AllBaseThemesAreInstalled(themeToEnable.BaseTheme))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// enable all theme features
|
||||||
|
EnableThemeFeatures(themeToEnable.ThemeName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public ITheme GetRequestTheme(RequestContext requestContext) {
|
public ITheme GetRequestTheme(RequestContext requestContext) {
|
||||||
var requestTheme = _themeSelectors
|
var requestTheme = _themeSelectors
|
||||||
.Select(x => x.GetTheme(requestContext))
|
.Select(x => x.GetTheme(requestContext))
|
||||||
@@ -188,6 +205,10 @@ namespace Orchard.Themes.Services {
|
|||||||
return localized;
|
return localized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsThemeEnabled(ExtensionDescriptor descriptor) {
|
||||||
|
return _shellDescriptorManager.GetShellDescriptor().Features.Any(sf => sf.Name == descriptor.Name);
|
||||||
|
}
|
||||||
|
|
||||||
private ITheme CreateTheme(ExtensionDescriptor descriptor) {
|
private ITheme CreateTheme(ExtensionDescriptor descriptor) {
|
||||||
|
|
||||||
var localizer = LocalizationUtilities.Resolve(_workContextAccessor.GetContext(), String.Concat(descriptor.Location, "/", descriptor.Name, "/Theme.txt"));
|
var localizer = LocalizationUtilities.Resolve(_workContextAccessor.GetContext(), String.Concat(descriptor.Location, "/", descriptor.Name, "/Theme.txt"));
|
||||||
@@ -202,6 +223,7 @@ namespace Orchard.Themes.Services {
|
|||||||
Tags = TryLocalize("Tags", descriptor.Tags, localizer) ?? "",
|
Tags = TryLocalize("Tags", descriptor.Tags, localizer) ?? "",
|
||||||
Zones = descriptor.Zones ?? "",
|
Zones = descriptor.Zones ?? "",
|
||||||
BaseTheme = descriptor.BaseTheme ?? "",
|
BaseTheme = descriptor.BaseTheme ?? "",
|
||||||
|
Enabled = IsThemeEnabled(descriptor)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,5 +4,6 @@ namespace Orchard.Themes.ViewModels {
|
|||||||
public class ThemesIndexViewModel {
|
public class ThemesIndexViewModel {
|
||||||
public ITheme CurrentTheme { get; set; }
|
public ITheme CurrentTheme { get; set; }
|
||||||
public IEnumerable<ITheme> Themes { get; set; }
|
public IEnumerable<ITheme> Themes { get; set; }
|
||||||
|
public IEnumerable<string> FeaturesThatNeedUpdate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -29,9 +29,13 @@
|
|||||||
<div>
|
<div>
|
||||||
<h3>@theme.DisplayName</h3>
|
<h3>@theme.DisplayName</h3>
|
||||||
@Html.Image(Href(Html.ThemePath(theme, "/Theme.png")), Html.Encode(theme.DisplayName), null)
|
@Html.Image(Href(Html.ThemePath(theme, "/Theme.png")), Html.Encode(theme.DisplayName), null)
|
||||||
|
@using (Html.BeginFormAntiForgeryPost(Url.Action(theme.Enabled ? "Disable" : "Enable"), FormMethod.Post, new { @class = "inline" })) {
|
||||||
|
@Html.Hidden("themeName", theme.ThemeName)
|
||||||
|
<button type="submit" title="@T(theme.Enabled ? "Disable" : "Enable")">@T(theme.Enabled ? "Disable" : "Enable")</button>
|
||||||
|
}
|
||||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) {
|
@using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) {
|
||||||
@Html.Hidden("themeName", theme.ThemeName)
|
@Html.Hidden("themeName", theme.ThemeName)
|
||||||
<button type="submit" title="@T("Activate")">@T("Activate")</button>
|
<button type="submit" title="@T("Activate")">@T("Set Current")</button>
|
||||||
}
|
}
|
||||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) {
|
@using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) {
|
||||||
@Html.Hidden("themeName", theme.ThemeName)
|
@Html.Hidden("themeName", theme.ThemeName)
|
||||||
@@ -43,6 +47,12 @@
|
|||||||
@theme.Description<br />
|
@theme.Description<br />
|
||||||
@theme.HomePage
|
@theme.HomePage
|
||||||
</p>
|
</p>
|
||||||
|
@if(Model.FeaturesThatNeedUpdate.Contains(theme.ThemeName)){
|
||||||
|
using (Html.BeginFormAntiForgeryPost(Url.Action("Update"), FormMethod.Post, new { @class = "inline link" })) {
|
||||||
|
@Html.Hidden("themeName", theme.ThemeName)
|
||||||
|
<button type="submit" class="update">@T("Update")</button> <br/>
|
||||||
|
}
|
||||||
|
}
|
||||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline link" })) {
|
@using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline link" })) {
|
||||||
@Html.Hidden("themeName", theme.ThemeName)
|
@Html.Hidden("themeName", theme.ThemeName)
|
||||||
<button type="submit" class="uninstall" title="@T("Uninstall")">@T("Uninstall")</button>
|
<button type="submit" class="uninstall" title="@T("Uninstall")">@T("Uninstall")</button>
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
/// Interface provided by the "themes" model.
|
/// Interface provided by the "themes" model.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITheme {
|
public interface ITheme {
|
||||||
|
bool Enabled { get; set; }
|
||||||
string ThemeName { get; set; }
|
string ThemeName { get; set; }
|
||||||
string DisplayName { get; set; }
|
string DisplayName { get; set; }
|
||||||
string Description { get; set; }
|
string Description { get; set; }
|
||||||
|
@@ -10,6 +10,9 @@ namespace Orchard.Themes {
|
|||||||
void SetSiteTheme(string themeName);
|
void SetSiteTheme(string themeName);
|
||||||
ITheme GetRequestTheme(RequestContext requestContext);
|
ITheme GetRequestTheme(RequestContext requestContext);
|
||||||
|
|
||||||
|
void EnableTheme(string themeName);
|
||||||
|
void DisableTheme(string themeName);
|
||||||
|
|
||||||
IEnumerable<ITheme> GetInstalledThemes();
|
IEnumerable<ITheme> GetInstalledThemes();
|
||||||
void InstallTheme(HttpPostedFileBase file);
|
void InstallTheme(HttpPostedFileBase file);
|
||||||
void UninstallTheme(string themeName);
|
void UninstallTheme(string themeName);
|
||||||
|
Reference in New Issue
Block a user