mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 03:25:23 +08:00
Fix computed set of views paths to allow themes in the admin
When looking for ViewPath to activate, the order should be: 1. Current active theme 2. Base themes of the current theme (in "base" order). Note that "base themes" for "TheAdmin" theme means all enabled themes 3. Modules which have at least one active feature, in feature dependency order Work Item: 16654 --HG-- branch : dev
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Web.Mvc;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
||||
public interface IThemeAwareViewEngine : IDependency {
|
||||
@@ -31,8 +32,12 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
||||
_configuredEnginesCache = configuredEnginesCache;
|
||||
_extensionManager = extensionManager;
|
||||
_shellDescriptor = shellDescriptor;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths) {
|
||||
var engines = _nullEngines;
|
||||
|
||||
@@ -71,21 +76,78 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
||||
|
||||
private IViewEngine DeepEngines(ExtensionDescriptor theme) {
|
||||
return _configuredEnginesCache.BindDeepEngines(theme.Id, () => {
|
||||
// The order for searching for views is:
|
||||
// 1. Current "theme"
|
||||
// 2. Base themes of the current theme (in "base" order)
|
||||
// 3. Active features from modules in dependency order
|
||||
|
||||
var engines = Enumerable.Empty<IViewEngine>();
|
||||
var themeLocation = theme.Location + "/" + theme.Id;
|
||||
|
||||
// 1. current theme
|
||||
var themeParams = new CreateThemeViewEngineParams { VirtualPath = themeLocation };
|
||||
engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateThemeViewEngine(themeParams)));
|
||||
|
||||
var activeFeatures = _extensionManager.AvailableFeatures().Where(fd => _shellDescriptor.Features.Any(sdf => sdf.Name == fd.Id));
|
||||
var activeModuleLocations = activeFeatures.Select(fd => fd.Extension.Location + "/" + fd.Extension.Id).Distinct();
|
||||
var moduleParams = new CreateModulesViewEngineParams { VirtualPaths = activeModuleLocations };
|
||||
// 2. Base themes of the current theme (in "base" order)
|
||||
var baseThemes = GetBaseThemes(theme);
|
||||
|
||||
// 3. Active features from modules in dependency order
|
||||
var enabledModules = _extensionManager.EnabledFeatures(_shellDescriptor)
|
||||
.Reverse() // reverse from (C <= B <= A) to (A => B => C)
|
||||
.Where(fd => !DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType)/*core + modules*/);
|
||||
|
||||
var allLocations = baseThemes.Concat(enabledModules)
|
||||
.Select(fd => fd.Extension.Location + "/" + fd.Extension.Id)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
var moduleParams = new CreateModulesViewEngineParams { VirtualPaths = allLocations };
|
||||
engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateModulesViewEngine(moduleParams)));
|
||||
|
||||
return new ViewEngineCollectionWrapper(engines);
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<FeatureDescriptor> GetBaseThemes(ExtensionDescriptor themeExtension) {
|
||||
if (themeExtension.Id.Equals("TheAdmin", StringComparison.OrdinalIgnoreCase)) {
|
||||
// Special case: conceptually, the base themes of "TheAdmin" is the list of all
|
||||
// enabled themes. This is so that any enabled theme can have controller/action/views
|
||||
// in the Admin of the site.
|
||||
return _extensionManager
|
||||
.EnabledFeatures(_shellDescriptor)
|
||||
.Reverse() // reverse from (C <= B <= A) to (A => B => C)
|
||||
.Where(fd => DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType));
|
||||
}
|
||||
else {
|
||||
var availableFeatures = _extensionManager.AvailableFeatures();
|
||||
var list = new List<FeatureDescriptor>();
|
||||
while(true) {
|
||||
if (themeExtension == null)
|
||||
break;
|
||||
|
||||
if (String.IsNullOrEmpty(themeExtension.BaseTheme))
|
||||
break;
|
||||
|
||||
var baseFeature = availableFeatures.FirstOrDefault(fd => fd.Id == themeExtension.BaseTheme);
|
||||
if (baseFeature == null) {
|
||||
Logger.Error("Base theme '{0}' of theme '{1}' not found in list of features", themeExtension.BaseTheme, themeExtension.Id);
|
||||
break;
|
||||
}
|
||||
|
||||
// Protect against potential infinite loop
|
||||
if (list.Contains(baseFeature)) {
|
||||
Logger.Error("Base theme '{0}' of theme '{1}' ignored, as it seems there is recursion in base themes", themeExtension.BaseTheme, themeExtension.Id);
|
||||
break;
|
||||
}
|
||||
|
||||
list.Add(baseFeature);
|
||||
|
||||
themeExtension = baseFeature.Extension;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseView(ControllerContext controllerContext, IView view) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
Reference in New Issue
Block a user