mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Moving ModuleService functionality to FeatureManager. Adding UT and comments. Removing Recipe module dependency on Modules module.
--HG-- branch : dev
This commit is contained in:
@@ -132,7 +132,7 @@ namespace Orchard.Tests.Modules.Media.Services {
|
||||
Record = new MediaSettingsPartRecord { UploadAllowedFileTypeWhitelist = "txt dll config" }
|
||||
};
|
||||
|
||||
StubWorkContextAccessor.WorkContextImpl.InitMethod = workContext => {
|
||||
StubWorkContextAccessor.WorkContextImpl._initMethod = workContext => {
|
||||
workContext.CurrentSite.ContentItem.Weld(mediaSettingsPart);
|
||||
};
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Orchard.Tests.Modules.Media.Services {
|
||||
Record = new MediaSettingsPartRecord { UploadAllowedFileTypeWhitelist = "txt dll config" }
|
||||
};
|
||||
|
||||
StubWorkContextAccessor.WorkContextImpl.InitMethod = workContext => {
|
||||
StubWorkContextAccessor.WorkContextImpl._initMethod = workContext => {
|
||||
workContext.CurrentSite.ContentItem.Weld(mediaSettingsPart);
|
||||
};
|
||||
|
||||
|
||||
74
src/Orchard.Tests/DatabaseEnabledTestsBase.cs
Normal file
74
src/Orchard.Tests/DatabaseEnabledTestsBase.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tests.Data;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests {
|
||||
public abstract class DatabaseEnabledTestsBase {
|
||||
|
||||
protected IContainer _container;
|
||||
|
||||
protected ISession _session;
|
||||
protected string _databaseFilePath;
|
||||
protected ISessionFactory _sessionFactory;
|
||||
protected StubClock _clock;
|
||||
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
_databaseFilePath = Path.GetTempFileName();
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TearDownFixture() {
|
||||
File.Delete(_databaseFilePath);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public virtual void Init() {
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(_databaseFilePath, DatabaseTypes.ToArray());
|
||||
_session = _sessionFactory.OpenSession();
|
||||
_clock = new StubClock();
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
//builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.RegisterInstance(new StubLocator(_session)).As<ISessionLocator>();
|
||||
builder.RegisterInstance(_clock).As<IClock>();
|
||||
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
|
||||
Register(builder);
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Cleanup() {
|
||||
if(_container != null)
|
||||
_container.Dispose();
|
||||
|
||||
if(_session != null)
|
||||
_session.Close();
|
||||
}
|
||||
|
||||
public abstract void Register(ContainerBuilder builder);
|
||||
|
||||
protected virtual IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return Enumerable.Empty<Type>();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ClearSession() {
|
||||
Trace.WriteLine("Flush and clear session");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
Trace.WriteLine("Flushed and cleared session");
|
||||
}
|
||||
}
|
||||
}
|
||||
188
src/Orchard.Tests/Environment/Features/FeatureManagerTests.cs
Normal file
188
src/Orchard.Tests/Environment/Features/FeatureManagerTests.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Core.Settings.Descriptor;
|
||||
using Orchard.Core.Settings.Descriptor.Records;
|
||||
using Orchard.Core.Settings.State;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Folders;
|
||||
using Orchard.Environment.Features;
|
||||
using Orchard.Environment.State;
|
||||
using Orchard.Events;
|
||||
using Orchard.Tests.Environment.Extensions;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Environment.Features {
|
||||
[TestFixture]
|
||||
public class FeatureManagerTests : DatabaseEnabledTestsBase {
|
||||
private ExtensionManagerTests.StubFolders _folders;
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] {
|
||||
typeof (ShellDescriptorRecord),
|
||||
typeof (ShellFeatureRecord),
|
||||
typeof (ShellParameterRecord),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register(ContainerBuilder builder) {
|
||||
_folders = new ExtensionManagerTests.StubFolders();
|
||||
builder.RegisterInstance(_folders).As<IExtensionFolders>();
|
||||
builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
|
||||
builder.RegisterType<FeatureManager>().As<IFeatureManager>();
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterType<ShellDescriptorManager>().As<IShellDescriptorManager>().SingleInstance();
|
||||
builder.RegisterType<ShellStateManager>().As<IShellStateManager>().SingleInstance();
|
||||
builder.RegisterType<StubEventBus>().As<IEventBus>().SingleInstance();
|
||||
builder.RegisterSource(new EventsRegistrationSource());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnableFeaturesTest() {
|
||||
_folders.Manifests.Add("SuperWiki", @"
|
||||
Name: SuperWiki
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
Features:
|
||||
SuperWiki:
|
||||
Description: My super wiki module for Orchard.
|
||||
");
|
||||
|
||||
// Initialize the shell descriptor with 0 features
|
||||
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>();
|
||||
IFeatureManager featureManager = _container.Resolve<IFeatureManager>();
|
||||
|
||||
shellDescriptorManager.UpdateShellDescriptor(0,
|
||||
Enumerable.Empty<ShellFeature>(),
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
IEnumerable<string> featuresToEnable = new [] { "SuperWiki" };
|
||||
|
||||
// Enable all features
|
||||
IEnumerable<string> enabledFeatures = featureManager.EnableFeatures(featuresToEnable);
|
||||
|
||||
Assert.That(enabledFeatures, Is.EqualTo(featuresToEnable));
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnableFeaturesWithDependenciesTest() {
|
||||
_folders.Manifests.Add("SuperWiki", @"
|
||||
Name: SuperWiki
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
Features:
|
||||
SuperWiki:
|
||||
Description: My super wiki module for Orchard.
|
||||
Dependencies: SuperWikiDep
|
||||
SuperWikiDep:
|
||||
Description: My super wiki module for Orchard dependency.
|
||||
");
|
||||
|
||||
// Initialize the shell descriptor with 0 features
|
||||
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>();
|
||||
IFeatureManager featureManager = _container.Resolve<IFeatureManager>();
|
||||
|
||||
shellDescriptorManager.UpdateShellDescriptor(0,
|
||||
Enumerable.Empty<ShellFeature>(),
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
IEnumerable<string> featuresToEnable = new[] { "SuperWiki" };
|
||||
|
||||
// Try to enable without forcing dependencies should fail
|
||||
IEnumerable<string> enabledFeatures = featureManager.EnableFeatures(featuresToEnable, false);
|
||||
Assert.That(enabledFeatures.Count(), Is.EqualTo(0));
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(0));
|
||||
|
||||
// Enabling while forcing dependencies should succeed.
|
||||
enabledFeatures = featureManager.EnableFeatures(featuresToEnable, true);
|
||||
Assert.That(enabledFeatures.Contains("SuperWiki"), Is.True);
|
||||
Assert.That(enabledFeatures.Contains("SuperWikiDep"), Is.True);
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableFeaturesTest() {
|
||||
_folders.Manifests.Add("SuperWiki", @"
|
||||
Name: SuperWiki
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
Features:
|
||||
SuperWiki:
|
||||
Description: My super wiki module for Orchard.
|
||||
");
|
||||
|
||||
// Initialize the shell descriptor with 0 features
|
||||
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>();
|
||||
IFeatureManager featureManager = _container.Resolve<IFeatureManager>();
|
||||
|
||||
shellDescriptorManager.UpdateShellDescriptor(0,
|
||||
new [] { new ShellFeature { Name = "SuperWiki" } },
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
IEnumerable<string> featuresToDisable = new [] { "SuperWiki" };
|
||||
|
||||
// Disable the feature
|
||||
featureManager.DisableFeatures(featuresToDisable);
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableFeaturesWithDependenciesTest() {
|
||||
_folders.Manifests.Add("SuperWiki", @"
|
||||
Name: SuperWiki
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
Features:
|
||||
SuperWiki:
|
||||
Description: My super wiki module for Orchard.
|
||||
Dependencies: SuperWikiDep
|
||||
SuperWikiDep:
|
||||
Description: My super wiki module for Orchard dependency.
|
||||
");
|
||||
|
||||
// Initialize the shell descriptor with 0 features
|
||||
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>();
|
||||
IFeatureManager featureManager = _container.Resolve<IFeatureManager>();
|
||||
|
||||
shellDescriptorManager.UpdateShellDescriptor(0,
|
||||
Enumerable.Empty<ShellFeature>(),
|
||||
Enumerable.Empty<ShellParameter>());
|
||||
|
||||
// Enable both features by relying on the dependency
|
||||
Assert.That(featureManager.EnableFeatures(new [] { "SuperWiki"}, true).Count(), Is.EqualTo(2));
|
||||
|
||||
IEnumerable<string> featuresToDisable = new[] { "SuperWikiDep" };
|
||||
|
||||
// Try to enable without forcing dependencies should fail
|
||||
IEnumerable<string> disabledFeatures = featureManager.DisableFeatures(featuresToDisable, false);
|
||||
Assert.That(disabledFeatures.Count(), Is.EqualTo(0));
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(2));
|
||||
|
||||
// Enabling while forcing dependencies should succeed.
|
||||
disabledFeatures = featureManager.DisableFeatures(featuresToDisable, true);
|
||||
Assert.That(disabledFeatures.Contains("SuperWiki"), Is.True);
|
||||
Assert.That(disabledFeatures.Contains("SuperWikiDep"), Is.True);
|
||||
Assert.That(featureManager.GetEnabledFeatures().Count(), Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
public class StubEventBus : IEventBus {
|
||||
public string LastMessageName { get; set; }
|
||||
public IDictionary<string, object> LastEventData { get; set; }
|
||||
|
||||
public IEnumerable Notify(string messageName, IDictionary<string, object> eventData) {
|
||||
LastMessageName = messageName;
|
||||
LastEventData = eventData;
|
||||
return new object[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,6 +207,7 @@
|
||||
<Compile Include="ContentManagement\Records\GammaRecord.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DatabaseEnabledTestsBase.cs" />
|
||||
<Compile Include="DataMigration\SchemaBuilderTests.cs" />
|
||||
<Compile Include="DataMigration\DataMigrationTests.cs" />
|
||||
<Compile Include="DataMigration\Utilities\NullInterpreter.cs" />
|
||||
@@ -233,6 +234,7 @@
|
||||
<Compile Include="Environment\AutofacUtil\DynamicProxy2\DynamicProxyTests.cs" />
|
||||
<Compile Include="Environment\DefaultWorkContextAccessorTests.cs" />
|
||||
<Compile Include="Environment\Extensions\ExtensionLoaderCoordinatorTests.cs" />
|
||||
<Compile Include="Environment\Features\FeatureManagerTests.cs" />
|
||||
<Compile Include="Environment\State\DefaultProcessingEngineTests.cs" />
|
||||
<Compile Include="Environment\RunningShellTableTests.cs" />
|
||||
<Compile Include="Environment\StubHostEnvironment.cs" />
|
||||
@@ -304,6 +306,10 @@
|
||||
<Compile Include="Utility\ReflectTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Orchard.Web\Core\Orchard.Core.csproj">
|
||||
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
|
||||
<Name>Orchard.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
|
||||
@@ -9,7 +9,7 @@ using Orchard.Settings;
|
||||
namespace Orchard.Tests.Stubs {
|
||||
public class StubWorkContextAccessor : IWorkContextAccessor {
|
||||
private readonly ILifetimeScope _lifetimeScope;
|
||||
private WorkContext _workContext;
|
||||
private readonly WorkContext _workContext;
|
||||
|
||||
public StubWorkContextAccessor(ILifetimeScope lifetimeScope) {
|
||||
_lifetimeScope = lifetimeScope;
|
||||
@@ -18,9 +18,11 @@ namespace Orchard.Tests.Stubs {
|
||||
|
||||
public class WorkContextImpl : WorkContext {
|
||||
private readonly ILifetimeScope _lifetimeScope;
|
||||
private Dictionary<string, object> _contextDictonary;
|
||||
private readonly Dictionary<string, object> _contextDictonary;
|
||||
|
||||
public delegate void MyInitMethod(WorkContextImpl workContextImpl);
|
||||
public static MyInitMethod InitMethod;
|
||||
|
||||
public static MyInitMethod _initMethod;
|
||||
|
||||
public WorkContextImpl(ILifetimeScope lifetimeScope) {
|
||||
_contextDictonary = new Dictionary<string, object>();
|
||||
@@ -30,8 +32,8 @@ namespace Orchard.Tests.Stubs {
|
||||
CurrentSite = ci.As<ISite>();
|
||||
_lifetimeScope = lifetimeScope;
|
||||
|
||||
if (InitMethod != null) {
|
||||
InitMethod(this);
|
||||
if (_initMethod != null) {
|
||||
_initMethod(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ OrchardVersion: 1.0
|
||||
Description: Description for the module
|
||||
Features:
|
||||
Orchard.MediaPicker:
|
||||
Name: MediaPicker
|
||||
Dependencies: Orchard.Media, Orchard.jQuery
|
||||
Name: MediaPicker
|
||||
Dependencies: Orchard.Media, Orchard.jQuery
|
||||
Description: UI for browsing for, uploading, or selecting an image for an HTML editor.
|
||||
Category: Input Editor
|
||||
Category: Input Editor
|
||||
@@ -1,12 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Modules.Models;
|
||||
|
||||
namespace Orchard.Modules.Services {
|
||||
public interface IModuleService : IDependency {
|
||||
void EnableFeatures(IEnumerable<string> featureNames);
|
||||
void EnableFeatures(IEnumerable<string> featureNames, bool force);
|
||||
void DisableFeatures(IEnumerable<string> featureNames);
|
||||
void DisableFeatures(IEnumerable<string> featureNames, bool force);
|
||||
bool IsRecentlyInstalled(ExtensionDescriptor module);
|
||||
/// <summary>
|
||||
/// Retrieves an enumeration of the available features together with its state (enabled / disabled).
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of the available features together with its state (enabled / disabled).</returns>
|
||||
IEnumerable<ModuleFeature> GetAvailableFeatures();
|
||||
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
void EnableFeatures(IEnumerable<string> featureIds);
|
||||
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
void EnableFeatures(IEnumerable<string> featureIds, bool force);
|
||||
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
void DisableFeatures(IEnumerable<string> featureIds);
|
||||
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should disable the features which depend on it if required or fail otherwise.</param>
|
||||
void DisableFeatures(IEnumerable<string> featureIds, bool force);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if an extension was recently installed.
|
||||
/// </summary>
|
||||
/// <param name="extensionDescriptor">The extension descriptor.</param>
|
||||
/// <returns>True if the feature was recently installed; false otherwise.</returns>
|
||||
bool IsRecentlyInstalled(ExtensionDescriptor extensionDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Features;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Modules.Models;
|
||||
@@ -12,28 +12,38 @@ using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Modules.Services {
|
||||
public class ModuleService : IModuleService {
|
||||
private readonly IFeatureManager _featureManager;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||
|
||||
public ModuleService(
|
||||
IFeatureManager featureManager,
|
||||
IOrchardServices orchardServices,
|
||||
IVirtualPathProvider virtualPathProvider,
|
||||
IExtensionManager extensionManager,
|
||||
IShellDescriptorManager shellDescriptorManager) {
|
||||
|
||||
Services = orchardServices;
|
||||
|
||||
_featureManager = featureManager;
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_extensionManager = extensionManager;
|
||||
_shellDescriptorManager = shellDescriptorManager;
|
||||
|
||||
if (_featureManager.FeatureDependencyNotification == null) {
|
||||
_featureManager.FeatureDependencyNotification = GenerateWarning;
|
||||
}
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an enumeration of the available features together with its state (enabled / disabled).
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of the available features together with its state (enabled / disabled).</returns>
|
||||
public IEnumerable<ModuleFeature> GetAvailableFeatures() {
|
||||
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().Features;
|
||||
return _extensionManager.AvailableExtensions()
|
||||
@@ -42,64 +52,50 @@ namespace Orchard.Modules.Services {
|
||||
.FirstOrDefault(sf => string.Equals(sf.Name, f.Descriptor.Id, StringComparison.OrdinalIgnoreCase)) != null));
|
||||
}
|
||||
|
||||
public void EnableFeatures(IEnumerable<string> featureNames) {
|
||||
EnableFeatures(featureNames, false);
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
public void EnableFeatures(IEnumerable<string> featureIds) {
|
||||
EnableFeatures(featureIds, false);
|
||||
}
|
||||
|
||||
public void EnableFeatures(IEnumerable<string> features, bool force) {
|
||||
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
var enabledFeatures = shellDescriptor.Features.ToList();
|
||||
var availableFeatures = GetAvailableFeatures().ToList();
|
||||
|
||||
var featuresToEnable = features
|
||||
.Select(s => EnableFeature(s, availableFeatures, force)).ToList()
|
||||
.SelectMany(ies => ies.Select(s => s));
|
||||
|
||||
if (featuresToEnable.Count() == 0)
|
||||
return;
|
||||
|
||||
foreach (var featureToEnable in featuresToEnable) {
|
||||
var feature = featureToEnable;
|
||||
enabledFeatures.Add(new ShellFeature { Name = feature });
|
||||
Services.Notifier.Information(T("{0} was enabled", featureToEnable));
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
public void EnableFeatures(IEnumerable<string> featureIds, bool force) {
|
||||
foreach (string featureId in _featureManager.EnableFeatures(featureIds, force)) {
|
||||
Services.Notifier.Information(T("{0} was enabled", featureId));
|
||||
}
|
||||
|
||||
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
||||
shellDescriptor.Parameters);
|
||||
}
|
||||
|
||||
public void DisableFeatures(IEnumerable<string> featureNames) {
|
||||
DisableFeatures(featureNames, false);
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
public void DisableFeatures(IEnumerable<string> featureIds) {
|
||||
DisableFeatures(featureIds, false);
|
||||
}
|
||||
|
||||
public void DisableFeatures(IEnumerable<string> features, bool force) {
|
||||
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
var enabledFeatures = shellDescriptor.Features.ToList();
|
||||
var availableFeatures = GetAvailableFeatures().ToList();
|
||||
|
||||
var featuresToDisable = features
|
||||
.Select(s => DisableFeature(s, availableFeatures, force)).ToList()
|
||||
.SelectMany(ies => ies.Select(s => s));
|
||||
|
||||
if (featuresToDisable.Count() == 0)
|
||||
return;
|
||||
|
||||
foreach (var featureToDisable in featuresToDisable) {
|
||||
var feature = featureToDisable;
|
||||
enabledFeatures.RemoveAll(f => f.Name == feature);
|
||||
Services.Notifier.Information(T("{0} was disabled", feature));
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should disable the features which depend on it if required or fail otherwise.</param>
|
||||
public void DisableFeatures(IEnumerable<string> featureIds, bool force) {
|
||||
foreach (string featureId in _featureManager.DisableFeatures(featureIds, force)) {
|
||||
Services.Notifier.Information(T("{0} was disabled", featureId));
|
||||
}
|
||||
|
||||
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
||||
shellDescriptor.Parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a module was recently installed by using the project's last written time.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The extension descriptor.</param>
|
||||
public bool IsRecentlyInstalled(ExtensionDescriptor descriptor) {
|
||||
string projectFile = GetManifestPath(descriptor);
|
||||
/// <param name="extensionDescriptor">The extension descriptor.</param>
|
||||
public bool IsRecentlyInstalled(ExtensionDescriptor extensionDescriptor) {
|
||||
string projectFile = GetManifestPath(extensionDescriptor);
|
||||
if (!string.IsNullOrEmpty(projectFile)) {
|
||||
// If project file was modified less than 24 hours ago, the module was recently deployed
|
||||
return DateTime.UtcNow.Subtract(_virtualPathProvider.GetFileLastWriteTimeUtc(projectFile)) < new TimeSpan(1, 0, 0, 0);
|
||||
@@ -108,9 +104,13 @@ namespace Orchard.Modules.Services {
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetManifestPath(ExtensionDescriptor descriptor) {
|
||||
string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
|
||||
"module.txt");
|
||||
/// <summary>
|
||||
/// Retrieves the full path of the manifest file for a module's extension descriptor.
|
||||
/// </summary>
|
||||
/// <param name="extensionDescriptor">The module's extension descriptor.</param>
|
||||
/// <returns>The full path to the module's manifest file.</returns>
|
||||
private string GetManifestPath(ExtensionDescriptor extensionDescriptor) {
|
||||
string projectPath = _virtualPathProvider.Combine(extensionDescriptor.Location, extensionDescriptor.Id, "module.txt");
|
||||
|
||||
if (!_virtualPathProvider.FileExists(projectPath)) {
|
||||
return null;
|
||||
@@ -119,81 +119,13 @@ namespace Orchard.Modules.Services {
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
private IEnumerable<string> EnableFeature(string featureName, IEnumerable<ModuleFeature> features, bool force) {
|
||||
var featuresList = features.ToList();
|
||||
var getDisabledDependencies =
|
||||
new Func<string, IEnumerable<ModuleFeature>, IEnumerable<ModuleFeature>>(
|
||||
(n, fs) => {
|
||||
var feature = fs.Single(f => f.Descriptor.Id == n);
|
||||
return feature.Descriptor.Dependencies != null
|
||||
? feature.Descriptor.Dependencies.Select(
|
||||
fn => fs.Single(f => f.Descriptor.Id == fn)).Where(f => !f.IsEnabled)
|
||||
: Enumerable.Empty<ModuleFeature>();
|
||||
});
|
||||
|
||||
var featuresToEnable = GetAffectedFeatures(featureName, featuresList, getDisabledDependencies);
|
||||
|
||||
if (featuresToEnable.Count() > 1 && !force) {
|
||||
GenerateWarning("If you want {0} enabled, then you'll also need to enable {1}.",
|
||||
featureName,
|
||||
featuresToEnable.Where(fn => fn != featureName));
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return featuresToEnable;
|
||||
}
|
||||
|
||||
private IEnumerable<string> DisableFeature(string featureName, IEnumerable<ModuleFeature> features, bool force) {
|
||||
var featuresList = features.ToList();
|
||||
var getEnabledDependants =
|
||||
new Func<string, IEnumerable<ModuleFeature>, IEnumerable<ModuleFeature>>(
|
||||
(n, fs) => fs.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(n)));
|
||||
|
||||
var featuresToDisable = GetAffectedFeatures(featureName, featuresList, getEnabledDependants);
|
||||
|
||||
if (featuresToDisable.Count() > 1 && !force) {
|
||||
GenerateWarning("If {0} is disabled, then you'll also lose {1}.",
|
||||
featureName,
|
||||
featuresToDisable.Where(fn => fn != featureName));
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return featuresToDisable;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetAffectedFeatures(string featureName, IEnumerable<ModuleFeature> features, Func<string, IEnumerable<ModuleFeature>, IEnumerable<ModuleFeature>> getAffectedDependencies) {
|
||||
var dependencies = new List<string> {featureName};
|
||||
|
||||
foreach (var dependency in getAffectedDependencies(featureName, features))
|
||||
dependencies.AddRange(GetAffectedFeatures(dependency.Descriptor.Id, features, getAffectedDependencies));
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private void GenerateWarning(string messageFormat, string featureName, IEnumerable<string> featuresInQuestion) {
|
||||
if (featuresInQuestion.Count() < 1)
|
||||
return;
|
||||
|
||||
Services.Notifier.Warning(T(
|
||||
messageFormat,
|
||||
featureName,
|
||||
featuresInQuestion.Count() > 1
|
||||
? string.Join("",
|
||||
featuresInQuestion.Select(
|
||||
(fn, i) =>
|
||||
T(i == featuresInQuestion.Count() - 1
|
||||
? "{0}"
|
||||
: (i == featuresInQuestion.Count() - 2
|
||||
? "{0} and "
|
||||
: "{0}, "), fn).ToString()).ToArray())
|
||||
: featuresInQuestion.First()));
|
||||
}
|
||||
|
||||
private static ModuleFeature AssembleModuleFromDescriptor(Feature feature, bool isEnabled) {
|
||||
return new ModuleFeature {
|
||||
Descriptor = feature.Descriptor,
|
||||
IsEnabled = isEnabled
|
||||
};
|
||||
}
|
||||
|
||||
private void GenerateWarning(string messageFormat, string featureName, IEnumerable<string> featuresInQuestion) {
|
||||
if (featuresInQuestion.Count() < 1)
|
||||
return;
|
||||
@@ -73,10 +73,6 @@
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Modules\Orchard.Modules.csproj">
|
||||
<Project>{17F86780-9A1F-4AA1-86F1-875EEC2730C7}</Project>
|
||||
<Name>Orchard.Modules</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Packaging\Orchard.Packaging.csproj">
|
||||
<Project>{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}</Project>
|
||||
<Name>Orchard.Packaging</Name>
|
||||
|
||||
@@ -4,18 +4,15 @@ using System.Linq;
|
||||
using Orchard.Environment.Features;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Modules.Services;
|
||||
using Orchard.Recipes.Models;
|
||||
using Orchard.Recipes.Services;
|
||||
|
||||
namespace Orchard.Recipes.RecipeHandlers {
|
||||
public class FeatureRecipeHandler : IRecipeHandler {
|
||||
private readonly IFeatureManager _featureManager;
|
||||
private readonly IModuleService _moduleService;
|
||||
|
||||
public FeatureRecipeHandler(IFeatureManager featureManager, IModuleService moduleService) {
|
||||
public FeatureRecipeHandler(IFeatureManager featureManager) {
|
||||
_featureManager = featureManager;
|
||||
_moduleService = moduleService;
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -58,10 +55,10 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
}
|
||||
|
||||
if (featuresToDisable.Count != 0) {
|
||||
_moduleService.DisableFeatures(featuresToDisable, true);
|
||||
_featureManager.DisableFeatures(featuresToDisable, true);
|
||||
}
|
||||
if (featuresToEnable.Count != 0) {
|
||||
_moduleService.EnableFeatures(featuresToEnable, true);
|
||||
_featureManager.EnableFeatures(featuresToEnable, true);
|
||||
}
|
||||
|
||||
recipeContext.Executed = true;
|
||||
|
||||
@@ -4,9 +4,9 @@ using System.Web.Hosting;
|
||||
using Orchard.Data.Migration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.Features;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Modules.Services;
|
||||
using Orchard.Packaging.Models;
|
||||
using Orchard.Packaging.Services;
|
||||
using Orchard.Recipes.Models;
|
||||
@@ -17,20 +17,21 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
private readonly IPackagingSourceManager _packagingSourceManager;
|
||||
private readonly IPackageManager _packageManager;
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IModuleService _moduleService;
|
||||
private readonly IFeatureManager _featureManager;
|
||||
private readonly IDataMigrationManager _dataMigrationManager;
|
||||
|
||||
public ModuleRecipeHandler(
|
||||
IPackagingSourceManager packagingSourceManager,
|
||||
IPackageManager packageManager,
|
||||
IExtensionManager extensionManager,
|
||||
IModuleService moduleService,
|
||||
IFeatureManager featureManager,
|
||||
IDataMigrationManager dataMigrationManager) {
|
||||
_packagingSourceManager = packagingSourceManager;
|
||||
_packageManager = packageManager;
|
||||
_extensionManager = extensionManager;
|
||||
_moduleService = moduleService;
|
||||
_featureManager = featureManager;
|
||||
_dataMigrationManager = dataMigrationManager;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -89,7 +90,7 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
from extensionDescriptor in extensions
|
||||
where String.Equals(extensionDescriptor.Name, packagingEntry.Title, StringComparison.OrdinalIgnoreCase)
|
||||
select extensionDescriptor.Features.Select(f => f.Name).ToArray()) {
|
||||
_moduleService.EnableFeatures(features);
|
||||
_featureManager.EnableFeatures(features);
|
||||
_dataMigrationManager.Update(features);
|
||||
installed = true;
|
||||
}
|
||||
|
||||
@@ -1,124 +1,202 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Environment.Features {
|
||||
public interface IFeatureManager : IDependency {
|
||||
IEnumerable<FeatureDescriptor> GetAvailableFeatures();
|
||||
IEnumerable<FeatureDescriptor> GetEnabledFeatures();
|
||||
|
||||
void EnableFeatures(IEnumerable<string> featureNames);
|
||||
void DisableFeatures(IEnumerable<string> featureNames);
|
||||
}
|
||||
|
||||
public class FeatureManager : IFeatureManager {
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly ShellDescriptor _shellDescriptor;
|
||||
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to notify about feature dependencies.
|
||||
/// </summary>
|
||||
public FeatureDependencyNotificationHandler FeatureDependencyNotification { get; set; }
|
||||
|
||||
public FeatureManager(
|
||||
IExtensionManager extensionManager,
|
||||
ShellDescriptor shellDescriptor,
|
||||
IShellDescriptorManager shellDescriptorManager) {
|
||||
_extensionManager = extensionManager;
|
||||
_shellDescriptor = shellDescriptor;
|
||||
_shellDescriptorManager = shellDescriptorManager;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the available features.
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of feature descriptors for the available features.</returns>
|
||||
public IEnumerable<FeatureDescriptor> GetAvailableFeatures() {
|
||||
return _extensionManager.AvailableFeatures();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the enabled features.
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of feature descriptors for the enabled features.</returns>
|
||||
public IEnumerable<FeatureDescriptor> GetEnabledFeatures() {
|
||||
var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
return _extensionManager.EnabledFeatures(currentShellDescriptor);
|
||||
}
|
||||
|
||||
public void EnableFeatures(IEnumerable<string> featureNames) {
|
||||
var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
|
||||
var updatedFeatures = currentShellDescriptor.Features
|
||||
.Union(featureNames
|
||||
.Where(name => !currentShellDescriptor.Features.Any(sf => sf.Name == name))
|
||||
.Select(name => new ShellFeature {Name = name}));
|
||||
|
||||
_shellDescriptorManager.UpdateShellDescriptor(
|
||||
currentShellDescriptor.SerialNumber,
|
||||
updatedFeatures,
|
||||
currentShellDescriptor.Parameters);
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
public IEnumerable<string> EnableFeatures(IEnumerable<string> featureIds) {
|
||||
return EnableFeatures(featureIds, false);
|
||||
}
|
||||
|
||||
public void DisableFeatures(IEnumerable<string> featureNames) {
|
||||
var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
public IEnumerable<string> EnableFeatures(IEnumerable<string> featureIds, bool force) {
|
||||
ShellDescriptor shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
List<ShellFeature> enabledFeatures = shellDescriptor.Features.ToList();
|
||||
|
||||
var updatedFeatures = currentShellDescriptor.Features
|
||||
.Where(sf => !featureNames.Contains(sf.Name));
|
||||
IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
|
||||
.ToDictionary(featureDescriptor => featureDescriptor,
|
||||
featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null);
|
||||
|
||||
_shellDescriptorManager.UpdateShellDescriptor(
|
||||
currentShellDescriptor.SerialNumber,
|
||||
updatedFeatures,
|
||||
currentShellDescriptor.Parameters);
|
||||
IEnumerable<string> featuresToEnable = featureIds
|
||||
.Select(featureId => EnableFeature(featureId, availableFeatures, force)).ToList()
|
||||
.SelectMany(ies => ies.Select(s => s));
|
||||
|
||||
if (featuresToEnable.Count() > 0) {
|
||||
foreach (string featureId in featuresToEnable) {
|
||||
string id = featureId;
|
||||
|
||||
enabledFeatures.Add(new ShellFeature { Name = id });
|
||||
Logger.Information(T("{0} was enabled", featureId).ToString());
|
||||
}
|
||||
|
||||
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
||||
shellDescriptor.Parameters);
|
||||
}
|
||||
|
||||
return featuresToEnable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <returns>An enumeration with the disabled feature IDs.</returns>
|
||||
public IEnumerable<string> DisableFeatures(IEnumerable<string> featureIds) {
|
||||
return DisableFeatures(featureIds, false);
|
||||
}
|
||||
|
||||
//private void DisableThemeFeatures(string themeName) {
|
||||
// var themes = new Queue<string>();
|
||||
// while (themeName != null) {
|
||||
// if (themes.Contains(themeName))
|
||||
// throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features disabled.", themeName).Text);
|
||||
// var theme = GetThemeByName(themeName);
|
||||
// if (theme == null)
|
||||
// break;
|
||||
// themes.Enqueue(themeName);
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should disable the features which depend on it if required or fail otherwise.</param>
|
||||
/// <returns>An enumeration with the disabled feature IDs.</returns>
|
||||
public IEnumerable<string> DisableFeatures(IEnumerable<string> featureIds, bool force) {
|
||||
ShellDescriptor shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||
List<ShellFeature> enabledFeatures = shellDescriptor.Features.ToList();
|
||||
|
||||
// themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
|
||||
// ? theme.BaseTheme
|
||||
// : null;
|
||||
IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
|
||||
.ToDictionary(featureDescriptor => featureDescriptor,
|
||||
featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null);
|
||||
|
||||
// }
|
||||
IEnumerable<string> featuresToDisable = featureIds
|
||||
.Select(featureId => DisableFeature(featureId, availableFeatures, force)).ToList()
|
||||
.SelectMany(ies => ies.Select(s => s));
|
||||
|
||||
// while (themes.Count > 0)
|
||||
// _moduleService.DisableFeatures(new[] { themes.Dequeue() });
|
||||
//}
|
||||
if (featuresToDisable.Count() > 0) {
|
||||
foreach (string featureId in featuresToDisable) {
|
||||
string id = featureId;
|
||||
|
||||
//private void EnableThemeFeatures(string themeName) {
|
||||
// var themes = new Stack<string>();
|
||||
// while (themeName != null) {
|
||||
// if (themes.Contains(themeName))
|
||||
// throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features enabled.", themeName).Text);
|
||||
// themes.Push(themeName);
|
||||
enabledFeatures.RemoveAll(shellFeature => shellFeature.Name == id);
|
||||
Logger.Information(T("{0} was disabled", featureId).ToString());
|
||||
}
|
||||
|
||||
// var theme = GetThemeByName(themeName);
|
||||
// themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
|
||||
// ? theme.BaseTheme
|
||||
// : null;
|
||||
// }
|
||||
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
||||
shellDescriptor.Parameters);
|
||||
}
|
||||
|
||||
// while (themes.Count > 0)
|
||||
// _moduleService.EnableFeatures(new[] { themes.Pop() });
|
||||
//}
|
||||
return featuresToDisable;
|
||||
}
|
||||
|
||||
//private bool DoEnableTheme(string themeName) {
|
||||
// if (string.IsNullOrWhiteSpace(themeName))
|
||||
// return false;
|
||||
/// <summary>
|
||||
/// Enables a feature.
|
||||
/// </summary>
|
||||
/// <param name="featureId">The ID of the feature to be enabled.</param>
|
||||
/// <param name="availableFeatures">A dictionary of the available feature descriptors and their current state (enabled / disabled).</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
/// <returns>An enumeration of the enabled features.</returns>
|
||||
private IEnumerable<string> EnableFeature(string featureId, IDictionary<FeatureDescriptor, bool> availableFeatures, bool force) {
|
||||
var getDisabledDependencies =
|
||||
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
||||
(currentFeatureId, featuresState) => {
|
||||
KeyValuePair<FeatureDescriptor, bool> feature = featuresState.Single(featureState => featureState.Key.Id == currentFeatureId);
|
||||
|
||||
// //todo: (heskew) need messages given in addition to all of these early returns so something meaningful can be presented to the user
|
||||
// var themeToEnable = GetThemeByName(themeName);
|
||||
// if (themeToEnable == null)
|
||||
// return false;
|
||||
// Retrieve disabled dependencies for the current feature
|
||||
return feature.Key.Dependencies
|
||||
.Select(fId => featuresState.Single(featureState => featureState.Key.Id == fId))
|
||||
.Where(featureState => !featureState.Value)
|
||||
.ToDictionary(f => f.Key, f => f.Value);
|
||||
});
|
||||
|
||||
// // ensure all base themes down the line are present and accounted for
|
||||
// //todo: (heskew) dito on the need of a meaningful message
|
||||
// if (!AllBaseThemesAreInstalled(themeToEnable.BaseTheme))
|
||||
// return false;
|
||||
IEnumerable<string> featuresToEnable = GetAffectedFeatures(featureId, availableFeatures, getDisabledDependencies);
|
||||
if (featuresToEnable.Count() > 1 && !force) {
|
||||
Logger.Warning(T("Aditional features need to be enabled.").ToString());
|
||||
if (FeatureDependencyNotification != null) {
|
||||
FeatureDependencyNotification("If {0} is enabled, then you'll also need to enable {1}.", featureId, featuresToEnable.Where(fId => fId != featureId));
|
||||
}
|
||||
|
||||
// // enable all theme features
|
||||
// EnableThemeFeatures(themeToEnable.Name);
|
||||
// return true;
|
||||
//}
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return featuresToEnable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables a feature.
|
||||
/// </summary>
|
||||
/// <param name="featureId">The ID of the feature to be enabled.</param>
|
||||
/// <param name="availableFeatures"></param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
/// <returns>An enumeration of the disabled features.</returns>
|
||||
private IEnumerable<string> DisableFeature(string featureId, IDictionary<FeatureDescriptor, bool> availableFeatures, bool force) {
|
||||
var getEnabledDependants =
|
||||
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
||||
(currentFeatureId, fs) => fs.Where(f => f.Value && f.Key.Dependencies != null && f.Key.Dependencies.Contains(currentFeatureId))
|
||||
.ToDictionary(f => f.Key, f => f.Value));
|
||||
|
||||
IEnumerable<string> featuresToDisable = GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
||||
if (featuresToDisable.Count() > 1 && !force) {
|
||||
Logger.Warning(T("Aditional features need to be disabled.").ToString());
|
||||
if (FeatureDependencyNotification != null) {
|
||||
FeatureDependencyNotification("If {0} is disabled, then you'll also need to disable {1}.", featureId, featuresToDisable.Where(fId => fId != featureId));
|
||||
}
|
||||
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return featuresToDisable;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetAffectedFeatures(string featureId, IDictionary<FeatureDescriptor, bool> features, Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>> getAffectedDependencies) {
|
||||
var dependencies = new List<string> { featureId };
|
||||
|
||||
foreach (KeyValuePair<FeatureDescriptor, bool> dependency in getAffectedDependencies(featureId, features)) {
|
||||
dependencies.AddRange(GetAffectedFeatures(dependency.Key.Id, features, getAffectedDependencies));
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
src/Orchard/Environment/Features/IFeatureManager.cs
Normal file
52
src/Orchard/Environment/Features/IFeatureManager.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.Environment.Features {
|
||||
public delegate void FeatureDependencyNotificationHandler(string messageFormat, string featureId, IEnumerable<string> featureIds);
|
||||
|
||||
public interface IFeatureManager : IDependency {
|
||||
FeatureDependencyNotificationHandler FeatureDependencyNotification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the available features.
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of feature descriptors for the available features.</returns>
|
||||
IEnumerable<FeatureDescriptor> GetAvailableFeatures();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the enabled features.
|
||||
/// </summary>
|
||||
/// <returns>An enumeration of feature descriptors for the enabled features.</returns>
|
||||
IEnumerable<FeatureDescriptor> GetEnabledFeatures();
|
||||
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
/// <returns>An enumeration with the enabled feature IDs.</returns>
|
||||
IEnumerable<string> EnableFeatures(IEnumerable<string> featureIds);
|
||||
|
||||
/// <summary>
|
||||
/// Enables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be enabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||
/// <returns>An enumeration with the enabled feature IDs.</returns>
|
||||
IEnumerable<string> EnableFeatures(IEnumerable<string> featureIds, bool force);
|
||||
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <returns>An enumeration with the disabled feature IDs.</returns>
|
||||
IEnumerable<string> DisableFeatures(IEnumerable<string> featureIds);
|
||||
|
||||
/// <summary>
|
||||
/// Disables a list of features.
|
||||
/// </summary>
|
||||
/// <param name="featureIds">The IDs for the features to be disabled.</param>
|
||||
/// <param name="force">Boolean parameter indicating if the feature should disable the features which depend on it if required or fail otherwise.</param>
|
||||
/// <returns>An enumeration with the disabled feature IDs.</returns>
|
||||
IEnumerable<string> DisableFeatures(IEnumerable<string> featureIds, bool force);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Localization {
|
||||
public delegate LocalizedString Localizer(string text, params object[] args);
|
||||
|
||||
}
|
||||
|
||||
namespace Orchard.Mvc.Html {
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeDisplayEvents.cs" />
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeFactoryEvents.cs" />
|
||||
<Compile Include="DisplayManagement\Shapes\ITagBuilderFactory.cs" />
|
||||
<Compile Include="Environment\Features\IFeatureManager.cs" />
|
||||
<Compile Include="Environment\IAssemblyNameResolver.cs" />
|
||||
<Compile Include="Environment\Extensions\Models\DefaultExtensionTypes.cs" />
|
||||
<Compile Include="Environment\HostEnvironment.cs" />
|
||||
|
||||
Reference in New Issue
Block a user