mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-17 18:01:19 +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();
|
ShellDescriptor shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||||
List<ShellFeature> enabledFeatures = shellDescriptor.Features.ToList();
|
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
|
IEnumerable<string> featuresToDisable = featureIds
|
||||||
.Select(featureId => DisableFeature(featureId, availableFeatures, force)).ToList()
|
.Select(featureId => DisableFeature(featureId, force)).ToList()
|
||||||
.SelectMany(ies => ies.Select(s => s));
|
.SelectMany(ies => ies.Select(s => s));
|
||||||
|
|
||||||
if (featuresToDisable.Any()) {
|
if (featuresToDisable.Any()) {
|
||||||
@@ -130,6 +126,30 @@ namespace Orchard.Environment.Features {
|
|||||||
return featuresToDisable;
|
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>
|
/// <summary>
|
||||||
/// Enables a feature.
|
/// Enables a feature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -179,16 +199,11 @@ namespace Orchard.Environment.Features {
|
|||||||
/// Disables a feature.
|
/// Disables a feature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="featureId">The ID of the feature to be enabled.</param>
|
/// <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>
|
/// <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>
|
/// <returns>An enumeration of the disabled features.</returns>
|
||||||
private IEnumerable<string> DisableFeature(string featureId, IDictionary<FeatureDescriptor, bool> availableFeatures, bool force) {
|
private IEnumerable<string> DisableFeature(string featureId, bool force) {
|
||||||
var getEnabledDependants =
|
IEnumerable<string> featuresToDisable = GetDependentFeatures(featureId);
|
||||||
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) {
|
if (featuresToDisable.Count() > 1 && !force) {
|
||||||
Logger.Warning("Additional features need to be disabled.");
|
Logger.Warning("Additional features need to be disabled.");
|
||||||
if (FeatureDependencyNotification != null) {
|
if (FeatureDependencyNotification != null) {
|
||||||
@@ -201,11 +216,21 @@ namespace Orchard.Environment.Features {
|
|||||||
return featuresToDisable;
|
return featuresToDisable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetAffectedFeatures(string featureId, IDictionary<FeatureDescriptor, bool> features, Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>> getAffectedDependencies) {
|
private static IEnumerable<string> GetAffectedFeatures(
|
||||||
var dependencies = new List<string> { featureId };
|
string featureId, IDictionary<FeatureDescriptor, bool> features,
|
||||||
|
Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>> getAffectedDependencies) {
|
||||||
|
|
||||||
foreach (KeyValuePair<FeatureDescriptor, bool> dependency in getAffectedDependencies(featureId, features)) {
|
var dependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { featureId };
|
||||||
dependencies.AddRange(GetAffectedFeatures(dependency.Key.Id, features, getAffectedDependencies));
|
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;
|
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>
|
/// <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>
|
/// <returns>An enumeration with the disabled feature IDs.</returns>
|
||||||
IEnumerable<string> DisableFeatures(IEnumerable<string> featureIds, bool force);
|
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