/src/Orchard/Environment/Features/FeatureManager.cs
C# | 202 lines | 121 code | 35 blank | 46 comment | 19 complexity | b960ffb3c728755bd3ad4cbffe0af9aa MD5 | raw file
Possible License(s): LGPL-2.1, MIT, BSD-3-Clause, Apache-2.0, CPL-1.0, CC-BY-SA-3.0, GPL-2.0
- 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 class FeatureManager : IFeatureManager {
- private readonly IExtensionManager _extensionManager;
- private readonly IShellDescriptorManager _shellDescriptorManager;
-
- /// <summary>
- /// Delegate to notify about feature dependencies.
- /// </summary>
- public FeatureDependencyNotificationHandler FeatureDependencyNotification { get; set; }
-
- public FeatureManager(
- IExtensionManager extensionManager,
- IShellDescriptorManager shellDescriptorManager) {
- _extensionManager = extensionManager;
- _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);
- }
-
- /// <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);
- }
-
- /// <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();
-
- IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
- .ToDictionary(featureDescriptor => featureDescriptor,
- featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null);
-
- 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("{0} was enabled", featureId);
- }
-
- _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);
- }
-
- /// <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();
-
- IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
- .ToDictionary(featureDescriptor => featureDescriptor,
- featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name.Equals(featureDescriptor.Id)) != null);
-
- IEnumerable<string> featuresToDisable = featureIds
- .Select(featureId => DisableFeature(featureId, availableFeatures, force)).ToList()
- .SelectMany(ies => ies.Select(s => s));
-
- if (featuresToDisable.Any()) {
- foreach (string featureId in featuresToDisable) {
- string id = featureId;
-
- enabledFeatures.RemoveAll(shellFeature => shellFeature.Name == id);
- Logger.Information("{0} was disabled", featureId);
- }
-
- _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
- shellDescriptor.Parameters);
- }
-
- return featuresToDisable;
- }
-
- /// <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.Equals(currentFeatureId, StringComparison.OrdinalIgnoreCase));
-
- // Retrieve disabled dependencies for the current feature
- return feature.Key.Dependencies
- .Select(fId => featuresState.Single(featureState => featureState.Key.Id.Equals(fId, StringComparison.OrdinalIgnoreCase)))
- .Where(featureState => !featureState.Value)
- .ToDictionary(f => f.Key, f => f.Value);
- });
-
- IEnumerable<string> featuresToEnable = GetAffectedFeatures(featureId, availableFeatures, getDisabledDependencies);
- if (featuresToEnable.Count() > 1 && !force) {
- Logger.Warning("Additional features need to be enabled.");
- if (FeatureDependencyNotification != null) {
- FeatureDependencyNotification("If {0} is enabled, then you'll also need to enable {1}.", featureId, featuresToEnable.Where(fId => fId != featureId));
- }
-
- 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.Select(s => s.ToLowerInvariant()).Contains(currentFeatureId.ToLowerInvariant()))
- .ToDictionary(f => f.Key, f => f.Value));
-
- IEnumerable<string> featuresToDisable = GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
- if (featuresToDisable.Count() > 1 && !force) {
- Logger.Warning("Additional features need to be disabled.");
- 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;
- }
- }
- }