mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge
--HG-- branch : dev
This commit is contained in:
@@ -21,9 +21,9 @@ namespace Orchard.Specs.Bindings {
|
|||||||
webApp.GivenIHaveACleanSiteWith(
|
webApp.GivenIHaveACleanSiteWith(
|
||||||
virtualDirectory,
|
virtualDirectory,
|
||||||
TableData(
|
TableData(
|
||||||
new { extension = DefaultExtensionTypes.Module, names = "Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce" },
|
new { extension = "Module", names = "Orchard.Setup, Orchard.Pages, Orchard.Blogs, Orchard.Messaging, Orchard.Modules, Orchard.Packaging, Orchard.PublishLater, Orchard.Themes, Orchard.Scripting, Orchard.Widgets, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.jQuery, Orchard.Tags, TinyMce" },
|
||||||
new { extension = DefaultExtensionTypes.Core, names = "Common, Dashboard, Feeds, HomePage, Navigation, Contents, Routable, Scheduling, Settings, Shapes, XmlRpc" },
|
new { extension = "Core", names = "Common, Dashboard, Feeds, HomePage, Navigation, Contents, Routable, Scheduling, Settings, Shapes, XmlRpc" },
|
||||||
new { extension = DefaultExtensionTypes.Theme, names = "SafeMode, TheAdmin, TheThemeMachine" }));
|
new { extension = "Theme", names = "SafeMode, TheAdmin, TheThemeMachine" }));
|
||||||
|
|
||||||
webApp.WhenIGoTo("Setup");
|
webApp.WhenIGoTo("Setup");
|
||||||
|
|
||||||
|
@@ -140,13 +140,13 @@ namespace Orchard.Specs.Bindings {
|
|||||||
foreach (var row in table.Rows) {
|
foreach (var row in table.Rows) {
|
||||||
foreach (var name in row["names"].Split(',').Select(x => x.Trim())) {
|
foreach (var name in row["names"].Split(',').Select(x => x.Trim())) {
|
||||||
switch (row["extension"]) {
|
switch (row["extension"]) {
|
||||||
case DefaultExtensionTypes.Core:
|
case "Core":
|
||||||
GivenIHaveCore(name);
|
GivenIHaveCore(name);
|
||||||
break;
|
break;
|
||||||
case DefaultExtensionTypes.Module:
|
case "Module":
|
||||||
GivenIHaveModule(name);
|
GivenIHaveModule(name);
|
||||||
break;
|
break;
|
||||||
case DefaultExtensionTypes.Theme:
|
case "Theme":
|
||||||
GivenIHaveTheme(name);
|
GivenIHaveTheme(name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//temporarily "disable" actions on core features
|
//temporarily "disable" actions on core features
|
||||||
var showActions = categoryName.ToString() != "Core";
|
bool showActions;
|
||||||
<li class="@categoryClassName">
|
<li class="@categoryClassName">
|
||||||
<h2>@categoryName</h2>
|
<h2>@categoryName</h2>
|
||||||
<ul>@{
|
<ul>@{
|
||||||
@@ -46,9 +46,7 @@
|
|||||||
select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
||||||
var missingDependencies = feature.Descriptor.Dependencies
|
var missingDependencies = feature.Descriptor.Dependencies
|
||||||
.Where(d => !Model.Features.Any(f => f.Descriptor.Id == d));
|
.Where(d => !Model.Features.Any(f => f.Descriptor.Id == d));
|
||||||
if (showActions) {
|
showActions = categoryName.ToString() != "Core" && missingDependencies.Count() == 0;
|
||||||
showActions = missingDependencies.Count() == 0;
|
|
||||||
}
|
|
||||||
<li class="@featureClassName" id="@featureId" title="@T("{0} is {1}", Html.AttributeEncode(featureName), featureState)">
|
<li class="@featureClassName" id="@featureId" title="@T("{0} is {1}", Html.AttributeEncode(featureName), featureState)">
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<div class="properties">
|
<div class="properties">
|
||||||
|
@@ -143,7 +143,8 @@
|
|||||||
<probing privatePath="App_Data/Dependencies"/>
|
<probing privatePath="App_Data/Dependencies"/>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
||||||
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
|
<bindingRedirect oldVersion="1.0.0.0" newVersion="3.0.0.0"/>
|
||||||
|
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
@@ -15,13 +15,7 @@ namespace Orchard.Environment.Extensions {
|
|||||||
|
|
||||||
public static class ExtensionManagerExtensions {
|
public static class ExtensionManagerExtensions {
|
||||||
public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
||||||
return extensionManager.AvailableExtensions()
|
return extensionManager.AvailableFeatures().Where(fd => descriptor.Features.Any(sf => sf.Name == fd.Id));
|
||||||
.SelectMany(extensionDescriptor => extensionDescriptor.Features)
|
|
||||||
.Where(featureDescriptor => IsFeatureEnabledInDescriptor(featureDescriptor, descriptor));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsFeatureEnabledInDescriptor(FeatureDescriptor featureDescriptor, ShellDescriptor shellDescriptor) {
|
|
||||||
return shellDescriptor.Features.Any(shellDescriptorFeature => shellDescriptorFeature.Name == featureDescriptor.Id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ namespace Orchard.Environment.Extensions.Models {
|
|||||||
public static class DefaultExtensionTypes {
|
public static class DefaultExtensionTypes {
|
||||||
public const string Module = "Module";
|
public const string Module = "Module";
|
||||||
public const string Theme = "Theme";
|
public const string Theme = "Theme";
|
||||||
public const string Core = "Core";
|
|
||||||
|
|
||||||
public static bool IsModule(string extensionType) {
|
public static bool IsModule(string extensionType) {
|
||||||
return string.Equals(extensionType, Module, StringComparison.OrdinalIgnoreCase);
|
return string.Equals(extensionType, Module, StringComparison.OrdinalIgnoreCase);
|
||||||
|
@@ -5,6 +5,7 @@ using System.Web.Mvc;
|
|||||||
using Orchard.Environment.Descriptor.Models;
|
using Orchard.Environment.Descriptor.Models;
|
||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
using Orchard.Logging;
|
||||||
|
|
||||||
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
||||||
public interface IThemeAwareViewEngine : IDependency {
|
public interface IThemeAwareViewEngine : IDependency {
|
||||||
@@ -31,8 +32,12 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
|||||||
_configuredEnginesCache = configuredEnginesCache;
|
_configuredEnginesCache = configuredEnginesCache;
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
_shellDescriptor = shellDescriptor;
|
_shellDescriptor = shellDescriptor;
|
||||||
|
|
||||||
|
Logger = NullLogger.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths) {
|
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths) {
|
||||||
var engines = _nullEngines;
|
var engines = _nullEngines;
|
||||||
|
|
||||||
@@ -71,21 +76,82 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
|||||||
|
|
||||||
private IViewEngine DeepEngines(ExtensionDescriptor theme) {
|
private IViewEngine DeepEngines(ExtensionDescriptor theme) {
|
||||||
return _configuredEnginesCache.BindDeepEngines(theme.Id, () => {
|
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 engines = Enumerable.Empty<IViewEngine>();
|
||||||
var themeLocation = theme.Location + "/" + theme.Id;
|
// 1. current theme
|
||||||
|
engines = engines.Concat(CreateThemeViewEngines(theme));
|
||||||
|
|
||||||
var themeParams = new CreateThemeViewEngineParams { VirtualPath = themeLocation };
|
// 2. Base themes of the current theme (in "base" order)
|
||||||
engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateThemeViewEngine(themeParams)));
|
engines = GetBaseThemes(theme).Aggregate(engines, (current, baseTheme) => current.Concat(CreateThemeViewEngines(baseTheme)));
|
||||||
|
|
||||||
var activeFeatures = _extensionManager.AvailableFeatures().Where(fd => _shellDescriptor.Features.Any(sdf => sdf.Name == fd.Id));
|
// 3. Active features from modules in dependency order
|
||||||
var activeModuleLocations = activeFeatures.Select(fd => fd.Extension.Location + "/" + fd.Extension.Id).Distinct();
|
var enabledModules = _extensionManager.EnabledFeatures(_shellDescriptor)
|
||||||
var moduleParams = new CreateModulesViewEngineParams { VirtualPaths = activeModuleLocations };
|
.Reverse() // reverse from (C <= B <= A) to (A => B => C)
|
||||||
|
.Where(fd => DefaultExtensionTypes.IsModule(fd.Extension.ExtensionType));
|
||||||
|
|
||||||
|
var allLocations = enabledModules.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)));
|
engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateModulesViewEngine(moduleParams)));
|
||||||
|
|
||||||
return new ViewEngineCollectionWrapper(engines);
|
return new ViewEngineCollectionWrapper(engines);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<IViewEngine> CreateThemeViewEngines(ExtensionDescriptor theme) {
|
||||||
|
var themeLocation = theme.Location + "/" + theme.Id;
|
||||||
|
var themeParams = new CreateThemeViewEngineParams {VirtualPath = themeLocation};
|
||||||
|
return _viewEngineProviders.Select(vep => vep.CreateThemeViewEngine(themeParams));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<ExtensionDescriptor> 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)
|
||||||
|
.Select(fd => fd.Extension)
|
||||||
|
.Where(fd => DefaultExtensionTypes.IsTheme(fd.ExtensionType));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var availableFeatures = _extensionManager.AvailableFeatures();
|
||||||
|
var list = new List<ExtensionDescriptor>();
|
||||||
|
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.Extension)) {
|
||||||
|
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.Extension);
|
||||||
|
|
||||||
|
themeExtension = baseFeature.Extension;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ReleaseView(ControllerContext controllerContext, IView view) {
|
public void ReleaseView(ControllerContext controllerContext, IView view) {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user