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:
@@ -8,6 +8,7 @@ using Autofac.Core;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.Topology;
|
||||
@@ -51,16 +52,21 @@ namespace Orchard.Tests.Environment {
|
||||
});
|
||||
}
|
||||
|
||||
private static ShellSettings BuildDefaultSettings() {
|
||||
return new ShellSettings { Name = "Default" };
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TopologyIsNotNull() {
|
||||
var descriptor = Build.TopologyDescriptor();
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
Assert.That(topology, Is.Not.Null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void DependenciesFromFeatureArePutIntoTopology() {
|
||||
var descriptor = Build.TopologyDescriptor().WithFeatures("Foo", "Bar");
|
||||
@@ -74,7 +80,7 @@ namespace Orchard.Tests.Environment {
|
||||
_featureTypes["Bar"] = new[] { typeof(BarService1) };
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
Assert.That(topology, Is.Not.Null);
|
||||
Assert.That(topology.Dependencies.Count(), Is.EqualTo(2));
|
||||
@@ -115,7 +121,7 @@ namespace Orchard.Tests.Environment {
|
||||
_featureTypes["Foo"] = new[] { typeof(FooService1) };
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
var foo = topology.Dependencies.SingleOrDefault(t => t.Type == typeof(FooService1));
|
||||
Assert.That(foo, Is.Not.Null);
|
||||
@@ -137,10 +143,10 @@ namespace Orchard.Tests.Environment {
|
||||
_featureTypes["Bar"] = new[] { typeof(BetaModule) };
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
var alpha = topology.Modules.Single(x => x.Type == typeof (AlphaModule));
|
||||
var beta = topology.Modules.Single(x => x.Type == typeof (BetaModule));
|
||||
var alpha = topology.Dependencies.Single(x => x.Type == typeof(AlphaModule));
|
||||
var beta = topology.Dependencies.Single(x => x.Type == typeof(BetaModule));
|
||||
|
||||
Assert.That(alpha.Feature.Descriptor.Name, Is.EqualTo("Foo"));
|
||||
Assert.That(beta.Feature.Descriptor.Name, Is.EqualTo("Bar"));
|
||||
@@ -170,11 +176,11 @@ namespace Orchard.Tests.Environment {
|
||||
_featureTypes["Bar Minus"] = new[] { typeof(DeltaController), typeof(EpsilonController) };
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
var gamma = topology.Controllers.Single(x => x.Type == typeof (GammaController));
|
||||
var delta = topology.Controllers.Single(x => x.Type == typeof (DeltaController));
|
||||
var epsilon = topology.Controllers.Single(x => x.Type == typeof (EpsilonController));
|
||||
var gamma = topology.Controllers.Single(x => x.Type == typeof(GammaController));
|
||||
var delta = topology.Controllers.Single(x => x.Type == typeof(DeltaController));
|
||||
var epsilon = topology.Controllers.Single(x => x.Type == typeof(EpsilonController));
|
||||
|
||||
Assert.That(gamma.Feature.Descriptor.Name, Is.EqualTo("Foo Plus"));
|
||||
Assert.That(gamma.AreaName, Is.EqualTo("MyCompany.Foo"));
|
||||
@@ -189,7 +195,7 @@ namespace Orchard.Tests.Environment {
|
||||
Assert.That(epsilon.ControllerName, Is.EqualTo("Epsilon"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class GammaController : Controller {
|
||||
}
|
||||
|
||||
@@ -205,7 +211,7 @@ namespace Orchard.Tests.Environment {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void RecordsArePutIntoTopologyWithTableName() {
|
||||
var descriptor = Build.TopologyDescriptor().WithFeatures("Foo Plus", "Bar", "Bar Minus");
|
||||
@@ -221,10 +227,10 @@ namespace Orchard.Tests.Environment {
|
||||
_featureTypes["Bar Minus"] = Enumerable.Empty<Type>();
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
var foo = topology.Records.Single(x => x.Type == typeof (FooRecord));
|
||||
var bar = topology.Records.Single(x => x.Type == typeof (BarRecord));
|
||||
var foo = topology.Records.Single(x => x.Type == typeof(FooRecord));
|
||||
var bar = topology.Records.Single(x => x.Type == typeof(BarRecord));
|
||||
|
||||
Assert.That(foo.Feature.Descriptor.Name, Is.EqualTo("Foo Plus"));
|
||||
Assert.That(foo.TableName, Is.EqualTo("MyCompany_Foo_FooRecord"));
|
||||
@@ -236,14 +242,14 @@ namespace Orchard.Tests.Environment {
|
||||
[Test]
|
||||
public void CoreRecordsAreAddedAutomatically() {
|
||||
var descriptor = Build.TopologyDescriptor().WithFeatures("Orchard.Framework");
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(descriptor);
|
||||
|
||||
var ct = topology.Records.Single(x => x.Type == typeof (ContentTypeRecord));
|
||||
var ci = topology.Records.Single(x => x.Type == typeof (ContentItemRecord));
|
||||
var civ = topology.Records.Single(x => x.Type == typeof (ContentItemVersionRecord));
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(BuildDefaultSettings(), descriptor);
|
||||
|
||||
var ct = topology.Records.Single(x => x.Type == typeof(ContentTypeRecord));
|
||||
var ci = topology.Records.Single(x => x.Type == typeof(ContentItemRecord));
|
||||
var civ = topology.Records.Single(x => x.Type == typeof(ContentItemVersionRecord));
|
||||
|
||||
Assert.That(ct.Feature.Descriptor.Name, Is.EqualTo("Orchard.Framework"));
|
||||
Assert.That(ct.TableName, Is.EqualTo("Orchard_Framework_ContentTypeRecord"));
|
||||
|
||||
@@ -252,6 +258,36 @@ namespace Orchard.Tests.Environment {
|
||||
|
||||
Assert.That(civ.Feature.Descriptor.Name, Is.EqualTo("Orchard.Framework"));
|
||||
Assert.That(civ.TableName, Is.EqualTo("Orchard_Framework_ContentItemVersionRecord"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataPrefixChangesTableName() {
|
||||
var settings = BuildDefaultSettings();
|
||||
settings.DataPrefix = "Yadda";
|
||||
var descriptor = Build.TopologyDescriptor().WithFeatures("Foo Plus", "Bar", "Bar Minus");
|
||||
|
||||
_extensionDescriptors = new[] {
|
||||
Build.ExtensionDescriptor("MyCompany.Foo", "Foo").WithFeatures("Foo", "Foo Plus"),
|
||||
Build.ExtensionDescriptor("Bar").WithFeatures("Bar", "Bar Minus"),
|
||||
};
|
||||
|
||||
_featureTypes["Foo"] = Enumerable.Empty<Type>();
|
||||
_featureTypes["Foo Plus"] = new[] { typeof(FooRecord) };
|
||||
_featureTypes["Bar"] = new[] { typeof(BarRecord) };
|
||||
_featureTypes["Bar Minus"] = Enumerable.Empty<Type>();
|
||||
|
||||
var compositionStrategy = _container.Resolve<ICompositionStrategy>();
|
||||
var topology = compositionStrategy.Compose(settings, descriptor);
|
||||
|
||||
var foo = topology.Records.Single(x => x.Type == typeof(FooRecord));
|
||||
var bar = topology.Records.Single(x => x.Type == typeof(BarRecord));
|
||||
|
||||
Assert.That(foo.Feature.Descriptor.Name, Is.EqualTo("Foo Plus"));
|
||||
Assert.That(foo.TableName, Is.EqualTo("Yadda_MyCompany_Foo_FooRecord"));
|
||||
|
||||
Assert.That(bar.Feature.Descriptor.Name, Is.EqualTo("Bar"));
|
||||
Assert.That(bar.TableName, Is.EqualTo("Yadda_Bar_BarRecord"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -295,5 +295,23 @@ features:
|
||||
Assert.That((type == typeof(Alpha) || (type == typeof(Beta))));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ModuleNameIsIntroducedAsFeatureImplicitly() {
|
||||
var extensionLoader = new StubLoaders();
|
||||
var extensionFolder = new StubFolders();
|
||||
|
||||
extensionFolder.Manifests.Add("Minimalistic", @"
|
||||
name: Minimalistic
|
||||
version: 1.0.3
|
||||
orchardversion: 1
|
||||
");
|
||||
|
||||
ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader });
|
||||
var minimalisticModule = extensionManager.AvailableExtensions().Single(x => x.Name == "Minimalistic");
|
||||
|
||||
Assert.That(minimalisticModule.Features.Count(), Is.EqualTo(1));
|
||||
Assert.That(minimalisticModule.Features.Single().Name, Is.EqualTo("Minimalistic"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -34,15 +34,14 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
}
|
||||
ShellTopology CreateTopology(params ShellTopologyItem[] items) {
|
||||
return new ShellTopology {
|
||||
Modules = items.OfType<ModuleTopology>(),
|
||||
Dependencies = items.OfType<DependencyTopology>(),
|
||||
Controllers = items.OfType<ControllerTopology>(),
|
||||
Records = items.OfType<RecordTopology>(),
|
||||
};
|
||||
}
|
||||
|
||||
ModuleTopology WithModule<T>() {
|
||||
return new ModuleTopology { Type = typeof(T) };
|
||||
DependencyTopology WithModule<T>() {
|
||||
return new DependencyTopology { Type = typeof(T), Parameters = Enumerable.Empty<ShellParameter>() };
|
||||
}
|
||||
|
||||
ControllerTopology WithController<T>(string areaName, string controllerName) {
|
||||
|
@@ -34,7 +34,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
.Returns(topologyDescriptor);
|
||||
|
||||
_container.Mock<ICompositionStrategy>()
|
||||
.Setup(x => x.Compose(topologyDescriptor))
|
||||
.Setup(x => x.Compose(settings, topologyDescriptor))
|
||||
.Returns(topology);
|
||||
|
||||
_container.Mock<IShellContainerFactory>()
|
||||
@@ -47,7 +47,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
|
||||
var factory = _container.Resolve<IShellContextFactory>();
|
||||
|
||||
var context = factory.Create(settings);
|
||||
var context = factory.CreateShellContext(settings);
|
||||
|
||||
Assert.That(context.Settings, Is.SameAs(settings));
|
||||
Assert.That(context.Descriptor, Is.SameAs(topologyDescriptor));
|
||||
@@ -58,10 +58,11 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
|
||||
[Test]
|
||||
public void NullSettingsReturnsSetupContext() {
|
||||
var settings = new ShellSettings { Name = "Default" };
|
||||
var topology = new ShellTopology();
|
||||
|
||||
_container.Mock<ICompositionStrategy>()
|
||||
.Setup(x => x.Compose(It.IsAny<ShellDescriptor>()))
|
||||
.Setup(x => x.Compose(settings, It.IsAny<ShellDescriptor>()))
|
||||
.Returns(topology);
|
||||
|
||||
_container.Mock<IShellContainerFactory>()
|
||||
@@ -69,7 +70,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
.Returns(_container.BeginLifetimeScope("shell"));
|
||||
|
||||
var factory = _container.Resolve<IShellContextFactory>();
|
||||
var context = factory.Create(null);
|
||||
var context = factory.CreateShellContext(null);
|
||||
|
||||
Assert.That(context.Descriptor.EnabledFeatures, Has.Some.With.Property("Name").EqualTo("Orchard.Setup"));
|
||||
}
|
||||
|
@@ -1,5 +1,2 @@
|
||||
name: Settings
|
||||
antiforgery: enabled
|
||||
features:
|
||||
Settings:
|
||||
description: Site configuration support
|
||||
|
@@ -1,10 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Data.Conventions;
|
||||
|
||||
namespace Orchard.Core.Settings.Topology.Records {
|
||||
public class TopologyRecord {
|
||||
public virtual int Id { get; set; }
|
||||
public virtual int SerialNumber { get; set; }
|
||||
|
||||
[CascadeAllDeleteOrphan]
|
||||
public virtual IList<TopologyFeatureRecord> EnabledFeatures { get; set; }
|
||||
|
||||
[CascadeAllDeleteOrphan]
|
||||
public virtual IList<TopologyParameterRecord> Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Comments.Models;
|
||||
using Orchard.ContentManagement;
|
||||
@@ -9,6 +10,9 @@ using Orchard.Data;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Environment.Topology;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Setup.ViewModels;
|
||||
@@ -22,16 +26,22 @@ namespace Orchard.Setup.Controllers {
|
||||
private readonly INotifier _notifier;
|
||||
private readonly IOrchardHost _orchardHost;
|
||||
private readonly IShellSettingsManager _shellSettingsManager;
|
||||
private readonly IShellContainerFactory _shellContainerFactory;
|
||||
private readonly ICompositionStrategy _compositionStrategy;
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
public SetupController(
|
||||
INotifier notifier,
|
||||
IOrchardHost orchardHost,
|
||||
IOrchardHost orchardHost,
|
||||
IShellSettingsManager shellSettingsManager,
|
||||
IShellContainerFactory shellContainerFactory,
|
||||
ICompositionStrategy compositionStrategy,
|
||||
IAppDataFolder appDataFolder) {
|
||||
_notifier = notifier;
|
||||
_orchardHost = orchardHost;
|
||||
_shellSettingsManager = shellSettingsManager;
|
||||
_shellContainerFactory = shellContainerFactory;
|
||||
_compositionStrategy = compositionStrategy;
|
||||
_appDataFolder = appDataFolder;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -71,26 +81,44 @@ namespace Orchard.Setup.Controllers {
|
||||
DataConnectionString = model.DatabaseConnectionString
|
||||
};
|
||||
|
||||
const string hardcoded = @"Orchard.Framework,
|
||||
Common,Dashboard,Feeds,HomePage,Navigation,Scheduling,Settings,Themes,XmlRpc,
|
||||
Orchard.Users,Orchard.Roles,TinyMce,
|
||||
Orchard.Pages,Orchard.Comments";
|
||||
|
||||
var shellDescriptor = new ShellDescriptor {
|
||||
EnabledFeatures = hardcoded.Split(',').Select(name => new ShellFeature { Name = name.Trim() })
|
||||
};
|
||||
|
||||
var shellToplogy = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
||||
|
||||
// initialize database explicitly, and store shell descriptor
|
||||
var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellToplogy);
|
||||
using (var environment = new StandaloneEnvironment(bootstrapLifetimeScope)) {
|
||||
environment.Resolve<ISessionFactoryHolder>().CreateDatabase();
|
||||
|
||||
environment.Resolve<IShellDescriptorManager>().UpdateShellDescriptor(
|
||||
0,
|
||||
shellDescriptor.EnabledFeatures,
|
||||
shellDescriptor.Parameters);
|
||||
}
|
||||
|
||||
|
||||
// creating a standalone environment.
|
||||
// in theory this environment can be used to resolve any normal components by interface, and those
|
||||
// components will exist entirely in isolation - no crossover between the safemode container currently in effect
|
||||
using (var finiteEnvironment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||
try {
|
||||
// initialize database before the transaction is created
|
||||
var sessionFactoryHolder = finiteEnvironment.Resolve<ISessionFactoryHolder>();
|
||||
sessionFactoryHolder.CreateDatabase();
|
||||
|
||||
|
||||
// create superuser
|
||||
var membershipService = finiteEnvironment.Resolve<IMembershipService>();
|
||||
var membershipService = environment.Resolve<IMembershipService>();
|
||||
var user =
|
||||
membershipService.CreateUser(new CreateUserParams(model.AdminUsername, model.AdminPassword,
|
||||
String.Empty, String.Empty, String.Empty,
|
||||
true));
|
||||
|
||||
|
||||
|
||||
// set site name and settings
|
||||
var siteService = finiteEnvironment.Resolve<ISiteService>();
|
||||
var siteService = environment.Resolve<ISiteService>();
|
||||
var siteSettings = siteService.GetSiteSettings().As<SiteSettings>();
|
||||
siteSettings.Record.SiteSalt = Guid.NewGuid().ToString("N");
|
||||
siteSettings.Record.SiteName = model.SiteName;
|
||||
@@ -98,13 +126,13 @@ namespace Orchard.Setup.Controllers {
|
||||
siteSettings.Record.PageTitleSeparator = " - ";
|
||||
|
||||
// set site theme
|
||||
var themeService = finiteEnvironment.Resolve<IThemeService>();
|
||||
var themeService = environment.Resolve<IThemeService>();
|
||||
themeService.SetSiteTheme("Classic");
|
||||
|
||||
var contentManager = finiteEnvironment.Resolve<IContentManager>();
|
||||
var contentManager = environment.Resolve<IContentManager>();
|
||||
|
||||
// simulate installation-time module activation events
|
||||
var hackInstallationGenerator = finiteEnvironment.Resolve<IHackInstallationGenerator>();
|
||||
var hackInstallationGenerator = environment.Resolve<IHackInstallationGenerator>();
|
||||
hackInstallationGenerator.GenerateInstallEvents();
|
||||
|
||||
// create home page as a CMS page
|
||||
@@ -124,12 +152,12 @@ namespace Orchard.Setup.Controllers {
|
||||
menuItem.As<MenuPart>().OnMainMenu = true;
|
||||
menuItem.As<MenuItem>().Url = "";
|
||||
|
||||
var authenticationService = finiteEnvironment.Resolve<IAuthenticationService>();
|
||||
var authenticationService = environment.Resolve<IAuthenticationService>();
|
||||
authenticationService.SignIn(user, true);
|
||||
|
||||
|
||||
}
|
||||
catch {
|
||||
finiteEnvironment.Resolve<ITransactionManager>().Cancel();
|
||||
environment.Resolve<ITransactionManager>().Cancel();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +171,7 @@ namespace Orchard.Setup.Controllers {
|
||||
}
|
||||
catch (Exception exception) {
|
||||
_notifier.Error(T("Setup failed:"));
|
||||
for(var scan = exception; scan !=null; scan = scan.InnerException){
|
||||
for (var scan = exception; scan != null; scan = scan.InnerException) {
|
||||
_notifier.Error(scan.Message);
|
||||
}
|
||||
return IndexViewResult(model);
|
||||
|
@@ -1,5 +1,2 @@
|
||||
name: Setup
|
||||
antiforgery: enabled
|
||||
features:
|
||||
Orchard.Setup:
|
||||
description: Components needed to initialize a new instance or tenant
|
||||
|
@@ -1,4 +1,9 @@
|
||||
namespace Orchard.Environment.Configuration {
|
||||
/// <summary>
|
||||
/// Represents the minimalistic set of fields stored for each tenant. This
|
||||
/// model is obtained from the IShellSettingsManager, which by default reads this
|
||||
/// from the App_Data settings.txt files.
|
||||
/// </summary>
|
||||
public class ShellSettings {
|
||||
public string Name { get; set; }
|
||||
public string DataProvider { get; set; }
|
||||
|
@@ -92,12 +92,12 @@ namespace Orchard.Environment {
|
||||
|
||||
ShellContext CreateSetupContext() {
|
||||
Logger.Debug("Creating shell context for setup");
|
||||
return _shellContextFactory.Create(null);
|
||||
return _shellContextFactory.CreateSetupContext();
|
||||
}
|
||||
|
||||
ShellContext CreateShellContext(ShellSettings settings) {
|
||||
Logger.Debug("Creating shell context for tenant {0}", settings.Name);
|
||||
return _shellContextFactory.Create(settings);
|
||||
return _shellContextFactory.CreateShellContext(settings);
|
||||
}
|
||||
|
||||
protected virtual void BeginRequest() {
|
||||
|
@@ -88,26 +88,33 @@ namespace Orchard.Environment.Extensions {
|
||||
|
||||
private static IEnumerable<FeatureDescriptor> GetFeaturesForExtension(Mapping features, ExtensionDescriptor extensionDescriptor) {
|
||||
List<FeatureDescriptor> featureDescriptors = new List<FeatureDescriptor>();
|
||||
if (features == null) return featureDescriptors;
|
||||
foreach (var entity in features.Entities) {
|
||||
FeatureDescriptor featureDescriptor = new FeatureDescriptor {
|
||||
Extension = extensionDescriptor,
|
||||
Name = entity.Key.ToString(),
|
||||
};
|
||||
Mapping featureMapping = (Mapping)entity.Value;
|
||||
foreach (var featureEntity in featureMapping.Entities) {
|
||||
if (String.Equals(featureEntity.Key.ToString(), "description", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Description = featureEntity.Value.ToString();
|
||||
}
|
||||
else if (String.Equals(featureEntity.Key.ToString(), "category", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Category = featureEntity.Value.ToString();
|
||||
}
|
||||
else if (String.Equals(featureEntity.Key.ToString(), "dependencies", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Dependencies = ParseFeatureDependenciesEntry(featureEntity.Value.ToString());
|
||||
if (features != null) {
|
||||
foreach (var entity in features.Entities) {
|
||||
FeatureDescriptor featureDescriptor = new FeatureDescriptor {
|
||||
Extension = extensionDescriptor,
|
||||
Name = entity.Key.ToString(),
|
||||
};
|
||||
Mapping featureMapping = (Mapping)entity.Value;
|
||||
foreach (var featureEntity in featureMapping.Entities) {
|
||||
if (String.Equals(featureEntity.Key.ToString(), "description", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Description = featureEntity.Value.ToString();
|
||||
}
|
||||
else if (String.Equals(featureEntity.Key.ToString(), "category", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Category = featureEntity.Value.ToString();
|
||||
}
|
||||
else if (String.Equals(featureEntity.Key.ToString(), "dependencies", StringComparison.OrdinalIgnoreCase)) {
|
||||
featureDescriptor.Dependencies = ParseFeatureDependenciesEntry(featureEntity.Value.ToString());
|
||||
}
|
||||
}
|
||||
featureDescriptors.Add(featureDescriptor);
|
||||
}
|
||||
featureDescriptors.Add(featureDescriptor);
|
||||
|
||||
}
|
||||
if (!featureDescriptors.Any(fd => fd.Name == extensionDescriptor.Name)) {
|
||||
featureDescriptors.Add(new FeatureDescriptor {
|
||||
Name = extensionDescriptor.Name,
|
||||
Dependencies = new string[0],
|
||||
Extension = extensionDescriptor,
|
||||
});
|
||||
}
|
||||
return featureDescriptors;
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
|
||||
|
||||
public interface IShellContainerFactory {
|
||||
ILifetimeScope CreateContainer(ShellSettings settings, ShellTopology topology);
|
||||
}
|
||||
@@ -26,10 +26,16 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
public ILifetimeScope CreateContainer(ShellSettings settings, ShellTopology topology) {
|
||||
var intermediateScope = _lifetimeScope.BeginLifetimeScope(
|
||||
builder => {
|
||||
foreach (var item in topology.Modules) {
|
||||
RegisterType(builder, item)
|
||||
foreach (var item in topology.Dependencies.Where(t => typeof(IModule).IsAssignableFrom(t.Type))) {
|
||||
var registration = RegisterType(builder, item)
|
||||
.Keyed<IModule>(item.Type)
|
||||
.InstancePerDependency();
|
||||
|
||||
foreach (var parameter in item.Parameters) {
|
||||
registration = registration
|
||||
.WithParameter(parameter.Name, parameter.Value)
|
||||
.WithProperty(parameter.Name, parameter.Value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,11 +49,11 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
builder.Register(ctx => topology);
|
||||
|
||||
var moduleIndex = intermediateScope.Resolve<IIndex<Type, IModule>>();
|
||||
foreach (var item in topology.Modules) {
|
||||
foreach (var item in topology.Dependencies.Where(t => typeof(IModule).IsAssignableFrom(t.Type))) {
|
||||
builder.RegisterModule(moduleIndex[item.Type]);
|
||||
}
|
||||
|
||||
foreach (var item in topology.Dependencies) {
|
||||
foreach (var item in topology.Dependencies.Where(t => typeof(IDependency).IsAssignableFrom(t.Type))) {
|
||||
var registration = RegisterType(builder, item)
|
||||
.EnableDynamicProxy(dynamicProxyContext)
|
||||
.InstancePerLifetimeScope();
|
||||
|
@@ -6,9 +6,21 @@ using Orchard.Environment.Topology.Models;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Environment.ShellBuilders {
|
||||
|
||||
/// <summary>
|
||||
/// High-level coordinator that exercises other component capabilities to
|
||||
/// build all of the artifacts for a running shell given a tenant settings.
|
||||
/// </summary>
|
||||
public interface IShellContextFactory {
|
||||
ShellContext Create(ShellSettings settings);
|
||||
/// <summary>
|
||||
/// Builds a shell context given a specific tenant settings structure
|
||||
/// </summary>
|
||||
ShellContext CreateShellContext(ShellSettings settings);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a shell context for an uninitialized Orchard instance. Needed
|
||||
/// to display setup user interface.
|
||||
/// </summary>
|
||||
ShellContext CreateSetupContext();
|
||||
}
|
||||
|
||||
public class ShellContextFactory : IShellContextFactory {
|
||||
@@ -28,10 +40,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ShellContext Create(ShellSettings settings) {
|
||||
if (settings == null) {
|
||||
return CreateSetupContext();
|
||||
}
|
||||
public ShellContext CreateShellContext(ShellSettings settings) {
|
||||
|
||||
Logger.Debug("Creating shell context for tenant {0}", settings.Name);
|
||||
|
||||
@@ -41,7 +50,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
knownDescriptor = MinimumTopologyDescriptor();
|
||||
}
|
||||
|
||||
var topology = _compositionStrategy.Compose(knownDescriptor);
|
||||
var topology = _compositionStrategy.Compose(settings, knownDescriptor);
|
||||
var shellScope = _shellContainerFactory.CreateContainer(settings, topology);
|
||||
|
||||
ShellDescriptor currentDescriptor;
|
||||
@@ -54,7 +63,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
Logger.Information("Newer topology obtained. Rebuilding shell container.");
|
||||
|
||||
_shellDescriptorCache.Store(settings.Name, currentDescriptor);
|
||||
topology = _compositionStrategy.Compose(currentDescriptor);
|
||||
topology = _compositionStrategy.Compose(settings, currentDescriptor);
|
||||
shellScope = _shellContainerFactory.CreateContainer(settings, topology);
|
||||
}
|
||||
|
||||
@@ -78,16 +87,17 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
};
|
||||
}
|
||||
|
||||
private ShellContext CreateSetupContext() {
|
||||
public ShellContext CreateSetupContext() {
|
||||
Logger.Warning("No shell settings available. Creating shell context for setup");
|
||||
|
||||
var settings = new ShellSettings { Name = "__Orchard__Setup__" };
|
||||
|
||||
var descriptor = new ShellDescriptor {
|
||||
SerialNumber = -1,
|
||||
EnabledFeatures = new[] { new ShellFeature { Name = "Orchard.Setup" } },
|
||||
};
|
||||
|
||||
var topology = _compositionStrategy.Compose(descriptor);
|
||||
var topology = _compositionStrategy.Compose(settings, descriptor);
|
||||
var shellScope = _shellContainerFactory.CreateContainer(settings, topology);
|
||||
|
||||
return new ShellContext {
|
||||
|
@@ -6,6 +6,7 @@ using System.Web.Mvc;
|
||||
using Autofac.Core;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.Topology.Models;
|
||||
@@ -19,7 +20,7 @@ namespace Orchard.Environment.Topology {
|
||||
/// Using information from the IExtensionManager, transforms and populates all of the
|
||||
/// topology model the shell builders will need to correctly initialize a tenant IoC container.
|
||||
/// </summary>
|
||||
ShellTopology Compose(ShellDescriptor descriptor);
|
||||
ShellTopology Compose(ShellSettings settings, ShellDescriptor descriptor);
|
||||
}
|
||||
|
||||
public class CompositionStrategy : ICompositionStrategy {
|
||||
@@ -29,7 +30,7 @@ namespace Orchard.Environment.Topology {
|
||||
_extensionManager = extensionManager;
|
||||
}
|
||||
|
||||
public ShellTopology Compose(ShellDescriptor descriptor) {
|
||||
public ShellTopology Compose(ShellSettings settings, ShellDescriptor descriptor) {
|
||||
var enabledFeatures = _extensionManager.AvailableExtensions()
|
||||
.SelectMany(extensionDescriptor => extensionDescriptor.Features)
|
||||
.Where(featureDescriptor => IsFeatureEnabledInTopology(featureDescriptor, descriptor));
|
||||
@@ -39,11 +40,15 @@ namespace Orchard.Environment.Topology {
|
||||
if (descriptor.EnabledFeatures.Any(feature => feature.Name == "Orchard.Framework"))
|
||||
features = features.Concat(BuiltinFeatures());
|
||||
|
||||
var modules = BuildTopology<DependencyTopology>(features, IsModule, BuildModule);
|
||||
var dependencies = BuildTopology(features, IsDependency, (t, f) => BuildDependency(t, f, descriptor));
|
||||
var controllers = BuildTopology<ControllerTopology>(features, IsController, BuildController);
|
||||
var records = BuildTopology(features, IsRecord, (t, f) => BuildRecord(t, f, settings));
|
||||
|
||||
return new ShellTopology {
|
||||
Modules = BuildTopology<ModuleTopology>(features, IsModule, BuildModule),
|
||||
Dependencies = BuildTopology(features, IsDependency, (t, f) => BuildDependency(t, f, descriptor)),
|
||||
Controllers = BuildTopology<ControllerTopology>(features, IsController, BuildController),
|
||||
Records = BuildTopology<RecordTopology>(features, IsRecord, BuildRecord),
|
||||
Dependencies = dependencies.Concat(modules).ToArray(),
|
||||
Controllers = controllers,
|
||||
Records = records,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,8 +86,8 @@ namespace Orchard.Environment.Topology {
|
||||
return typeof(IModule).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
private static ModuleTopology BuildModule(Type type, Feature feature) {
|
||||
return new ModuleTopology { Type = type, Feature = feature };
|
||||
private static DependencyTopology BuildModule(Type type, Feature feature) {
|
||||
return new DependencyTopology { Type = type, Feature = feature, Parameters = Enumerable.Empty<ShellParameter>() };
|
||||
}
|
||||
|
||||
private static bool IsDependency(Type type) {
|
||||
@@ -125,14 +130,18 @@ namespace Orchard.Environment.Topology {
|
||||
(!typeof(IContent).IsAssignableFrom(type) || typeof(ContentPartRecord).IsAssignableFrom(type));
|
||||
}
|
||||
|
||||
private static RecordTopology BuildRecord(Type type, Feature feature) {
|
||||
private static RecordTopology BuildRecord(Type type, Feature feature, ShellSettings settings) {
|
||||
var extensionDescriptor = feature.Descriptor.Extension;
|
||||
var extensionName = extensionDescriptor.Name.Replace('.', '_');
|
||||
|
||||
var dataPrefix = "";
|
||||
if (!string.IsNullOrEmpty(settings.DataPrefix))
|
||||
dataPrefix = settings.DataPrefix + "_";
|
||||
|
||||
return new RecordTopology {
|
||||
Type = type,
|
||||
Feature = feature,
|
||||
TableName = extensionName + '_' + type.Name,
|
||||
TableName = dataPrefix + extensionName + '_' + type.Name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,13 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.Environment.Topology.Models {
|
||||
|
||||
/// <summary>
|
||||
/// Contains a snapshot of a tenant's enabled features.
|
||||
/// The information is drawn out of the shell via IShellDescriptorManager
|
||||
/// and cached by the host via IShellDescriptorCache. It is
|
||||
/// passed to the ICompositionStrategy to build the ShellTopology.
|
||||
/// </summary>
|
||||
public class ShellDescriptor {
|
||||
public ShellDescriptor() {
|
||||
EnabledFeatures = Enumerable.Empty<ShellFeature>();
|
||||
|
@@ -1,15 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.Environment.Topology.Models {
|
||||
|
||||
/// <summary>
|
||||
/// The topology of the shell (humor)
|
||||
/// Contains the information necessary to initialize an IoC container
|
||||
/// for a particular tenant. This model is created by the ICompositionStrategy
|
||||
/// and is passed into the IShellContainerFactory.
|
||||
/// </summary>
|
||||
public class ShellTopology {
|
||||
public IEnumerable<ModuleTopology> Modules { get; set; }
|
||||
public IEnumerable<DependencyTopology> Dependencies { get; set; }
|
||||
public IEnumerable<ControllerTopology> Controllers { get; set; }
|
||||
public IEnumerable<RecordTopology> Records { get; set; }
|
||||
@@ -20,9 +20,6 @@ namespace Orchard.Environment.Topology.Models {
|
||||
public Feature Feature { get; set; }
|
||||
}
|
||||
|
||||
public class ModuleTopology : ShellTopologyItem {
|
||||
}
|
||||
|
||||
public class DependencyTopology : ShellTopologyItem {
|
||||
public IEnumerable<ShellParameter> Parameters { get; set; }
|
||||
}
|
||||
|
Reference in New Issue
Block a user