--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-04-20 14:28:19 -07:00
16 changed files with 227 additions and 105 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,2 @@
name: Settings
antiforgery: enabled
features:
Settings:
description: Site configuration support

View File

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

View File

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

View File

@@ -1,5 +1,2 @@
name: Setup
antiforgery: enabled
features:
Orchard.Setup:
description: Components needed to initialize a new instance or tenant

View File

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

View File

@@ -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() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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