--HG--
branch : dev
This commit is contained in:
Suha Can
2010-12-08 18:58:32 -08:00
7 changed files with 84 additions and 26 deletions

View File

@@ -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");

View File

@@ -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:

View File

@@ -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">

View File

@@ -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>

View File

@@ -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);
} }
} }
} }

View File

@@ -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);

View File

@@ -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();
} }