mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Merge pull request #5634 from OrchardCMS/feature/auto-enable-dependencies
Auto enable dependencies Fixes #3132
This commit is contained in:
@@ -25,7 +25,6 @@ using Orchard.Tests.Stubs;
|
|||||||
using Orchard.Tests.Utility;
|
using Orchard.Tests.Utility;
|
||||||
using Orchard.WebApi.Routes;
|
using Orchard.WebApi.Routes;
|
||||||
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
||||||
using Orchard.Tasks;
|
|
||||||
|
|
||||||
namespace Orchard.Tests.Environment {
|
namespace Orchard.Tests.Environment {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
@@ -139,8 +138,6 @@ namespace Orchard.Tests.Environment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Test, Ignore("containers are disposed when calling BeginRequest, maybe by the StubVirtualPathMonitor")]
|
[Test, Ignore("containers are disposed when calling BeginRequest, maybe by the StubVirtualPathMonitor")]
|
||||||
public void NormalDependenciesShouldBeUniquePerRequestContainer() {
|
public void NormalDependenciesShouldBeUniquePerRequestContainer() {
|
||||||
var host = _lifetime.Resolve<IOrchardHost>();
|
var host = _lifetime.Resolve<IOrchardHost>();
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ Features:
|
|||||||
Category: Content types
|
Category: Content types
|
||||||
AnotherWiki Editor:
|
AnotherWiki Editor:
|
||||||
Description: A rich editor for wiki contents.
|
Description: A rich editor for wiki contents.
|
||||||
Dependencies: TinyMCE, AnotherWiki
|
Dependencies: TinyMce, AnotherWiki
|
||||||
Category: Input methods
|
Category: Input methods
|
||||||
AnotherWiki DistributionList:
|
AnotherWiki DistributionList:
|
||||||
Description: Sends e-mail alerts when wiki contents gets published.
|
Description: Sends e-mail alerts when wiki contents gets published.
|
||||||
@@ -241,7 +241,7 @@ Features:
|
|||||||
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
||||||
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("TinyMCE"));
|
Assert.That(featureDescriptor.Dependencies.Contains("TinyMce"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
||||||
break;
|
break;
|
||||||
case "AnotherWiki DistributionList":
|
case "AnotherWiki DistributionList":
|
||||||
@@ -287,7 +287,7 @@ Category: Content types
|
|||||||
Features:
|
Features:
|
||||||
AnotherWiki Editor:
|
AnotherWiki Editor:
|
||||||
Description: A rich editor for wiki contents.
|
Description: A rich editor for wiki contents.
|
||||||
Dependencies: TinyMCE, AnotherWiki
|
Dependencies: TinyMce, AnotherWiki
|
||||||
Category: Input methods
|
Category: Input methods
|
||||||
AnotherWiki DistributionList:
|
AnotherWiki DistributionList:
|
||||||
Description: Sends e-mail alerts when wiki contents gets published.
|
Description: Sends e-mail alerts when wiki contents gets published.
|
||||||
@@ -323,7 +323,7 @@ Features:
|
|||||||
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
||||||
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("TinyMCE"));
|
Assert.That(featureDescriptor.Dependencies.Contains("TinyMce"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
||||||
break;
|
break;
|
||||||
case "AnotherWiki DistributionList":
|
case "AnotherWiki DistributionList":
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ Features:
|
|||||||
Category: Content types
|
Category: Content types
|
||||||
AnotherWiki Editor:
|
AnotherWiki Editor:
|
||||||
Description: A rich editor for wiki contents.
|
Description: A rich editor for wiki contents.
|
||||||
Dependencies: TinyMCE, AnotherWiki
|
Dependencies: TinyMce, AnotherWiki
|
||||||
Category: Input methods
|
Category: Input methods
|
||||||
AnotherWiki DistributionList:
|
AnotherWiki DistributionList:
|
||||||
Description: Sends e-mail alerts when wiki contents gets published.
|
Description: Sends e-mail alerts when wiki contents gets published.
|
||||||
@@ -243,7 +243,7 @@ Features:
|
|||||||
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
Assert.That(featureDescriptor.Description, Is.EqualTo("A rich editor for wiki contents."));
|
||||||
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
Assert.That(featureDescriptor.Category, Is.EqualTo("Input methods"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
Assert.That(featureDescriptor.Dependencies.Count(), Is.EqualTo(2));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("TinyMCE"));
|
Assert.That(featureDescriptor.Dependencies.Contains("TinyMce"));
|
||||||
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
Assert.That(featureDescriptor.Dependencies.Contains("AnotherWiki"));
|
||||||
break;
|
break;
|
||||||
case "AnotherWiki DistributionList":
|
case "AnotherWiki DistributionList":
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Autofac;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
using Orchard.Environment.Descriptor.Models;
|
||||||
|
using Orchard.Environment.Extensions;
|
||||||
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
using Orchard.Environment.ShellBuilders;
|
||||||
|
using Orchard.Tests.Environment.TestDependencies;
|
||||||
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
|
namespace Orchard.Tests.Environment.ShellBuilders {
|
||||||
|
[TestFixture]
|
||||||
|
public class CompositionStrategyTests : ContainerTestBase {
|
||||||
|
private CompositionStrategy _compositionStrategy;
|
||||||
|
private Mock<IExtensionManager> _extensionManager;
|
||||||
|
|
||||||
|
protected override void Register(ContainerBuilder builder) {
|
||||||
|
_extensionManager = new Mock<IExtensionManager>(MockBehavior.Loose);
|
||||||
|
|
||||||
|
builder.RegisterType<CompositionStrategy>().AsSelf();
|
||||||
|
builder.RegisterInstance(_extensionManager.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Resolve(ILifetimeScope container) {
|
||||||
|
_compositionStrategy = container.Resolve<CompositionStrategy>();
|
||||||
|
|
||||||
|
var alphaExtension = new ExtensionDescriptor {
|
||||||
|
Id = "Alpha",
|
||||||
|
Name = "Alpha",
|
||||||
|
ExtensionType = "Module"
|
||||||
|
};
|
||||||
|
|
||||||
|
var alphaFeatureDescriptor = new FeatureDescriptor {
|
||||||
|
Id = "Alpha",
|
||||||
|
Name = "Alpha",
|
||||||
|
Extension = alphaExtension
|
||||||
|
};
|
||||||
|
|
||||||
|
var betaFeatureDescriptor = new FeatureDescriptor {
|
||||||
|
Id = "Beta",
|
||||||
|
Name = "Beta",
|
||||||
|
Extension = alphaExtension,
|
||||||
|
Dependencies = new List<string> {
|
||||||
|
"Alpha"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
alphaExtension.Features = new List<FeatureDescriptor> {
|
||||||
|
alphaFeatureDescriptor,
|
||||||
|
betaFeatureDescriptor
|
||||||
|
};
|
||||||
|
|
||||||
|
var features = new List<Feature> {
|
||||||
|
new Feature {
|
||||||
|
Descriptor = alphaFeatureDescriptor,
|
||||||
|
ExportedTypes = new List<Type> {
|
||||||
|
typeof(AlphaDependency)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Feature {
|
||||||
|
Descriptor = betaFeatureDescriptor,
|
||||||
|
ExportedTypes = new List<Type> {
|
||||||
|
typeof(BetaDependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_extensionManager.Setup(x => x.AvailableExtensions()).Returns(new List<ExtensionDescriptor> {
|
||||||
|
alphaExtension
|
||||||
|
});
|
||||||
|
|
||||||
|
_extensionManager.Setup(x => x.AvailableFeatures()).Returns(
|
||||||
|
_extensionManager.Object.AvailableExtensions()
|
||||||
|
.SelectMany(ext => ext.Features)
|
||||||
|
.ToReadOnlyCollection());
|
||||||
|
|
||||||
|
_extensionManager.Setup(x => x.LoadFeatures(It.IsAny<IEnumerable<FeatureDescriptor>>())).Returns(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ComposeReturnsBlueprintWithExpectedDependencies() {
|
||||||
|
var shellSettings = CreateShell();
|
||||||
|
var shellDescriptor = CreateShellDescriptor("Alpha", "Beta");
|
||||||
|
var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
||||||
|
|
||||||
|
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof (AlphaDependency)), Is.EqualTo(1));
|
||||||
|
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(BetaDependency)), Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ComposeReturnsBlueprintWithAutoEnabledDependencyFeatures() {
|
||||||
|
var shellSettings = CreateShell();
|
||||||
|
var shellDescriptor = CreateShellDescriptor("Beta"); // Beta has a dependency on Alpha, but is not enabled initially.
|
||||||
|
var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
||||||
|
|
||||||
|
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(AlphaDependency)), Is.EqualTo(1));
|
||||||
|
Assert.That(shellDescriptor.Features.Count(x => x.Name == "Alpha"), Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShellSettings CreateShell() {
|
||||||
|
return new ShellSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShellDescriptor CreateShellDescriptor(params string[] enabledFeatures) {
|
||||||
|
var shellDescriptor = new ShellDescriptor {
|
||||||
|
Features = enabledFeatures.Select(x => new ShellFeature {
|
||||||
|
Name = x
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
return shellDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Orchard.Tests.Environment.TestDependencies {
|
||||||
|
|
||||||
|
public interface IAlphaDependency : IDependency {
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlphaDependency : IAlphaDependency {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Orchard.Tests.Environment.TestDependencies {
|
||||||
|
|
||||||
|
public interface IBetaDependency : IDependency {
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BetaDependency : IBetaDependency {
|
||||||
|
public IAlphaDependency Alpha { get; set; }
|
||||||
|
|
||||||
|
public BetaDependency(IAlphaDependency alpha) {
|
||||||
|
Alpha = alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -245,9 +245,12 @@
|
|||||||
<Compile Include="Environment\Extensions\ExtensionLoaderCoordinatorTests.cs" />
|
<Compile Include="Environment\Extensions\ExtensionLoaderCoordinatorTests.cs" />
|
||||||
<Compile Include="Environment\Features\FeatureManagerTests.cs" />
|
<Compile Include="Environment\Features\FeatureManagerTests.cs" />
|
||||||
<Compile Include="Environment\Loaders\DynamicExtensionLoaderTests.cs" />
|
<Compile Include="Environment\Loaders\DynamicExtensionLoaderTests.cs" />
|
||||||
|
<Compile Include="Environment\ShellBuilders\CompositionStrategyTests.cs" />
|
||||||
<Compile Include="Environment\State\DefaultProcessingEngineTests.cs" />
|
<Compile Include="Environment\State\DefaultProcessingEngineTests.cs" />
|
||||||
<Compile Include="Environment\RunningShellTableTests.cs" />
|
<Compile Include="Environment\RunningShellTableTests.cs" />
|
||||||
<Compile Include="Environment\StubHostEnvironment.cs" />
|
<Compile Include="Environment\StubHostEnvironment.cs" />
|
||||||
|
<Compile Include="Environment\TestDependencies\AlphaDependency.cs" />
|
||||||
|
<Compile Include="Environment\TestDependencies\BetaDependency.cs" />
|
||||||
<Compile Include="Environment\Utility\Build.cs" />
|
<Compile Include="Environment\Utility\Build.cs" />
|
||||||
<Compile Include="Environment\Warmup\WarmupUtilityTests.cs" />
|
<Compile Include="Environment\Warmup\WarmupUtilityTests.cs" />
|
||||||
<Compile Include="FileSystems\AppData\AppDataFolderTests.cs" />
|
<Compile Include="FileSystems\AppData\AppDataFolderTests.cs" />
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./jquery.fileupload"],e):e(window.jQuery)}(function(e){"use strict";var s=e.blueimp.fileupload.prototype.options.add;e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{processQueue:[],add:function(r,i){var o=e(this);i.process(function(){return o.fileupload("process",i)}),s.call(this,r,i)}},processActions:{},_processFile:function(s,r){var i=this,o=e.Deferred().resolveWith(i,[s]),t=o.promise();return this._trigger("process",null,s),e.each(s.processQueue,function(s,o){var n=function(s){return r.errorThrown?e.Deferred().rejectWith(i,[r]).promise():i.processActions[o.action].call(i,s,o)};t=t.pipe(n,o.always&&n)}),t.done(function(){i._trigger("processdone",null,s),i._trigger("processalways",null,s)}).fail(function(){i._trigger("processfail",null,s),i._trigger("processalways",null,s)}),t},_transformProcessQueue:function(s){var r=[];e.each(s.processQueue,function(){var i={},o=this.action,t=this.prefix===!0?o:this.prefix;e.each(this,function(r,o){i[r]="string"===e.type(o)&&"@"===o.charAt(0)?s[o.slice(1)||(t?t+r.charAt(0).toUpperCase()+r.slice(1):r)]:o}),r.push(i)}),s.processQueue=r},processing:function(){return this._processing},process:function(s){var r=this,i=e.extend({},this.options,s);return i.processQueue&&i.processQueue.length&&(this._transformProcessQueue(i),0===this._processing&&this._trigger("processstart"),e.each(s.files,function(o){var t=o?e.extend({},i):i,n=function(){return s.errorThrown?e.Deferred().rejectWith(r,[s]).promise():r._processFile(t,s)};t.index=o,r._processing+=1,r._processingQueue=r._processingQueue.pipe(n,n).always(function(){r._processing-=1,0===r._processing&&r._trigger("processstop")})})),this._processingQueue},_create:function(){this._super(),this._processing=0,this._processingQueue=e.Deferred().resolveWith(this).promise()}})});
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./jquery.fileupload-process"],e):e(window.jQuery)}(function(e){"use strict";e.blueimp.fileupload.prototype.options.processQueue.push({action:"validate",always:!0,acceptFileTypes:"@",maxFileSize:"@",minFileSize:"@",maxNumberOfFiles:"@",disabled:"@disableValidation"}),e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{getNumberOfFiles:e.noop,messages:{maxNumberOfFiles:"Maximum number of files exceeded",acceptFileTypes:"File type not allowed",maxFileSize:"File is too large",minFileSize:"File is too small"}},processActions:{validate:function(i,l){if(l.disabled)return i;var r,s=e.Deferred(),t=this.options,o=i.files[i.index];return(l.minFileSize||l.maxFileSize)&&(r=o.size),"number"===e.type(l.maxNumberOfFiles)&&(t.getNumberOfFiles()||0)+i.files.length>l.maxNumberOfFiles?o.error=t.i18n("maxNumberOfFiles"):!l.acceptFileTypes||l.acceptFileTypes.test(o.type)||l.acceptFileTypes.test(o.name)?r>l.maxFileSize?o.error=t.i18n("maxFileSize"):"number"===e.type(r)&&r<l.minFileSize?o.error=t.i18n("minFileSize"):delete o.error:o.error=t.i18n("acceptFileTypes"),o.error||i.files.error?(i.files.error=!0,s.rejectWith(this,[i])):s.resolveWith(this,[i]),s.promise()}}})});
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,11 +0,0 @@
|
|||||||
--- CommandBackgroundService.cs
|
|
||||||
+++ CommandBackgroundService.cs
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
using Orchard.Tasks;
|
|
||||||
|
|
||||||
namespace Orchard.Commands {
|
|
||||||
- public class CommandBackgroundService : IBackgroundService {
|
|
||||||
+ class CommandBackgroundService : IBackgroundService {
|
|
||||||
public void Sweep() {
|
|
||||||
// Don't run any background service in command line
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@ using Orchard.Logging;
|
|||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
// All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter
|
// All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter.
|
||||||
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
|
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
|
||||||
private readonly IHostLocalRestart _hostLocalRestart;
|
private readonly IHostLocalRestart _hostLocalRestart;
|
||||||
private readonly IShellSettingsManager _shellSettingsManager;
|
private readonly IShellSettingsManager _shellSettingsManager;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Autofac.Features.OwnedInstances;
|
using Autofac.Features.OwnedInstances;
|
||||||
using Microsoft.Owin.Builder;
|
using Microsoft.Owin.Builder;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
@@ -12,7 +11,6 @@ using Orchard.Owin;
|
|||||||
using Orchard.Tasks;
|
using Orchard.Tasks;
|
||||||
using Orchard.UI;
|
using Orchard.UI;
|
||||||
using Orchard.WebApi.Routes;
|
using Orchard.WebApi.Routes;
|
||||||
using Owin;
|
|
||||||
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
@@ -37,6 +35,7 @@ namespace Orchard.Environment {
|
|||||||
ISweepGenerator sweepGenerator,
|
ISweepGenerator sweepGenerator,
|
||||||
IEnumerable<IOwinMiddlewareProvider> owinMiddlewareProviders,
|
IEnumerable<IOwinMiddlewareProvider> owinMiddlewareProviders,
|
||||||
ShellSettings shellSettings) {
|
ShellSettings shellSettings) {
|
||||||
|
|
||||||
_eventsFactory = eventsFactory;
|
_eventsFactory = eventsFactory;
|
||||||
_routeProviders = routeProviders;
|
_routeProviders = routeProviders;
|
||||||
_httpRouteProviders = httpRouteProviders;
|
_httpRouteProviders = httpRouteProviders;
|
||||||
@@ -53,7 +52,7 @@ namespace Orchard.Environment {
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public void Activate() {
|
public void Activate() {
|
||||||
IAppBuilder appBuilder = new AppBuilder();
|
var appBuilder = new AppBuilder();
|
||||||
appBuilder.Properties["host.AppName"] = _shellSettings.Name;
|
appBuilder.Properties["host.AppName"] = _shellSettings.Name;
|
||||||
|
|
||||||
var orderedMiddlewares = _owinMiddlewareProviders
|
var orderedMiddlewares = _owinMiddlewareProviders
|
||||||
@@ -64,11 +63,10 @@ namespace Orchard.Environment {
|
|||||||
middleware.Configure(appBuilder);
|
middleware.Configure(appBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the Orchard middleware after all others
|
// Register the Orchard middleware after all others.
|
||||||
appBuilder.UseOrchard();
|
appBuilder.UseOrchard();
|
||||||
|
|
||||||
Func<IDictionary<string, object>, Task> pipeline = appBuilder.Build();
|
var pipeline = appBuilder.Build();
|
||||||
|
|
||||||
var allRoutes = new List<RouteDescriptor>();
|
var allRoutes = new List<RouteDescriptor>();
|
||||||
allRoutes.AddRange(_routeProviders.SelectMany(provider => provider.GetRoutes()));
|
allRoutes.AddRange(_routeProviders.SelectMany(provider => provider.GetRoutes()));
|
||||||
allRoutes.AddRange(_httpRouteProviders.SelectMany(provider => provider.GetRoutes()));
|
allRoutes.AddRange(_httpRouteProviders.SelectMany(provider => provider.GetRoutes()));
|
||||||
@@ -79,16 +77,17 @@ namespace Orchard.Environment {
|
|||||||
using (var events = _eventsFactory()) {
|
using (var events = _eventsFactory()) {
|
||||||
events.Value.Activated();
|
events.Value.Activated();
|
||||||
}
|
}
|
||||||
|
|
||||||
_sweepGenerator.Activate();
|
_sweepGenerator.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Terminate() {
|
public void Terminate() {
|
||||||
SafelyTerminate(() => {
|
SafelyTerminate(() => {
|
||||||
using (var events = _eventsFactory()) {
|
using (var events = _eventsFactory()) {
|
||||||
SafelyTerminate(() => events.Value.Terminating());
|
var localEvents = events;
|
||||||
}
|
SafelyTerminate(() => localEvents.Value.Terminating());
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
SafelyTerminate(() => _sweepGenerator.Terminate());
|
SafelyTerminate(() => _sweepGenerator.Terminate());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Orchard.Environment.Descriptor {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Alters databased information to match information passed as arguments.
|
/// Alters databased information to match information passed as arguments.
|
||||||
/// Prior SerialNumber used for optomistic concurrency, and an exception
|
/// Prior SerialNumber used for optimistic concurrency, and an exception
|
||||||
/// should be thrown if the number in storage doesn't match what's provided.
|
/// should be thrown if the number in storage doesn't match what's provided.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void UpdateShellDescriptor(
|
void UpdateShellDescriptor(
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Orchard.Environment.Descriptor.Models;
|
|
||||||
using Orchard.Environment.Extensions.Models;
|
|
||||||
|
|
||||||
namespace Orchard.Environment.Extensions.Helpers {
|
|
||||||
public static class ExtensionManagerExtensions {
|
|
||||||
public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
|
||||||
return extensionManager.AvailableFeatures().Where(fd => descriptor.Features.Any(sf => sf.Name == fd.Id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<FeatureDescriptor> DisabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
|
||||||
return extensionManager.AvailableFeatures().Where(fd => descriptor.Features.All(sf => sf.Name != fd.Id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Orchard.Environment.Descriptor.Models;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
namespace Orchard.Environment.Extensions {
|
namespace Orchard.Environment.Extensions {
|
||||||
@@ -10,4 +12,18 @@ namespace Orchard.Environment.Extensions {
|
|||||||
|
|
||||||
IEnumerable<Feature> LoadFeatures(IEnumerable<FeatureDescriptor> featureDescriptors);
|
IEnumerable<Feature> LoadFeatures(IEnumerable<FeatureDescriptor> featureDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ExtensionManagerExtensions {
|
||||||
|
public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
||||||
|
return EnabledFeatures(extensionManager, descriptor.Features);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, IEnumerable<ShellFeature> features) {
|
||||||
|
return extensionManager.AvailableFeatures().Where(fd => features.Any(sf => sf.Name == fd.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<FeatureDescriptor> DisabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) {
|
||||||
|
return extensionManager.AvailableFeatures().Where(fd => descriptor.Features.All(sf => sf.Name != fd.Id));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Web.Http.Controllers;
|
using System.Web.Http.Controllers;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Autofac.Core;
|
using Autofac.Core;
|
||||||
@@ -16,17 +15,6 @@ using Orchard.Environment.ShellBuilders.Models;
|
|||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
|
||||||
namespace Orchard.Environment.ShellBuilders {
|
namespace Orchard.Environment.ShellBuilders {
|
||||||
/// <summary>
|
|
||||||
/// Service at the host level to transform the cachable descriptor into the loadable blueprint.
|
|
||||||
/// </summary>
|
|
||||||
public interface ICompositionStrategy {
|
|
||||||
/// <summary>
|
|
||||||
/// Using information from the IExtensionManager, transforms and populates all of the
|
|
||||||
/// blueprint model the shell builders will need to correctly initialize a tenant IoC container.
|
|
||||||
/// </summary>
|
|
||||||
ShellBlueprint Compose(ShellSettings settings, ShellDescriptor descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompositionStrategy : ICompositionStrategy {
|
public class CompositionStrategy : ICompositionStrategy {
|
||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
|
|
||||||
@@ -41,14 +29,19 @@ namespace Orchard.Environment.ShellBuilders {
|
|||||||
public ShellBlueprint Compose(ShellSettings settings, ShellDescriptor descriptor) {
|
public ShellBlueprint Compose(ShellSettings settings, ShellDescriptor descriptor) {
|
||||||
Logger.Debug("Composing blueprint");
|
Logger.Debug("Composing blueprint");
|
||||||
|
|
||||||
var enabledFeatures = _extensionManager.EnabledFeatures(descriptor);
|
var builtinFeatures = BuiltinFeatures().ToList();
|
||||||
var features = _extensionManager.LoadFeatures(enabledFeatures);
|
var builtinFeatureDescriptors = builtinFeatures.Select(x => x.Descriptor).ToList();
|
||||||
|
var availableFeatures = _extensionManager.AvailableFeatures().Concat(builtinFeatureDescriptors).ToDictionary(x => x.Id);
|
||||||
|
var enabledFeatures = _extensionManager.EnabledFeatures(descriptor).Select(x => x.Id).ToList();
|
||||||
|
var expandedFeatures = ExpandDependencies(availableFeatures, descriptor.Features.Select(x => x.Name)).ToList();
|
||||||
|
var autoEnabledDependencyFeatures = expandedFeatures.Except(enabledFeatures).Except(builtinFeatureDescriptors.Select(x => x.Id)).ToList();
|
||||||
|
var featureDescriptors = _extensionManager.EnabledFeatures(expandedFeatures.Select(x => new ShellFeature { Name = x})).ToList();
|
||||||
|
var features = _extensionManager.LoadFeatures(featureDescriptors);
|
||||||
|
|
||||||
if (descriptor.Features.Any(feature => feature.Name == "Orchard.Framework"))
|
if (descriptor.Features.Any(feature => feature.Name == "Orchard.Framework"))
|
||||||
features = BuiltinFeatures().Concat(features);
|
features = builtinFeatures.Concat(features);
|
||||||
|
|
||||||
var excludedTypes = GetExcludedTypes(features);
|
var excludedTypes = GetExcludedTypes(features);
|
||||||
|
|
||||||
var modules = BuildBlueprint(features, IsModule, BuildModule, excludedTypes);
|
var modules = BuildBlueprint(features, IsModule, BuildModule, excludedTypes);
|
||||||
var dependencies = BuildBlueprint(features, IsDependency, (t, f) => BuildDependency(t, f, descriptor), excludedTypes);
|
var dependencies = BuildBlueprint(features, IsDependency, (t, f) => BuildDependency(t, f, descriptor), excludedTypes);
|
||||||
var controllers = BuildBlueprint(features, IsController, BuildController, excludedTypes);
|
var controllers = BuildBlueprint(features, IsController, BuildController, excludedTypes);
|
||||||
@@ -64,16 +57,41 @@ namespace Orchard.Environment.ShellBuilders {
|
|||||||
Records = records,
|
Records = records,
|
||||||
};
|
};
|
||||||
|
|
||||||
Logger.Debug("Done composing blueprint");
|
Logger.Debug("Done composing blueprint.");
|
||||||
|
|
||||||
|
if (autoEnabledDependencyFeatures.Any()) {
|
||||||
|
// Add any dependencies previously not enabled to the shell descriptor.
|
||||||
|
descriptor.Features = descriptor.Features.Concat(autoEnabledDependencyFeatures.Select(x => new ShellFeature { Name = x })).ToList();
|
||||||
|
Logger.Information("Automatically enabled the following dependency features: {0}.", String.Join(", ", autoEnabledDependencyFeatures));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> ExpandDependencies(IDictionary<string, FeatureDescriptor> availableFeatures, IEnumerable<string> features) {
|
||||||
|
return ExpandDependenciesInternal(availableFeatures, features).Distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> ExpandDependenciesInternal(IDictionary<string, FeatureDescriptor> availableFeatures, IEnumerable<string> features) {
|
||||||
|
foreach (var shellFeature in features) {
|
||||||
|
var feature = availableFeatures[shellFeature];
|
||||||
|
|
||||||
|
foreach (var childDependency in ExpandDependenciesInternal(availableFeatures, feature.Dependencies))
|
||||||
|
yield return childDependency;
|
||||||
|
|
||||||
|
foreach (var dependency in feature.Dependencies)
|
||||||
|
yield return dependency;
|
||||||
|
|
||||||
|
yield return shellFeature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetExcludedTypes(IEnumerable<Feature> features) {
|
private static IEnumerable<string> GetExcludedTypes(IEnumerable<Feature> features) {
|
||||||
var excludedTypes = new HashSet<string>();
|
var excludedTypes = new HashSet<string>();
|
||||||
|
|
||||||
// Identify replaced types
|
// Identify replaced types.
|
||||||
foreach (Feature feature in features) {
|
foreach (var feature in features) {
|
||||||
foreach (Type type in feature.ExportedTypes) {
|
foreach (var type in feature.ExportedTypes) {
|
||||||
foreach (OrchardSuppressDependencyAttribute replacedType in type.GetCustomAttributes(typeof(OrchardSuppressDependencyAttribute), false)) {
|
foreach (OrchardSuppressDependencyAttribute replacedType in type.GetCustomAttributes(typeof(OrchardSuppressDependencyAttribute), false)) {
|
||||||
excludedTypes.Add(replacedType.FullName);
|
excludedTypes.Add(replacedType.FullName);
|
||||||
}
|
}
|
||||||
@@ -160,7 +178,7 @@ namespace Orchard.Environment.ShellBuilders {
|
|||||||
private static bool IsRecord(Type type) {
|
private static bool IsRecord(Type type) {
|
||||||
return ((type.Namespace ?? "").EndsWith(".Models") || (type.Namespace ?? "").EndsWith(".Records")) &&
|
return ((type.Namespace ?? "").EndsWith(".Models") || (type.Namespace ?? "").EndsWith(".Records")) &&
|
||||||
type.GetProperty("Id") != null &&
|
type.GetProperty("Id") != null &&
|
||||||
(type.GetProperty("Id").GetAccessors() ?? Enumerable.Empty<MethodInfo>()).All(x => x.IsVirtual) &&
|
(type.GetProperty("Id").GetAccessors()).All(x => x.IsVirtual) &&
|
||||||
!type.IsSealed &&
|
!type.IsSealed &&
|
||||||
!type.IsAbstract &&
|
!type.IsAbstract &&
|
||||||
(!typeof(IContent).IsAssignableFrom(type) || typeof(ContentPartRecord).IsAssignableFrom(type));
|
(!typeof(IContent).IsAssignableFrom(type) || typeof(ContentPartRecord).IsAssignableFrom(type));
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
using Orchard.Environment.Descriptor.Models;
|
||||||
|
using Orchard.Environment.ShellBuilders.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Environment.ShellBuilders {
|
||||||
|
/// <summary>
|
||||||
|
/// Service at the host level to transform the cachable descriptor into the loadable blueprint.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICompositionStrategy {
|
||||||
|
/// <summary>
|
||||||
|
/// Using information from the IExtensionManager, transforms and populates all of the
|
||||||
|
/// blueprint model the shell builders will need to correctly initialize a tenant IoC container.
|
||||||
|
/// </summary>
|
||||||
|
ShellBlueprint Compose(ShellSettings settings, ShellDescriptor descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,7 +119,7 @@ namespace Orchard.Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void CompileDirectory(CompilationContext context, string viewDirectory) {
|
private void CompileDirectory(CompilationContext context, string viewDirectory) {
|
||||||
// Prevent processing of the same directories multiple times (sligh performance optimization,
|
// Prevent processing of the same directories multiple times (slight performance optimization,
|
||||||
// as the build manager second call to compile a view is essentially a "no-op".
|
// as the build manager second call to compile a view is essentially a "no-op".
|
||||||
if (context.ProcessedDirectories.Contains(viewDirectory))
|
if (context.ProcessedDirectories.Contains(viewDirectory))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -151,8 +151,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Data\Migration\Schema\AddUniqueConstraintCommand.cs" />
|
<Compile Include="Data\Migration\Schema\AddUniqueConstraintCommand.cs" />
|
||||||
<Compile Include="Data\Migration\Schema\DropUniqueConstraintCommand.cs" />
|
<Compile Include="Data\Migration\Schema\DropUniqueConstraintCommand.cs" />
|
||||||
<Compile Include="Environment\Extensions\Helpers\ExtensionManagerExtensions.cs" />
|
|
||||||
<Compile Include="Environment\Extensions\Models\LifecycleStatus.cs" />
|
<Compile Include="Environment\Extensions\Models\LifecycleStatus.cs" />
|
||||||
|
<Compile Include="Environment\ShellBuilders\ICompositionStrategy.cs" />
|
||||||
<Compile Include="Mvc\Updater.cs" />
|
<Compile Include="Mvc\Updater.cs" />
|
||||||
<Compile Include="Recipes\Models\ConfigurationContext.cs" />
|
<Compile Include="Recipes\Models\ConfigurationContext.cs" />
|
||||||
<Compile Include="Recipes\Models\RecipeBuilderStepConfigurationContext.cs" />
|
<Compile Include="Recipes\Models\RecipeBuilderStepConfigurationContext.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user