mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Refactoring feature manager. Added method for fetching dependent features. Removed recursion when traversing dependency tree and added circular dependency safeguard.
This commit is contained in:
@@ -107,12 +107,8 @@ namespace Orchard.Environment.Features {
|
||||
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()
|
||||
.Select(featureId => DisableFeature(featureId, force)).ToList()
|
||||
.SelectMany(ies => ies.Select(s => s));
|
||||
|
||||
if (featuresToDisable.Any()) {
|
||||
@@ -130,6 +126,30 @@ namespace Orchard.Environment.Features {
|
||||
return featuresToDisable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists all enabled features that depend on a given feature.
|
||||
/// </summary>
|
||||
/// <param name="featureId">ID of the feature to check.</param>
|
||||
/// <returns>An enumeration with dependent feature IDs.</returns>
|
||||
public IEnumerable<string> GetDependentFeatures(string featureId) {
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
return GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables a feature.
|
||||
/// </summary>
|
||||
@@ -179,16 +199,11 @@ namespace Orchard.Environment.Features {
|
||||
/// 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));
|
||||
private IEnumerable<string> DisableFeature(string featureId, bool force) {
|
||||
IEnumerable<string> featuresToDisable = GetDependentFeatures(featureId);
|
||||
|
||||
IEnumerable<string> featuresToDisable = GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
||||
if (featuresToDisable.Count() > 1 && !force) {
|
||||
Logger.Warning("Additional features need to be disabled.");
|
||||
if (FeatureDependencyNotification != null) {
|
||||
@@ -201,11 +216,21 @@ namespace Orchard.Environment.Features {
|
||||
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 };
|
||||
private static IEnumerable<string> GetAffectedFeatures(
|
||||
string featureId, IDictionary<FeatureDescriptor, bool> features,
|
||||
Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>> getAffectedDependencies) {
|
||||
|
||||
foreach (KeyValuePair<FeatureDescriptor, bool> dependency in getAffectedDependencies(featureId, features)) {
|
||||
dependencies.AddRange(GetAffectedFeatures(dependency.Key.Id, features, getAffectedDependencies));
|
||||
var dependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { featureId };
|
||||
var stack = new Stack<IDictionary<FeatureDescriptor, bool>>();
|
||||
|
||||
stack.Push(getAffectedDependencies(featureId, features));
|
||||
|
||||
while (stack.Any()) {
|
||||
var next = stack.Pop();
|
||||
foreach (var dependency in next.Where(dependency => !dependencies.Contains(dependency.Key.Id))) {
|
||||
dependencies.Add(dependency.Key.Id);
|
||||
stack.Push(getAffectedDependencies(dependency.Key.Id, features));
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
|
@@ -48,5 +48,12 @@ namespace Orchard.Environment.Features {
|
||||
/// <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);
|
||||
|
||||
/// <summary>
|
||||
/// Lists all enabled features that depend on a given feature.
|
||||
/// </summary>
|
||||
/// <param name="featureId">ID of the feature to check.</param>
|
||||
/// <returns>An enumeration with dependent feature IDs.</returns>
|
||||
IEnumerable<string> GetDependentFeatures(string featureId);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user