2010-04-24 06:10:47 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Web;
|
|
|
|
|
using Orchard.Environment.Extensions;
|
2010-04-28 02:24:06 +08:00
|
|
|
|
using Orchard.Environment.Extensions.Models;
|
2010-06-12 08:28:46 +08:00
|
|
|
|
using Orchard.Environment.Descriptor;
|
|
|
|
|
using Orchard.Environment.Descriptor.Models;
|
2010-05-19 01:04:14 +08:00
|
|
|
|
using Orchard.Localization;
|
2010-04-24 06:10:47 +08:00
|
|
|
|
using Orchard.Modules.Models;
|
2010-05-19 01:04:14 +08:00
|
|
|
|
using Orchard.UI.Notify;
|
2010-04-24 06:10:47 +08:00
|
|
|
|
|
|
|
|
|
namespace Orchard.Modules.Services {
|
|
|
|
|
public class ModuleService : IModuleService {
|
2010-04-28 02:24:06 +08:00
|
|
|
|
private const string ModuleExtensionType = "module";
|
2010-04-24 06:10:47 +08:00
|
|
|
|
private readonly IExtensionManager _extensionManager;
|
2010-04-29 02:47:29 +08:00
|
|
|
|
private readonly IShellDescriptorManager _shellDescriptorManager;
|
2010-10-12 06:24:11 +08:00
|
|
|
|
private readonly IWorkContextAccessor _workContextAccessor;
|
2010-04-24 06:10:47 +08:00
|
|
|
|
|
2010-10-12 06:24:11 +08:00
|
|
|
|
public ModuleService(
|
|
|
|
|
IOrchardServices orchardServices,
|
|
|
|
|
IExtensionManager extensionManager,
|
|
|
|
|
IShellDescriptorManager shellDescriptorManager,
|
|
|
|
|
IWorkContextAccessor workContextAccessor) {
|
2010-05-19 01:04:14 +08:00
|
|
|
|
Services = orchardServices;
|
2010-04-24 06:10:47 +08:00
|
|
|
|
_extensionManager = extensionManager;
|
2010-04-29 02:47:29 +08:00
|
|
|
|
_shellDescriptorManager = shellDescriptorManager;
|
2010-10-12 06:24:11 +08:00
|
|
|
|
_workContextAccessor = workContextAccessor;
|
2010-05-19 01:04:14 +08:00
|
|
|
|
T = NullLocalizer.Instance;
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-06-03 04:54:50 +08:00
|
|
|
|
public Localizer T { get; set; }
|
2010-05-19 01:04:14 +08:00
|
|
|
|
public IOrchardServices Services { get; set; }
|
|
|
|
|
|
2010-04-24 06:10:47 +08:00
|
|
|
|
public IModule GetModuleByName(string moduleName) {
|
2010-07-19 04:10:10 +08:00
|
|
|
|
return _extensionManager
|
|
|
|
|
.AvailableExtensions()
|
|
|
|
|
.Where(e => string.Equals(e.Name, moduleName, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
.Where(e => string.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
.Select(descriptor => AssembleModuleFromDescriptor(descriptor))
|
|
|
|
|
.FirstOrDefault();
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<IModule> GetInstalledModules() {
|
2010-07-19 04:10:10 +08:00
|
|
|
|
return _extensionManager
|
|
|
|
|
.AvailableExtensions()
|
|
|
|
|
.Where(e => String.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
.Select(descriptor => AssembleModuleFromDescriptor(descriptor));
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InstallModule(HttpPostedFileBase file) {
|
2010-04-28 02:24:06 +08:00
|
|
|
|
_extensionManager.InstallExtension(ModuleExtensionType, file);
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UninstallModule(string moduleName) {
|
2010-04-28 02:24:06 +08:00
|
|
|
|
_extensionManager.UninstallExtension(ModuleExtensionType, moduleName);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-29 02:47:29 +08:00
|
|
|
|
public IEnumerable<IModuleFeature> GetAvailableFeatures() {
|
2010-05-29 04:03:57 +08:00
|
|
|
|
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().Features;
|
2010-10-01 05:14:57 +08:00
|
|
|
|
return _extensionManager.AvailableExtensions()
|
2010-04-29 02:47:29 +08:00
|
|
|
|
.SelectMany(m => _extensionManager.LoadFeatures(m.Features))
|
2010-07-19 04:10:10 +08:00
|
|
|
|
.Select(f => AssembleModuleFromDescriptor(f, enabledFeatures
|
|
|
|
|
.FirstOrDefault(sf => string.Equals(sf.Name, f.Descriptor.Name, StringComparison.OrdinalIgnoreCase)) != null));
|
2010-04-29 02:47:29 +08:00
|
|
|
|
}
|
2010-04-28 02:24:06 +08:00
|
|
|
|
|
2010-05-19 15:00:56 +08:00
|
|
|
|
public void EnableFeatures(IEnumerable<string> featureNames) {
|
|
|
|
|
EnableFeatures(featureNames, false);
|
2010-04-28 02:24:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 15:00:56 +08:00
|
|
|
|
public void EnableFeatures(IEnumerable<string> features, bool force) {
|
2010-04-29 02:47:29 +08:00
|
|
|
|
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
2010-05-29 04:03:57 +08:00
|
|
|
|
var enabledFeatures = shellDescriptor.Features.ToList();
|
2010-05-19 15:00:56 +08:00
|
|
|
|
|
|
|
|
|
var featuresToEnable =
|
|
|
|
|
features.Select(s => EnableFeature(s, GetAvailableFeatures(), force)).
|
|
|
|
|
SelectMany(ies => ies.Select(s => s));
|
|
|
|
|
|
|
|
|
|
if (featuresToEnable.Count() == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (var featureToEnable in featuresToEnable) {
|
|
|
|
|
enabledFeatures.Add(new ShellFeature {Name = featureToEnable});
|
|
|
|
|
Services.Notifier.Information(T("{0} was enabled", featureToEnable));
|
2010-05-19 01:04:14 +08:00
|
|
|
|
}
|
2010-04-29 02:47:29 +08:00
|
|
|
|
|
2010-05-19 15:00:56 +08:00
|
|
|
|
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
|
|
|
|
shellDescriptor.Parameters);
|
2010-04-28 02:24:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DisableFeatures(IEnumerable<string> featureNames) {
|
2010-05-19 15:00:56 +08:00
|
|
|
|
DisableFeatures(featureNames, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DisableFeatures(IEnumerable<string> features, bool force) {
|
2010-04-29 02:47:29 +08:00
|
|
|
|
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
2010-05-29 04:03:57 +08:00
|
|
|
|
var enabledFeatures = shellDescriptor.Features.ToList();
|
2010-10-16 05:29:04 +08:00
|
|
|
|
var availableFeatures = GetAvailableFeatures().ToList();
|
2010-05-19 15:00:56 +08:00
|
|
|
|
|
|
|
|
|
var featuresToDisable =
|
2010-10-16 05:29:04 +08:00
|
|
|
|
features.Select(s => DisableFeature(s, availableFeatures, force)).SelectMany(
|
2010-05-19 15:00:56 +08:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures,
|
|
|
|
|
shellDescriptor.Parameters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IModule GetModuleByFeatureName(string featureName) {
|
|
|
|
|
return GetInstalledModules()
|
|
|
|
|
.Where(
|
|
|
|
|
m =>
|
|
|
|
|
m.Features.FirstOrDefault(
|
|
|
|
|
f => string.Equals(f.Name, featureName, StringComparison.OrdinalIgnoreCase)) !=
|
|
|
|
|
null).FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<string> EnableFeature(string featureName, IEnumerable<IModuleFeature> features, bool force) {
|
|
|
|
|
var featuresList = features.ToList();
|
|
|
|
|
var getDisabledDependencies =
|
|
|
|
|
new Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>>(
|
|
|
|
|
(n, fs) => {
|
|
|
|
|
var feature = fs.Single(f => f.Descriptor.Name == n);
|
|
|
|
|
return feature.Descriptor.Dependencies != null
|
|
|
|
|
? feature.Descriptor.Dependencies.Select(
|
|
|
|
|
fn => fs.Single(f => f.Descriptor.Name == fn)).Where(f => !f.IsEnabled)
|
|
|
|
|
: Enumerable.Empty<IModuleFeature>();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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>();
|
2010-05-15 06:52:22 +08:00
|
|
|
|
}
|
2010-04-29 02:47:29 +08:00
|
|
|
|
|
2010-05-19 15:00:56 +08:00
|
|
|
|
return featuresToEnable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<string> DisableFeature(string featureName, IEnumerable<IModuleFeature> features, bool force) {
|
|
|
|
|
var featuresList = features.ToList();
|
|
|
|
|
var getEnabledDependants =
|
|
|
|
|
new Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>>(
|
|
|
|
|
(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<IModuleFeature> features, Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>> getAffectedDependencies) {
|
|
|
|
|
var dependencies = new List<string> {featureName};
|
|
|
|
|
|
|
|
|
|
foreach (var dependency in getAffectedDependencies(featureName, features))
|
|
|
|
|
dependencies.AddRange(GetAffectedFeatures(dependency.Descriptor.Name, 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()));
|
2010-04-28 02:24:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-12 06:24:11 +08:00
|
|
|
|
private static string TryLocalize(string key, string original, Localizer localizer) {
|
|
|
|
|
var localized = localizer(key).Text;
|
|
|
|
|
|
|
|
|
|
if(key == localized) {
|
|
|
|
|
// no specific localization available
|
|
|
|
|
return original;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return localized;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IModule AssembleModuleFromDescriptor(ExtensionDescriptor extensionDescriptor) {
|
|
|
|
|
|
|
|
|
|
var localizer = LocalizationUtilities.Resolve(_workContextAccessor.GetContext(), String.Concat(extensionDescriptor.Location, "/", extensionDescriptor.Name, "/Module.txt"));
|
|
|
|
|
|
2010-04-28 02:24:06 +08:00
|
|
|
|
return new Module {
|
2010-10-12 06:24:11 +08:00
|
|
|
|
ModuleName = extensionDescriptor.Name,
|
|
|
|
|
DisplayName = TryLocalize("Name", extensionDescriptor.DisplayName, localizer),
|
|
|
|
|
Description = TryLocalize("Description", extensionDescriptor.Description, localizer),
|
|
|
|
|
Version = extensionDescriptor.Version,
|
|
|
|
|
Author = TryLocalize("Author", extensionDescriptor.Author, localizer),
|
|
|
|
|
HomePage = TryLocalize("Website", extensionDescriptor.WebSite, localizer),
|
|
|
|
|
Tags = TryLocalize("Tags", extensionDescriptor.Tags, localizer),
|
|
|
|
|
Features = extensionDescriptor.Features.Select(f => new FeatureDescriptor {
|
|
|
|
|
Category = TryLocalize(f.Name + " Category", f.Category, localizer),
|
|
|
|
|
Dependencies = f.Dependencies,
|
2010-10-17 03:24:38 +08:00
|
|
|
|
Description = TryLocalize(f.Name + " Description", f.Description, localizer),
|
2010-10-18 11:46:01 +08:00
|
|
|
|
DisplayName = TryLocalize(f.Name + " Name", f.DisplayName, localizer),
|
2010-10-12 06:24:11 +08:00
|
|
|
|
Extension = f.Extension,
|
2010-10-17 03:15:09 +08:00
|
|
|
|
Name = f.Name,
|
2010-10-12 06:24:11 +08:00
|
|
|
|
})
|
|
|
|
|
};
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
2010-04-29 02:47:29 +08:00
|
|
|
|
|
|
|
|
|
private static IModuleFeature AssembleModuleFromDescriptor(Feature feature, bool isEnabled) {
|
|
|
|
|
return new ModuleFeature {
|
|
|
|
|
Descriptor = feature.Descriptor,
|
|
|
|
|
IsEnabled = isEnabled
|
|
|
|
|
};
|
|
|
|
|
}
|
2010-04-24 06:10:47 +08:00
|
|
|
|
}
|
|
|
|
|
}
|